1 /*****************************************************************************
2 * gtk_callbacks.c : Callbacks for the Gtk+ plugin.
3 *****************************************************************************
4 * Copyright (C) 2000, 2001, 2003 VideoLAN
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 var_SetInteger( p_intf->p_sys->p_input, PLAYING_S );
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 var_SetInteger( p_intf->p_sys->p_input, PLAYING_S );
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 var_SetInteger( p_intf->p_sys->p_input, PLAYING_S );
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 var_SetInteger( p_intf->p_sys->p_input, PLAYING_S );
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 var_SetTime( p_intf->p_sys->p_input, "time",
409 (int64_t)(i_seconds+60*i_minutes+3600*i_hours)*I64C(1000000));
411 gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
415 void GtkJumpCancel( GtkButton *button,
418 gtk_widget_hide( gtk_widget_get_toplevel( GTK_WIDGET (button) ) );
421 /****************************************************************************
422 * Callbacks for disc ejection
423 ****************************************************************************/
424 gboolean GtkDiscEject ( GtkWidget *widget, gpointer user_data )
426 char *psz_device = NULL;
430 intf_thread_t *p_intf = GtkGetIntf( widget );
431 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
433 if( p_playlist == NULL )
438 vlc_mutex_lock( &p_playlist->object_lock );
440 if( p_playlist->i_index < 0 )
442 vlc_mutex_unlock( &p_playlist->object_lock );
443 vlc_object_release( p_playlist );
447 psz_current = p_playlist->pp_items[ p_playlist->i_index ]->input.psz_name;
450 * Get the active input
451 * Determine whether we can eject a media, ie it's a VCD or DVD
452 * If it's neither a VCD nor a DVD, then return
456 * Don't really know if I must lock the stuff here, we're using it read-only
459 if( psz_current != NULL )
461 if( !strncmp(psz_current, "dvd://", 4) )
463 switch( psz_current[strlen("dvd://")] )
467 psz_device = config_GetPsz( p_intf, "dvd" );
470 /* Omit the first MRL-selector characters */
471 psz_device = strdup( psz_current + strlen("dvd://" ) );
475 else if( !strncmp(psz_current, "vcd:", strlen("vcd:")) )
477 switch( psz_current[strlen("vcd:")] )
481 psz_device = config_GetPsz( p_intf, VCD_MRL );
484 /* Omit the beginning MRL-selector characters */
485 psz_device = strdup( psz_current + strlen(VCD_MRL) );
489 else if( !strncmp(psz_current, CDDA_MRL, strlen(CDDA_MRL) ) )
491 switch( psz_current[strlen(CDDA_MRL)] )
495 psz_device = config_GetPsz( p_intf, "cd-audio" );
498 /* Omit the beginning MRL-selector characters */
499 psz_device = strdup( psz_current + strlen(CDDA_MRL) );
505 psz_device = strdup( psz_current );
509 vlc_mutex_unlock( &p_playlist->object_lock );
510 vlc_object_release( p_playlist );
512 if( psz_device == NULL )
517 /* Remove what we have after @ */
518 psz_parser = psz_device;
519 for( psz_parser = psz_device ; *psz_parser ; psz_parser++ )
521 if( *psz_parser == '@' )
528 /* If there's a stream playing, we aren't allowed to eject ! */
529 if( p_intf->p_sys->p_input == NULL )
531 msg_Dbg( p_intf, "ejecting %s", psz_device );
533 intf_Eject( p_intf, psz_device );
541 /****************************************************************************
543 ****************************************************************************/
545 gboolean GtkMessagesShow( GtkWidget *widget,
548 static GdkColor black = { 0, 0x0000, 0x0000, 0x0000 };
549 static GdkColormap *colormap;
550 intf_thread_t *p_intf = GtkGetIntf( widget );
552 gtk_widget_show( p_intf->p_sys->p_messages );
553 colormap = gdk_colormap_get_system ();
554 gdk_color_alloc( colormap, &black );
555 gdk_window_set_background( p_intf->p_sys->p_messages_text->text_area,
558 gdk_window_raise( p_intf->p_sys->p_messages->window );
560 gtk_text_set_point( p_intf->p_sys->p_messages_text,
561 gtk_text_get_length( p_intf->p_sys->p_messages_text ) );
567 GtkMessagesOk (GtkButton *button,
570 intf_thread_t *p_intf = GtkGetIntf( button );
571 gtk_widget_hide( p_intf->p_sys->p_messages );
576 GtkMessagesDelete (GtkWidget *widget,
580 intf_thread_t *p_intf = GtkGetIntf( widget );
581 gtk_widget_hide( p_intf->p_sys->p_messages );
587 GtkOpenNotebookChanged (GtkNotebook *notebook,
588 GtkNotebookPage *page,
592 GtkOpenChanged( GTK_WIDGET( notebook ), user_data );
595 /****************************************************************************
597 ****************************************************************************/
598 void GtkVolumeUp ( GtkMenuItem *menuitem,
601 intf_thread_t *p_intf = GtkGetIntf( menuitem );
602 audio_volume_t i_volume;
604 aout_VolumeUp( p_intf, 1, &i_volume );
605 p_intf->p_sys->b_mute = ( i_volume == 0 ) ? 1 : 0;
609 void GtkVolumeDown ( GtkMenuItem *menuitem,
612 intf_thread_t *p_intf = GtkGetIntf( menuitem );
613 audio_volume_t i_volume;
615 aout_VolumeDown( p_intf, 1, &i_volume );
616 p_intf->p_sys->b_mute = ( i_volume == 0 ) ? 1 : 0;
620 void GtkVolumeMute ( GtkMenuItem *menuitem,
623 intf_thread_t *p_intf = GtkGetIntf( menuitem );
624 audio_volume_t i_volume;
626 aout_VolumeMute( p_intf, &i_volume );
627 p_intf->p_sys->b_mute = ( i_volume == 0 ) ? 1 : 0;
631 GtkMenubarDeinterlace ( GtkMenuItem *menuitem,
634 intf_thread_t *p_intf = GtkGetIntf( menuitem );
637 msg_Dbg( p_intf, "GtkMenubarDeinterlace" );
642 GtkPopupDeinterlace (GtkRadioMenuItem *radiomenuitem,
645 intf_thread_t *p_intf = GtkGetIntf( radiomenuitem );
648 msg_Dbg( p_intf, "GtkPopupDeinterlace" );