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