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