]> git.sesse.net Git - vlc/blob - modules/gui/gtk/gtk_callbacks.c
* Coding style cleanup: removed tabs and trailing spaces.
[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: gtk_callbacks.c,v 1.16 2003/12/22 14:32:56 sam Exp $
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         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
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         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
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         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
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         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
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     input_Seek( p_intf->p_sys->p_input,
409                 i_seconds + 60 * i_minutes + 3600 * i_hours,
410                 INPUT_SEEK_SECONDS | INPUT_SEEK_SET );
411
412     gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
413 }
414
415
416 void GtkJumpCancel( GtkButton       *button,
417                     gpointer         user_data)
418 {
419     gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
420 }
421
422 /****************************************************************************
423  * Callbacks for disc ejection
424  ****************************************************************************/
425 gboolean GtkDiscEject ( GtkWidget *widget, gpointer user_data )
426 {
427     char *psz_device = NULL;
428     char *psz_parser;
429     char *psz_current;
430
431     intf_thread_t *p_intf = GtkGetIntf( widget );
432     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
433                                                        FIND_ANYWHERE );
434     if( p_playlist == NULL )
435     {
436         return FALSE;
437     }
438
439     vlc_mutex_lock( &p_playlist->object_lock );
440
441     if( p_playlist->i_index < 0 )
442     {
443         vlc_mutex_unlock( &p_playlist->object_lock );
444         vlc_object_release( p_playlist );
445         return FALSE;
446     }
447
448     psz_current = p_playlist->pp_items[ p_playlist->i_index ]->psz_name;
449
450     /*
451      * Get the active input
452      * Determine whether we can eject a media, ie it's a VCD or DVD
453      * If it's neither a VCD nor a DVD, then return
454      */
455
456     /*
457      * Don't really know if I must lock the stuff here, we're using it read-only
458      */
459
460     if( psz_current != NULL )
461     {
462         if( !strncmp(psz_current, "dvd://", 4) )
463         {
464             switch( psz_current[strlen("dvd://")] )
465             {
466             case '\0':
467             case '@':
468                 psz_device = config_GetPsz( p_intf, "dvd" );
469                 break;
470             default:
471                 /* Omit the first MRL-selector characters */
472                 psz_device = strdup( psz_current + strlen("dvd://" ) );
473                 break;
474             }
475         }
476         else if( !strncmp(psz_current, "vcd:", strlen("vcd:")) )
477         {
478             switch( psz_current[strlen("vcd:")] )
479             {
480             case '\0':
481             case '@':
482                 psz_device = config_GetPsz( p_intf, VCD_MRL );
483                 break;
484             default:
485                 /* Omit the beginning MRL-selector characters */
486                 psz_device = strdup( psz_current + strlen(VCD_MRL) );
487                 break;
488             }
489         }
490         else if( !strncmp(psz_current, CDDA_MRL, strlen(CDDA_MRL) ) )
491         {
492             switch( psz_current[strlen(CDDA_MRL)] )
493             {
494             case '\0':
495             case '@':
496                 psz_device = config_GetPsz( p_intf, "cd-audio" );
497                 break;
498             default:
499                 /* Omit the beginning MRL-selector characters */
500                 psz_device = strdup( psz_current + strlen(CDDA_MRL) );
501                 break;
502             }
503         }
504         else
505         {
506             psz_device = strdup( psz_current );
507         }
508     }
509
510     vlc_mutex_unlock( &p_playlist->object_lock );
511     vlc_object_release( p_playlist );
512
513     if( psz_device == NULL )
514     {
515         return TRUE;
516     }
517
518     /* Remove what we have after @ */
519     psz_parser = psz_device;
520     for( psz_parser = psz_device ; *psz_parser ; psz_parser++ )
521     {
522         if( *psz_parser == '@' )
523         {
524             *psz_parser = '\0';
525             break;
526         }
527     }
528
529     /* If there's a stream playing, we aren't allowed to eject ! */
530     if( p_intf->p_sys->p_input == NULL )
531     {
532         msg_Dbg( p_intf, "ejecting %s", psz_device );
533
534         intf_Eject( p_intf, psz_device );
535     }
536
537     free(psz_device);
538
539     return TRUE;
540 }
541
542 /****************************************************************************
543  * Messages window
544  ****************************************************************************/
545
546 gboolean GtkMessagesShow( GtkWidget       *widget,
547                           gpointer         user_data)
548 {
549     static GdkColor black = { 0, 0x0000, 0x0000, 0x0000 };
550     static GdkColormap *colormap;
551     intf_thread_t *p_intf = GtkGetIntf( widget );
552
553     gtk_widget_show( p_intf->p_sys->p_messages );
554     colormap = gdk_colormap_get_system ();
555     gdk_color_alloc( colormap, &black );
556     gdk_window_set_background( p_intf->p_sys->p_messages_text->text_area,
557                                &black );
558
559     gdk_window_raise( p_intf->p_sys->p_messages->window );
560
561     gtk_text_set_point( p_intf->p_sys->p_messages_text,
562                     gtk_text_get_length( p_intf->p_sys->p_messages_text ) );
563
564     return TRUE;
565 }
566
567 void
568 GtkMessagesOk                          (GtkButton       *button,
569                                         gpointer         user_data)
570 {
571     intf_thread_t *p_intf = GtkGetIntf( button );
572     gtk_widget_hide( p_intf->p_sys->p_messages );
573 }
574
575
576 gboolean
577 GtkMessagesDelete                      (GtkWidget       *widget,
578                                         GdkEvent        *event,
579                                         gpointer         user_data)
580 {
581     intf_thread_t *p_intf = GtkGetIntf( widget );
582     gtk_widget_hide( p_intf->p_sys->p_messages );
583     return TRUE;
584 }
585
586
587 void
588 GtkOpenNotebookChanged                 (GtkNotebook     *notebook,
589                                         GtkNotebookPage *page,
590                                         gint             page_num,
591                                         gpointer         user_data)
592 {
593     GtkOpenChanged( GTK_WIDGET( notebook ), user_data );
594 }
595
596 /****************************************************************************
597  * Audio management
598  ****************************************************************************/
599 void GtkVolumeUp                      ( GtkMenuItem     *menuitem,
600                                         gpointer         user_data )
601 {
602     intf_thread_t   *p_intf = GtkGetIntf( menuitem );
603     audio_volume_t  i_volume;
604
605     aout_VolumeUp( p_intf, 1, &i_volume );
606     p_intf->p_sys->b_mute = ( i_volume == 0 ) ? 1 : 0;
607 }
608
609
610 void GtkVolumeDown                    ( GtkMenuItem     *menuitem,
611                                         gpointer         user_data )
612 {
613     intf_thread_t   *p_intf = GtkGetIntf( menuitem );
614     audio_volume_t  i_volume;
615
616     aout_VolumeDown( p_intf, 1, &i_volume );
617     p_intf->p_sys->b_mute = ( i_volume == 0 ) ? 1 : 0;
618 }
619
620
621 void GtkVolumeMute                    ( GtkMenuItem     *menuitem,
622                                         gpointer         user_data )
623 {
624     intf_thread_t   *p_intf = GtkGetIntf( menuitem );
625     audio_volume_t i_volume;
626
627     aout_VolumeMute( p_intf, &i_volume );
628     p_intf->p_sys->b_mute = ( i_volume == 0 ) ? 1 : 0;
629 }
630
631 void
632 GtkMenubarDeinterlace                  ( GtkMenuItem     *menuitem,
633                                         gpointer         user_data)
634 {
635     intf_thread_t   *p_intf = GtkGetIntf( menuitem );
636
637     if( p_intf )
638         msg_Dbg( p_intf, "GtkMenubarDeinterlace" );
639 }
640
641
642 void
643 GtkPopupDeinterlace                    (GtkRadioMenuItem *radiomenuitem,
644                                         gpointer         user_data)
645 {
646     intf_thread_t   *p_intf = GtkGetIntf( radiomenuitem );
647
648     if( p_intf )
649         msg_Dbg( p_intf, "GtkPopupDeinterlace" );
650 }
651
652
653