58332ce1bcb1784337e2586c64b170b85910511f
[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.43 2002/06/04 20:33:25 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                   GdkEventButton  *event,
59                   gpointer         user_data )
60 {
61     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), (char*)user_data );
62
63     vlc_mutex_lock( &p_intf->change_lock );
64     p_intf->p_vlc->b_die = 1;
65     vlc_mutex_unlock( &p_intf->change_lock );
66
67     return TRUE;
68 }
69
70 gboolean GtkWindowDelete( GtkWidget       *widget,
71                           GdkEvent        *event,
72                           gpointer         user_data )
73 {
74     GtkExit( GTK_WIDGET( widget ), NULL, user_data );
75
76     return TRUE;
77 }
78
79
80 gboolean GtkWindowToggle( GtkWidget       *widget,
81                           GdkEventButton  *event,
82                           gpointer         user_data )
83 {
84     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), (char*)user_data );
85     
86     if( GTK_WIDGET_VISIBLE(p_intf->p_sys->p_window) )
87     {
88         gtk_widget_hide( p_intf->p_sys->p_window);
89
90     } 
91     else 
92     {
93         gtk_widget_show( p_intf->p_sys->p_window );
94     }
95
96     return TRUE;
97 }
98
99 gboolean GtkFullscreen( GtkWidget       *widget,
100                         GdkEventButton  *event,
101                         gpointer         user_data)
102 {
103     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), (char*)user_data );
104     vout_thread_t *p_vout;
105
106     p_vout = vlc_object_find( p_intf->p_sys->p_input,
107                               VLC_OBJECT_VOUT, FIND_CHILD );
108
109     if( p_vout )
110     {
111         p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
112         vlc_object_release( p_vout );
113         return TRUE;
114     }
115
116     return FALSE;
117 }
118
119 void GtkWindowDrag( GtkWidget       *widget,
120                     GdkDragContext  *drag_context,
121                     gint             x,
122                     gint             y,
123                     GtkSelectionData *data,
124                     guint            info,
125                     guint            time,
126                     gpointer         user_data)
127 {
128 #if 0 /* PLAYLIST TARASS */
129     intf_thread_t * p_intf =  GetIntf( GTK_WIDGET(widget), "intf_window" );
130     int end = p_intf->p_vlc->p_playlist->i_size;
131     GtkDropDataReceived( p_intf, data, info, PLAYLIST_END );
132
133     if( p_intf->p_sys->p_input != NULL )
134     {
135         /* FIXME: temporary hack */
136         p_intf->p_sys->p_input->b_eof = 1;
137     }
138      
139     intf_PlaylistJumpto( p_intf->p_vlc->p_playlist, end-1 );
140 #endif
141 }
142
143
144 /****************************************************************************
145  * Slider management
146  ****************************************************************************/
147
148 gboolean GtkSliderRelease( 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 = 1;
156     vlc_mutex_unlock( &p_intf->change_lock );
157
158     return FALSE;
159 }
160
161
162 gboolean GtkSliderPress( GtkWidget       *widget,
163                          GdkEventButton  *event,
164                          gpointer         user_data)
165 {
166     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), "intf_window" );
167
168     vlc_mutex_lock( &p_intf->change_lock );
169     p_intf->p_sys->b_slider_free = 0;
170     vlc_mutex_unlock( &p_intf->change_lock );
171
172     return FALSE;
173 }
174
175
176 /****************************************************************************
177  * DVD specific items
178  ****************************************************************************/
179
180 void GtkTitlePrev( GtkButton * button, gpointer user_data )
181 {
182     intf_thread_t *  p_intf;
183     input_area_t *   p_area;
184     int              i_id;
185
186     p_intf = GetIntf( GTK_WIDGET(button), (char*)user_data );
187
188     i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_id - 1;
189
190     /* Disallow area 0 since it is used for video_ts.vob */
191     if( i_id > 0 )
192     {
193         p_area = p_intf->p_sys->p_input->stream.pp_areas[i_id];
194         input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );
195
196         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
197
198         p_intf->p_sys->b_title_update = 1;
199         vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
200         GtkSetupMenus( p_intf );
201         vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
202     }
203
204     vlc_object_release( p_intf->p_sys->p_input );
205 }
206
207
208 void GtkTitleNext( GtkButton * button, gpointer user_data )
209 {
210     intf_thread_t * p_intf;
211     input_area_t *  p_area;
212     int             i_id;
213
214     p_intf = GetIntf( GTK_WIDGET(button), (char*)user_data );
215     i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_id + 1;
216
217     if( i_id < p_intf->p_sys->p_input->stream.i_area_nb )
218     {
219         p_area = p_intf->p_sys->p_input->stream.pp_areas[i_id];   
220         input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );
221
222         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
223
224         p_intf->p_sys->b_title_update = 1;
225         vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
226         GtkSetupMenus( p_intf );
227         vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
228     }
229
230 }
231
232
233 void GtkChapterPrev( GtkButton * button, gpointer user_data )
234 {
235     intf_thread_t * p_intf;
236     input_area_t *  p_area;
237
238     p_intf = GetIntf( GTK_WIDGET(button), (char*)user_data );
239     p_area = p_intf->p_sys->p_input->stream.p_selected_area;
240
241     if( p_area->i_part > 0 )
242     {
243         p_area->i_part--;
244         input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );
245
246         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
247
248         p_intf->p_sys->b_chapter_update = 1;
249         vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
250         GtkSetupMenus( p_intf );
251         vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
252     }
253 }
254
255
256 void GtkChapterNext( GtkButton * button, gpointer user_data )
257 {
258     intf_thread_t * p_intf;
259     input_area_t *  p_area;
260
261     p_intf = GetIntf( GTK_WIDGET(button), (char*)user_data );
262     p_area = p_intf->p_sys->p_input->stream.p_selected_area;
263
264     if( p_area->i_part < p_area->i_part_nb )
265     {
266         p_area->i_part++;
267         input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );
268
269         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
270
271         p_intf->p_sys->b_chapter_update = 1;
272         vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
273         GtkSetupMenus( p_intf );
274         vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
275     }
276 }
277
278 /****************************************************************************
279  * Network specific items
280  ****************************************************************************/
281 void GtkNetworkJoin( GtkEditable * editable, gpointer user_data )
282 {
283     int     i_channel;
284
285     i_channel = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( editable ) );
286 //    msg_Dbg( "intf info: joining channel %d", i_channel );
287
288 //    network_ChannelJoin( i_channel );
289 }
290
291 void GtkChannelGo( GtkButton * button, gpointer user_data )
292 {
293     GtkWidget *     window;
294     GtkWidget *     spin;
295     int             i_channel;
296
297     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(button), (char*)user_data );
298
299     window = gtk_widget_get_toplevel( GTK_WIDGET (button) );
300     spin = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( window ),
301                        "network_channel_spinbutton" ) );
302
303     i_channel = gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( spin ) );
304     msg_Dbg( p_intf, "joining channel %d", i_channel );
305
306     vlc_mutex_lock( &p_intf->change_lock );
307     network_ChannelJoin( p_intf, i_channel );
308     vlc_mutex_unlock( &p_intf->change_lock );
309
310 //    input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
311 }
312
313
314 /****************************************************************************
315  * About box
316  ****************************************************************************/
317
318 gboolean GtkAboutShow( GtkWidget       *widget,
319                        GdkEventButton  *event,
320                        gpointer         user_data)
321 {
322     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), (char*)user_data );
323
324     if( !GTK_IS_WIDGET( p_intf->p_sys->p_about ) )
325     {
326         p_intf->p_sys->p_about = create_intf_about();
327         gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_about ),
328                              "p_intf", p_intf );
329     }
330     gtk_widget_show( p_intf->p_sys->p_about );
331     gdk_window_raise( p_intf->p_sys->p_about->window );
332
333     return TRUE;
334 }
335
336 void GtkAboutOk( GtkButton * button, gpointer user_data)
337 {
338     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(button), (char*)user_data );
339
340     gtk_widget_hide( p_intf->p_sys->p_about );
341 }
342
343
344 /****************************************************************************
345  * Jump box
346  ****************************************************************************/
347
348 gboolean GtkJumpShow( GtkWidget       *widget,
349                       GdkEventButton  *event,
350                       gpointer         user_data)
351 {
352     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), (char*)user_data );
353
354     if( !GTK_IS_WIDGET( p_intf->p_sys->p_jump ) )
355     {
356         p_intf->p_sys->p_jump = create_intf_jump();
357         gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_jump ),
358                              "p_intf", p_intf );
359     }
360
361     gtk_widget_show( p_intf->p_sys->p_jump );
362     gdk_window_raise( p_intf->p_sys->p_jump->window );
363
364     return FALSE;
365 }
366
367
368 void GtkJumpOk( GtkButton       *button,
369                 gpointer         user_data)
370 {
371     intf_thread_t * p_intf = GetIntf( GTK_WIDGET( button ), (char*)user_data );
372     int i_hours, i_minutes, i_seconds;
373
374 #define GET_VALUE( name )                                                   \
375     gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( gtk_object_get_data( \
376         GTK_OBJECT( p_intf->p_sys->p_jump ), name ) ) )
377     i_hours   = GET_VALUE( "jump_hour_spinbutton" );
378     i_minutes = GET_VALUE( "jump_minute_spinbutton" );
379     i_seconds = GET_VALUE( "jump_second_spinbutton" );
380 #undef GET_VALUE
381
382     input_Seek( p_intf, i_seconds + 60 * i_minutes + 3600 * i_hours,
383                         INPUT_SEEK_SECONDS | INPUT_SEEK_SET );
384
385 #if 0 /* PLAYLIST TARASS */
386     p_intf->p_vlc->p_playlist->b_stopped = 0;
387 #endif
388     gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
389 }
390
391
392 void GtkJumpCancel( GtkButton       *button,
393                     gpointer         user_data)
394 {
395     gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
396 }
397
398
399 /****************************************************************************
400  * Callbacks for menuitems
401  ****************************************************************************/
402 void GtkExitActivate( GtkMenuItem * menuitem, gpointer user_data )
403 {
404     GtkExit( GTK_WIDGET( menuitem ), NULL, user_data );
405 }
406
407
408 void GtkFullscreenActivate( GtkMenuItem * menuitem, gpointer user_data )
409 {
410     GtkFullscreen( GTK_WIDGET( menuitem ), NULL, user_data );
411 }
412
413
414 void GtkWindowToggleActivate( GtkMenuItem * menuitem, gpointer user_data )
415 {
416     GtkWindowToggle( GTK_WIDGET( menuitem ), NULL, user_data );
417 }
418
419
420 void GtkAboutActivate( GtkMenuItem * menuitem, gpointer user_data )
421 {
422     GtkAboutShow( GTK_WIDGET( menuitem ), NULL, user_data );
423 }
424
425
426 void GtkJumpActivate( GtkMenuItem * menuitem, gpointer user_data )
427 {
428     GtkJumpShow( GTK_WIDGET( menuitem ), NULL, user_data );
429 }
430
431
432 void GtkMessagesActivate( GtkMenuItem * menuitem, gpointer user_data )
433 {
434     GtkMessagesShow( GTK_WIDGET( menuitem ), NULL, user_data );
435 }
436
437
438 /****************************************************************************
439  * Callbacks for disc ejection
440  ****************************************************************************/
441 gboolean GtkDiscEject ( GtkWidget *widget, GdkEventButton *event,
442                         gpointer user_data )
443 {
444 #if 0 /* PLAYLIST TARASS */
445     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), (char*)user_data );
446
447     char *psz_device = NULL;
448     char *psz_parser;
449     char *psz_current = p_intf->p_vlc->p_playlist->current.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     if( psz_device == NULL )
498     {
499         return TRUE;
500     }
501
502     /* Remove what we have after @ */
503     psz_parser = psz_device;
504     for( psz_parser = psz_device ; *psz_parser ; psz_parser++ )
505     {
506         if( *psz_parser == '@' )
507         {
508             *psz_parser = '\0';
509             break;
510         }
511     }
512
513     /* If there's a stream playing, we aren't allowed to eject ! */
514     if( p_intf->p_sys->p_input == NULL )
515     {
516         msg_Dbg( p_intf, "ejecting %s", psz_device );
517
518         intf_Eject( p_intf, psz_device );
519     }
520
521     free(psz_device);
522 #endif
523     return TRUE;
524 }
525
526 void GtkEjectDiscActivate ( GtkMenuItem *menuitem, gpointer user_data )
527 {
528     GtkDiscEject( GTK_WIDGET( menuitem ), NULL, user_data );
529 }
530
531 /****************************************************************************
532  * Messages window
533  ****************************************************************************/
534
535 gboolean GtkMessagesShow( GtkWidget       *widget,
536                           GdkEventButton  *event,
537                           gpointer         user_data)
538 {
539     static GdkColor black = { 0, 0x0000, 0x0000, 0x0000 };
540     static GdkColormap *colormap;
541     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), (char*)user_data );
542
543     gtk_widget_show( p_intf->p_sys->p_messages );
544     colormap = gdk_colormap_get_system ();
545     gdk_color_alloc( colormap, &black );
546     gdk_window_set_background( p_intf->p_sys->p_messages_text->text_area,
547                                &black );
548
549     gdk_window_raise( p_intf->p_sys->p_messages->window );
550
551     gtk_text_set_point( p_intf->p_sys->p_messages_text,
552                     gtk_text_get_length( p_intf->p_sys->p_messages_text ) );
553
554     return TRUE;
555 }
556
557
558 void
559 GtkMessagesOk                          (GtkButton       *button,
560                                         gpointer         user_data)
561 {
562     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(button), (char*)user_data );
563     gtk_widget_hide( p_intf->p_sys->p_messages );
564 }
565
566
567 gboolean
568 GtkMessagesDelete                      (GtkWidget       *widget,
569                                         GdkEvent        *event,
570                                         gpointer         user_data)
571 {
572     intf_thread_t *p_intf = GetIntf( GTK_WIDGET(widget), (char*)user_data );
573     gtk_widget_hide( p_intf->p_sys->p_messages );
574     return TRUE;
575 }
576