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