1 /*****************************************************************************
2 * gtk_callbacks.c : Callbacks for the Gtk+ plugin.
3 *****************************************************************************
4 * Copyright (C) 2000, 2001, 2003 VideoLAN
5 * $Id: gtk_callbacks.c,v 1.16 2003/12/22 14:32:56 sam Exp $
7 * Authors: Sam Hocevar <sam@zoy.org>
8 * Stéphane Borel <stef@via.ecp.fr>
9 * Julien BLACHE <jb@technologeek.org>
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.
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.
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 *****************************************************************************/
26 /*****************************************************************************
28 *****************************************************************************/
29 #include <sys/types.h> /* off_t */
43 #include "gtk_callbacks.h"
44 #include "gtk_interface.h"
45 #include "gtk_support.h"
50 #define CDDA_MRL "cddax://"
52 #define CDDA_MRL "cdda://"
56 #define VCD_MRL "vcdx://"
58 #define VCD_MRL "vcdx://"
61 /*****************************************************************************
62 * Useful function to retrieve p_intf
63 ****************************************************************************/
64 void * E_(__GtkGetIntf)( GtkWidget * widget )
68 if( GTK_IS_MENU_ITEM( widget ) )
70 /* Look for a GTK_MENU */
71 while( widget->parent && !GTK_IS_MENU( widget ) )
73 widget = widget->parent;
76 /* Maybe this one has the data */
77 p_data = gtk_object_get_data( GTK_OBJECT( widget ), "p_intf" );
83 /* Otherwise, the parent widget has it */
84 widget = gtk_menu_get_attach_widget( GTK_MENU( widget ) );
85 p_data = gtk_object_get_data( GTK_OBJECT( widget ), "p_intf" );
92 /* We look for the top widget */
93 widget = gtk_widget_get_toplevel( GTK_WIDGET( widget ) );
94 p_data = gtk_object_get_data( GTK_OBJECT( widget ), "p_intf" );
99 /*****************************************************************************
101 *****************************************************************************/
104 * Main interface callbacks
107 #ifdef MODULE_NAME_IS_gtk
108 # define GTKEXIT GtkExit
110 # define GTKEXIT GnomeExit
113 gboolean GTKEXIT( GtkWidget *widget,
116 intf_thread_t *p_intf = GtkGetIntf( widget );
118 vlc_mutex_lock( &p_intf->change_lock );
119 p_intf->p_vlc->b_die = VLC_TRUE;
120 vlc_mutex_unlock( &p_intf->change_lock );
125 void GtkClose( GtkMenuItem *menuitem,
128 intf_thread_t *p_intf = GtkGetIntf( menuitem );
129 p_intf->b_die = VLC_TRUE;
132 gboolean GtkWindowDelete( GtkWidget *widget,
136 GTKEXIT( GTK_WIDGET( widget ), user_data );
142 gboolean GtkWindowToggle( GtkWidget *widget,
145 intf_thread_t *p_intf = GtkGetIntf( widget );
147 if( GTK_WIDGET_VISIBLE(p_intf->p_sys->p_window) )
149 gtk_widget_hide( p_intf->p_sys->p_window);
153 gtk_widget_show( p_intf->p_sys->p_window );
159 gboolean GtkFullscreen( GtkWidget *widget,
162 intf_thread_t *p_intf = GtkGetIntf( widget );
163 vout_thread_t *p_vout;
165 if( p_intf->p_sys->p_input == NULL )
170 p_vout = vlc_object_find( p_intf->p_sys->p_input,
171 VLC_OBJECT_VOUT, FIND_CHILD );
177 p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
178 vlc_object_release( p_vout );
182 void GtkWindowDrag( GtkWidget *widget,
183 GdkDragContext *drag_context,
186 GtkSelectionData *data,
191 intf_thread_t * p_intf = GtkGetIntf( widget );
192 GtkDropDataReceived( p_intf, data, info, PLAYLIST_END );
196 /****************************************************************************
198 ****************************************************************************/
200 gboolean GtkSliderRelease( GtkWidget *widget,
201 GdkEventButton *event,
204 intf_thread_t *p_intf = GtkGetIntf( widget );
206 vlc_mutex_lock( &p_intf->change_lock );
207 p_intf->p_sys->b_slider_free = VLC_TRUE;
208 vlc_mutex_unlock( &p_intf->change_lock );
214 gboolean GtkSliderPress( GtkWidget *widget,
215 GdkEventButton *event,
218 intf_thread_t *p_intf = GtkGetIntf( widget );
220 vlc_mutex_lock( &p_intf->change_lock );
221 p_intf->p_sys->b_slider_free = VLC_FALSE;
222 vlc_mutex_unlock( &p_intf->change_lock );
228 /****************************************************************************
230 ****************************************************************************/
232 void GtkTitlePrev( GtkButton * button, gpointer user_data )
234 intf_thread_t * p_intf;
235 input_area_t * p_area;
238 p_intf = GtkGetIntf( button );
239 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
240 i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_id - 1;
244 p_area = p_intf->p_sys->p_input->stream.pp_areas[i_id];
245 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
247 input_ChangeArea( p_intf->p_sys->p_input, p_area );
248 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
250 p_intf->p_sys->b_title_update = VLC_TRUE;
251 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
252 GtkSetupMenus( p_intf );
255 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
259 void GtkTitleNext( GtkButton * button, gpointer user_data )
261 intf_thread_t * p_intf;
262 input_area_t * p_area;
265 p_intf = GtkGetIntf( button );
266 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
267 i_id = p_intf->p_sys->p_input->stream.p_selected_area->i_id + 1;
269 if( i_id < p_intf->p_sys->p_input->stream.i_area_nb )
271 p_area = p_intf->p_sys->p_input->stream.pp_areas[i_id];
272 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
274 input_ChangeArea( p_intf->p_sys->p_input, p_area );
275 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
277 p_intf->p_sys->b_title_update = VLC_TRUE;
278 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
279 GtkSetupMenus( p_intf );
282 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
286 void GtkChapterPrev( GtkButton * button, gpointer user_data )
288 intf_thread_t * p_intf;
289 input_area_t * p_area;
291 p_intf = GtkGetIntf( button );
292 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
293 p_area = p_intf->p_sys->p_input->stream.p_selected_area;
295 if( p_area->i_part - 1 > 0 )
298 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
300 input_ChangeArea( p_intf->p_sys->p_input, p_area );
301 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
303 p_intf->p_sys->b_chapter_update = VLC_TRUE;
304 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
305 GtkSetupMenus( p_intf );
308 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
312 void GtkChapterNext( GtkButton * button, gpointer user_data )
314 intf_thread_t * p_intf;
315 input_area_t * p_area;
317 p_intf = GtkGetIntf( button );
318 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
319 p_area = p_intf->p_sys->p_input->stream.p_selected_area;
321 if( p_area->i_part + 1 < p_area->i_part_nb )
324 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
326 input_ChangeArea( p_intf->p_sys->p_input, p_area );
327 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
329 p_intf->p_sys->b_chapter_update = VLC_TRUE;
330 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
331 GtkSetupMenus( p_intf );
334 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
337 /****************************************************************************
339 ****************************************************************************/
341 gboolean GtkAboutShow( GtkWidget *widget,
344 intf_thread_t *p_intf = GtkGetIntf( widget );
346 if( !GTK_IS_WIDGET( p_intf->p_sys->p_about ) )
348 p_intf->p_sys->p_about = create_intf_about();
349 gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_about ),
352 gtk_widget_show( p_intf->p_sys->p_about );
353 gdk_window_raise( p_intf->p_sys->p_about->window );
358 void GtkAboutOk( GtkButton * button, gpointer user_data)
360 intf_thread_t *p_intf = GtkGetIntf( button );
362 gtk_widget_hide( p_intf->p_sys->p_about );
366 /****************************************************************************
368 ****************************************************************************/
370 gboolean GtkJumpShow( GtkWidget *widget,
373 intf_thread_t *p_intf = GtkGetIntf( widget );
375 if( !GTK_IS_WIDGET( p_intf->p_sys->p_jump ) )
377 p_intf->p_sys->p_jump = create_intf_jump();
378 gtk_object_set_data( GTK_OBJECT( p_intf->p_sys->p_jump ),
382 gtk_widget_show( p_intf->p_sys->p_jump );
383 gdk_window_raise( p_intf->p_sys->p_jump->window );
389 void GtkJumpOk( GtkButton *button,
392 intf_thread_t * p_intf = GtkGetIntf( button );
393 int i_hours, i_minutes, i_seconds;
395 if( p_intf->p_sys->p_input == NULL )
400 #define GET_VALUE( name ) \
401 gtk_spin_button_get_value_as_int( GTK_SPIN_BUTTON( gtk_object_get_data( \
402 GTK_OBJECT( p_intf->p_sys->p_jump ), name ) ) )
403 i_hours = GET_VALUE( "jump_hour_spinbutton" );
404 i_minutes = GET_VALUE( "jump_minute_spinbutton" );
405 i_seconds = GET_VALUE( "jump_second_spinbutton" );
408 input_Seek( p_intf->p_sys->p_input,
409 i_seconds + 60 * i_minutes + 3600 * i_hours,
410 INPUT_SEEK_SECONDS | INPUT_SEEK_SET );
412 gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
416 void GtkJumpCancel( GtkButton *button,
419 gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
422 /****************************************************************************
423 * Callbacks for disc ejection
424 ****************************************************************************/
425 gboolean GtkDiscEject ( GtkWidget *widget, gpointer user_data )
427 char *psz_device = NULL;
431 intf_thread_t *p_intf = GtkGetIntf( widget );
432 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
434 if( p_playlist == NULL )
439 vlc_mutex_lock( &p_playlist->object_lock );
441 if( p_playlist->i_index < 0 )
443 vlc_mutex_unlock( &p_playlist->object_lock );
444 vlc_object_release( p_playlist );
448 psz_current = p_playlist->pp_items[ p_playlist->i_index ]->psz_name;
451 * Get the active input
452 * Determine whether we can eject a media, ie it's a VCD or DVD
453 * If it's neither a VCD nor a DVD, then return
457 * Don't really know if I must lock the stuff here, we're using it read-only
460 if( psz_current != NULL )
462 if( !strncmp(psz_current, "dvd://", 4) )
464 switch( psz_current[strlen("dvd://")] )
468 psz_device = config_GetPsz( p_intf, "dvd" );
471 /* Omit the first MRL-selector characters */
472 psz_device = strdup( psz_current + strlen("dvd://" ) );
476 else if( !strncmp(psz_current, "vcd:", strlen("vcd:")) )
478 switch( psz_current[strlen("vcd:")] )
482 psz_device = config_GetPsz( p_intf, VCD_MRL );
485 /* Omit the beginning MRL-selector characters */
486 psz_device = strdup( psz_current + strlen(VCD_MRL) );
490 else if( !strncmp(psz_current, CDDA_MRL, strlen(CDDA_MRL) ) )
492 switch( psz_current[strlen(CDDA_MRL)] )
496 psz_device = config_GetPsz( p_intf, "cd-audio" );
499 /* Omit the beginning MRL-selector characters */
500 psz_device = strdup( psz_current + strlen(CDDA_MRL) );
506 psz_device = strdup( psz_current );
510 vlc_mutex_unlock( &p_playlist->object_lock );
511 vlc_object_release( p_playlist );
513 if( psz_device == NULL )
518 /* Remove what we have after @ */
519 psz_parser = psz_device;
520 for( psz_parser = psz_device ; *psz_parser ; psz_parser++ )
522 if( *psz_parser == '@' )
529 /* If there's a stream playing, we aren't allowed to eject ! */
530 if( p_intf->p_sys->p_input == NULL )
532 msg_Dbg( p_intf, "ejecting %s", psz_device );
534 intf_Eject( p_intf, psz_device );
542 /****************************************************************************
544 ****************************************************************************/
546 gboolean GtkMessagesShow( GtkWidget *widget,
549 static GdkColor black = { 0, 0x0000, 0x0000, 0x0000 };
550 static GdkColormap *colormap;
551 intf_thread_t *p_intf = GtkGetIntf( widget );
553 gtk_widget_show( p_intf->p_sys->p_messages );
554 colormap = gdk_colormap_get_system ();
555 gdk_color_alloc( colormap, &black );
556 gdk_window_set_background( p_intf->p_sys->p_messages_text->text_area,
559 gdk_window_raise( p_intf->p_sys->p_messages->window );
561 gtk_text_set_point( p_intf->p_sys->p_messages_text,
562 gtk_text_get_length( p_intf->p_sys->p_messages_text ) );
568 GtkMessagesOk (GtkButton *button,
571 intf_thread_t *p_intf = GtkGetIntf( button );
572 gtk_widget_hide( p_intf->p_sys->p_messages );
577 GtkMessagesDelete (GtkWidget *widget,
581 intf_thread_t *p_intf = GtkGetIntf( widget );
582 gtk_widget_hide( p_intf->p_sys->p_messages );
588 GtkOpenNotebookChanged (GtkNotebook *notebook,
589 GtkNotebookPage *page,
593 GtkOpenChanged( GTK_WIDGET( notebook ), user_data );
596 /****************************************************************************
598 ****************************************************************************/
599 void GtkVolumeUp ( GtkMenuItem *menuitem,
602 intf_thread_t *p_intf = GtkGetIntf( menuitem );
603 audio_volume_t i_volume;
605 aout_VolumeUp( p_intf, 1, &i_volume );
606 p_intf->p_sys->b_mute = ( i_volume == 0 ) ? 1 : 0;
610 void GtkVolumeDown ( GtkMenuItem *menuitem,
613 intf_thread_t *p_intf = GtkGetIntf( menuitem );
614 audio_volume_t i_volume;
616 aout_VolumeDown( p_intf, 1, &i_volume );
617 p_intf->p_sys->b_mute = ( i_volume == 0 ) ? 1 : 0;
621 void GtkVolumeMute ( GtkMenuItem *menuitem,
624 intf_thread_t *p_intf = GtkGetIntf( menuitem );
625 audio_volume_t i_volume;
627 aout_VolumeMute( p_intf, &i_volume );
628 p_intf->p_sys->b_mute = ( i_volume == 0 ) ? 1 : 0;
632 GtkMenubarDeinterlace ( GtkMenuItem *menuitem,
635 intf_thread_t *p_intf = GtkGetIntf( menuitem );
638 msg_Dbg( p_intf, "GtkMenubarDeinterlace" );
643 GtkPopupDeinterlace (GtkRadioMenuItem *radiomenuitem,
646 intf_thread_t *p_intf = GtkGetIntf( radiomenuitem );
649 msg_Dbg( p_intf, "GtkPopupDeinterlace" );