~ubuntu-branches/ubuntu/natty/vlc/natty

« back to all changes in this revision

Viewing changes to modules/gui/hildon/maemo.c

  • Committer: Bazaar Package Importer
  • Author(s): Benjamin Drung
  • Date: 2010-06-25 01:09:16 UTC
  • mfrom: (1.1.30 upstream)
  • Revision ID: james.westby@ubuntu.com-20100625010916-asxhep2mutg6g6pd
Tags: 1.1.0-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - build and install the libx264 plugin
  - add Xb-Npp header to vlc package
  - Add apport hook to include more vlc dependencies in bug reports
* Drop xulrunner patches.
* Drop 502_xulrunner_191.diff.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
 * maemo.c : Maemo plugin for VLC
 
3
 *****************************************************************************
 
4
 * Copyright (C) 2008 the VideoLAN team
 
5
 * $Id: 401860f8453a743410b7da4b16031e53c9ef9797 $
 
6
 *
 
7
 * Authors: Antoine Lejeune <phytos@videolan.org>
 
8
 *          Gildas Bazin <gbazin@videolan.org>
 
9
 *
 
10
 * This program is free software; you can redistribute it and/or modify
 
11
 * it under the terms of the GNU General Public License as published by
 
12
 * the Free Software Foundation; either version 2 of the License, or
 
13
 * (at your option) any later version.
 
14
 *
 
15
 * This program is distributed in the hope that it will be useful,
 
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
 * GNU General Public License for more details.
 
19
 *
 
20
 * You should have received a copy of the GNU General Public License
 
21
 * along with this program; if not, write to the Free Software
 
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 
23
 *****************************************************************************/
 
24
 
 
25
#ifdef HAVE_CONFIG_H
 
26
# include "config.h"
 
27
#endif
 
28
 
 
29
#include <vlc_common.h>
 
30
#include <vlc_plugin.h>
 
31
#include <vlc_interface.h>
 
32
#include <vlc_vout_window.h>
 
33
#include <vlc_xlib.h>
 
34
 
 
35
#include <hildon/hildon-program.h>
 
36
#include <hildon/hildon-banner.h>
 
37
#include <gtk/gtk.h>
 
38
#include <gdk/gdkx.h>
 
39
#include <stdio.h>
 
40
#include <inttypes.h>
 
41
 
 
42
#include "maemo.h"
 
43
#include "maemo_callbacks.h"
 
44
#include "maemo_input.h"
 
45
#include "maemo_interface.h"
 
46
 
 
47
/*****************************************************************************
 
48
 * Local prototypes
 
49
 *****************************************************************************/
 
50
static int      Open               ( vlc_object_t * );
 
51
static void     Close              ( vlc_object_t * );
 
52
static void     *Thread            ( void * );
 
53
static int      OpenWindow         ( vlc_object_t * );
 
54
static void     CloseWindow        ( vlc_object_t * );
 
55
static int      ControlWindow      ( vout_window_t *, int, va_list );
 
56
static gboolean interface_ready    ( gpointer );
 
57
 
 
58
/*****************************************************************************
 
59
* Module descriptor
 
60
*****************************************************************************/
 
61
vlc_module_begin();
 
62
    set_shortname( "Maemo" );
 
63
    set_description( N_("Maemo hildon interface") );
 
64
    set_category( CAT_INTERFACE );
 
65
    set_subcategory( SUBCAT_INTERFACE_MAIN );
 
66
    set_capability( "interface", 70 );
 
67
    set_callbacks( Open, Close );
 
68
    add_shortcut( "maemo" );
 
69
 
 
70
    add_submodule();
 
71
        set_capability( "vout window xid", 50 );
 
72
        set_callbacks( OpenWindow, CloseWindow );
 
73
vlc_module_end();
 
74
 
 
75
/*****************************************************************************
 
76
 * Module callbacks
 
77
 *****************************************************************************/
 
78
static int Open( vlc_object_t *p_this )
 
79
{
 
80
    intf_thread_t *p_intf = (intf_thread_t *)p_this;
 
81
    intf_sys_t *p_sys;
 
82
    vlc_value_t val;
 
83
 
 
84
    if( !vlc_xlib_init( p_this ) )
 
85
        return VLC_EGENERIC;
 
86
 
 
87
    /* Allocate instance and initialize some members */
 
88
    p_intf->p_sys = p_sys = malloc( sizeof( intf_sys_t ) );
 
89
    if( p_intf->p_sys == NULL )
 
90
        return VLC_ENOMEM;
 
91
 
 
92
    p_sys->p_playlist = pl_Get( p_intf );
 
93
    p_sys->p_input = NULL;
 
94
 
 
95
    p_sys->p_main_window = NULL;
 
96
    p_sys->p_video_window = NULL;
 
97
    p_sys->p_control_window = NULL;
 
98
    p_sys->b_fullscreen = false;
 
99
    p_sys->i_event = 0;
 
100
 
 
101
    vlc_spin_init( &p_sys->event_lock );
 
102
 
 
103
    /* Create separate thread for main interface */
 
104
    vlc_sem_init (&p_sys->ready, 0);
 
105
    if( vlc_clone( &p_sys->thread, Thread, p_intf, VLC_THREAD_PRIORITY_LOW ) )
 
106
    {
 
107
        free (p_sys);
 
108
        return VLC_ENOMEM;
 
109
    }
 
110
 
 
111
    /* Wait for interface thread to be fully initialised */
 
112
    vlc_sem_wait (&p_sys->ready);
 
113
    vlc_sem_destroy (&p_sys->ready);
 
114
 
 
115
    var_Create (p_this->p_libvlc, "hildon-iface", VLC_VAR_ADDRESS);
 
116
    val.p_address = p_this;
 
117
    var_Set (p_this->p_libvlc, "hildon-iface", val);
 
118
 
 
119
    return VLC_SUCCESS;
 
120
}
 
121
 
 
122
static void Close( vlc_object_t *p_this )
 
123
{
 
124
    intf_thread_t *p_intf = (intf_thread_t *)p_this;
 
125
 
 
126
    var_Destroy (p_this->p_libvlc, "hildon-iface");
 
127
 
 
128
    gtk_main_quit();
 
129
    vlc_join (p_intf->p_sys->thread, NULL);
 
130
    vlc_spin_destroy( &p_intf->p_sys->event_lock );
 
131
    free( p_intf->p_sys );
 
132
}
 
133
 
 
134
static gint quit_event( GtkWidget *widget, GdkEvent *event, gpointer data )
 
135
{
 
136
    intf_thread_t *p_intf = (intf_thread_t *)data;
 
137
    (void)widget; (void)event;
 
138
    libvlc_Quit( p_intf->p_libvlc );
 
139
    return TRUE;
 
140
}
 
141
 
 
142
/*****************************************************************************
 
143
* Initialize and launch the interface
 
144
*****************************************************************************/
 
145
static void *Thread( void *obj )
 
146
{
 
147
    intf_thread_t *p_intf = (intf_thread_t *)obj;
 
148
    const char *p_args[] = { "vlc" };
 
149
    int i_args = sizeof(p_args)/sizeof(char *);
 
150
    char **pp_args  = (char **)p_args;
 
151
 
 
152
    HildonProgram *program;
 
153
    HildonWindow *window;
 
154
    GtkWidget *main_vbox, *bottom_hbox;
 
155
    GtkWidget *video, *seekbar;
 
156
    GtkWidget *play_button, *prev_button, *next_button;
 
157
    GtkWidget *stop_button, *playlist_button;
 
158
 
 
159
    gtk_init( &i_args, &pp_args );
 
160
 
 
161
    program = HILDON_PROGRAM( hildon_program_get_instance() );
 
162
    g_set_application_name( "VLC Media Player" );
 
163
 
 
164
    window = HILDON_WINDOW( hildon_window_new() );
 
165
    hildon_program_add_window( program, window );
 
166
    gtk_object_set_data( GTK_OBJECT( window ), "p_intf", p_intf );
 
167
    p_intf->p_sys->p_main_window = window;
 
168
 
 
169
    g_signal_connect( GTK_WIDGET(window), "key-press-event",
 
170
                      G_CALLBACK( key_cb ), p_intf );
 
171
    g_signal_connect (GTK_WIDGET(window), "delete_event",
 
172
                      GTK_SIGNAL_FUNC( quit_event), p_intf );
 
173
 
 
174
    // A little theming
 
175
    char *psz_rc_file = NULL;
 
176
    char *psz_data = config_GetDataDir( p_intf );
 
177
    if( asprintf( &psz_rc_file, "%s/maemo/vlc_intf.rc", psz_data ) != -1 )
 
178
    {
 
179
        gtk_rc_parse( psz_rc_file );
 
180
        free( psz_rc_file );
 
181
    }
 
182
    free( psz_data );
 
183
 
 
184
    // We create the main vertical box
 
185
    main_vbox = gtk_vbox_new( FALSE, 0 );
 
186
    gtk_container_add( GTK_CONTAINER( window ), main_vbox );
 
187
 
 
188
    // Menubar
 
189
    GtkWidget *main_menu = create_menu( p_intf );
 
190
#ifdef HAVE_MAEMO
 
191
    hildon_window_set_menu( HILDON_WINDOW( p_intf->p_sys->p_main_window ),
 
192
                            GTK_MENU( main_menu ) );
 
193
#else
 
194
    GtkWidget *menu_bar = gtk_menu_bar_new ();
 
195
    GtkWidget *item = gtk_menu_item_new_with_label ("Menu");
 
196
    gtk_menu_bar_append(menu_bar, item);
 
197
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), main_menu);
 
198
    gtk_widget_show_all (menu_bar);
 
199
    gtk_box_pack_start(GTK_BOX(main_vbox), menu_bar, FALSE, FALSE, 0);
 
200
#endif
 
201
 
 
202
    // We put first the embedded video
 
203
    video = gtk_event_box_new();
 
204
    GdkColor black = {0,0,0,0};
 
205
    gtk_widget_modify_bg(video, GTK_STATE_NORMAL, &black);
 
206
    p_intf->p_sys->p_video_window = video;
 
207
    gtk_box_pack_start( GTK_BOX( main_vbox ), video, TRUE, TRUE, 0 );
 
208
 
 
209
    create_playlist( p_intf );
 
210
    gtk_box_pack_start( GTK_BOX( main_vbox ), p_intf->p_sys->p_playlist_window, TRUE, TRUE, 0 );
 
211
 
 
212
    // We put the horizontal box which contains all the buttons
 
213
    p_intf->p_sys->p_control_window = bottom_hbox = gtk_hbox_new( FALSE, 0 );
 
214
 
 
215
    // We create the buttons
 
216
    play_button = gtk_button_new();
 
217
    gtk_button_set_image( GTK_BUTTON( play_button ),
 
218
                   gtk_image_new_from_stock( "vlc-play", GTK_ICON_SIZE_BUTTON ) );
 
219
    p_intf->p_sys->p_play_button = play_button;
 
220
    stop_button = gtk_button_new();
 
221
    gtk_button_set_image( GTK_BUTTON( stop_button ),
 
222
                          gtk_image_new_from_stock( "vlc-stop", GTK_ICON_SIZE_BUTTON ) );
 
223
    prev_button = gtk_button_new();
 
224
    gtk_button_set_image( GTK_BUTTON( prev_button ),
 
225
                      gtk_image_new_from_stock( "vlc-previous", GTK_ICON_SIZE_BUTTON ) );
 
226
    next_button = gtk_button_new();
 
227
    gtk_button_set_image( GTK_BUTTON( next_button ),
 
228
                      gtk_image_new_from_stock( "vlc-next", GTK_ICON_SIZE_BUTTON ) );
 
229
    playlist_button = gtk_button_new();
 
230
    gtk_button_set_image( GTK_BUTTON( playlist_button ),
 
231
                          gtk_image_new_from_stock( "vlc-playlist", GTK_ICON_SIZE_BUTTON ) );
 
232
    seekbar = hildon_seekbar_new();
 
233
    p_intf->p_sys->p_seekbar = HILDON_SEEKBAR( seekbar );
 
234
 
 
235
    // We add them to the hbox
 
236
    gtk_box_pack_start( GTK_BOX( bottom_hbox ), play_button, FALSE, FALSE, 0 );
 
237
    gtk_box_pack_start( GTK_BOX( bottom_hbox ), stop_button, FALSE, FALSE, 0 );
 
238
    gtk_box_pack_start( GTK_BOX( bottom_hbox ), prev_button, FALSE, FALSE, 0 );
 
239
    gtk_box_pack_start( GTK_BOX( bottom_hbox ), next_button, FALSE, FALSE, 0 );
 
240
    gtk_box_pack_start( GTK_BOX( bottom_hbox ), playlist_button, FALSE, FALSE, 0 );
 
241
    gtk_box_pack_start( GTK_BOX( bottom_hbox ), seekbar    , TRUE , TRUE , 5 );
 
242
    // We add the hbox to the main vbox
 
243
    gtk_box_pack_start( GTK_BOX( main_vbox ), bottom_hbox, FALSE, FALSE, 0 );
 
244
 
 
245
    g_signal_connect( play_button, "clicked", G_CALLBACK( play_cb ), NULL );
 
246
    g_signal_connect( stop_button, "clicked", G_CALLBACK( stop_cb ), NULL );
 
247
    g_signal_connect( prev_button, "clicked", G_CALLBACK( prev_cb ), NULL );
 
248
    g_signal_connect( next_button, "clicked", G_CALLBACK( next_cb ), NULL );
 
249
    g_signal_connect( playlist_button, "clicked", G_CALLBACK( playlist_cb ), NULL );
 
250
    g_signal_connect( seekbar, "change-value",
 
251
                      G_CALLBACK( seekbar_changed_cb ), NULL );
 
252
 
 
253
    gtk_widget_show_all( GTK_WIDGET( window ) );
 
254
    gtk_widget_hide_all( p_intf->p_sys->p_playlist_window );
 
255
 
 
256
#if 1
 
257
    /* HACK: Only one X11 client can subscribe to mouse button press events.
 
258
     * VLC currently handles those in the video display.
 
259
     * Force GTK to unsubscribe from mouse press and release events. */
 
260
    Display *dpy = GDK_WINDOW_XDISPLAY( gtk_widget_get_window(p_intf->p_sys->p_video_window) );
 
261
    Window w = GDK_WINDOW_XID( gtk_widget_get_window(p_intf->p_sys->p_video_window) );
 
262
    XWindowAttributes attr;
 
263
 
 
264
    XGetWindowAttributes( dpy, w, &attr );
 
265
    attr.your_event_mask &= ~(ButtonPressMask|ButtonReleaseMask);
 
266
    XSelectInput( dpy, w, attr.your_event_mask );
 
267
#endif
 
268
 
 
269
    // The embedded video is only ready after gtk_main and windows are shown
 
270
    g_idle_add( interface_ready, p_intf );
 
271
 
 
272
    gtk_main();
 
273
 
 
274
    delete_input( p_intf );
 
275
    delete_playlist( p_intf );
 
276
 
 
277
    gtk_object_destroy( GTK_OBJECT( main_menu ) );
 
278
    gtk_object_destroy( GTK_OBJECT( window ) );
 
279
 
 
280
    return NULL;
 
281
}
 
282
 
 
283
/**
 
284
* Video output window provider
 
285
*/
 
286
static int OpenWindow (vlc_object_t *p_obj)
 
287
{
 
288
    vout_window_t *p_wnd = (vout_window_t *)p_obj;
 
289
    intf_thread_t *p_intf;
 
290
    vlc_value_t val;
 
291
 
 
292
    if (p_wnd->cfg->is_standalone)
 
293
        return VLC_EGENERIC;
 
294
 
 
295
    if( var_Get( p_obj->p_libvlc, "hildon-iface", &val ) )
 
296
        val.p_address = NULL;
 
297
 
 
298
    p_intf = (intf_thread_t *)val.p_address;
 
299
    if( !p_intf )
 
300
    {   /* If another interface is used, this plugin cannot work */
 
301
        msg_Dbg( p_obj, "Hildon interface not found" );
 
302
        return VLC_EGENERIC;
 
303
    }
 
304
 
 
305
    p_wnd->handle.xid = p_intf->p_sys->xid;
 
306
 
 
307
    if (!p_wnd->handle.xid)
 
308
        return VLC_EGENERIC;
 
309
 
 
310
    p_wnd->control = ControlWindow;
 
311
    p_wnd->sys = (vout_window_sys_t*)p_intf;
 
312
 
 
313
    return VLC_SUCCESS;
 
314
}
 
315
 
 
316
static int ControlWindow (vout_window_t *p_wnd, int query, va_list args)
 
317
{
 
318
    intf_thread_t *p_intf = (intf_thread_t *)p_wnd->sys;
 
319
 
 
320
    switch( query )
 
321
    {
 
322
    case VOUT_WINDOW_SET_SIZE:
 
323
    {
 
324
        int i_width  = (int)va_arg( args, int );
 
325
        int i_height = (int)va_arg( args, int );
 
326
 
 
327
        int i_current_w, i_current_h;
 
328
        gdk_drawable_get_size( GDK_DRAWABLE( p_intf->p_sys->p_video_window ),
 
329
                               &i_current_w, &i_current_h );
 
330
        if( i_width != i_current_w || i_height != i_current_h )
 
331
            return VLC_EGENERIC;
 
332
        return VLC_SUCCESS;
 
333
    }
 
334
    case VOUT_WINDOW_SET_FULLSCREEN:
 
335
    {
 
336
        bool b_fs = va_arg( args, int );
 
337
        p_intf->p_sys->b_fullscreen = b_fs;
 
338
        g_idle_add( fullscreen_cb, p_intf );
 
339
        return VLC_SUCCESS;
 
340
    }
 
341
    default:
 
342
        return VLC_EGENERIC;
 
343
    }
 
344
}
 
345
 
 
346
static void CloseWindow (vlc_object_t *p_obj)
 
347
{
 
348
    vout_window_t *p_wnd = (vout_window_t *)p_obj;
 
349
    intf_thread_t *p_intf = (intf_thread_t *)p_wnd->sys;
 
350
 
 
351
    if( p_intf->p_sys->b_fullscreen )
 
352
    {
 
353
        p_intf->p_sys->b_fullscreen = false;
 
354
        g_idle_add( fullscreen_cb, p_intf );
 
355
    }
 
356
}
 
357
 
 
358
static gboolean interface_ready( gpointer data )
 
359
{
 
360
    intf_thread_t *p_intf = (intf_thread_t *)data;
 
361
 
 
362
    p_intf->p_sys->xid =
 
363
        GDK_WINDOW_XID( gtk_widget_get_window(p_intf->p_sys->p_video_window) );
 
364
 
 
365
    // Refresh playlist
 
366
    post_event( p_intf, EVENT_PLAYLIST_CURRENT );
 
367
 
 
368
    // Everything is initialised
 
369
    vlc_sem_post (&p_intf->p_sys->ready);
 
370
 
 
371
    // We want it to be executed only one time
 
372
    return FALSE;
 
373
}