1 /*****************************************************************************
2 * menu.c : functions to handle menu items.
3 *****************************************************************************
4 * Copyright (C) 2000, 2001 VideoLAN
5 * $Id: menu.c,v 1.8 2003/02/05 22:11:52 sam Exp $
7 * Authors: Samuel Hocevar <sam@zoy.org>
8 * Stéphane Borel <stef@via.ecp.fr>
9 * Johan Bilien <jobi@via.ecp.fr>
10 * Laurent Aimar <fenrir@via.ecp.fr>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
25 *****************************************************************************/
27 /*****************************************************************************
29 *****************************************************************************/
30 #include <sys/types.h> /* off_t */
38 #ifdef MODULE_NAME_IS_gnome
46 #include "gtk_callbacks.h"
47 #include "gtk_interface.h"
48 #include "gtk_support.h"
56 static gint GtkLanguageMenus( gpointer , GtkWidget *, es_descriptor_t *, gint,
57 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) );
59 void GtkMenubarAudioToggle ( GtkCheckMenuItem *, gpointer );
60 void GtkPopupAudioToggle ( GtkCheckMenuItem *, gpointer );
61 void GtkMenubarSubtitleToggle( GtkCheckMenuItem *, gpointer );
62 void GtkPopupSubtitleToggle ( GtkCheckMenuItem *, gpointer );
63 static gint GtkTitleMenu( gpointer, GtkWidget *,
64 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) );
65 static gint GtkRadioMenu( intf_thread_t *, GtkWidget *, GSList *,
66 char *, int, int, int,
67 void( *pf_toggle )( GtkCheckMenuItem *, gpointer ) );
69 static void GtkMenubarDeinterlaceToggle( GtkCheckMenuItem * menuitem, gpointer user_data );
70 static void GtkPopupDeinterlaceToggle( GtkCheckMenuItem * menuitem, gpointer user_data );
71 static gint GtkDeinterlaceMenus( gpointer p_data,
73 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) );
75 gint GtkSetupMenus( intf_thread_t * p_intf );
77 /****************************************************************************
78 * Gtk*Toggle: callbacks to toggle the value of a checkmenuitem
79 ****************************************************************************
80 * We need separate functions for menubar and popup here since we can't use
81 * user_data to transmit intf_* and we need to refresh the other menu.
82 ****************************************************************************/
84 #define GTKLANGTOGGLE( window, menu, type, callback, b_update ) \
85 intf_thread_t * p_intf; \
87 es_descriptor_t * p_es; \
89 p_intf = GtkGetIntf( menuitem ); \
91 if( !p_intf->p_sys->b_update ) \
93 p_menu = GTK_WIDGET( gtk_object_get_data( \
94 GTK_OBJECT( p_intf->p_sys->window ), (menu) ) ); \
95 p_es = (es_descriptor_t*)user_data; \
97 input_ToggleES( p_intf->p_sys->p_input, \
98 p_es, menuitem->active ); \
100 p_intf->p_sys->b_update = menuitem->active; \
102 if( p_intf->p_sys->b_update ) \
104 GtkLanguageMenus( p_intf, p_menu, p_es, type, callback ); \
107 p_intf->p_sys->b_update = VLC_FALSE; \
114 void GtkMenubarAudioToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
116 GTKLANGTOGGLE( p_popup, "popup_language", AUDIO_ES,
117 GtkPopupAudioToggle, b_audio_update );
120 void GtkPopupAudioToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
122 GTKLANGTOGGLE( p_window, "menubar_audio", AUDIO_ES,
123 GtkMenubarAudioToggle, b_audio_update );
130 void GtkMenubarSubtitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
132 GTKLANGTOGGLE( p_popup, "popup_subpictures", SPU_ES,
133 GtkPopupSubtitleToggle, b_spu_update );
136 void GtkPopupSubtitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
138 GTKLANGTOGGLE( p_window, "menubar_subpictures", SPU_ES,
139 GtkMenubarSubtitleToggle, b_spu_update );
148 void GtkPopupNavigationToggle( GtkCheckMenuItem * menuitem,
151 intf_thread_t * p_intf = GtkGetIntf( menuitem );
153 if( menuitem->active &&
154 !p_intf->p_sys->b_title_update &&
155 !p_intf->p_sys->b_chapter_update )
157 input_area_t *p_area;
159 guint i_title = DATA2TITLE( user_data );
160 guint i_chapter = DATA2CHAPTER( user_data );
162 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
163 p_area = p_intf->p_sys->p_input->stream.p_selected_area;
165 i_title = __MIN( i_title,
166 p_intf->p_sys->p_input->stream.i_area_nb - 1 );
167 i_title = __MAX( i_title, 1 );
169 if( p_area != p_intf->p_sys->p_input->stream.pp_areas[i_title] )
171 p_area = p_intf->p_sys->p_input->stream.pp_areas[i_title];
172 p_intf->p_sys->b_title_update = VLC_TRUE;
175 i_chapter = __MIN( i_chapter, p_area->i_part_nb - 1 );
176 i_chapter = __MAX( i_chapter, 1 );
177 p_area->i_part = i_chapter;
179 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
181 input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );
183 p_intf->p_sys->b_chapter_update = VLC_TRUE;
184 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
185 GtkSetupMenus( p_intf );
186 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
188 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
195 #define GTKPROGRAMTOGGLE( ) \
196 intf_thread_t * p_intf = GtkGetIntf( menuitem ); \
198 if( menuitem->active && !p_intf->p_sys->b_program_update ) \
200 int i_program_id = (ptrdiff_t)user_data; \
202 input_ChangeProgram( p_intf->p_sys->p_input, i_program_id ); \
204 p_intf->p_sys->b_program_update = VLC_TRUE; \
206 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock ); \
207 GtkSetupMenus( p_intf ); \
208 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock ); \
210 p_intf->p_sys->b_program_update = VLC_FALSE; \
212 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY ); \
215 void GtkMenubarProgramToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
220 void GtkPopupProgramToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
229 void GtkMenubarTitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
231 intf_thread_t * p_intf = GtkGetIntf( menuitem );
233 if( menuitem->active && !p_intf->p_sys->b_title_update )
235 guint i_title = (ptrdiff_t)user_data;
237 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
238 i_title = __MIN( i_title,
239 p_intf->p_sys->p_input->stream.i_area_nb - 1 );
240 i_title = __MAX( i_title, 1 );
241 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
243 input_ChangeArea( p_intf->p_sys->p_input,
244 p_intf->p_sys->p_input->stream.pp_areas[i_title] );
246 p_intf->p_sys->b_title_update = VLC_TRUE;
247 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
248 GtkSetupMenus( p_intf );
249 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
250 p_intf->p_sys->b_title_update = VLC_FALSE;
252 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
260 void GtkMenubarChapterToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
262 intf_thread_t * p_intf;
263 input_area_t * p_area;
265 GtkWidget * p_popup_menu;
267 p_intf = GtkGetIntf( menuitem );
268 p_area = p_intf->p_sys->p_input->stream.p_selected_area;
269 i_chapter = (ptrdiff_t)user_data;
271 if( menuitem->active && !p_intf->p_sys->b_chapter_update )
273 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
274 i_chapter = __MIN( i_chapter, p_area->i_part_nb - 1 );
275 i_chapter = __MAX( i_chapter, 1 );
276 p_area->i_part = i_chapter;
277 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
279 input_ChangeArea( p_intf->p_sys->p_input, (input_area_t*)p_area );
281 p_intf->p_sys->b_chapter_update = VLC_TRUE;
282 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
283 p_intf->p_sys->p_popup ), "popup_navigation" ) );
285 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
286 GtkTitleMenu( p_intf, p_popup_menu, GtkPopupNavigationToggle );
287 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
289 p_intf->p_sys->b_chapter_update = VLC_FALSE;
291 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
296 static void GtkPopupObjectToggle( GtkCheckMenuItem * menuitem, gpointer user_data,
297 int i_object_type, char *psz_variable )
299 intf_thread_t *p_intf = GtkGetIntf( menuitem );
302 p_label = GTK_LABEL( ( GTK_BIN( menuitem )->child ) );
304 if( menuitem->active && !p_intf->p_sys->b_aout_update && !p_intf->p_sys->b_vout_update )
306 vlc_object_t * p_obj;
308 p_obj = (vlc_object_t *)vlc_object_find( p_intf, i_object_type,
314 gtk_label_get( p_label, &val.psz_string );
316 if( var_Set( p_obj, psz_variable, val ) < 0 )
318 msg_Warn( p_obj, "cannot set variable (%s)", val.psz_string );
320 vlc_object_release( p_obj );
324 static void GtkPopupAoutChannelsToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
326 GtkPopupObjectToggle( menuitem, user_data, VLC_OBJECT_AOUT, "audio-channels" );
329 static void GtkPopupAoutDeviceToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
331 GtkPopupObjectToggle( menuitem, user_data, VLC_OBJECT_AOUT, "audio-device" );
335 static void GtkPopupVoutDeviceToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
337 GtkPopupObjectToggle( menuitem, user_data, VLC_OBJECT_VOUT, "video-device" );
341 static void GtkDeinterlaceUpdate( intf_thread_t *p_intf, char *psz_mode )
346 psz_filter = config_GetPsz( p_intf, "filter" );
348 if( !strcmp( psz_mode, "None" ) )
350 config_PutPsz( p_intf, "filter", "" );
354 if( !psz_filter || !*psz_filter )
356 config_PutPsz( p_intf, "filter", "deinterlace" );
360 if( strstr( psz_filter, "deinterlace" ) == NULL )
362 psz_filter = realloc( psz_filter, strlen( psz_filter ) + 20 );
363 strcat( psz_filter, ",deinterlace" );
365 config_PutPsz( p_intf, "filter", psz_filter );
372 /* now restart all video stream */
373 if( p_intf->p_sys->p_input )
375 vout_thread_t *p_vout;
376 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
378 /* Warn the vout we are about to change the filter chain */
379 p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT,
383 p_vout->b_filter_change = VLC_TRUE;
384 vlc_object_release( p_vout );
387 #define ES p_intf->p_sys->p_input->stream.pp_es[i]
388 /* create a set of language buttons and append them to the container */
389 for( i = 0 ; i < p_intf->p_sys->p_input->stream.i_es_number ; i++ )
391 if( ( ES->i_cat == VIDEO_ES ) &&
392 ES->p_decoder_fifo != NULL )
394 input_UnselectES( p_intf->p_sys->p_input, ES );
395 input_SelectES( p_intf->p_sys->p_input, ES );
399 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
402 if( strcmp( psz_mode, "None" ) )
404 vout_thread_t *p_vout;
405 p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT,
411 val.psz_string = psz_mode;
412 if( var_Set( p_vout, "deinterlace-mode", val ) != VLC_SUCCESS )
413 config_PutPsz( p_intf, "deinterlace-mode", psz_mode );
415 vlc_object_release( p_vout );
418 config_PutPsz( p_intf, "deinterlace-mode", psz_mode );
423 static void GtkMenubarDeinterlaceToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
425 intf_thread_t *p_intf = GtkGetIntf( menuitem );
428 GtkWidget *p_popup_menu;
430 p_label = GTK_LABEL( ( GTK_BIN( menuitem )->child ) );
432 if( !p_intf->p_sys->b_deinterlace_update && menuitem->active )
434 gtk_label_get( p_label, &psz_mode );
435 GtkDeinterlaceUpdate( p_intf, psz_mode );
437 p_intf->p_sys->b_deinterlace_update = VLC_TRUE;
439 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
440 p_intf->p_sys->p_popup ), "popup_deinterlace" ) );
442 GtkDeinterlaceMenus( p_intf, p_popup_menu, GtkPopupDeinterlaceToggle );
444 p_intf->p_sys->b_deinterlace_update = VLC_FALSE;
449 static void GtkPopupDeinterlaceToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
451 intf_thread_t *p_intf = GtkGetIntf( menuitem );
454 GtkWidget *p_menubar_menu;
456 p_label = GTK_LABEL( ( GTK_BIN( menuitem )->child ) );
458 if( !p_intf->p_sys->b_deinterlace_update && menuitem->active )
460 gtk_label_get( p_label, &psz_mode );
461 GtkDeinterlaceUpdate( p_intf, psz_mode );
463 p_intf->p_sys->b_deinterlace_update = VLC_TRUE;
465 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
466 p_intf->p_sys->p_window ), "menubar_deinterlace" ) );
468 GtkDeinterlaceMenus( p_intf, p_menubar_menu, GtkMenubarDeinterlaceToggle );
470 p_intf->p_sys->b_deinterlace_update = VLC_FALSE;
474 /****************************************************************************
475 * Functions to generate menus
476 ****************************************************************************/
478 /*****************************************************************************
479 * GtkRadioMenu: update interactive menus of the interface
480 *****************************************************************************
481 * Sets up menus with information from input
482 * Warning: since this function is designed to be called by management
483 * function, the interface lock has to be taken
484 *****************************************************************************/
485 static gint GtkRadioMenu( intf_thread_t * p_intf,
486 GtkWidget * p_root, GSList * p_menu_group,
487 char * psz_item_name,
488 int i_start, int i_end, int i_selected,
489 void( *pf_toggle )( GtkCheckMenuItem *, gpointer ) )
491 char psz_name[ GTK_MENU_LABEL_SIZE ];
493 GtkWidget * p_submenu;
494 GtkWidget * p_item_group;
496 GtkWidget * p_item_selected;
500 /* temporary hack to avoid blank menu when an open menu is removed */
501 if( GTK_MENU_ITEM(p_root)->submenu != NULL )
503 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
505 /* removes previous menu */
506 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
507 gtk_widget_set_sensitive( p_root, FALSE );
511 p_item_selected = NULL;
512 p_group = p_menu_group;
514 p_menu = gtk_menu_new();
515 gtk_object_set_data( GTK_OBJECT( p_menu ), "p_intf", p_intf );
517 for( i_item = i_start ; i_item <= i_end ; i_item++ )
519 /* we group chapters in packets of ten for small screens */
520 if( ( i_item % 10 == i_start ) && ( i_end > i_start + 20 ) )
522 if( i_item != i_start )
524 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_item_group ),
526 gtk_menu_append( GTK_MENU( p_menu ), p_item_group );
529 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
530 "%ss %d to %d", psz_item_name, i_item, i_item + 9 );
531 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
532 p_item_group = gtk_menu_item_new_with_label( psz_name );
533 gtk_widget_show( p_item_group );
534 p_submenu = gtk_menu_new();
535 gtk_object_set_data( GTK_OBJECT( p_submenu ), "p_intf", p_intf );
538 snprintf( psz_name, GTK_MENU_LABEL_SIZE, "%s %d",
539 psz_item_name, i_item );
540 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
542 p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
543 p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
545 if( i_selected == i_item )
547 p_item_selected = p_item;
550 gtk_widget_show( p_item );
552 /* setup signal hanling */
553 gtk_signal_connect( GTK_OBJECT( p_item ),
555 GTK_SIGNAL_FUNC( pf_toggle ),
556 (gpointer)((long)(i_item)) );
558 if( i_end > i_start + 20 )
560 gtk_menu_append( GTK_MENU( p_submenu ), p_item );
564 gtk_menu_append( GTK_MENU( p_menu ), p_item );
568 if( i_end > i_start + 20 )
570 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_item_group ), p_submenu );
571 gtk_menu_append( GTK_MENU( p_menu ), p_item_group );
574 /* link the new menu to the title menu item */
575 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
577 /* toggle currently selected chapter
578 * We have to release the lock since input_ToggleES needs it */
579 if( p_item_selected != NULL )
581 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_selected ),
585 /* be sure that menu is sensitive, if there are several items */
586 if( i_end > i_start )
588 gtk_widget_set_sensitive( p_root, TRUE );
594 /*****************************************************************************
595 * GtkProgramMenu: update the programs menu of the interface
596 *****************************************************************************
597 * Builds the program menu according to what have been found in the PAT
598 * by the input. Usefull for multi-programs streams such as DVB ones.
599 *****************************************************************************/
600 static gint GtkProgramMenu( gpointer p_data,
602 pgrm_descriptor_t * p_pgrm,
603 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
605 intf_thread_t * p_intf;
608 GtkWidget * p_item_active;
610 char psz_name[ GTK_MENU_LABEL_SIZE ];
614 p_intf = (intf_thread_t *)p_data;
616 /* temporary hack to avoid blank menu when an open menu is removed */
617 if( GTK_MENU_ITEM(p_root)->submenu != NULL )
619 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
621 /* removes previous menu */
622 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
623 gtk_widget_set_sensitive( p_root, FALSE );
628 p_menu = gtk_menu_new();
629 gtk_object_set_data( GTK_OBJECT( p_menu ), "p_intf", p_intf );
631 p_item_active = NULL;
633 /* create a set of program buttons and append them to the container */
634 for( i = 0 ; i < p_intf->p_sys->p_input->stream.i_pgrm_number ; i++ )
636 snprintf( psz_name, GTK_MENU_LABEL_SIZE, "id %d",
637 p_intf->p_sys->p_input->stream.pp_programs[i]->i_number );
638 psz_name[GTK_MENU_LABEL_SIZE-1] = '\0';
640 p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
642 gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
644 if( p_pgrm == p_intf->p_sys->p_input->stream.pp_programs[i] )
646 /* don't lose p_item when we append into menu */
647 p_item_active = p_item;
650 gtk_widget_show( p_item );
652 /* setup signal hanling */
653 gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
654 GTK_SIGNAL_FUNC( pf_toggle ),
655 (gpointer)(ptrdiff_t)( p_intf->p_sys->p_input->
656 stream.pp_programs[i]->i_number ) );
658 gtk_menu_append( GTK_MENU( p_menu ), p_item );
661 /* link the new menu to the menubar item */
662 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
664 /* activation will call signals so we can only do it
665 * when submenu is attached to menu - to get intf_window
666 * We have to release the lock since input_ToggleES needs it */
667 if( p_item_active != NULL )
669 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
673 /* be sure that menu is sensitive if more than 1 program */
674 if( p_intf->p_sys->p_input->stream.i_pgrm_number > 1 )
676 gtk_widget_set_sensitive( p_root, TRUE );
682 /*****************************************************************************
683 * GtkLanguageMenus: update interactive menus of the interface
684 *****************************************************************************
685 * Sets up menus with information from input:
688 * Warning: since this function is designed to be called by management
689 * function, the interface lock has to be taken
690 *****************************************************************************/
691 static gint GtkLanguageMenus( gpointer p_data,
693 es_descriptor_t * p_es,
695 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
697 intf_thread_t * p_intf;
699 GtkWidget * p_separator;
701 GtkWidget * p_item_active;
703 char psz_name[ GTK_MENU_LABEL_SIZE ];
707 p_intf = (intf_thread_t *)p_data;
709 /* temporary hack to avoid blank menu when an open menu is removed */
710 if( GTK_MENU_ITEM(p_root)->submenu != NULL )
712 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
714 /* removes previous menu */
715 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
716 gtk_widget_set_sensitive( p_root, FALSE );
721 p_menu = gtk_menu_new();
722 gtk_object_set_data( GTK_OBJECT( p_menu ), "p_intf", p_intf );
724 /* special case for "off" item */
725 snprintf( psz_name, GTK_MENU_LABEL_SIZE, _("None") );
726 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
728 p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
729 p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
731 gtk_widget_show( p_item );
733 /* signal hanling for off */
734 gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
735 GTK_SIGNAL_FUNC ( pf_toggle ), NULL );
737 gtk_menu_append( GTK_MENU( p_menu ), p_item );
739 p_separator = gtk_menu_item_new();
740 gtk_widget_set_sensitive( p_separator, FALSE );
741 gtk_widget_show( p_separator );
742 gtk_menu_append( GTK_MENU( p_menu ), p_separator );
744 p_item_active = NULL;
747 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
749 #define ES p_intf->p_sys->p_input->stream.pp_es[i]
750 /* create a set of language buttons and append them to the container */
751 for( i = 0 ; i < p_intf->p_sys->p_input->stream.i_es_number ; i++ )
753 if( ( ES->i_cat == i_cat ) &&
756 p_intf->p_sys->p_input->stream.p_selected_program ) )
760 p_intf->p_sys->p_input->stream.pp_es[i]->psz_desc );
761 if( psz_name[0] == '\0' )
763 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
764 "Language %d", i_item );
765 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
768 p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
770 gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
772 if( p_es == p_intf->p_sys->p_input->stream.pp_es[i] )
774 /* don't lose p_item when we append into menu */
775 p_item_active = p_item;
778 gtk_widget_show( p_item );
780 /* setup signal hanling */
781 gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
782 GTK_SIGNAL_FUNC( pf_toggle ),
783 (gpointer)( p_intf->p_sys->p_input->stream.pp_es[i] ) );
785 gtk_menu_append( GTK_MENU( p_menu ), p_item );
789 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
791 /* link the new menu to the menubar item */
792 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
794 /* acitvation will call signals so we can only do it
795 * when submenu is attached to menu - to get intf_window
796 * We have to release the lock since input_ToggleES needs it */
797 if( p_item_active != NULL )
799 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
803 /* be sure that menu is sensitive if non empty */
806 gtk_widget_set_sensitive( p_root, TRUE );
812 /*****************************************************************************
813 * GtkTitleMenu: sets menus for titles and chapters selection
814 *****************************************************************************
815 * Generates two types of menus:
816 * -simple list of titles
817 * -cascaded lists of chapters for each title
818 *****************************************************************************/
819 static gint GtkTitleMenu( gpointer p_data,
820 GtkWidget * p_navigation,
821 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
823 intf_thread_t * p_intf;
824 char psz_name[ GTK_MENU_LABEL_SIZE ];
825 GtkWidget * p_title_menu;
826 GtkWidget * p_title_submenu;
827 GtkWidget * p_title_item;
828 GtkWidget * p_item_active;
829 GtkWidget * p_chapter_menu;
830 GtkWidget * p_chapter_submenu;
831 GtkWidget * p_title_menu_item;
832 GtkWidget * p_chapter_menu_item;
834 GSList * p_title_group;
835 GSList * p_chapter_group;
842 p_intf = (intf_thread_t*)p_data;
844 /* temporary hack to avoid blank menu when an open menu is removed */
845 if( GTK_MENU_ITEM(p_navigation)->submenu != NULL )
847 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_navigation)->submenu ) );
849 /* removes previous menu */
850 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_navigation ) );
851 gtk_widget_set_sensitive( p_navigation, FALSE );
853 p_title_menu = gtk_menu_new();
854 p_title_group = NULL;
855 p_title_submenu = NULL;
856 p_title_menu_item = NULL;
857 p_chapter_group = NULL;
858 p_chapter_submenu = NULL;
859 p_chapter_menu_item = NULL;
860 p_item_active = NULL;
861 i_title_nb = p_intf->p_sys->p_input->stream.i_area_nb - 1;
863 gtk_object_set_data( GTK_OBJECT( p_title_menu ), "p_intf", p_intf );
866 for( i_title = 1 ; i_title <= i_title_nb ; i_title++ )
868 /* we group titles in packets of ten for small screens */
869 if( ( i_title % 10 == 1 ) && ( i_title_nb > 20 ) )
873 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_menu_item ),
875 gtk_menu_append( GTK_MENU( p_title_menu ), p_title_menu_item );
878 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
879 "%d - %d", i_title, i_title + 9 );
880 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
881 p_title_menu_item = gtk_menu_item_new_with_label( psz_name );
882 gtk_widget_show( p_title_menu_item );
883 p_title_submenu = gtk_menu_new();
884 gtk_object_set_data( GTK_OBJECT( p_title_submenu ),
888 snprintf( psz_name, GTK_MENU_LABEL_SIZE, _("Title %d (%d)"), i_title,
889 p_intf->p_sys->p_input->stream.pp_areas[i_title]->i_part_nb - 1);
890 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
892 if( pf_toggle == on_menubar_title_toggle )
894 p_title_item = gtk_radio_menu_item_new_with_label( p_title_group,
897 gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_title_item ) );
899 if( p_intf->p_sys->p_input->stream.pp_areas[i_title] ==
900 p_intf->p_sys->p_input->stream.p_selected_area )
902 p_item_active = p_title_item;
905 /* setup signal hanling */
906 gtk_signal_connect( GTK_OBJECT( p_title_item ),
908 GTK_SIGNAL_FUNC( pf_toggle ),
909 (gpointer)(p_intf->p_sys->p_input->stream.pp_areas[i_title]) );
911 if( p_intf->p_sys->p_input->stream.i_area_nb > 1 )
913 /* be sure that menu is sensitive */
914 gtk_widget_set_sensitive( p_navigation, TRUE );
920 p_title_item = gtk_menu_item_new_with_label( psz_name );
923 p_chapter_menu = gtk_menu_new();
924 gtk_object_set_data( GTK_OBJECT( p_chapter_menu ),
927 p_intf->p_sys->p_input->stream.pp_areas[i_title]->i_part_nb - 1;
929 for( i_chapter = 1 ; i_chapter <= i_chapter_nb ; i_chapter++ )
931 /* we group chapters in packets of ten for small screens */
932 if( ( i_chapter % 10 == 1 ) && ( i_chapter_nb > 20 ) )
936 gtk_menu_item_set_submenu(
937 GTK_MENU_ITEM( p_chapter_menu_item ),
939 gtk_menu_append( GTK_MENU( p_chapter_menu ),
940 p_chapter_menu_item );
943 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
944 "%d - %d", i_chapter, i_chapter + 9 );
945 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
946 p_chapter_menu_item =
947 gtk_menu_item_new_with_label( psz_name );
948 gtk_widget_show( p_chapter_menu_item );
949 p_chapter_submenu = gtk_menu_new();
950 gtk_object_set_data( GTK_OBJECT( p_chapter_submenu ),
954 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
955 _("Chapter %d"), i_chapter );
956 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
958 p_item = gtk_radio_menu_item_new_with_label(
959 p_chapter_group, psz_name );
960 p_chapter_group = gtk_radio_menu_item_group(
961 GTK_RADIO_MENU_ITEM( p_item ) );
962 gtk_widget_show( p_item );
964 #define p_area p_intf->p_sys->p_input->stream.pp_areas[i_title]
966 p_intf->p_sys->p_input->stream.p_selected_area ) &&
967 ( p_area->i_part == i_chapter ) )
969 p_item_active = p_item;
973 /* setup signal hanling */
974 gtk_signal_connect( GTK_OBJECT( p_item ),
976 GTK_SIGNAL_FUNC( pf_toggle ),
977 (gpointer)POS2DATA( i_title, i_chapter ) );
979 if( i_chapter_nb > 20 )
981 gtk_menu_append( GTK_MENU( p_chapter_submenu ), p_item );
985 gtk_menu_append( GTK_MENU( p_chapter_menu ), p_item );
989 if( i_chapter_nb > 20 )
991 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_chapter_menu_item ),
993 gtk_menu_append( GTK_MENU( p_chapter_menu ),
994 p_chapter_menu_item );
997 /* link the new menu to the title menu item */
998 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_item ),
1001 if( p_intf->p_sys->p_input->stream.pp_areas[i_title]->i_part_nb > 1 )
1003 /* be sure that menu is sensitive */
1004 gtk_widget_set_sensitive( p_navigation, TRUE );
1007 GtkRadioMenu( p_intf, p_title_item, p_chapter_group, _("Chapter"),
1008 p_intf->p_sys->p_input->stream.pp_areas[i_title]->i_part_nb - 1,
1010 p_intf->p_sys->p_input->stream.p_selected_area->i_part +
1011 p_intf->p_sys->p_input->stream.p_selected_area->i_id *100,
1016 gtk_widget_show( p_title_item );
1018 if( i_title_nb > 20 )
1020 gtk_menu_append( GTK_MENU( p_title_submenu ), p_title_item );
1024 gtk_menu_append( GTK_MENU( p_title_menu ), p_title_item );
1028 if( i_title_nb > 20 )
1030 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_menu_item ),
1032 gtk_menu_append( GTK_MENU( p_title_menu ), p_title_menu_item );
1035 /* be sure that menu is sensitive */
1036 gtk_widget_set_sensitive( p_title_menu, TRUE );
1038 /* link the new menu to the menubar item */
1039 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_navigation ), p_title_menu );
1041 /* Default selected chapter
1042 * We have to release the lock since input_ToggleES needs it */
1043 if( p_item_active != NULL )
1045 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
1049 if( p_intf->p_sys->p_input->stream.i_area_nb > 1 )
1051 /* be sure that menu is sensitive */
1052 gtk_widget_set_sensitive( p_navigation, TRUE );
1059 /*****************************************************************************
1061 *****************************************************************************
1063 *****************************************************************************/
1064 static gint GtkSetupVarMenu( intf_thread_t * p_intf,
1065 vlc_object_t * p_object,
1067 char * psz_variable,
1068 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
1073 GSList * p_group = NULL;
1075 GtkWidget * p_item_active = NULL;
1079 /* temporary hack to avoid blank menu when an open menu is removed */
1080 if( GTK_MENU_ITEM(p_root)->submenu != NULL )
1082 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
1084 /* removes previous menu */
1085 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
1086 gtk_widget_set_sensitive( p_root, FALSE );
1088 /* get the current value */
1089 if( var_Get( p_object, psz_variable, &val ) < 0 )
1093 psz_value = val.psz_string;
1095 if( var_Change( p_object, psz_variable, VLC_VAR_GETLIST, &val ) < 0 )
1101 /* menu container */
1102 p_menu = gtk_menu_new();
1103 gtk_object_set_data( GTK_OBJECT( p_menu ), "p_intf", p_intf );
1105 for( i_item = 0; i_item < val.p_list->i_count; i_item++ )
1107 p_item = gtk_radio_menu_item_new_with_label( p_group,
1108 val.p_list->p_values[i_item].psz_string );
1109 p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
1111 if( !strcmp( psz_value, val.p_list->p_values[i_item].psz_string ) )
1113 p_item_active = p_item;
1116 gtk_widget_show( p_item );
1118 /* signal hanling for off */
1119 gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
1120 GTK_SIGNAL_FUNC ( pf_toggle ), NULL );
1122 gtk_menu_append( GTK_MENU( p_menu ), p_item );
1125 /* link the new menu to the menubar item */
1126 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
1130 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (p_item_active), TRUE);
1133 if( val.p_list->i_count > 0 )
1135 gtk_widget_set_sensitive( p_root, TRUE );
1138 /* clean up everything */
1139 var_Change( p_object, psz_variable, VLC_VAR_FREELIST, &val );
1144 /*****************************************************************************
1145 * GtkDeinterlaceMenus: update interactive menus of the interface
1146 *****************************************************************************
1147 *****************************************************************************/
1148 static gint GtkDeinterlaceMenus( gpointer p_data,
1150 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
1152 intf_thread_t * p_intf;
1154 GtkWidget * p_separator;
1156 GtkWidget * p_item_active;
1160 char *ppsz_deinterlace_mode[] = { "discard", "blend", "mean", "bob", "linear", NULL };
1161 char *psz_deinterlace_option;
1164 p_intf = (intf_thread_t *)p_data;
1166 /* temporary hack to avoid blank menu when an open menu is removed */
1167 if( GTK_MENU_ITEM(p_root)->submenu != NULL )
1169 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
1171 /* removes previous menu */
1172 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
1173 gtk_widget_set_sensitive( p_root, FALSE );
1177 /* menu container */
1178 p_menu = gtk_menu_new();
1179 gtk_object_set_data( GTK_OBJECT( p_menu ), "p_intf", p_intf );
1181 /* special case for "off" item */
1182 p_item = gtk_radio_menu_item_new_with_label( p_group, "None" );
1183 p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
1185 gtk_widget_show( p_item );
1187 /* signal hanling for off */
1188 gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
1189 GTK_SIGNAL_FUNC ( pf_toggle ), NULL );
1191 gtk_menu_append( GTK_MENU( p_menu ), p_item );
1193 p_separator = gtk_menu_item_new();
1194 gtk_widget_set_sensitive( p_separator, FALSE );
1195 gtk_widget_show( p_separator );
1196 gtk_menu_append( GTK_MENU( p_menu ), p_separator );
1199 /* search actual deinterlace mode */
1200 psz_filter = config_GetPsz( p_intf, "filter" );
1201 psz_deinterlace_option = strdup( "None" );
1203 if( psz_filter && *psz_filter )
1205 if( strstr ( psz_filter, "deinterlace" ) )
1208 vout_thread_t *p_vout;
1210 p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT,
1213 var_Get( p_vout, "deinterlace-mode", &val ) == VLC_SUCCESS )
1215 if( val.psz_string && *val.psz_string )
1217 free( psz_deinterlace_option );
1218 psz_deinterlace_option = val.psz_string;
1220 else if( val.psz_string ) free( val.psz_string );
1223 if( p_vout ) vlc_object_release( p_vout );
1229 p_item_active = NULL;
1232 /* create a set of deinteralce buttons and append them to the container */
1233 for( i = 0; ppsz_deinterlace_mode[i] != NULL; i++ )
1237 p_item = gtk_radio_menu_item_new_with_label( p_group, ppsz_deinterlace_mode[i] );
1238 p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
1239 gtk_widget_show( p_item );
1241 if( !strcmp( ppsz_deinterlace_mode[i], psz_deinterlace_option ) )
1243 p_item_active = p_item;
1245 /* setup signal hanling */
1246 gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
1247 GTK_SIGNAL_FUNC( pf_toggle ),
1250 gtk_menu_append( GTK_MENU( p_menu ), p_item );
1254 /* link the new menu to the menubar item */
1255 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
1257 /* acitvation will call signals so we can only do it
1258 * when submenu is attached to menu - to get intf_window
1259 * We have to release the lock since input_ToggleES needs it */
1260 if( p_item_active != NULL )
1262 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
1266 /* be sure that menu is sensitive if non empty */
1269 gtk_widget_set_sensitive( p_root, TRUE );
1277 /*****************************************************************************
1278 * GtkSetupMenus: function that generates title/chapter/audio/subpic
1279 * menus with help from preceding functions
1280 *****************************************************************************
1281 * Function called with the lock on stream
1282 *****************************************************************************/
1283 gint GtkSetupMenus( intf_thread_t * p_intf )
1285 es_descriptor_t * p_audio_es;
1286 es_descriptor_t * p_spu_es;
1287 GtkWidget * p_menubar_menu;
1288 GtkWidget * p_popup_menu;
1291 p_intf->p_sys->b_chapter_update |= p_intf->p_sys->b_title_update;
1292 p_intf->p_sys->b_audio_update |= p_intf->p_sys->b_title_update |
1293 p_intf->p_sys->b_program_update;
1294 p_intf->p_sys->b_spu_update |= p_intf->p_sys->b_title_update |
1295 p_intf->p_sys->b_program_update;
1299 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1300 p_intf->p_sys->p_window ), "menubar_deinterlace" ) );
1301 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1302 p_intf->p_sys->p_popup ), "popup_deinterlace" ) );
1304 p_intf->p_sys->b_deinterlace_update = VLC_TRUE;
1305 GtkDeinterlaceMenus( p_intf, p_menubar_menu, GtkMenubarDeinterlaceToggle );
1306 p_intf->p_sys->b_deinterlace_update = VLC_TRUE;
1307 GtkDeinterlaceMenus( p_intf, p_popup_menu, GtkPopupDeinterlaceToggle );
1309 p_intf->p_sys->b_deinterlace_update = VLC_FALSE;
1312 if( p_intf->p_sys->b_program_update )
1314 pgrm_descriptor_t * p_pgrm;
1316 if( p_intf->p_sys->p_input->stream.p_new_program )
1318 p_pgrm = p_intf->p_sys->p_input->stream.p_new_program;
1322 p_pgrm = p_intf->p_sys->p_input->stream.p_selected_program;
1325 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1326 p_intf->p_sys->p_window ), "menubar_program" ) );
1327 GtkProgramMenu( p_intf, p_menubar_menu, p_pgrm,
1328 GtkMenubarProgramToggle );
1330 p_intf->p_sys->b_program_update = VLC_TRUE;
1331 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1332 p_intf->p_sys->p_popup ), "popup_program" ) );
1333 GtkProgramMenu( p_intf, p_popup_menu, p_pgrm,
1334 GtkPopupProgramToggle );
1336 p_intf->p_sys->b_program_update = VLC_FALSE;
1339 if( p_intf->p_sys->b_title_update )
1343 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1344 p_intf->p_sys->p_window ), "menubar_title" ) );
1345 GtkRadioMenu( p_intf, p_menubar_menu, NULL, _("Title"), 1,
1346 p_intf->p_sys->p_input->stream.i_area_nb - 1,
1347 p_intf->p_sys->p_input->stream.p_selected_area->i_id,
1348 GtkMenubarTitleToggle );
1350 snprintf( psz_title, 4, "%d",
1351 p_intf->p_sys->p_input->stream.p_selected_area->i_id );
1352 psz_title[ 4 ] = '\0';
1353 gtk_label_set_text( p_intf->p_sys->p_label_title, psz_title );
1355 p_intf->p_sys->b_title_update = VLC_FALSE;
1358 if( p_intf->p_sys->b_chapter_update )
1360 char psz_chapter[5];
1362 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1363 p_intf->p_sys->p_popup ), "popup_navigation" ) );
1364 GtkTitleMenu( p_intf, p_popup_menu, GtkPopupNavigationToggle );
1366 GtkRadioMenu( p_intf, p_menubar_menu, NULL, _("Title"), 1,
1367 p_intf->p_sys->p_input->stream.i_area_nb - 1,
1368 p_intf->p_sys->p_input->stream.p_selected_area->i_id,
1369 on_menubar_chapter_toggle );
1372 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1373 p_intf->p_sys->p_window ), "menubar_chapter" ) );
1375 GtkRadioMenu( p_intf, p_menubar_menu, NULL, _("Chapter"), 1,
1376 p_intf->p_sys->p_input->stream.p_selected_area->i_part_nb - 1,
1377 p_intf->p_sys->p_input->stream.p_selected_area->i_part,
1378 GtkMenubarChapterToggle );
1381 snprintf( psz_chapter, 4, "%d",
1382 p_intf->p_sys->p_input->stream.p_selected_area->i_part );
1383 psz_chapter[ 4 ] = '\0';
1384 gtk_label_set_text( p_intf->p_sys->p_label_chapter, psz_chapter );
1386 p_intf->p_sys->i_part =
1387 p_intf->p_sys->p_input->stream.p_selected_area->i_part;
1389 p_intf->p_sys->b_chapter_update = VLC_FALSE;
1392 /* look for selected ES */
1396 for( i = 0 ; i < p_intf->p_sys->p_input->stream.i_selected_es_number ; i++ )
1398 if( p_intf->p_sys->p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES )
1400 p_audio_es = p_intf->p_sys->p_input->stream.pp_selected_es[i];
1403 if( p_intf->p_sys->p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
1405 p_spu_es = p_intf->p_sys->p_input->stream.pp_selected_es[i];
1409 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
1412 if( p_intf->p_sys->b_audio_update )
1414 /* find audio root menu */
1415 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1416 p_intf->p_sys->p_window ), "menubar_audio" ) );
1418 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1419 p_intf->p_sys->p_popup ), "popup_language" ) );
1421 p_intf->p_sys->b_audio_update = VLC_TRUE;
1422 GtkLanguageMenus( p_intf, p_menubar_menu, p_audio_es, AUDIO_ES,
1423 GtkMenubarAudioToggle );
1424 p_intf->p_sys->b_audio_update = VLC_TRUE;
1425 GtkLanguageMenus( p_intf, p_popup_menu, p_audio_es, AUDIO_ES,
1426 GtkPopupAudioToggle );
1428 p_intf->p_sys->b_audio_update = VLC_FALSE;
1431 /* sub picture menus */
1432 if( p_intf->p_sys->b_spu_update )
1434 /* find spu root menu */
1435 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1436 p_intf->p_sys->p_window ), "menubar_subpictures" ) );
1438 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1439 p_intf->p_sys->p_popup ), "popup_subpictures" ) );
1441 p_intf->p_sys->b_spu_update = VLC_TRUE;
1442 GtkLanguageMenus( p_intf, p_menubar_menu, p_spu_es, SPU_ES,
1443 GtkMenubarSubtitleToggle );
1444 p_intf->p_sys->b_spu_update = VLC_TRUE;
1445 GtkLanguageMenus( p_intf, p_popup_menu, p_spu_es, SPU_ES,
1446 GtkPopupSubtitleToggle );
1448 p_intf->p_sys->b_spu_update = VLC_FALSE;
1450 /* create audio channels and device menu (in menubar _and_ popup */
1451 if( p_intf->p_sys->b_aout_update )
1453 aout_instance_t *p_aout;
1455 p_aout = (aout_instance_t*)vlc_object_find( p_intf, VLC_OBJECT_AOUT, FIND_ANYWHERE );
1457 if( p_aout != NULL )
1460 val.b_bool = VLC_FALSE;
1462 var_Set( (vlc_object_t *)p_aout, "intf-change", val );
1464 /* audio-channels */
1465 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1466 p_intf->p_sys->p_window ), "menubar_audio_channels" ) );
1467 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1468 p_intf->p_sys->p_popup ), "popup_audio_channels" ) );
1469 GtkSetupVarMenu( p_intf, (vlc_object_t *)p_aout, p_popup_menu,
1470 "audio-channels", GtkPopupAoutChannelsToggle );
1471 GtkSetupVarMenu( p_intf, (vlc_object_t *)p_aout, p_menubar_menu,
1472 "audio-channels", GtkPopupAoutChannelsToggle );
1475 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1476 p_intf->p_sys->p_window ), "menubar_audio_device" ) );
1477 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1478 p_intf->p_sys->p_popup ), "popup_audio_device" ) );
1479 GtkSetupVarMenu( p_intf, (vlc_object_t *)p_aout, p_popup_menu,
1480 "audio-device", GtkPopupAoutDeviceToggle );
1481 GtkSetupVarMenu( p_intf, (vlc_object_t *)p_aout, p_menubar_menu,
1482 "audio-device", GtkPopupAoutDeviceToggle );
1484 vlc_object_release( (vlc_object_t *)p_aout );
1486 p_intf->p_sys->b_aout_update = VLC_FALSE;
1489 if( p_intf->p_sys->b_vout_update )
1491 vout_thread_t *p_vout;
1493 p_vout = (vout_thread_t*)vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
1495 if( p_vout != NULL )
1498 val.b_bool = VLC_FALSE;
1500 var_Set( (vlc_object_t *)p_vout, "intf-change", val );
1503 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1504 p_intf->p_sys->p_window ), "menubar_video_device" ) );
1505 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1506 p_intf->p_sys->p_popup ), "popup_video_device" ) );
1507 GtkSetupVarMenu( p_intf, (vlc_object_t *)p_vout, p_popup_menu,
1508 "video-device", GtkPopupVoutDeviceToggle );
1509 GtkSetupVarMenu( p_intf, (vlc_object_t *)p_vout, p_menubar_menu,
1510 "video-device", GtkPopupVoutDeviceToggle );
1513 vlc_object_release( (vlc_object_t *)p_vout );
1515 p_intf->p_sys->b_vout_update = VLC_FALSE;
1517 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );