]> git.sesse.net Git - vlc/blob - modules/gui/gtk/gtk_callbacks.c
+ configure.ac: don't build OpenGL support on BeOS although it has gl.h
[vlc] / modules / gui / gtk / gtk_callbacks.c
1 /*****************************************************************************
2  * gtk_callbacks.c : Callbacks for the Gtk+ plugin.
3  *****************************************************************************
4  * Copyright (C) 2000, 2001, 2003 VideoLAN
5  * $Id$
6  *
7  * Authors: Sam Hocevar <sam@zoy.org>
8  *          Stéphane Borel <stef@via.ecp.fr>
9  *          Julien BLACHE <jb@technologeek.org>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
24  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include <sys/types.h>                                              /* off_t */
30 #include <stdlib.h>
31
32 #include <vlc/vlc.h>
33 #include <vlc/intf.h>
34 #include <vlc/vout.h>
35 #include <vlc/aout.h>
36
37 #include <unistd.h>
38
39 #include <gtk/gtk.h>
40
41 #include <string.h>
42
43 #include "gtk_callbacks.h"
44 #include "gtk_interface.h"
45 #include "gtk_support.h"
46
47 #include "common.h"
48
49 #ifdef HAVE_CDDAX
50 #define CDDA_MRL "cddax://"
51 #else
52 #define CDDA_MRL "cdda://"
53 #endif
54
55 #ifdef HAVE_VCDX
56 #define VCD_MRL "vcdx://"
57 #else
58 #define VCD_MRL "vcdx://"
59 #endif
60
61 /*****************************************************************************
62  * Useful function to retrieve p_intf
63  ****************************************************************************/
64 void * E_(__GtkGetIntf)( GtkWidget * widget )
65 {
66     void *p_data;
67
68     if( GTK_IS_MENU_ITEM( widget ) )
69     {
70         /* Look for a GTK_MENU */
71         while( widget->parent && !GTK_IS_MENU( widget ) )
72         {
73             widget = widget->parent;
74         }
75
76         /* Maybe this one has the data */
77         p_data = gtk_object_get_data( GTK_OBJECT( widget ), "p_intf" );
78         if( p_data )
79         {
80             return p_data;
81         }
82
83         /* Otherwise, the parent widget has it */
84         widget = gtk_menu_get_attach_widget( GTK_MENU( widget ) );
85         p_data = gtk_object_get_data( GTK_OBJECT( widget ), "p_intf" );
86         if( p_data )
87         {
88             return p_data;
89         }
90     }
91
92     /* We look for the top widget */
93     widget = gtk_widget_get_toplevel( GTK_WIDGET( widget ) );
94     p_data = gtk_object_get_data( GTK_OBJECT( widget ), "p_intf" );
95
96     return p_data;
97 }
98
99 /*****************************************************************************
100  * Callbacks
101  *****************************************************************************/
102
103 /*
104  * Main interface callbacks
105  */
106
107 #ifdef MODULE_NAME_IS_gtk
108 #   define GTKEXIT GtkExit
109 #else
110 #   define GTKEXIT GnomeExit
111 #endif
112
113 gboolean GTKEXIT( GtkWidget       *widget,
114                   gpointer         user_data )
115 {
116     intf_thread_t *p_intf = GtkGetIntf( widget );
117
118     vlc_mutex_lock( &p_intf->change_lock );
119     p_intf->p_vlc->b_die = VLC_TRUE;
120     vlc_mutex_unlock( &p_intf->change_lock );
121
122     return TRUE;
123 }
124
125 void GtkClose( GtkMenuItem     *menuitem,
126                gpointer         user_data )
127 {
128     intf_thread_t *p_intf = GtkGetIntf( menuitem );
129     p_intf->b_die = VLC_TRUE;
130 }
131
132 gboolean GtkWindowDelete( GtkWidget       *widget,
133                           GdkEvent        *event,
134                           gpointer         user_data )
135 {
136     GTKEXIT( GTK_WIDGET( widget ), user_data );
137
138     return TRUE;
139 }
140
141
142 gboolean GtkWindowToggle( GtkWidget       *widget,
143                           gpointer         user_data )
144 {
145     intf_thread_t *p_intf = GtkGetIntf( widget );
146
147     if( GTK_WIDGET_VISIBLE(p_intf->p_sys->p_window) )
148     {
149         gtk_widget_hide( p_intf->p_sys->p_window);
150     }
151     else
152     {
153         gtk_widget_show( p_intf->p_sys->p_window );
154     }
155
156     return TRUE;
157 }
158
159 gboolean GtkFullscreen( GtkWidget       *widget,
160                         gpointer         user_data)
161 {
162     intf_thread_t *p_intf = GtkGetIntf( widget );
163     vout_thread_t *p_vout;
164
165     if( p_intf->p_sys->p_input == NULL )
166     {
167         return FALSE;
168     }
169
170     p_vout = vlc_object_find( p_intf->p_sys->p_input,
171                               VLC_OBJECT_VOUT, FIND_CHILD );
172     if( p_vout == NULL )
173     {
174         return FALSE;
175     }
176
177     p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
178     vlc_object_release( p_vout );
179     return TRUE;
180 }
181
182 void GtkWindowDrag( GtkWidget       *widget,
183                     GdkDragContext  *drag_context,
184                     gint             x,
185                     gint             y,
186                     GtkSelectionData *data,
187                     guint            info,
188                     guint            time,
189                     gpointer         user_data)
190 {
191     intf_thread_t * p_intf = GtkGetIntf( widget );
192     GtkDropDataReceived( p_intf, data, info, PLAYLIST_END );
193 }
194
195
196 /****************************************************************************
197  * Slider management
198  ****************************************************************************/
199
200 gboolean GtkSliderRelease( GtkWidget       *widget,
201                            GdkEventButton  *event,
202                            gpointer         user_data )
203 {
204     intf_thread_t *p_intf = GtkGetIntf( widget );
205
206     vlc_mutex_lock( &p_intf->change_lock );
207     p_intf->p_sys->b_slider_free = VLC_TRUE;
208     vlc_mutex_unlock( &p_intf->change_lock );
209
210     return FALSE;
211 }
212
213
214 gboolean GtkSliderPress( GtkWidget       *widget,
215                          GdkEventButton  *event,
216                          gpointer         user_data)
217 {
218     intf_thread_t *p_intf = GtkGetIntf( widget );
219
220     vlc_mutex_lock( &p_intf->change_lock );
221     p_intf->p_sys->b_slider_free = VLC_FALSE;
222     vlc_mutex_unlock( &p_intf->change_lock );
223
224     return FALSE;
225 }
226
227
228 /****************************************************************************
229  * DVD specific items
230  ****************************************************************************/
231
232 void GtkTitlePrev( GtkButton * button, gpointer user_data )
233 {
234     intf_thread_t *  p_intf = GtkGetIntf( button );
235
236     var_SetVoid( p_intf->p_sys->p_input, "prev-title" );
237
238     p_intf->p_sys->b_title_update = VLC_TRUE;
239     vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
240     GtkSetupMenus( p_intf );
241     vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
242 }
243
244
245 void GtkTitleNext( GtkButton * button, gpointer user_data )
246 {
247     intf_thread_t * p_intf = GtkGetIntf( button );
248
249     var_SetVoid( p_intf->p_sys->p_input, "next-title" );
250
251     p_intf->p_sys->b_title_update = VLC_TRUE;
252     vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
253     GtkSetupMenus( p_intf );
254     vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
255 }
256
257
258 void GtkChapterPrev( GtkButton * button, gpointer user_data )
259 {
260     intf_thread_t *  p_intf = GtkGetIntf( button );
261
262     var_SetVoid( p_intf->p_sys->p_input, "prev-chapter" );
263
264     p_intf->p_sys->b_chapter_update = VLC_TRUE;
265     vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
266     GtkSetupMenus( p_intf );
267     vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
268 }
269
270
271 void GtkChapterNext( GtkButton * button, gpointer user_data )
272 {
273     intf_thread_t *  p_intf = GtkGetIntf( button );
274
275     var_SetVoid( p_intf->p_sys->p_input, "next-chapter" );
276
277     p_intf->p_sys->b_chapter_update = VLC_TRUE;
278     vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
279     GtkSetupMenus( p_intf );
280     vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
281 }
282
283 /****************************************************************************
284  * About box
285  ****************************************************************************/
286
287 gboolean GtkAboutShow( GtkWidget       *widget,
288                        gpointer         user_data)
289 {
290     intf_thread_t *p_intf = GtkGetIntf( widget );
291
292     if( !GTK_IS_WIDGET( p_intf->p_sys->p_about ) )
293     {
294         p_intf->p_sys->p_about = create_intf_about();
295         gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_about ),
296                              "p_intf", p_intf );
297     }
298     gtk_widget_show( p_intf->p_sys->p_about );
299     gdk_window_raise( p_intf->p_sys->p_about->window );
300
301     return TRUE;
302 }
303
304 void GtkAboutOk( GtkButton * button, gpointer user_data)
305 {
306     intf_thread_t *p_intf = GtkGetIntf( button );
307
308     gtk_widget_hide( p_intf->p_sys->p_about );
309 }
310
311
312 /****************************************************************************
313  * Jump box
314  ****************************************************************************/
315
316 gboolean GtkJumpShow( GtkWidget       *widget,
317                       gpointer         user_data)
318 {
319     intf_thread_t *p_intf = GtkGetIntf( widget );
320
321     if( !GTK_IS_WIDGET( p_intf->p_sys->p_jump ) )
322     {
323         p_intf->p_sys->p_jump = create_intf_jump();
324         gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_jump ),
325                              "p_intf", p_intf );
326     }
327
328     gtk_widget_show( p_intf->p_sys->p_jump );
329     gdk_window_raise( p_intf->p_sys->p_jump->window );
330
331     return FALSE;
332 }
333
334
335 void GtkJumpOk( GtkButton       *button,
336                 gpointer         user_data)
337 {
338     intf_thread_t * p_intf = GtkGetIntf( button );
339     int i_hours, i_minutes, i_seconds;
340
341     if( p_intf->p_sys->p_input == NULL )
342     {
343         return;
344     }
345
346 #define GET_VALUE( name )                                                   \
347     gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( gtk_object_get_data( \
348         GTK_OBJECT( p_intf->p_sys->p_jump ), name ) ) )
349     i_hours   = GET_VALUE( "jump_hour_spinbutton" );
350     i_minutes = GET_VALUE( "jump_minute_spinbutton" );
351     i_seconds = GET_VALUE( "jump_second_spinbutton" );
352 #undef GET_VALUE
353
354     var_SetTime( p_intf->p_sys->p_input, "time",
355                  (int64_t)(i_seconds+60*i_minutes+3600*i_hours)*I64C(1000000));
356
357     gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
358 }
359
360
361 void GtkJumpCancel( GtkButton       *button,
362                     gpointer         user_data)
363 {
364     gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
365 }
366
367 /****************************************************************************
368  * Callbacks for disc ejection
369  ****************************************************************************/
370 gboolean GtkDiscEject ( GtkWidget *widget, gpointer user_data )
371 {
372     char *psz_device = NULL;
373     char *psz_parser;
374     char *psz_current;
375
376     intf_thread_t *p_intf = GtkGetIntf( widget );
377     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
378                                                        FIND_ANYWHERE );
379     if( p_playlist == NULL )
380     {
381         return FALSE;
382     }
383
384     vlc_mutex_lock( &p_playlist->object_lock );
385
386     if( p_playlist->i_index < 0 )
387     {
388         vlc_mutex_unlock( &p_playlist->object_lock );
389         vlc_object_release( p_playlist );
390         return FALSE;
391     }
392
393     psz_current = p_playlist->pp_items[ p_playlist->i_index ]->input.psz_name;
394
395     /*
396      * Get the active input
397      * Determine whether we can eject a media, ie it's a VCD or DVD
398      * If it's neither a VCD nor a DVD, then return
399      */
400
401     /*
402      * Don't really know if I must lock the stuff here, we're using it read-only
403      */
404
405     if( psz_current != NULL )
406     {
407         if( !strncmp(psz_current, "dvd://", 4) )
408         {
409             switch( psz_current[strlen("dvd://")] )
410             {
411             case '\0':
412             case '@':
413                 psz_device = config_GetPsz( p_intf, "dvd" );
414                 break;
415             default:
416                 /* Omit the first MRL-selector characters */
417                 psz_device = strdup( psz_current + strlen("dvd://" ) );
418                 break;
419             }
420         }
421         else if( !strncmp(psz_current, "vcd:", strlen("vcd:")) )
422         {
423             switch( psz_current[strlen("vcd:")] )
424             {
425             case '\0':
426             case '@':
427                 psz_device = config_GetPsz( p_intf, VCD_MRL );
428                 break;
429             default:
430                 /* Omit the beginning MRL-selector characters */
431                 psz_device = strdup( psz_current + strlen(VCD_MRL) );
432                 break;
433             }
434         }
435         else if( !strncmp(psz_current, CDDA_MRL, strlen(CDDA_MRL) ) )
436         {
437             switch( psz_current[strlen(CDDA_MRL)] )
438             {
439             case '\0':
440             case '@':
441                 psz_device = config_GetPsz( p_intf, "cd-audio" );
442                 break;
443             default:
444                 /* Omit the beginning MRL-selector characters */
445                 psz_device = strdup( psz_current + strlen(CDDA_MRL) );
446                 break;
447             }
448         }
449         else
450         {
451             psz_device = strdup( psz_current );
452         }
453     }
454
455     vlc_mutex_unlock( &p_playlist->object_lock );
456     vlc_object_release( p_playlist );
457
458     if( psz_device == NULL )
459     {
460         return TRUE;
461     }
462
463     /* Remove what we have after @ */
464     psz_parser = psz_device;
465     for( psz_parser = psz_device ; *psz_parser ; psz_parser++ )
466     {
467         if( *psz_parser == '@' )
468         {
469             *psz_parser = '\0';
470             break;
471         }
472     }
473
474     /* If there's a stream playing, we aren't allowed to eject ! */
475     if( p_intf->p_sys->p_input == NULL )
476     {
477         msg_Dbg( p_intf, "ejecting %s", psz_device );
478
479         intf_Eject( p_intf, psz_device );
480     }
481
482     free(psz_device);
483
484     return TRUE;
485 }
486
487 /****************************************************************************
488  * Messages window
489  ****************************************************************************/
490
491 gboolean GtkMessagesShow( GtkWidget       *widget,
492                           gpointer         user_data)
493 {
494     static GdkColor black = { 0, 0x0000, 0x0000, 0x0000 };
495     static GdkColormap *colormap;
496     intf_thread_t *p_intf = GtkGetIntf( widget );
497
498     gtk_widget_show( p_intf->p_sys->p_messages );
499     colormap = gdk_colormap_get_system ();
500     gdk_color_alloc( colormap, &black );
501     gdk_window_set_background( p_intf->p_sys->p_messages_text->text_area,
502                                &black );
503
504     gdk_window_raise( p_intf->p_sys->p_messages->window );
505
506     gtk_text_set_point( p_intf->p_sys->p_messages_text,
507                     gtk_text_get_length( p_intf->p_sys->p_messages_text ) );
508
509     return TRUE;
510 }
511
512 void
513 GtkMessagesOk                          (GtkButton       *button,
514                                         gpointer         user_data)
515 {
516     intf_thread_t *p_intf = GtkGetIntf( button );
517     gtk_widget_hide( p_intf->p_sys->p_messages );
518 }
519
520
521 gboolean
522 GtkMessagesDelete                      (GtkWidget       *widget,
523                                         GdkEvent        *event,
524                                         gpointer         user_data)
525 {
526     intf_thread_t *p_intf = GtkGetIntf( widget );
527     gtk_widget_hide( p_intf->p_sys->p_messages );
528     return TRUE;
529 }
530
531
532 void
533 GtkOpenNotebookChanged                 (GtkNotebook     *notebook,
534                                         GtkNotebookPage *page,
535                                         gint             page_num,
536                                         gpointer         user_data)
537 {
538     GtkOpenChanged( GTK_WIDGET( notebook ), user_data );
539 }
540
541 /****************************************************************************
542  * Audio management
543  ****************************************************************************/
544 void GtkVolumeUp                      ( GtkMenuItem     *menuitem,
545                                         gpointer         user_data )
546 {
547     intf_thread_t   *p_intf = GtkGetIntf( menuitem );
548     audio_volume_t  i_volume;
549
550     aout_VolumeUp( p_intf, 1, &i_volume );
551     p_intf->p_sys->b_mute = ( i_volume == 0 ) ? 1 : 0;
552 }
553
554
555 void GtkVolumeDown                    ( GtkMenuItem     *menuitem,
556                                         gpointer         user_data )
557 {
558     intf_thread_t   *p_intf = GtkGetIntf( menuitem );
559     audio_volume_t  i_volume;
560
561     aout_VolumeDown( p_intf, 1, &i_volume );
562     p_intf->p_sys->b_mute = ( i_volume == 0 ) ? 1 : 0;
563 }
564
565
566 void GtkVolumeMute                    ( GtkMenuItem     *menuitem,
567                                         gpointer         user_data )
568 {
569     intf_thread_t   *p_intf = GtkGetIntf( menuitem );
570     audio_volume_t i_volume;
571
572     aout_VolumeMute( p_intf, &i_volume );
573     p_intf->p_sys->b_mute = ( i_volume == 0 ) ? 1 : 0;
574 }
575
576 void
577 GtkMenubarDeinterlace                  ( GtkMenuItem     *menuitem,
578                                         gpointer         user_data)
579 {
580     intf_thread_t   *p_intf = GtkGetIntf( menuitem );
581
582     if( p_intf )
583         msg_Dbg( p_intf, "GtkMenubarDeinterlace" );
584 }
585
586
587 void
588 GtkPopupDeinterlace                    (GtkRadioMenuItem *radiomenuitem,
589                                         gpointer         user_data)
590 {
591     intf_thread_t   *p_intf = GtkGetIntf( radiomenuitem );
592
593     if( p_intf )
594         msg_Dbg( p_intf, "GtkPopupDeinterlace" );
595 }
596
597
598