1 /*****************************************************************************
2 * menu.c : functions to handle menu items.
3 *****************************************************************************
4 * Copyright (C) 2000, 2001 VideoLAN
5 * $Id: menu.c,v 1.10 2003/05/05 22:23:38 gbazin 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,
297 gpointer user_data, 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 &&
305 !p_intf->p_sys->b_vout_update )
307 vlc_object_t * p_obj;
309 p_obj = (vlc_object_t *)vlc_object_find( p_intf, i_object_type,
317 val = (vlc_value_t)user_data;
321 gtk_label_get( p_label, &val.psz_string );
324 if( var_Set( p_obj, psz_variable, val ) < 0 )
326 msg_Warn( p_obj, "cannot set variable (%s)", val.psz_string );
328 vlc_object_release( p_obj );
332 static void GtkPopupAoutChannelsToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
334 GtkPopupObjectToggle( menuitem, user_data, VLC_OBJECT_AOUT, "audio-channels" );
337 static void GtkPopupAoutDeviceToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
339 GtkPopupObjectToggle( menuitem, user_data, VLC_OBJECT_AOUT, "audio-device" );
343 static void GtkPopupVoutDeviceToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
345 GtkPopupObjectToggle( menuitem, user_data, VLC_OBJECT_VOUT, "video-device" );
349 static void GtkDeinterlaceUpdate( intf_thread_t *p_intf, char *psz_mode )
354 psz_filter = config_GetPsz( p_intf, "filter" );
356 if( !strcmp( psz_mode, "None" ) )
358 config_PutPsz( p_intf, "filter", "" );
362 if( !psz_filter || !*psz_filter )
364 config_PutPsz( p_intf, "filter", "deinterlace" );
368 if( strstr( psz_filter, "deinterlace" ) == NULL )
370 psz_filter = realloc( psz_filter, strlen( psz_filter ) + 20 );
371 strcat( psz_filter, ",deinterlace" );
373 config_PutPsz( p_intf, "filter", psz_filter );
380 /* now restart all video stream */
381 if( p_intf->p_sys->p_input )
383 vout_thread_t *p_vout;
384 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
386 /* Warn the vout we are about to change the filter chain */
387 p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT,
391 p_vout->b_filter_change = VLC_TRUE;
392 vlc_object_release( p_vout );
395 #define ES p_intf->p_sys->p_input->stream.pp_es[i]
396 /* create a set of language buttons and append them to the container */
397 for( i = 0 ; i < p_intf->p_sys->p_input->stream.i_es_number ; i++ )
399 if( ( ES->i_cat == VIDEO_ES ) &&
400 ES->p_decoder_fifo != NULL )
402 input_UnselectES( p_intf->p_sys->p_input, ES );
403 input_SelectES( p_intf->p_sys->p_input, ES );
407 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
410 if( strcmp( psz_mode, "None" ) )
412 vout_thread_t *p_vout;
413 p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT,
419 val.psz_string = psz_mode;
420 if( var_Set( p_vout, "deinterlace-mode", val ) != VLC_SUCCESS )
421 config_PutPsz( p_intf, "deinterlace-mode", psz_mode );
423 vlc_object_release( p_vout );
426 config_PutPsz( p_intf, "deinterlace-mode", psz_mode );
431 static void GtkMenubarDeinterlaceToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
433 intf_thread_t *p_intf = GtkGetIntf( menuitem );
436 GtkWidget *p_popup_menu;
438 p_label = GTK_LABEL( ( GTK_BIN( menuitem )->child ) );
440 if( !p_intf->p_sys->b_deinterlace_update && menuitem->active )
442 gtk_label_get( p_label, &psz_mode );
443 GtkDeinterlaceUpdate( p_intf, psz_mode );
445 p_intf->p_sys->b_deinterlace_update = VLC_TRUE;
447 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
448 p_intf->p_sys->p_popup ), "popup_deinterlace" ) );
450 GtkDeinterlaceMenus( p_intf, p_popup_menu, GtkPopupDeinterlaceToggle );
452 p_intf->p_sys->b_deinterlace_update = VLC_FALSE;
457 static void GtkPopupDeinterlaceToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
459 intf_thread_t *p_intf = GtkGetIntf( menuitem );
462 GtkWidget *p_menubar_menu;
464 p_label = GTK_LABEL( ( GTK_BIN( menuitem )->child ) );
466 if( !p_intf->p_sys->b_deinterlace_update && menuitem->active )
468 gtk_label_get( p_label, &psz_mode );
469 GtkDeinterlaceUpdate( p_intf, psz_mode );
471 p_intf->p_sys->b_deinterlace_update = VLC_TRUE;
473 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
474 p_intf->p_sys->p_window ), "menubar_deinterlace" ) );
476 GtkDeinterlaceMenus( p_intf, p_menubar_menu, GtkMenubarDeinterlaceToggle );
478 p_intf->p_sys->b_deinterlace_update = VLC_FALSE;
482 /****************************************************************************
483 * Functions to generate menus
484 ****************************************************************************/
486 /*****************************************************************************
487 * GtkRadioMenu: update interactive menus of the interface
488 *****************************************************************************
489 * Sets up menus with information from input
490 * Warning: since this function is designed to be called by management
491 * function, the interface lock has to be taken
492 *****************************************************************************/
493 static gint GtkRadioMenu( intf_thread_t * p_intf,
494 GtkWidget * p_root, GSList * p_menu_group,
495 char * psz_item_name,
496 int i_start, int i_end, int i_selected,
497 void( *pf_toggle )( GtkCheckMenuItem *, gpointer ) )
499 char psz_name[ GTK_MENU_LABEL_SIZE ];
501 GtkWidget * p_submenu;
502 GtkWidget * p_item_group;
504 GtkWidget * p_item_selected;
508 /* temporary hack to avoid blank menu when an open menu is removed */
509 if( GTK_MENU_ITEM(p_root)->submenu != NULL )
511 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
513 /* removes previous menu */
514 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
515 gtk_widget_set_sensitive( p_root, FALSE );
519 p_item_selected = NULL;
520 p_group = p_menu_group;
522 p_menu = gtk_menu_new();
523 gtk_object_set_data( GTK_OBJECT( p_menu ), "p_intf", p_intf );
525 for( i_item = i_start ; i_item <= i_end ; i_item++ )
527 /* we group chapters in packets of ten for small screens */
528 if( ( i_item % 10 == i_start ) && ( i_end > i_start + 20 ) )
530 if( i_item != i_start )
532 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_item_group ),
534 gtk_menu_append( GTK_MENU( p_menu ), p_item_group );
537 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
538 "%ss %d to %d", psz_item_name, i_item, i_item + 9 );
539 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
540 p_item_group = gtk_menu_item_new_with_label( psz_name );
541 gtk_widget_show( p_item_group );
542 p_submenu = gtk_menu_new();
543 gtk_object_set_data( GTK_OBJECT( p_submenu ), "p_intf", p_intf );
546 snprintf( psz_name, GTK_MENU_LABEL_SIZE, "%s %d",
547 psz_item_name, i_item );
548 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
550 p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
551 p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
553 if( i_selected == i_item )
555 p_item_selected = p_item;
558 gtk_widget_show( p_item );
560 /* setup signal hanling */
561 gtk_signal_connect( GTK_OBJECT( p_item ),
563 GTK_SIGNAL_FUNC( pf_toggle ),
564 (gpointer)((long)(i_item)) );
566 if( i_end > i_start + 20 )
568 gtk_menu_append( GTK_MENU( p_submenu ), p_item );
572 gtk_menu_append( GTK_MENU( p_menu ), p_item );
576 if( i_end > i_start + 20 )
578 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_item_group ), p_submenu );
579 gtk_menu_append( GTK_MENU( p_menu ), p_item_group );
582 /* link the new menu to the title menu item */
583 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
585 /* toggle currently selected chapter
586 * We have to release the lock since input_ToggleES needs it */
587 if( p_item_selected != NULL )
589 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_selected ),
593 /* be sure that menu is sensitive, if there are several items */
594 if( i_end > i_start )
596 gtk_widget_set_sensitive( p_root, TRUE );
602 /*****************************************************************************
603 * GtkProgramMenu: update the programs menu of the interface
604 *****************************************************************************
605 * Builds the program menu according to what have been found in the PAT
606 * by the input. Usefull for multi-programs streams such as DVB ones.
607 *****************************************************************************/
608 static gint GtkProgramMenu( gpointer p_data,
610 pgrm_descriptor_t * p_pgrm,
611 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
613 intf_thread_t * p_intf;
616 GtkWidget * p_item_active;
618 char psz_name[ GTK_MENU_LABEL_SIZE ];
622 p_intf = (intf_thread_t *)p_data;
624 /* temporary hack to avoid blank menu when an open menu is removed */
625 if( GTK_MENU_ITEM(p_root)->submenu != NULL )
627 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
629 /* removes previous menu */
630 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
631 gtk_widget_set_sensitive( p_root, FALSE );
636 p_menu = gtk_menu_new();
637 gtk_object_set_data( GTK_OBJECT( p_menu ), "p_intf", p_intf );
639 p_item_active = NULL;
641 /* create a set of program buttons and append them to the container */
642 for( i = 0 ; i < p_intf->p_sys->p_input->stream.i_pgrm_number ; i++ )
644 snprintf( psz_name, GTK_MENU_LABEL_SIZE, "id %d",
645 p_intf->p_sys->p_input->stream.pp_programs[i]->i_number );
646 psz_name[GTK_MENU_LABEL_SIZE-1] = '\0';
648 p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
650 gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
652 if( p_pgrm == p_intf->p_sys->p_input->stream.pp_programs[i] )
654 /* don't lose p_item when we append into menu */
655 p_item_active = p_item;
658 gtk_widget_show( p_item );
660 /* setup signal hanling */
661 gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
662 GTK_SIGNAL_FUNC( pf_toggle ),
663 (gpointer)(ptrdiff_t)( p_intf->p_sys->p_input->
664 stream.pp_programs[i]->i_number ) );
666 gtk_menu_append( GTK_MENU( p_menu ), p_item );
669 /* link the new menu to the menubar item */
670 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
672 /* activation will call signals so we can only do it
673 * when submenu is attached to menu - to get intf_window
674 * We have to release the lock since input_ToggleES needs it */
675 if( p_item_active != NULL )
677 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
681 /* be sure that menu is sensitive if more than 1 program */
682 if( p_intf->p_sys->p_input->stream.i_pgrm_number > 1 )
684 gtk_widget_set_sensitive( p_root, TRUE );
690 /*****************************************************************************
691 * GtkLanguageMenus: update interactive menus of the interface
692 *****************************************************************************
693 * Sets up menus with information from input:
696 * Warning: since this function is designed to be called by management
697 * function, the interface lock has to be taken
698 *****************************************************************************/
699 static gint GtkLanguageMenus( gpointer p_data,
701 es_descriptor_t * p_es,
703 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
705 intf_thread_t * p_intf;
707 GtkWidget * p_separator;
709 GtkWidget * p_item_active;
711 char psz_name[ GTK_MENU_LABEL_SIZE ];
715 p_intf = (intf_thread_t *)p_data;
717 /* temporary hack to avoid blank menu when an open menu is removed */
718 if( GTK_MENU_ITEM(p_root)->submenu != NULL )
720 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
722 /* removes previous menu */
723 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
724 gtk_widget_set_sensitive( p_root, FALSE );
729 p_menu = gtk_menu_new();
730 gtk_object_set_data( GTK_OBJECT( p_menu ), "p_intf", p_intf );
732 /* special case for "off" item */
733 snprintf( psz_name, GTK_MENU_LABEL_SIZE, _("None") );
734 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
736 p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
737 p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
739 gtk_widget_show( p_item );
741 /* signal hanling for off */
742 gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
743 GTK_SIGNAL_FUNC ( pf_toggle ), NULL );
745 gtk_menu_append( GTK_MENU( p_menu ), p_item );
747 p_separator = gtk_menu_item_new();
748 gtk_widget_set_sensitive( p_separator, FALSE );
749 gtk_widget_show( p_separator );
750 gtk_menu_append( GTK_MENU( p_menu ), p_separator );
752 p_item_active = NULL;
755 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
757 #define ES p_intf->p_sys->p_input->stream.pp_es[i]
758 /* create a set of language buttons and append them to the container */
759 for( i = 0 ; i < p_intf->p_sys->p_input->stream.i_es_number ; i++ )
761 if( ( ES->i_cat == i_cat ) &&
764 p_intf->p_sys->p_input->stream.p_selected_program ) )
767 if( !p_intf->p_sys->p_input->stream.pp_es[i]->psz_desc ||
768 !*p_intf->p_sys->p_input->stream.pp_es[i]->psz_desc )
770 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
771 "Language %d", i_item );
772 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
777 p_intf->p_sys->p_input->stream.pp_es[i]->psz_desc );
780 p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
782 gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
784 if( p_es == p_intf->p_sys->p_input->stream.pp_es[i] )
786 /* don't lose p_item when we append into menu */
787 p_item_active = p_item;
790 gtk_widget_show( p_item );
792 /* setup signal hanling */
793 gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
794 GTK_SIGNAL_FUNC( pf_toggle ),
795 (gpointer)( p_intf->p_sys->p_input->stream.pp_es[i] ) );
797 gtk_menu_append( GTK_MENU( p_menu ), p_item );
801 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
803 /* link the new menu to the menubar item */
804 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
806 /* acitvation will call signals so we can only do it
807 * when submenu is attached to menu - to get intf_window
808 * We have to release the lock since input_ToggleES needs it */
809 if( p_item_active != NULL )
811 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
815 /* be sure that menu is sensitive if non empty */
818 gtk_widget_set_sensitive( p_root, TRUE );
824 /*****************************************************************************
825 * GtkTitleMenu: sets menus for titles and chapters selection
826 *****************************************************************************
827 * Generates two types of menus:
828 * -simple list of titles
829 * -cascaded lists of chapters for each title
830 *****************************************************************************/
831 static gint GtkTitleMenu( gpointer p_data,
832 GtkWidget * p_navigation,
833 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
835 intf_thread_t * p_intf;
836 char psz_name[ GTK_MENU_LABEL_SIZE ];
837 GtkWidget * p_title_menu;
838 GtkWidget * p_title_submenu;
839 GtkWidget * p_title_item;
840 GtkWidget * p_item_active;
841 GtkWidget * p_chapter_menu;
842 GtkWidget * p_chapter_submenu;
843 GtkWidget * p_title_menu_item;
844 GtkWidget * p_chapter_menu_item;
846 GSList * p_title_group;
847 GSList * p_chapter_group;
854 p_intf = (intf_thread_t*)p_data;
856 /* temporary hack to avoid blank menu when an open menu is removed */
857 if( GTK_MENU_ITEM(p_navigation)->submenu != NULL )
859 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_navigation)->submenu ) );
861 /* removes previous menu */
862 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_navigation ) );
863 gtk_widget_set_sensitive( p_navigation, FALSE );
865 p_title_menu = gtk_menu_new();
866 p_title_group = NULL;
867 p_title_submenu = NULL;
868 p_title_menu_item = NULL;
869 p_chapter_group = NULL;
870 p_chapter_submenu = NULL;
871 p_chapter_menu_item = NULL;
872 p_item_active = NULL;
873 i_title_nb = p_intf->p_sys->p_input->stream.i_area_nb - 1;
875 gtk_object_set_data( GTK_OBJECT( p_title_menu ), "p_intf", p_intf );
878 for( i_title = 1 ; i_title <= i_title_nb ; i_title++ )
880 /* we group titles in packets of ten for small screens */
881 if( ( i_title % 10 == 1 ) && ( i_title_nb > 20 ) )
885 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_menu_item ),
887 gtk_menu_append( GTK_MENU( p_title_menu ), p_title_menu_item );
890 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
891 "%d - %d", i_title, i_title + 9 );
892 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
893 p_title_menu_item = gtk_menu_item_new_with_label( psz_name );
894 gtk_widget_show( p_title_menu_item );
895 p_title_submenu = gtk_menu_new();
896 gtk_object_set_data( GTK_OBJECT( p_title_submenu ),
900 snprintf( psz_name, GTK_MENU_LABEL_SIZE, _("Title %d (%d)"), i_title,
901 p_intf->p_sys->p_input->stream.pp_areas[i_title]->i_part_nb - 1);
902 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
904 if( pf_toggle == on_menubar_title_toggle )
906 p_title_item = gtk_radio_menu_item_new_with_label( p_title_group,
909 gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_title_item ) );
911 if( p_intf->p_sys->p_input->stream.pp_areas[i_title] ==
912 p_intf->p_sys->p_input->stream.p_selected_area )
914 p_item_active = p_title_item;
917 /* setup signal hanling */
918 gtk_signal_connect( GTK_OBJECT( p_title_item ),
920 GTK_SIGNAL_FUNC( pf_toggle ),
921 (gpointer)(p_intf->p_sys->p_input->stream.pp_areas[i_title]) );
923 if( p_intf->p_sys->p_input->stream.i_area_nb > 1 )
925 /* be sure that menu is sensitive */
926 gtk_widget_set_sensitive( p_navigation, TRUE );
932 p_title_item = gtk_menu_item_new_with_label( psz_name );
935 p_chapter_menu = gtk_menu_new();
936 gtk_object_set_data( GTK_OBJECT( p_chapter_menu ),
939 p_intf->p_sys->p_input->stream.pp_areas[i_title]->i_part_nb - 1;
941 for( i_chapter = 1 ; i_chapter <= i_chapter_nb ; i_chapter++ )
943 /* we group chapters in packets of ten for small screens */
944 if( ( i_chapter % 10 == 1 ) && ( i_chapter_nb > 20 ) )
948 gtk_menu_item_set_submenu(
949 GTK_MENU_ITEM( p_chapter_menu_item ),
951 gtk_menu_append( GTK_MENU( p_chapter_menu ),
952 p_chapter_menu_item );
955 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
956 "%d - %d", i_chapter, i_chapter + 9 );
957 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
958 p_chapter_menu_item =
959 gtk_menu_item_new_with_label( psz_name );
960 gtk_widget_show( p_chapter_menu_item );
961 p_chapter_submenu = gtk_menu_new();
962 gtk_object_set_data( GTK_OBJECT( p_chapter_submenu ),
966 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
967 _("Chapter %d"), i_chapter );
968 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
970 p_item = gtk_radio_menu_item_new_with_label(
971 p_chapter_group, psz_name );
972 p_chapter_group = gtk_radio_menu_item_group(
973 GTK_RADIO_MENU_ITEM( p_item ) );
974 gtk_widget_show( p_item );
976 #define p_area p_intf->p_sys->p_input->stream.pp_areas[i_title]
978 p_intf->p_sys->p_input->stream.p_selected_area ) &&
979 ( p_area->i_part == i_chapter ) )
981 p_item_active = p_item;
985 /* setup signal hanling */
986 gtk_signal_connect( GTK_OBJECT( p_item ),
988 GTK_SIGNAL_FUNC( pf_toggle ),
989 (gpointer)POS2DATA( i_title, i_chapter ) );
991 if( i_chapter_nb > 20 )
993 gtk_menu_append( GTK_MENU( p_chapter_submenu ), p_item );
997 gtk_menu_append( GTK_MENU( p_chapter_menu ), p_item );
1001 if( i_chapter_nb > 20 )
1003 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_chapter_menu_item ),
1004 p_chapter_submenu );
1005 gtk_menu_append( GTK_MENU( p_chapter_menu ),
1006 p_chapter_menu_item );
1009 /* link the new menu to the title menu item */
1010 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_item ),
1013 if( p_intf->p_sys->p_input->stream.pp_areas[i_title]->i_part_nb > 1 )
1015 /* be sure that menu is sensitive */
1016 gtk_widget_set_sensitive( p_navigation, TRUE );
1019 GtkRadioMenu( p_intf, p_title_item, p_chapter_group, _("Chapter"),
1020 p_intf->p_sys->p_input->stream.pp_areas[i_title]->i_part_nb - 1,
1022 p_intf->p_sys->p_input->stream.p_selected_area->i_part +
1023 p_intf->p_sys->p_input->stream.p_selected_area->i_id *100,
1028 gtk_widget_show( p_title_item );
1030 if( i_title_nb > 20 )
1032 gtk_menu_append( GTK_MENU( p_title_submenu ), p_title_item );
1036 gtk_menu_append( GTK_MENU( p_title_menu ), p_title_item );
1040 if( i_title_nb > 20 )
1042 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_menu_item ),
1044 gtk_menu_append( GTK_MENU( p_title_menu ), p_title_menu_item );
1047 /* be sure that menu is sensitive */
1048 gtk_widget_set_sensitive( p_title_menu, TRUE );
1050 /* link the new menu to the menubar item */
1051 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_navigation ), p_title_menu );
1053 /* Default selected chapter
1054 * We have to release the lock since input_ToggleES needs it */
1055 if( p_item_active != NULL )
1057 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
1061 if( p_intf->p_sys->p_input->stream.i_area_nb > 1 )
1063 /* be sure that menu is sensitive */
1064 gtk_widget_set_sensitive( p_navigation, TRUE );
1071 /*****************************************************************************
1073 *****************************************************************************
1075 *****************************************************************************/
1076 static gint GtkSetupVarMenu( intf_thread_t * p_intf,
1077 vlc_object_t * p_object,
1079 char * psz_variable,
1080 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
1082 vlc_value_t val, text, val_list, text_list;
1084 GSList * p_group = NULL;
1086 GtkWidget * p_item_active = NULL;
1090 /* temporary hack to avoid blank menu when an open menu is removed */
1091 if( GTK_MENU_ITEM(p_root)->submenu != NULL )
1093 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
1095 /* removes previous menu */
1096 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
1097 gtk_widget_set_sensitive( p_root, FALSE );
1099 /* Check the type of the object variable */
1100 i_type = var_Type( p_object, psz_variable );
1102 /* Make sure we want to display the variable */
1103 if( i_type & VLC_VAR_HASCHOICE )
1105 var_Change( p_object, psz_variable, VLC_VAR_CHOICESCOUNT, &val, NULL );
1106 if( val.i_int == 0 ) return FALSE;
1109 /* Get the descriptive name of the variable */
1110 var_Change( p_object, psz_variable, VLC_VAR_GETTEXT, &text, NULL );
1112 /* get the current value */
1113 if( var_Get( p_object, psz_variable, &val ) < 0 )
1118 if( var_Change( p_object, psz_variable, VLC_VAR_GETLIST,
1119 &val_list, &text_list ) < 0 )
1121 if( i_type == VLC_VAR_STRING ) free( val.psz_string );
1125 /* menu container */
1126 p_menu = gtk_menu_new();
1127 gtk_object_set_data( GTK_OBJECT( p_menu ), "p_intf", p_intf );
1129 for( i_item = 0; i_item < val_list.p_list->i_count; i_item++ )
1131 switch( i_type & VLC_VAR_TYPE )
1133 case VLC_VAR_STRING:
1134 p_item = gtk_radio_menu_item_new_with_label( p_group,
1135 text_list.p_list->p_values[i_item].psz_string ?
1136 text_list.p_list->p_values[i_item].psz_string :
1137 val_list.p_list->p_values[i_item].psz_string );
1139 /* signal hanling for off */
1140 gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
1141 GTK_SIGNAL_FUNC ( pf_toggle ),
1142 /* FIXME memory leak */
1143 strdup(val_list.p_list->p_values[i_item].psz_string) );
1145 if( !strcmp( val.psz_string,
1146 val_list.p_list->p_values[i_item].psz_string ) )
1148 p_item_active = p_item;
1151 case VLC_VAR_INTEGER:
1152 p_item = gtk_radio_menu_item_new_with_label( p_group,
1153 text_list.p_list->p_values[i_item].psz_string ?
1154 text_list.p_list->p_values[i_item].psz_string :
1157 /* signal hanling for off */
1158 gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
1159 GTK_SIGNAL_FUNC ( pf_toggle ),
1160 (gpointer)val_list.p_list->p_values[i_item].i_int );
1162 if( val.i_int == val_list.p_list->p_values[i_item].i_int )
1164 p_item_active = p_item;
1172 p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
1174 gtk_widget_show( p_item );
1176 gtk_menu_append( GTK_MENU( p_menu ), p_item );
1179 /* link the new menu to the menubar item */
1180 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
1184 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(p_item_active),
1188 if( val_list.p_list->i_count > 0 )
1190 gtk_widget_set_sensitive( p_root, TRUE );
1193 /* clean up everything */
1194 if( i_type == VLC_VAR_STRING ) free( val.psz_string );
1195 var_Change( p_object, psz_variable, VLC_VAR_FREELIST,
1196 &val_list, &text_list );
1201 /*****************************************************************************
1202 * GtkDeinterlaceMenus: update interactive menus of the interface
1203 *****************************************************************************
1204 *****************************************************************************/
1205 static gint GtkDeinterlaceMenus( gpointer p_data,
1207 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
1209 intf_thread_t * p_intf;
1211 GtkWidget * p_separator;
1213 GtkWidget * p_item_active;
1217 char *ppsz_deinterlace_mode[] = { "discard", "blend", "mean", "bob", "linear", NULL };
1218 char *psz_deinterlace_option;
1221 p_intf = (intf_thread_t *)p_data;
1223 /* temporary hack to avoid blank menu when an open menu is removed */
1224 if( GTK_MENU_ITEM(p_root)->submenu != NULL )
1226 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
1228 /* removes previous menu */
1229 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
1230 gtk_widget_set_sensitive( p_root, FALSE );
1234 /* menu container */
1235 p_menu = gtk_menu_new();
1236 gtk_object_set_data( GTK_OBJECT( p_menu ), "p_intf", p_intf );
1238 /* special case for "off" item */
1239 p_item = gtk_radio_menu_item_new_with_label( p_group, "None" );
1240 p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
1242 gtk_widget_show( p_item );
1244 /* signal hanling for off */
1245 gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
1246 GTK_SIGNAL_FUNC ( pf_toggle ), NULL );
1248 gtk_menu_append( GTK_MENU( p_menu ), p_item );
1250 p_separator = gtk_menu_item_new();
1251 gtk_widget_set_sensitive( p_separator, FALSE );
1252 gtk_widget_show( p_separator );
1253 gtk_menu_append( GTK_MENU( p_menu ), p_separator );
1256 /* search actual deinterlace mode */
1257 psz_filter = config_GetPsz( p_intf, "filter" );
1258 psz_deinterlace_option = strdup( "None" );
1260 if( psz_filter && *psz_filter )
1262 if( strstr ( psz_filter, "deinterlace" ) )
1265 vout_thread_t *p_vout;
1267 p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT,
1270 var_Get( p_vout, "deinterlace-mode", &val ) == VLC_SUCCESS )
1272 if( val.psz_string && *val.psz_string )
1274 free( psz_deinterlace_option );
1275 psz_deinterlace_option = val.psz_string;
1277 else if( val.psz_string ) free( val.psz_string );
1280 if( p_vout ) vlc_object_release( p_vout );
1286 p_item_active = NULL;
1289 /* create a set of deinteralce buttons and append them to the container */
1290 for( i = 0; ppsz_deinterlace_mode[i] != NULL; i++ )
1294 p_item = gtk_radio_menu_item_new_with_label( p_group, ppsz_deinterlace_mode[i] );
1295 p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
1296 gtk_widget_show( p_item );
1298 if( !strcmp( ppsz_deinterlace_mode[i], psz_deinterlace_option ) )
1300 p_item_active = p_item;
1302 /* setup signal hanling */
1303 gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
1304 GTK_SIGNAL_FUNC( pf_toggle ),
1307 gtk_menu_append( GTK_MENU( p_menu ), p_item );
1311 /* link the new menu to the menubar item */
1312 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
1314 /* acitvation will call signals so we can only do it
1315 * when submenu is attached to menu - to get intf_window
1316 * We have to release the lock since input_ToggleES needs it */
1317 if( p_item_active != NULL )
1319 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
1323 /* be sure that menu is sensitive if non empty */
1326 gtk_widget_set_sensitive( p_root, TRUE );
1334 /*****************************************************************************
1335 * GtkSetupMenus: function that generates title/chapter/audio/subpic
1336 * menus with help from preceding functions
1337 *****************************************************************************
1338 * Function called with the lock on stream
1339 *****************************************************************************/
1340 gint GtkSetupMenus( intf_thread_t * p_intf )
1342 es_descriptor_t * p_audio_es;
1343 es_descriptor_t * p_spu_es;
1344 GtkWidget * p_menubar_menu;
1345 GtkWidget * p_popup_menu;
1348 p_intf->p_sys->b_chapter_update |= p_intf->p_sys->b_title_update;
1349 p_intf->p_sys->b_audio_update |= p_intf->p_sys->b_title_update |
1350 p_intf->p_sys->b_program_update;
1351 p_intf->p_sys->b_spu_update |= p_intf->p_sys->b_title_update |
1352 p_intf->p_sys->b_program_update;
1356 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1357 p_intf->p_sys->p_window ), "menubar_deinterlace" ) );
1358 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1359 p_intf->p_sys->p_popup ), "popup_deinterlace" ) );
1361 p_intf->p_sys->b_deinterlace_update = VLC_TRUE;
1362 GtkDeinterlaceMenus( p_intf, p_menubar_menu, GtkMenubarDeinterlaceToggle );
1363 p_intf->p_sys->b_deinterlace_update = VLC_TRUE;
1364 GtkDeinterlaceMenus( p_intf, p_popup_menu, GtkPopupDeinterlaceToggle );
1366 p_intf->p_sys->b_deinterlace_update = VLC_FALSE;
1369 if( p_intf->p_sys->b_program_update )
1371 pgrm_descriptor_t * p_pgrm;
1373 if( p_intf->p_sys->p_input->stream.p_new_program )
1375 p_pgrm = p_intf->p_sys->p_input->stream.p_new_program;
1379 p_pgrm = p_intf->p_sys->p_input->stream.p_selected_program;
1382 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1383 p_intf->p_sys->p_window ), "menubar_program" ) );
1384 GtkProgramMenu( p_intf, p_menubar_menu, p_pgrm,
1385 GtkMenubarProgramToggle );
1387 p_intf->p_sys->b_program_update = VLC_TRUE;
1388 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1389 p_intf->p_sys->p_popup ), "popup_program" ) );
1390 GtkProgramMenu( p_intf, p_popup_menu, p_pgrm,
1391 GtkPopupProgramToggle );
1393 p_intf->p_sys->b_program_update = VLC_FALSE;
1396 if( p_intf->p_sys->b_title_update )
1400 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1401 p_intf->p_sys->p_window ), "menubar_title" ) );
1402 GtkRadioMenu( p_intf, p_menubar_menu, NULL, _("Title"), 1,
1403 p_intf->p_sys->p_input->stream.i_area_nb - 1,
1404 p_intf->p_sys->p_input->stream.p_selected_area->i_id,
1405 GtkMenubarTitleToggle );
1407 snprintf( psz_title, 4, "%d",
1408 p_intf->p_sys->p_input->stream.p_selected_area->i_id );
1409 psz_title[ 4 ] = '\0';
1410 gtk_label_set_text( p_intf->p_sys->p_label_title, psz_title );
1412 p_intf->p_sys->b_title_update = VLC_FALSE;
1415 if( p_intf->p_sys->b_chapter_update )
1417 char psz_chapter[5];
1419 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1420 p_intf->p_sys->p_popup ), "popup_navigation" ) );
1421 GtkTitleMenu( p_intf, p_popup_menu, GtkPopupNavigationToggle );
1423 GtkRadioMenu( p_intf, p_menubar_menu, NULL, _("Title"), 1,
1424 p_intf->p_sys->p_input->stream.i_area_nb - 1,
1425 p_intf->p_sys->p_input->stream.p_selected_area->i_id,
1426 on_menubar_chapter_toggle );
1429 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1430 p_intf->p_sys->p_window ), "menubar_chapter" ) );
1432 GtkRadioMenu( p_intf, p_menubar_menu, NULL, _("Chapter"), 1,
1433 p_intf->p_sys->p_input->stream.p_selected_area->i_part_nb - 1,
1434 p_intf->p_sys->p_input->stream.p_selected_area->i_part,
1435 GtkMenubarChapterToggle );
1438 snprintf( psz_chapter, 4, "%d",
1439 p_intf->p_sys->p_input->stream.p_selected_area->i_part );
1440 psz_chapter[ 4 ] = '\0';
1441 gtk_label_set_text( p_intf->p_sys->p_label_chapter, psz_chapter );
1443 p_intf->p_sys->i_part =
1444 p_intf->p_sys->p_input->stream.p_selected_area->i_part;
1446 p_intf->p_sys->b_chapter_update = VLC_FALSE;
1449 /* look for selected ES */
1453 for( i = 0 ; i < p_intf->p_sys->p_input->stream.i_selected_es_number ; i++ )
1455 if( p_intf->p_sys->p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES )
1457 p_audio_es = p_intf->p_sys->p_input->stream.pp_selected_es[i];
1460 if( p_intf->p_sys->p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
1462 p_spu_es = p_intf->p_sys->p_input->stream.pp_selected_es[i];
1466 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
1469 if( p_intf->p_sys->b_audio_update )
1471 /* find audio root menu */
1472 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1473 p_intf->p_sys->p_window ), "menubar_audio" ) );
1475 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1476 p_intf->p_sys->p_popup ), "popup_language" ) );
1478 p_intf->p_sys->b_audio_update = VLC_TRUE;
1479 GtkLanguageMenus( p_intf, p_menubar_menu, p_audio_es, AUDIO_ES,
1480 GtkMenubarAudioToggle );
1481 p_intf->p_sys->b_audio_update = VLC_TRUE;
1482 GtkLanguageMenus( p_intf, p_popup_menu, p_audio_es, AUDIO_ES,
1483 GtkPopupAudioToggle );
1485 p_intf->p_sys->b_audio_update = VLC_FALSE;
1488 /* sub picture menus */
1489 if( p_intf->p_sys->b_spu_update )
1491 /* find spu root menu */
1492 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1493 p_intf->p_sys->p_window ), "menubar_subpictures" ) );
1495 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1496 p_intf->p_sys->p_popup ), "popup_subpictures" ) );
1498 p_intf->p_sys->b_spu_update = VLC_TRUE;
1499 GtkLanguageMenus( p_intf, p_menubar_menu, p_spu_es, SPU_ES,
1500 GtkMenubarSubtitleToggle );
1501 p_intf->p_sys->b_spu_update = VLC_TRUE;
1502 GtkLanguageMenus( p_intf, p_popup_menu, p_spu_es, SPU_ES,
1503 GtkPopupSubtitleToggle );
1505 p_intf->p_sys->b_spu_update = VLC_FALSE;
1507 /* create audio channels and device menu (in menubar _and_ popup */
1508 if( p_intf->p_sys->b_aout_update )
1510 aout_instance_t *p_aout;
1512 p_aout = (aout_instance_t*)vlc_object_find( p_intf, VLC_OBJECT_AOUT, FIND_ANYWHERE );
1514 if( p_aout != NULL )
1517 val.b_bool = VLC_FALSE;
1519 var_Set( (vlc_object_t *)p_aout, "intf-change", val );
1521 /* audio-channels */
1522 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1523 p_intf->p_sys->p_window ), "menubar_audio_channels" ) );
1524 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1525 p_intf->p_sys->p_popup ), "popup_audio_channels" ) );
1526 GtkSetupVarMenu( p_intf, (vlc_object_t *)p_aout, p_popup_menu,
1527 "audio-channels", GtkPopupAoutChannelsToggle );
1528 GtkSetupVarMenu( p_intf, (vlc_object_t *)p_aout, p_menubar_menu,
1529 "audio-channels", GtkPopupAoutChannelsToggle );
1532 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1533 p_intf->p_sys->p_window ), "menubar_audio_device" ) );
1534 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1535 p_intf->p_sys->p_popup ), "popup_audio_device" ) );
1536 GtkSetupVarMenu( p_intf, (vlc_object_t *)p_aout, p_popup_menu,
1537 "audio-device", GtkPopupAoutDeviceToggle );
1538 GtkSetupVarMenu( p_intf, (vlc_object_t *)p_aout, p_menubar_menu,
1539 "audio-device", GtkPopupAoutDeviceToggle );
1541 vlc_object_release( (vlc_object_t *)p_aout );
1543 p_intf->p_sys->b_aout_update = VLC_FALSE;
1546 if( p_intf->p_sys->b_vout_update )
1548 vout_thread_t *p_vout;
1550 p_vout = (vout_thread_t*)vlc_object_find( p_intf, VLC_OBJECT_VOUT, FIND_ANYWHERE );
1552 if( p_vout != NULL )
1555 val.b_bool = VLC_FALSE;
1557 var_Set( (vlc_object_t *)p_vout, "intf-change", val );
1560 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1561 p_intf->p_sys->p_window ), "menubar_video_device" ) );
1562 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
1563 p_intf->p_sys->p_popup ), "popup_video_device" ) );
1564 GtkSetupVarMenu( p_intf, (vlc_object_t *)p_vout, p_popup_menu,
1565 "video-device", GtkPopupVoutDeviceToggle );
1566 GtkSetupVarMenu( p_intf, (vlc_object_t *)p_vout, p_menubar_menu,
1567 "video-device", GtkPopupVoutDeviceToggle );
1570 vlc_object_release( (vlc_object_t *)p_vout );
1572 p_intf->p_sys->b_vout_update = VLC_FALSE;
1574 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );