]> git.sesse.net Git - vlc/blob - modules/gui/gtk/gtk_callbacks.c
* use var_Set/Get "state"/"position"/"rate" instead of old functions.
[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;
235     input_area_t *   p_area;
236     int              i_id;
237
238     p_intf = GtkGetIntf( button );
239     vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
240     i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_id - 1;
241
242     if( i_id > 0 )
243     {
244         p_area = p_intf->p_sys->p_input->stream.pp_areas[i_id];
245         vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
246
247         input_ChangeArea( p_intf->p_sys->p_input, p_area );
248         var_SetInteger( p_intf->p_sys->p_input, PLAYING_S );
249
250         p_intf->p_sys->b_title_update = VLC_TRUE;
251         vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
252         GtkSetupMenus( p_intf );
253     }
254
255     vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
256 }
257
258
259 void GtkTitleNext( GtkButton * button, gpointer user_data )
260 {
261     intf_thread_t * p_intf;
262     input_area_t *  p_area;
263     unsigned int    i_id;
264
265     p_intf = GtkGetIntf( button );
266     vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
267     i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_id + 1;
268
269     if( i_id < p_intf->p_sys->p_input->stream.i_area_nb )
270     {
271         p_area = p_intf->p_sys->p_input->stream.pp_areas[i_id];
272         vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
273
274         input_ChangeArea( p_intf->p_sys->p_input, p_area );
275         var_SetInteger( p_intf->p_sys->p_input, PLAYING_S );
276
277         p_intf->p_sys->b_title_update = VLC_TRUE;
278         vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
279         GtkSetupMenus( p_intf );
280     }
281
282     vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
283 }
284
285
286 void GtkChapterPrev( GtkButton * button, gpointer user_data )
287 {
288     intf_thread_t * p_intf;
289     input_area_t *  p_area;
290
291     p_intf = GtkGetIntf( button );
292     vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
293     p_area = p_intf->p_sys->p_input->stream.p_selected_area;
294
295     if( p_area->i_part - 1 > 0 )
296     {
297         p_area->i_part--;
298         vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
299
300         input_ChangeArea( p_intf->p_sys->p_input, p_area );
301         var_SetInteger( p_intf->p_sys->p_input, PLAYING_S );
302
303         p_intf->p_sys->b_chapter_update = VLC_TRUE;
304         vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
305         GtkSetupMenus( p_intf );
306     }
307
308     vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
309 }
310
311
312 void GtkChapterNext( GtkButton * button, gpointer user_data )
313 {
314     intf_thread_t * p_intf;
315     input_area_t *  p_area;
316
317     p_intf = GtkGetIntf( button );
318     vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
319     p_area = p_intf->p_sys->p_input->stream.p_selected_area;
320
321     if( p_area->i_part + 1 < p_area->i_part_nb )
322     {
323         p_area->i_part++;
324         vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
325
326         input_ChangeArea( p_intf->p_sys->p_input, p_area );
327         var_SetInteger( p_intf->p_sys->p_input, PLAYING_S );
328
329         p_intf->p_sys->b_chapter_update = VLC_TRUE;
330         vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
331         GtkSetupMenus( p_intf );
332     }
333
334     vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
335 }
336
337 /****************************************************************************
338  * About box
339  ****************************************************************************/
340
341 gboolean GtkAboutShow( GtkWidget       *widget,
342                        gpointer         user_data)
343 {
344     intf_thread_t *p_intf = GtkGetIntf( widget );
345
346     if( !GTK_IS_WIDGET( p_intf->p_sys->p_about ) )
347     {
348         p_intf->p_sys->p_about = create_intf_about();
349         gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_about ),
350                              "p_intf", p_intf );
351     }
352     gtk_widget_show( p_intf->p_sys->p_about );
353     gdk_window_raise( p_intf->p_sys->p_about->window );
354
355     return TRUE;
356 }
357
358 void GtkAboutOk( GtkButton * button, gpointer user_data)
359 {
360     intf_thread_t *p_intf = GtkGetIntf( button );
361
362     gtk_widget_hide( p_intf->p_sys->p_about );
363 }
364
365
366 /****************************************************************************
367  * Jump box
368  ****************************************************************************/
369
370 gboolean GtkJumpShow( GtkWidget       *widget,
371                       gpointer         user_data)
372 {
373     intf_thread_t *p_intf = GtkGetIntf( widget );
374
375     if( !GTK_IS_WIDGET( p_intf->p_sys->p_jump ) )
376     {
377         p_intf->p_sys->p_jump = create_intf_jump();
378         gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_jump ),
379                              "p_intf", p_intf );
380     }
381
382     gtk_widget_show( p_intf->p_sys->p_jump );
383     gdk_window_raise( p_intf->p_sys->p_jump->window );
384
385     return FALSE;
386 }
387
388
389 void GtkJumpOk( GtkButton       *button,
390                 gpointer         user_data)
391 {
392     intf_thread_t * p_intf = GtkGetIntf( button );
393     int i_hours, i_minutes, i_seconds;
394
395     if( p_intf->p_sys->p_input == NULL )
396     {
397         return;
398     }
399
400 #define GET_VALUE( name )                                                   \
401     gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( gtk_object_get_data( \
402         GTK_OBJECT( p_intf->p_sys->p_jump ), name ) ) )
403     i_hours   = GET_VALUE( "jump_hour_spinbutton" );
404     i_minutes = GET_VALUE( "jump_minute_spinbutton" );
405     i_seconds = GET_VALUE( "jump_second_spinbutton" );
406 #undef GET_VALUE
407
408     var_SetTime( p_intf->p_sys->p_input, "time",
409                  (int64_t)(i_seconds+60*i_minutes+3600*i_hours)*I64C(1000000));
410
411     gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
412 }
413
414
415 void GtkJumpCancel( GtkButton       *button,
416                     gpointer         user_data)
417 {
418     gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
419 }
420
421 /****************************************************************************
422  * Callbacks for disc ejection
423  ****************************************************************************/
424 gboolean GtkDiscEject ( GtkWidget *widget, gpointer user_data )
425 {
426     char *psz_device = NULL;
427     char *psz_parser;
428     char *psz_current;
429
430     intf_thread_t *p_intf = GtkGetIntf( widget );
431     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
432                                                        FIND_ANYWHERE );
433     if( p_playlist == NULL )
434     {
435         return FALSE;
436     }
437
438     vlc_mutex_lock( &p_playlist->object_lock );
439
440     if( p_playlist->i_index < 0 )
441     {
442         vlc_mutex_unlock( &p_playlist->object_lock );
443         vlc_object_release( p_playlist );
444         return FALSE;
445     }
446
447     psz_current = p_playlist->pp_items[ p_playlist->i_index ]->input.psz_name;
448
449     /*
450      * Get the active input
451      * Determine whether we can eject a media, ie it's a VCD or DVD
452      * If it's neither a VCD nor a DVD, then return
453      */
454
455     /*
456      * Don't really know if I must lock the stuff here, we're using it read-only
457      */
458
459     if( psz_current != NULL )
460     {
461         if( !strncmp(psz_current, "dvd://", 4) )
462         {
463             switch( psz_current[strlen("dvd://")] )
464             {
465             case '\0':
466             case '@':
467                 psz_device = config_GetPsz( p_intf, "dvd" );
468                 break;
469             default:
470                 /* Omit the first MRL-selector characters */
471                 psz_device = strdup( psz_current + strlen("dvd://" ) );
472                 break;
473             }
474         }
475         else if( !strncmp(psz_current, "vcd:", strlen("vcd:")) )
476         {
477             switch( psz_current[strlen("vcd:")] )
478             {
479             case '\0':
480             case '@':
481                 psz_device = config_GetPsz( p_intf, VCD_MRL );
482                 break;
483             default:
484                 /* Omit the beginning MRL-selector characters */
485                 psz_device = strdup( psz_current + strlen(VCD_MRL) );
486                 break;
487             }
488         }
489         else if( !strncmp(psz_current, CDDA_MRL, strlen(CDDA_MRL) ) )
490         {
491             switch( psz_current[strlen(CDDA_MRL)] )
492             {
493             case '\0':
494             case '@':
495                 psz_device = config_GetPsz( p_intf, "cd-audio" );
496                 break;
497             default:
498                 /* Omit the beginning MRL-selector characters */
499                 psz_device = strdup( psz_current + strlen(CDDA_MRL) );
500                 break;
501             }
502         }
503         else
504         {
505             psz_device = strdup( psz_current );
506         }
507     }
508
509     vlc_mutex_unlock( &p_playlist->object_lock );
510     vlc_object_release( p_playlist );
511
512     if( psz_device == NULL )
513     {
514         return TRUE;
515     }
516
517     /* Remove what we have after @ */
518     psz_parser = psz_device;
519     for( psz_parser = psz_device ; *psz_parser ; psz_parser++ )
520     {
521         if( *psz_parser == '@' )
522         {
523             *psz_parser = '\0';
524             break;
525         }
526     }
527
528     /* If there's a stream playing, we aren't allowed to eject ! */
529     if( p_intf->p_sys->p_input == NULL )
530     {
531         msg_Dbg( p_intf, "ejecting %s", psz_device );
532
533         intf_Eject( p_intf, psz_device );
534     }
535
536     free(psz_device);
537
538     return TRUE;
539 }
540
541 /****************************************************************************
542  * Messages window
543  ****************************************************************************/
544
545 gboolean GtkMessagesShow( GtkWidget       *widget,
546                           gpointer         user_data)
547 {
548     static GdkColor black = { 0, 0x0000, 0x0000, 0x0000 };
549     static GdkColormap *colormap;
550     intf_thread_t *p_intf = GtkGetIntf( widget );
551
552     gtk_widget_show( p_intf->p_sys->p_messages );
553     colormap = gdk_colormap_get_system ();
554     gdk_color_alloc( colormap, &black );
555     gdk_window_set_background( p_intf->p_sys->p_messages_text->text_area,
556                                &black );
557
558     gdk_window_raise( p_intf->p_sys->p_messages->window );
559
560     gtk_text_set_point( p_intf->p_sys->p_messages_text,
561                     gtk_text_get_length( p_intf->p_sys->p_messages_text ) );
562
563     return TRUE;
564 }
565
566 void
567 GtkMessagesOk                          (GtkButton       *button,
568                                         gpointer         user_data)
569 {
570     intf_thread_t *p_intf = GtkGetIntf( button );
571     gtk_widget_hide( p_intf->p_sys->p_messages );
572 }
573
574
575 gboolean
576 GtkMessagesDelete                      (GtkWidget       *widget,
577                                         GdkEvent        *event,
578                                         gpointer         user_data)
579 {
580     intf_thread_t *p_intf = GtkGetIntf( widget );
581     gtk_widget_hide( p_intf->p_sys->p_messages );
582     return TRUE;
583 }
584
585
586 void
587 GtkOpenNotebookChanged                 (GtkNotebook     *notebook,
588                                         GtkNotebookPage *page,
589                                         gint             page_num,
590                                         gpointer         user_data)
591 {
592     GtkOpenChanged( GTK_WIDGET( notebook ), user_data );
593 }
594
595 /****************************************************************************
596  * Audio management
597  ****************************************************************************/
598 void GtkVolumeUp                      ( GtkMenuItem     *menuitem,
599                                         gpointer         user_data )
600 {
601     intf_thread_t   *p_intf = GtkGetIntf( menuitem );
602     audio_volume_t  i_volume;
603
604     aout_VolumeUp( p_intf, 1, &i_volume );
605     p_intf->p_sys->b_mute = ( i_volume == 0 ) ? 1 : 0;
606 }
607
608
609 void GtkVolumeDown                    ( GtkMenuItem     *menuitem,
610                                         gpointer         user_data )
611 {
612     intf_thread_t   *p_intf = GtkGetIntf( menuitem );
613     audio_volume_t  i_volume;
614
615     aout_VolumeDown( p_intf, 1, &i_volume );
616     p_intf->p_sys->b_mute = ( i_volume == 0 ) ? 1 : 0;
617 }
618
619
620 void GtkVolumeMute                    ( GtkMenuItem     *menuitem,
621                                         gpointer         user_data )
622 {
623     intf_thread_t   *p_intf = GtkGetIntf( menuitem );
624     audio_volume_t i_volume;
625
626     aout_VolumeMute( p_intf, &i_volume );
627     p_intf->p_sys->b_mute = ( i_volume == 0 ) ? 1 : 0;
628 }
629
630 void
631 GtkMenubarDeinterlace                  ( GtkMenuItem     *menuitem,
632                                         gpointer         user_data)
633 {
634     intf_thread_t   *p_intf = GtkGetIntf( menuitem );
635
636     if( p_intf )
637         msg_Dbg( p_intf, "GtkMenubarDeinterlace" );
638 }
639
640
641 void
642 GtkPopupDeinterlace                    (GtkRadioMenuItem *radiomenuitem,
643                                         gpointer         user_data)
644 {
645     intf_thread_t   *p_intf = GtkGetIntf( radiomenuitem );
646
647     if( p_intf )
648         msg_Dbg( p_intf, "GtkPopupDeinterlace" );
649 }
650
651
652