]> git.sesse.net Git - vlc/blob - modules/gui/gtk/gtk_callbacks.c
* ALL: the build mechanism now uses automake. See HACKING for more details.
[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.3 2002/09/30 11:05:39 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     i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_id - 1;
221
222     if( i_id >= 0 )
223     {
224         p_area = p_intf->p_sys->p_input->stream.pp_areas[i_id];
225         input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );
226
227         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
228
229         p_intf->p_sys->b_title_update = 1;
230         vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
231         GtkSetupMenus( p_intf );
232         vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
233     }
234 }
235
236
237 void GtkTitleNext( GtkButton * button, gpointer user_data )
238 {
239     intf_thread_t * p_intf;
240     input_area_t *  p_area;
241     int             i_id;
242
243     p_intf = GtkGetIntf( button );
244     i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_id + 1;
245
246     if( i_id < p_intf->p_sys->p_input->stream.i_area_nb )
247     {
248         p_area = p_intf->p_sys->p_input->stream.pp_areas[i_id];   
249         input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );
250
251         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
252
253         p_intf->p_sys->b_title_update = 1;
254         vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
255         GtkSetupMenus( p_intf );
256         vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
257     }
258 }
259
260
261 void GtkChapterPrev( GtkButton * button, gpointer user_data )
262 {
263     intf_thread_t * p_intf;
264     input_area_t *  p_area;
265
266     p_intf = GtkGetIntf( button );
267     p_area = p_intf->p_sys->p_input->stream.p_selected_area;
268
269     if( p_area->i_part > 0 )
270     {
271         p_area->i_part--;
272         input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );
273
274         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
275
276         p_intf->p_sys->b_chapter_update = 1;
277         vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
278         GtkSetupMenus( p_intf );
279         vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
280     }
281 }
282
283
284 void GtkChapterNext( GtkButton * button, gpointer user_data )
285 {
286     intf_thread_t * p_intf;
287     input_area_t *  p_area;
288
289     p_intf = GtkGetIntf( button );
290     p_area = p_intf->p_sys->p_input->stream.p_selected_area;
291
292     if( p_area->i_part < p_area->i_part_nb )
293     {
294         p_area->i_part++;
295         input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );
296
297         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
298
299         p_intf->p_sys->b_chapter_update = 1;
300         vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
301         GtkSetupMenus( p_intf );
302         vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
303     }
304 }
305
306 /****************************************************************************
307  * Network specific items
308  ****************************************************************************/
309 void GtkNetworkJoin( GtkEditable * editable, gpointer user_data )
310 {
311     int     i_channel;
312
313     i_channel = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( editable ) );
314 #if 0
315     msg_Dbg( "intf info: joining channel %d", i_channel );
316
317     network_ChannelJoin( i_channel );
318 #endif
319 }
320
321 void GtkChannelGo( GtkButton * button, gpointer user_data )
322 {
323     GtkWidget *     window;
324     GtkWidget *     spin;
325     int             i_channel;
326
327     intf_thread_t *p_intf = GtkGetIntf( button );
328
329     window = gtk_widget_get_toplevel( GTK_WIDGET (button) );
330     spin = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( window ),
331                        "network_channel_spinbutton" ) );
332
333     i_channel = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( spin ) );
334     msg_Dbg( p_intf, "joining channel %d", i_channel );
335
336     vlc_mutex_lock( &p_intf->change_lock );
337     network_ChannelJoin( p_intf, i_channel );
338     vlc_mutex_unlock( &p_intf->change_lock );
339
340 /*    input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY ); */
341 }
342
343
344 /****************************************************************************
345  * About box
346  ****************************************************************************/
347
348 gboolean GtkAboutShow( GtkWidget       *widget,
349                        gpointer         user_data)
350 {
351     intf_thread_t *p_intf = GtkGetIntf( widget );
352
353     if( !GTK_IS_WIDGET( p_intf->p_sys->p_about ) )
354     {
355         p_intf->p_sys->p_about = create_intf_about();
356         gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_about ),
357                              "p_intf", p_intf );
358     }
359     gtk_widget_show( p_intf->p_sys->p_about );
360     gdk_window_raise( p_intf->p_sys->p_about->window );
361
362     return TRUE;
363 }
364
365 void GtkAboutOk( GtkButton * button, gpointer user_data)
366 {
367     intf_thread_t *p_intf = GtkGetIntf( button );
368
369     gtk_widget_hide( p_intf->p_sys->p_about );
370 }
371
372
373 /****************************************************************************
374  * Jump box
375  ****************************************************************************/
376
377 gboolean GtkJumpShow( GtkWidget       *widget,
378                       gpointer         user_data)
379 {
380     intf_thread_t *p_intf = GtkGetIntf( widget );
381
382     if( !GTK_IS_WIDGET( p_intf->p_sys->p_jump ) )
383     {
384         p_intf->p_sys->p_jump = create_intf_jump();
385         gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_jump ),
386                              "p_intf", p_intf );
387     }
388
389     gtk_widget_show( p_intf->p_sys->p_jump );
390     gdk_window_raise( p_intf->p_sys->p_jump->window );
391
392     return FALSE;
393 }
394
395
396 void GtkJumpOk( GtkButton       *button,
397                 gpointer         user_data)
398 {
399     intf_thread_t * p_intf = GtkGetIntf( button );
400     int i_hours, i_minutes, i_seconds;
401
402     if( p_intf->p_sys->p_input == NULL )
403     {
404         return;
405     }
406
407 #define GET_VALUE( name )                                                   \
408     gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( gtk_object_get_data( \
409         GTK_OBJECT( p_intf->p_sys->p_jump ), name ) ) )
410     i_hours   = GET_VALUE( "jump_hour_spinbutton" );
411     i_minutes = GET_VALUE( "jump_minute_spinbutton" );
412     i_seconds = GET_VALUE( "jump_second_spinbutton" );
413 #undef GET_VALUE
414
415     input_Seek( p_intf->p_sys->p_input,
416                 i_seconds + 60 * i_minutes + 3600 * i_hours,
417                 INPUT_SEEK_SECONDS | INPUT_SEEK_SET );
418
419     gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
420 }
421
422
423 void GtkJumpCancel( GtkButton       *button,
424                     gpointer         user_data)
425 {
426     gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
427 }
428
429 /****************************************************************************
430  * Callbacks for disc ejection
431  ****************************************************************************/
432 gboolean GtkDiscEject ( GtkWidget *widget, gpointer user_data )
433 {
434     char *psz_device = NULL;
435     char *psz_parser;
436     char *psz_current;
437
438     intf_thread_t *p_intf = GtkGetIntf( widget );
439     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
440                                                        FIND_ANYWHERE );
441     if( p_playlist == NULL )
442     {
443         return FALSE;
444     }
445
446     vlc_mutex_lock( &p_playlist->object_lock );
447
448     if( p_playlist->i_index < 0 )
449     {
450         vlc_mutex_unlock( &p_playlist->object_lock );
451         vlc_object_release( p_playlist );
452         return FALSE;
453     }
454
455     psz_current = p_playlist->pp_items[ p_playlist->i_index ]->psz_name;
456
457     /*
458      * Get the active input
459      * Determine whether we can eject a media, ie it's a VCD or DVD
460      * If it's neither a VCD nor a DVD, then return
461      */
462
463     /*
464      * Don't really know if I must lock the stuff here, we're using it read-only
465      */
466
467     if( psz_current != NULL )
468     {
469         if( !strncmp(psz_current, "dvd:", 4) )
470         {
471             switch( psz_current[4] )
472             {
473             case '\0':
474             case '@':
475                 psz_device = config_GetPsz( p_intf, "dvd" );
476                 break;
477             default:
478                 /* Omit the first 4 characters */
479                 psz_device = strdup( psz_current + 4 );
480                 break;
481             }
482         }
483         else if( !strncmp(psz_current, "vcd:", 4) )
484         {
485             switch( psz_current[4] )
486             {
487             case '\0':
488             case '@':
489                 psz_device = config_GetPsz( p_intf, "vcd" );
490                 break;
491             default:
492                 /* Omit the first 4 characters */
493                 psz_device = strdup( psz_current + 4 );
494                 break;
495             }
496         }
497         else
498         {
499             psz_device = strdup( psz_current );
500         }
501     }
502
503     vlc_mutex_unlock( &p_playlist->object_lock );
504     vlc_object_release( p_playlist );
505
506     if( psz_device == NULL )
507     {
508         return TRUE;
509     }
510
511     /* Remove what we have after @ */
512     psz_parser = psz_device;
513     for( psz_parser = psz_device ; *psz_parser ; psz_parser++ )
514     {
515         if( *psz_parser == '@' )
516         {
517             *psz_parser = '\0';
518             break;
519         }
520     }
521
522     /* If there's a stream playing, we aren't allowed to eject ! */
523     if( p_intf->p_sys->p_input == NULL )
524     {
525         msg_Dbg( p_intf, "ejecting %s", psz_device );
526
527         intf_Eject( p_intf, psz_device );
528     }
529
530     free(psz_device);
531
532     return TRUE;
533 }
534
535 /****************************************************************************
536  * Messages window
537  ****************************************************************************/
538
539 gboolean GtkMessagesShow( GtkWidget       *widget,
540                           gpointer         user_data)
541 {
542     static GdkColor black = { 0, 0x0000, 0x0000, 0x0000 };
543     static GdkColormap *colormap;
544     intf_thread_t *p_intf = GtkGetIntf( widget );
545
546     gtk_widget_show( p_intf->p_sys->p_messages );
547     colormap = gdk_colormap_get_system ();
548     gdk_color_alloc( colormap, &black );
549     gdk_window_set_background( p_intf->p_sys->p_messages_text->text_area,
550                                &black );
551
552     gdk_window_raise( p_intf->p_sys->p_messages->window );
553
554     gtk_text_set_point( p_intf->p_sys->p_messages_text,
555                     gtk_text_get_length( p_intf->p_sys->p_messages_text ) );
556
557     return TRUE;
558 }
559
560
561 void
562 GtkMessagesOk                          (GtkButton       *button,
563                                         gpointer         user_data)
564 {
565     intf_thread_t *p_intf = GtkGetIntf( button );
566     gtk_widget_hide( p_intf->p_sys->p_messages );
567 }
568
569
570 gboolean
571 GtkMessagesDelete                      (GtkWidget       *widget,
572                                         GdkEvent        *event,
573                                         gpointer         user_data)
574 {
575     intf_thread_t *p_intf = GtkGetIntf( widget );
576     gtk_widget_hide( p_intf->p_sys->p_messages );
577     return TRUE;
578 }
579
580
581 void
582 GtkOpenNotebookChanged                 (GtkNotebook     *notebook,
583                                         GtkNotebookPage *page,
584                                         gint             page_num,
585                                         gpointer         user_data)
586 {
587     GtkOpenChanged( GTK_WIDGET( notebook ), user_data );
588 }
589