* ./src/playlist/playlist.c: lots of playlist behaviour enhancements.
[vlc.git] / plugins / 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.44 2002/06/07 14:30:40 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 #include "gtk_common.h"
46
47 #include "netutils.h"
48
49 /*****************************************************************************
50  * Callbacks
51  *****************************************************************************/
52
53 /*
54  * Main interface callbacks
55  */
56
57 gboolean GtkExit( GtkWidget       *widget,
58                   gpointer         user_data )
59 {
60     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), (char*)user_data );
61
62     vlc_mutex_lock( &p_intf->change_lock );
63     p_intf->p_vlc->b_die = 1;
64     vlc_mutex_unlock( &p_intf->change_lock );
65
66     return TRUE;
67 }
68
69 gboolean GtkWindowDelete( GtkWidget       *widget,
70                           GdkEvent        *event,
71                           gpointer         user_data )
72 {
73     GtkExit( GTK_WIDGET( widget ), user_data );
74
75     return TRUE;
76 }
77
78
79 gboolean GtkWindowToggle( GtkWidget       *widget,
80                           gpointer         user_data )
81 {
82     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), (char*)user_data );
83     
84     if( GTK_WIDGET_VISIBLE(p_intf->p_sys->p_window) )
85     {
86         gtk_widget_hide( p_intf->p_sys->p_window);
87
88     } 
89     else 
90     {
91         gtk_widget_show( p_intf->p_sys->p_window );
92     }
93
94     return TRUE;
95 }
96
97 gboolean GtkFullscreen( GtkWidget       *widget,
98                         gpointer         user_data)
99 {
100     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), (char*)user_data );
101     vout_thread_t *p_vout;
102
103     p_vout = vlc_object_find( p_intf->p_sys->p_input,
104                               VLC_OBJECT_VOUT, FIND_CHILD );
105
106     if( p_vout )
107     {
108         p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
109         vlc_object_release( p_vout );
110         return TRUE;
111     }
112
113     return FALSE;
114 }
115
116 void GtkWindowDrag( GtkWidget       *widget,
117                     GdkDragContext  *drag_context,
118                     gint             x,
119                     gint             y,
120                     GtkSelectionData *data,
121                     guint            info,
122                     guint            time,
123                     gpointer         user_data)
124 {
125     intf_thread_t * p_intf =  GetIntf( GTK_WIDGET(widget), "intf_window" );
126     GtkDropDataReceived( p_intf, data, info, PLAYLIST_END );
127 }
128
129
130 /****************************************************************************
131  * Slider management
132  ****************************************************************************/
133
134 gboolean GtkSliderRelease( GtkWidget       *widget,
135                            GdkEventButton  *event,
136                            gpointer         user_data )
137 {
138     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), "intf_window" );
139
140     vlc_mutex_lock( &p_intf->change_lock );
141     p_intf->p_sys->b_slider_free = 1;
142     vlc_mutex_unlock( &p_intf->change_lock );
143
144     return FALSE;
145 }
146
147
148 gboolean GtkSliderPress( GtkWidget       *widget,
149                          GdkEventButton  *event,
150                          gpointer         user_data)
151 {
152     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), "intf_window" );
153
154     vlc_mutex_lock( &p_intf->change_lock );
155     p_intf->p_sys->b_slider_free = 0;
156     vlc_mutex_unlock( &p_intf->change_lock );
157
158     return FALSE;
159 }
160
161
162 /****************************************************************************
163  * DVD specific items
164  ****************************************************************************/
165
166 void GtkTitlePrev( GtkButton * button, gpointer user_data )
167 {
168     intf_thread_t *  p_intf;
169     input_area_t *   p_area;
170     int              i_id;
171
172     p_intf = GetIntf( GTK_WIDGET(button), (char*)user_data );
173
174     i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_id - 1;
175
176     /* Disallow area 0 since it is used for video_ts.vob */
177     if( i_id > 0 )
178     {
179         p_area = p_intf->p_sys->p_input->stream.pp_areas[i_id];
180         input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );
181
182         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
183
184         p_intf->p_sys->b_title_update = 1;
185         vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
186         GtkSetupMenus( p_intf );
187         vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
188     }
189 }
190
191
192 void GtkTitleNext( GtkButton * button, gpointer user_data )
193 {
194     intf_thread_t * p_intf;
195     input_area_t *  p_area;
196     int             i_id;
197
198     p_intf = GetIntf( GTK_WIDGET(button), (char*)user_data );
199     i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_id + 1;
200
201     if( i_id < p_intf->p_sys->p_input->stream.i_area_nb )
202     {
203         p_area = p_intf->p_sys->p_input->stream.pp_areas[i_id];   
204         input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );
205
206         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
207
208         p_intf->p_sys->b_title_update = 1;
209         vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
210         GtkSetupMenus( p_intf );
211         vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
212     }
213 }
214
215
216 void GtkChapterPrev( GtkButton * button, gpointer user_data )
217 {
218     intf_thread_t * p_intf;
219     input_area_t *  p_area;
220
221     p_intf = GetIntf( GTK_WIDGET(button), (char*)user_data );
222     p_area = p_intf->p_sys->p_input->stream.p_selected_area;
223
224     if( p_area->i_part > 0 )
225     {
226         p_area->i_part--;
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_chapter_update = 1;
232         vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
233         GtkSetupMenus( p_intf );
234         vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
235     }
236 }
237
238
239 void GtkChapterNext( GtkButton * button, gpointer user_data )
240 {
241     intf_thread_t * p_intf;
242     input_area_t *  p_area;
243
244     p_intf = GetIntf( GTK_WIDGET(button), (char*)user_data );
245     p_area = p_intf->p_sys->p_input->stream.p_selected_area;
246
247     if( p_area->i_part < p_area->i_part_nb )
248     {
249         p_area->i_part++;
250         input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );
251
252         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
253
254         p_intf->p_sys->b_chapter_update = 1;
255         vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
256         GtkSetupMenus( p_intf );
257         vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
258     }
259 }
260
261 /****************************************************************************
262  * Network specific items
263  ****************************************************************************/
264 void GtkNetworkJoin( GtkEditable * editable, gpointer user_data )
265 {
266     int     i_channel;
267
268     i_channel = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( editable ) );
269 //    msg_Dbg( "intf info: joining channel %d", i_channel );
270
271 //    network_ChannelJoin( i_channel );
272 }
273
274 void GtkChannelGo( GtkButton * button, gpointer user_data )
275 {
276     GtkWidget *     window;
277     GtkWidget *     spin;
278     int             i_channel;
279
280     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(button), (char*)user_data );
281
282     window = gtk_widget_get_toplevel( GTK_WIDGET (button) );
283     spin = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( window ),
284                        "network_channel_spinbutton" ) );
285
286     i_channel = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( spin ) );
287     msg_Dbg( p_intf, "joining channel %d", i_channel );
288
289     vlc_mutex_lock( &p_intf->change_lock );
290     network_ChannelJoin( p_intf, i_channel );
291     vlc_mutex_unlock( &p_intf->change_lock );
292
293 //    input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
294 }
295
296
297 /****************************************************************************
298  * About box
299  ****************************************************************************/
300
301 gboolean GtkAboutShow( GtkWidget       *widget,
302                        gpointer         user_data)
303 {
304     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), (char*)user_data );
305
306     if( !GTK_IS_WIDGET( p_intf->p_sys->p_about ) )
307     {
308         p_intf->p_sys->p_about = create_intf_about();
309         gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_about ),
310                              "p_intf", p_intf );
311     }
312     gtk_widget_show( p_intf->p_sys->p_about );
313     gdk_window_raise( p_intf->p_sys->p_about->window );
314
315     return TRUE;
316 }
317
318 void GtkAboutOk( GtkButton * button, gpointer user_data)
319 {
320     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(button), (char*)user_data );
321
322     gtk_widget_hide( p_intf->p_sys->p_about );
323 }
324
325
326 /****************************************************************************
327  * Jump box
328  ****************************************************************************/
329
330 gboolean GtkJumpShow( GtkWidget       *widget,
331                       gpointer         user_data)
332 {
333     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), (char*)user_data );
334
335     if( !GTK_IS_WIDGET( p_intf->p_sys->p_jump ) )
336     {
337         p_intf->p_sys->p_jump = create_intf_jump();
338         gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_jump ),
339                              "p_intf", p_intf );
340     }
341
342     gtk_widget_show( p_intf->p_sys->p_jump );
343     gdk_window_raise( p_intf->p_sys->p_jump->window );
344
345     return FALSE;
346 }
347
348
349 void GtkJumpOk( GtkButton       *button,
350                 gpointer         user_data)
351 {
352     intf_thread_t * p_intf = GetIntf( GTK_WIDGET( button ), (char*)user_data );
353     int i_hours, i_minutes, i_seconds;
354
355     if( p_intf->p_sys->p_input == NULL )
356     {
357         return;
358     }
359
360 #define GET_VALUE( name )                                                   \
361     gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( gtk_object_get_data( \
362         GTK_OBJECT( p_intf->p_sys->p_jump ), name ) ) )
363     i_hours   = GET_VALUE( "jump_hour_spinbutton" );
364     i_minutes = GET_VALUE( "jump_minute_spinbutton" );
365     i_seconds = GET_VALUE( "jump_second_spinbutton" );
366 #undef GET_VALUE
367
368     input_Seek( p_intf->p_sys->p_input,
369                 i_seconds + 60 * i_minutes + 3600 * i_hours,
370                 INPUT_SEEK_SECONDS | INPUT_SEEK_SET );
371
372     gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
373 }
374
375
376 void GtkJumpCancel( GtkButton       *button,
377                     gpointer         user_data)
378 {
379     gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
380 }
381
382 /****************************************************************************
383  * Callbacks for disc ejection
384  ****************************************************************************/
385 gboolean GtkDiscEject ( GtkWidget *widget, gpointer user_data )
386 {
387 #if 0 /* PLAYLIST TARASS */
388     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), (char*)user_data );
389
390     char *psz_device = NULL;
391     char *psz_parser;
392     char *psz_current = p_intf->p_vlc->p_playlist->current.psz_name;
393
394     /*
395      * Get the active input
396      * Determine whether we can eject a media, ie it's a VCD or DVD
397      * If it's neither a VCD nor a DVD, then return
398      */
399
400     /*
401      * Don't really know if I must lock the stuff here, we're using it read-only
402      */
403
404     if( psz_current != NULL )
405     {
406         if( !strncmp(psz_current, "dvd:", 4) )
407         {
408             switch( psz_current[4] )
409             {
410             case '\0':
411             case '@':
412                 psz_device = config_GetPsz( p_intf, "dvd" );
413                 break;
414             default:
415                 /* Omit the first 4 characters */
416                 psz_device = strdup( psz_current + 4 );
417                 break;
418             }
419         }
420         else if( !strncmp(psz_current, "vcd:", 4) )
421         {
422             switch( psz_current[4] )
423             {
424             case '\0':
425             case '@':
426                 psz_device = config_GetPsz( p_intf, "vcd" );
427                 break;
428             default:
429                 /* Omit the first 4 characters */
430                 psz_device = strdup( psz_current + 4 );
431                 break;
432             }
433         }
434         else
435         {
436             psz_device = strdup( psz_current );
437         }
438     }
439
440     if( psz_device == NULL )
441     {
442         return TRUE;
443     }
444
445     /* Remove what we have after @ */
446     psz_parser = psz_device;
447     for( psz_parser = psz_device ; *psz_parser ; psz_parser++ )
448     {
449         if( *psz_parser == '@' )
450         {
451             *psz_parser = '\0';
452             break;
453         }
454     }
455
456     /* If there's a stream playing, we aren't allowed to eject ! */
457     if( p_intf->p_sys->p_input == NULL )
458     {
459         msg_Dbg( p_intf, "ejecting %s", psz_device );
460
461         intf_Eject( p_intf, psz_device );
462     }
463
464     free(psz_device);
465 #endif
466     return TRUE;
467 }
468
469 /****************************************************************************
470  * Messages window
471  ****************************************************************************/
472
473 gboolean GtkMessagesShow( GtkWidget       *widget,
474                           gpointer         user_data)
475 {
476     static GdkColor black = { 0, 0x0000, 0x0000, 0x0000 };
477     static GdkColormap *colormap;
478     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), (char*)user_data );
479
480     gtk_widget_show( p_intf->p_sys->p_messages );
481     colormap = gdk_colormap_get_system ();
482     gdk_color_alloc( colormap, &black );
483     gdk_window_set_background( p_intf->p_sys->p_messages_text->text_area,
484                                &black );
485
486     gdk_window_raise( p_intf->p_sys->p_messages->window );
487
488     gtk_text_set_point( p_intf->p_sys->p_messages_text,
489                     gtk_text_get_length( p_intf->p_sys->p_messages_text ) );
490
491     return TRUE;
492 }
493
494
495 void
496 GtkMessagesOk                          (GtkButton       *button,
497                                         gpointer         user_data)
498 {
499     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(button), (char*)user_data );
500     gtk_widget_hide( p_intf->p_sys->p_messages );
501 }
502
503
504 gboolean
505 GtkMessagesDelete                      (GtkWidget       *widget,
506                                         GdkEvent        *event,
507                                         gpointer         user_data)
508 {
509     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), (char*)user_data );
510     gtk_widget_hide( p_intf->p_sys->p_messages );
511     return TRUE;
512 }
513