1 /*****************************************************************************
2 * gtk_menu.c : functions to handle menu items.
3 *****************************************************************************
4 * Copyright (C) 2000, 2001 VideoLAN
5 * $Id: gtk_menu.c,v 1.8 2001/05/31 16:10:05 stef Exp $
7 * Authors: Samuel Hocevar <sam@zoy.org>
8 * Stéphane Borel <stef@via.ecp.fr>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
29 #include <sys/types.h> /* off_t */
41 #include "stream_control.h"
42 #include "input_ext-intf.h"
44 #include "interface.h"
45 #include "intf_playlist.h"
49 #include "video_output.h"
50 #include "audio_output.h"
52 #include "gtk_callbacks.h"
53 #include "gtk_interface.h"
54 #include "gtk_support.h"
55 #include "gtk_playlist.h"
60 #include "modules_export.h"
65 static gint GtkLanguageMenus( gpointer , GtkWidget *, es_descriptor_t *, gint,
66 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) );
68 void GtkMenubarAudioToggle ( GtkCheckMenuItem *, gpointer );
69 void GtkPopupAudioToggle ( GtkCheckMenuItem *, gpointer );
70 void GtkMenubarSubtitleToggle( GtkCheckMenuItem *, gpointer );
71 void GtkPopupSubtitleToggle ( GtkCheckMenuItem *, gpointer );
72 static gint GtkTitleMenu( gpointer, GtkWidget *,
73 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) );
74 static gint GtkRadioMenu( intf_thread_t *, GtkWidget *, GSList *,
76 void( *pf_toggle )( GtkCheckMenuItem *, gpointer ) );
77 void GtkMenubarAngleToggle( GtkCheckMenuItem *, gpointer );
78 void GtkPopupAngleToggle( GtkCheckMenuItem *, gpointer );
80 gint GtkSetupMenus( intf_thread_t * p_intf );
82 /****************************************************************************
83 * Gtk*Toggle: callbacks to toggle the value of a checkmenuitem
84 ****************************************************************************
85 * We need separate functions for menubar and popup here since we can't use
86 * user_data to transmit intf_* and we need to refresh the other menu.
87 ****************************************************************************/
89 #define GtkLangToggle( intf, window, menu, type, callback, b_update ) \
90 intf_thread_t * p_intf; \
92 es_descriptor_t * p_es; \
94 p_intf = GetIntf( GTK_WIDGET(menuitem), (intf) ); \
96 if( !p_intf->p_sys->b_update ) \
98 p_menu = GTK_WIDGET( gtk_object_get_data( \
99 GTK_OBJECT( p_intf->p_sys->window ), (menu) ) ); \
100 p_es = (es_descriptor_t*)user_data; \
102 input_ToggleES( p_intf->p_input, p_es, menuitem->active ); \
104 p_intf->p_sys->b_update = menuitem->active; \
106 if( p_intf->p_sys->b_update ) \
108 GtkLanguageMenus( p_intf, p_menu, p_es, type, callback ); \
111 p_intf->p_sys->b_update = 0; \
118 void GtkMenubarAudioToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
120 GtkLangToggle( "intf_window", p_popup, "popup_audio", AUDIO_ES,
121 GtkPopupAudioToggle, b_audio_update );
124 void GtkPopupAudioToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
126 GtkLangToggle( "intf_popup", p_window, "menubar_audio", AUDIO_ES,
127 GtkMenubarAudioToggle, b_audio_update );
134 void GtkMenubarSubtitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
136 GtkLangToggle( "intf_window", p_popup, "popup_subpictures", SPU_ES,
137 GtkPopupSubtitleToggle, b_spu_update );
140 void GtkPopupSubtitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
142 GtkLangToggle( "intf_popup", p_window, "menubar_subpictures", SPU_ES,
143 GtkMenubarSubtitleToggle, b_spu_update );
152 void GtkPopupNavigationToggle( GtkCheckMenuItem * menuitem,
155 intf_thread_t * p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_popup" );
157 if( menuitem->active &&
158 !p_intf->p_sys->b_title_update &&
159 !p_intf->p_sys->b_chapter_update )
161 input_area_t *p_area;
163 gint i_title = DATA2TITLE( user_data );
164 gint i_chapter = DATA2CHAPTER( user_data );
166 p_area = p_intf->p_input->stream.p_selected_area;
168 if( p_area != p_intf->p_input->stream.pp_areas[i_title] )
170 p_area = p_intf->p_input->stream.pp_areas[i_title];
171 p_intf->p_sys->b_title_update = 1;
174 p_area->i_part = i_chapter;
176 input_ChangeArea( p_intf->p_input, (input_area_t*)p_area );
178 p_intf->p_sys->b_chapter_update = 1;
179 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
180 GtkSetupMenus( p_intf );
181 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
183 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
191 void GtkMenubarTitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
193 intf_thread_t * p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_window" );
195 if( menuitem->active && !p_intf->p_sys->b_title_update )
197 gint i_title = (gint)user_data;
198 input_ChangeArea( p_intf->p_input,
199 p_intf->p_input->stream.pp_areas[i_title] );
201 p_intf->p_sys->b_title_update = 1;
202 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
203 GtkSetupMenus( p_intf );
204 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
205 p_intf->p_sys->b_title_update = 0;
207 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
216 void GtkMenubarChapterToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
218 intf_thread_t * p_intf;
219 input_area_t * p_area;
222 GtkWidget * p_popup_menu;
224 p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_window" );
225 p_area = p_intf->p_input->stream.p_selected_area;
226 i_chapter = (gint)user_data;
228 if( menuitem->active && !p_intf->p_sys->b_chapter_update )
230 p_area->i_part = i_chapter;
231 input_ChangeArea( p_intf->p_input, (input_area_t*)p_area );
233 snprintf( psz_chapter, 4, "%02d", p_area->i_part );
234 psz_chapter[ 4 ] = '\0';
235 gtk_label_set_text( p_intf->p_sys->p_label_chapter, psz_chapter );
237 p_intf->p_sys->b_chapter_update = 1;
238 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
239 p_intf->p_sys->p_popup ), "popup_navigation" ) );
241 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
242 GtkTitleMenu( p_intf, p_popup_menu, GtkPopupNavigationToggle );
243 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
245 p_intf->p_sys->b_chapter_update = 0;
247 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
256 #define GtkAngleToggle( intf, window, menu, callback ) \
257 intf_thread_t * p_intf; \
258 GtkWidget * p_menu; \
259 input_area_t * p_area; \
261 p_intf = GetIntf( GTK_WIDGET(menuitem), (intf) ); \
263 if( menuitem->active && !p_intf->p_sys->b_angle_update ) \
265 p_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( \
266 p_intf->p_sys->window ), (menu) ) ); \
267 p_area = p_intf->p_input->stream.p_selected_area; \
268 p_area->i_angle = (gint)user_data; \
270 input_ChangeArea( p_intf->p_input, (input_area_t*)p_area ); \
272 p_intf->p_sys->b_angle_update = 1; \
273 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock ); \
274 GtkRadioMenu( p_intf, p_menu, NULL, "Angle", \
275 p_area->i_angle_nb, p_area->i_angle, (callback) ); \
276 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock ); \
277 p_intf->p_sys->b_angle_update = 0; \
280 void GtkMenubarAngleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
282 GtkAngleToggle( "intf_window", p_popup, "popup_angle",
283 GtkPopupAngleToggle );
286 void GtkPopupAngleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
288 GtkAngleToggle( "intf_popup", p_window, "menubar_angle",
289 GtkMenubarAngleToggle );
292 #undef GtkAngleToggle
294 /****************************************************************************
295 * Functions to generate menus
296 ****************************************************************************/
298 /*****************************************************************************
299 * GtkRadioMenu: update interactive menus of the interface
300 *****************************************************************************
301 * Sets up menus with information from input
302 * Warning: since this function is designed to be called by management
303 * function, the interface lock has to be taken
304 *****************************************************************************/
305 static gint GtkRadioMenu( intf_thread_t * p_intf,
306 GtkWidget * p_root, GSList * p_menu_group,
307 char * psz_item_name,
308 int i_nb, int i_selected,
309 void( *pf_toggle )( GtkCheckMenuItem *, gpointer ) )
311 char psz_name[ GTK_MENU_LABEL_SIZE ];
313 GtkWidget * p_submenu;
314 GtkWidget * p_item_group;
316 GtkWidget * p_item_selected;
320 /* temporary hack to avoid blank menu when an open menu is removed */
321 if( GTK_MENU_ITEM(p_root)->submenu != NULL )
323 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
325 /* removes previous menu */
326 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
327 gtk_widget_set_sensitive( p_root, FALSE );
331 p_item_selected = NULL;
332 p_group = p_menu_group;
334 p_menu = gtk_menu_new();
336 for( i_item = 0 ; i_item < i_nb ; i_item++ )
338 /* we group chapters in packets of ten for small screens */
339 if( ( i_item % 10 == 0 ) && ( i_nb > 20 ) )
343 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_item_group ),
345 gtk_menu_append( GTK_MENU( p_menu ), p_item_group );
348 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
349 "%ss %d to %d", psz_item_name, i_item + 1, i_item + 10);
350 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
351 p_item_group = gtk_menu_item_new_with_label( psz_name );
352 gtk_widget_show( p_item_group );
353 p_submenu = gtk_menu_new();
356 snprintf( psz_name, GTK_MENU_LABEL_SIZE, "%s %d",
357 psz_item_name, i_item + 1 );
358 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
360 p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
361 p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
363 if( i_selected == i_item + 1 )
365 p_item_selected = p_item;
368 gtk_widget_show( p_item );
370 /* setup signal hanling */
371 gtk_signal_connect( GTK_OBJECT( p_item ),
373 GTK_SIGNAL_FUNC( pf_toggle ),
374 (gpointer)(i_item + 1) );
378 gtk_menu_append( GTK_MENU( p_submenu ), p_item );
382 gtk_menu_append( GTK_MENU( p_menu ), p_item );
388 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_item_group ), p_submenu );
389 gtk_menu_append( GTK_MENU( p_menu ), p_item_group );
392 /* link the new menu to the title menu item */
393 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
395 /* toggle currently selected chapter
396 * We have to release the lock since input_ToggleES needs it */
397 if( p_item_selected != NULL )
399 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
400 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_selected ),
402 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
405 /* be sure that menu is sensitive, if there are several items */
408 gtk_widget_set_sensitive( p_root, TRUE );
414 /*****************************************************************************
415 * GtkLanguageMenus: update interactive menus of the interface
416 *****************************************************************************
417 * Sets up menus with information from input:
420 * Warning: since this function is designed to be called by management
421 * function, the interface lock has to be taken
422 *****************************************************************************/
423 static gint GtkLanguageMenus( gpointer p_data,
425 es_descriptor_t * p_es,
427 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
429 intf_thread_t * p_intf;
431 GtkWidget * p_separator;
433 GtkWidget * p_item_active;
435 char psz_name[ GTK_MENU_LABEL_SIZE ];
442 p_intf = (intf_thread_t *)p_data;
444 /* temporary hack to avoid blank menu when an open menu is removed */
445 if( GTK_MENU_ITEM(p_root)->submenu != NULL )
447 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
449 /* removes previous menu */
450 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
451 gtk_widget_set_sensitive( p_root, FALSE );
456 p_menu = gtk_menu_new();
458 /* special case for "off" item */
459 snprintf( psz_name, GTK_MENU_LABEL_SIZE, "None" );
460 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
462 p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
463 p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
465 gtk_widget_show( p_item );
467 /* signal hanling for off */
468 gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
469 GTK_SIGNAL_FUNC ( pf_toggle ), NULL );
471 gtk_menu_append( GTK_MENU( p_menu ), p_item );
473 p_separator = gtk_menu_item_new();
474 gtk_widget_set_sensitive( p_separator, FALSE );
475 gtk_widget_show( p_separator );
476 gtk_menu_append( GTK_MENU( p_menu ), p_separator );
478 p_item_active = NULL;
481 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
483 /* create a set of language buttons and append them to the container */
484 for( i = 0 ; i < p_intf->p_input->stream.i_es_number ; i++ )
486 if( p_intf->p_input->stream.pp_es[i]->i_cat == i_cat )
489 strcpy( psz_name, p_intf->p_input->stream.pp_es[i]->psz_desc );
490 if( psz_name[0] == '\0' )
492 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
493 "Language %d", i_item );
494 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
497 p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
499 gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
501 if( p_es == p_intf->p_input->stream.pp_es[i] )
503 /* don't lose p_item when we append into menu */
504 p_item_active = p_item;
507 gtk_widget_show( p_item );
509 /* setup signal hanling */
510 gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
511 GTK_SIGNAL_FUNC( pf_toggle ),
512 (gpointer)( p_intf->p_input->stream.pp_es[i] ) );
514 gtk_menu_append( GTK_MENU( p_menu ), p_item );
518 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
520 /* link the new menu to the menubar item */
521 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
523 /* acitvation will call signals so we can only do it
524 * when submenu is attached to menu - to get intf_window
525 * We have to release the lock since input_ToggleES needs it */
526 if( p_item_active != NULL )
528 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
532 /* be sure that menu is sensitive if non empty */
535 gtk_widget_set_sensitive( p_root, TRUE );
541 /*****************************************************************************
542 * GtkTitleMenu: sets menus for titles and chapters selection
543 *****************************************************************************
544 * Generates two types of menus:
545 * -simple list of titles
546 * -cascaded lists of chapters for each title
547 *****************************************************************************/
548 static gint GtkTitleMenu( gpointer p_data,
549 GtkWidget * p_navigation,
550 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
552 intf_thread_t * p_intf;
553 char psz_name[ GTK_MENU_LABEL_SIZE ];
554 GtkWidget * p_title_menu;
555 GtkWidget * p_title_submenu;
556 GtkWidget * p_title_item;
557 GtkWidget * p_item_active;
558 GtkWidget * p_chapter_menu;
559 GtkWidget * p_chapter_submenu;
560 GtkWidget * p_title_menu_item;
561 GtkWidget * p_chapter_menu_item;
563 GSList * p_title_group;
564 GSList * p_chapter_group;
571 p_intf = (intf_thread_t*)p_data;
573 /* temporary hack to avoid blank menu when an open menu is removed */
574 if( GTK_MENU_ITEM(p_navigation)->submenu != NULL )
576 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_navigation)->submenu ) );
578 /* removes previous menu */
579 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_navigation ) );
580 gtk_widget_set_sensitive( p_navigation, FALSE );
582 p_title_menu = gtk_menu_new();
583 p_title_group = NULL;
584 p_title_submenu = NULL;
585 p_title_menu_item = NULL;
586 p_chapter_group = NULL;
587 p_chapter_submenu = NULL;
588 p_chapter_menu_item = NULL;
589 p_item_active = NULL;
590 i_title_nb = p_intf->p_input->stream.i_area_nb;
593 for( i_title = 1 ; i_title < i_title_nb ; i_title++ )
595 /* we group titles in packets of ten for small screens */
596 if( ( i_title % 10 == 1 ) && ( i_title_nb > 20 ) )
600 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_menu_item ),
602 gtk_menu_append( GTK_MENU( p_title_menu ), p_title_menu_item );
605 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
606 "%d - %d", i_title, i_title + 9 );
607 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
608 p_title_menu_item = gtk_menu_item_new_with_label( psz_name );
609 gtk_widget_show( p_title_menu_item );
610 p_title_submenu = gtk_menu_new();
613 snprintf( psz_name, GTK_MENU_LABEL_SIZE, "Title %d (%d)", i_title,
614 p_intf->p_input->stream.pp_areas[i_title]->i_part_nb );
615 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
617 if( pf_toggle == on_menubar_title_toggle )
619 p_title_item = gtk_radio_menu_item_new_with_label( p_title_group,
622 gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_title_item ) );
624 if( p_intf->p_input->stream.pp_areas[i_title] ==
625 p_intf->p_input->stream.p_selected_area )
627 p_item_active = p_title_item;
630 /* setup signal hanling */
631 gtk_signal_connect( GTK_OBJECT( p_title_item ),
633 GTK_SIGNAL_FUNC( pf_toggle ),
634 (gpointer)(p_intf->p_input->stream.pp_areas[i_title]) );
636 if( p_intf->p_input->stream.i_area_nb > 1 )
638 /* be sure that menu is sensitive */
639 gtk_widget_set_sensitive( p_navigation, TRUE );
645 p_title_item = gtk_menu_item_new_with_label( psz_name );
648 p_chapter_menu = gtk_menu_new();
650 p_intf->p_input->stream.pp_areas[i_title]->i_part_nb;
652 for( i_chapter = 0 ; i_chapter < i_chapter_nb ; i_chapter++ )
654 /* we group chapters in packets of ten for small screens */
655 if( ( i_chapter % 10 == 0 ) && ( i_chapter_nb > 20 ) )
659 gtk_menu_item_set_submenu(
660 GTK_MENU_ITEM( p_chapter_menu_item ),
662 gtk_menu_append( GTK_MENU( p_chapter_menu ),
663 p_chapter_menu_item );
666 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
667 "%d - %d", i_chapter + 1, i_chapter + 10 );
668 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
669 p_chapter_menu_item =
670 gtk_menu_item_new_with_label( psz_name );
671 gtk_widget_show( p_chapter_menu_item );
672 p_chapter_submenu = gtk_menu_new();
675 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
676 "Chapter %d", i_chapter + 1 );
677 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
679 p_item = gtk_radio_menu_item_new_with_label(
680 p_chapter_group, psz_name );
681 p_chapter_group = gtk_radio_menu_item_group(
682 GTK_RADIO_MENU_ITEM( p_item ) );
683 gtk_widget_show( p_item );
685 #define p_area p_intf->p_input->stream.pp_areas[i_title]
686 if( ( p_area == p_intf->p_input->stream.p_selected_area ) &&
687 ( p_area->i_part == i_chapter + 1 ) )
689 p_item_active = p_item;
693 /* setup signal hanling */
694 gtk_signal_connect( GTK_OBJECT( p_item ),
696 GTK_SIGNAL_FUNC( pf_toggle ),
697 (gpointer)POS2DATA( i_title, i_chapter + 1) );
699 if( i_chapter_nb > 20 )
701 gtk_menu_append( GTK_MENU( p_chapter_submenu ), p_item );
705 gtk_menu_append( GTK_MENU( p_chapter_menu ), p_item );
709 if( i_chapter_nb > 20 )
711 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_chapter_menu_item ),
713 gtk_menu_append( GTK_MENU( p_chapter_menu ),
714 p_chapter_menu_item );
717 /* link the new menu to the title menu item */
718 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_item ),
721 if( p_intf->p_input->stream.pp_areas[i_title]->i_part_nb > 1 )
723 /* be sure that menu is sensitive */
724 gtk_widget_set_sensitive( p_navigation, TRUE );
727 GtkRadioMenu( p_intf, p_title_item, p_chapter_group, "Chapter",
728 p_intf->p_input->stream.pp_areas[i_title]->i_part_nb,
730 p_intf->p_input->stream.p_selected_area->i_part +
731 p_intf->p_input->stream.p_selected_area->i_id *100,
736 gtk_widget_show( p_title_item );
738 if( i_title_nb > 20 )
740 gtk_menu_append( GTK_MENU( p_title_submenu ), p_title_item );
744 gtk_menu_append( GTK_MENU( p_title_menu ), p_title_item );
748 if( i_title_nb > 20 )
750 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_menu_item ),
752 gtk_menu_append( GTK_MENU( p_title_menu ), p_title_menu_item );
755 /* be sure that menu is sensitive */
756 gtk_widget_set_sensitive( p_title_menu, TRUE );
758 /* link the new menu to the menubar item */
759 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_navigation ), p_title_menu );
761 /* Default selected chapter
762 * We have to release the lock since input_ToggleES needs it */
763 if( p_item_active != NULL )
765 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
766 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
768 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
771 if( p_intf->p_input->stream.i_area_nb > 1 )
773 /* be sure that menu is sensitive */
774 gtk_widget_set_sensitive( p_navigation, TRUE );
781 /*****************************************************************************
782 * GtkSetupMenus: function that generates title/chapter/audio/subpic
783 * menus with help from preceding functions
784 *****************************************************************************/
785 gint GtkSetupMenus( intf_thread_t * p_intf )
787 es_descriptor_t * p_audio_es;
788 es_descriptor_t * p_spu_es;
789 GtkWidget * p_menubar_menu;
790 GtkWidget * p_popup_menu;
793 p_intf->p_sys->b_chapter_update |= p_intf->p_sys->b_title_update;
794 p_intf->p_sys->b_angle_update |= p_intf->p_sys->b_title_update;
795 p_intf->p_sys->b_audio_update |= p_intf->p_sys->b_title_update;
796 p_intf->p_sys->b_spu_update |= p_intf->p_sys->b_title_update;
798 // vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
800 if( p_intf->p_sys->b_title_update )
804 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
805 p_intf->p_sys->p_window ), "menubar_title" ) );
806 GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Title",
807 p_intf->p_input->stream.i_area_nb - 1,
808 p_intf->p_input->stream.p_selected_area->i_id,
809 GtkMenubarTitleToggle );
811 snprintf( psz_title, 4, "%d",
812 p_intf->p_input->stream.p_selected_area->i_id );
813 psz_title[ 4 ] = '\0';
814 gtk_label_set_text( p_intf->p_sys->p_label_title, psz_title );
816 p_intf->p_sys->b_title_update = 0;
819 if( p_intf->p_sys->b_chapter_update )
823 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
824 p_intf->p_sys->p_popup ), "popup_navigation" ) );
825 GtkTitleMenu( p_intf, p_popup_menu, GtkPopupNavigationToggle );
827 GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Title",
828 p_intf->p_input->stream.i_area_nb - 1,
829 p_intf->p_input->stream.p_selected_area->i_id,
830 on_menubar_chapter_toggle );
833 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
834 p_intf->p_sys->p_window ), "menubar_chapter" ) );
835 GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Chapter",
836 p_intf->p_input->stream.p_selected_area->i_part_nb,
837 p_intf->p_input->stream.p_selected_area->i_part,
838 GtkMenubarChapterToggle );
841 snprintf( psz_chapter, 4, "%d",
842 p_intf->p_input->stream.p_selected_area->i_part );
843 psz_chapter[ 4 ] = '\0';
844 gtk_label_set_text( p_intf->p_sys->p_label_chapter, psz_chapter );
846 p_intf->p_sys->i_part =
847 p_intf->p_input->stream.p_selected_area->i_part;
849 p_intf->p_sys->b_chapter_update = 0;
852 if( p_intf->p_sys->b_angle_update )
854 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
855 p_intf->p_sys->p_window ), "menubar_angle" ) );
856 GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Angle",
857 p_intf->p_input->stream.p_selected_area->i_angle_nb,
858 p_intf->p_input->stream.p_selected_area->i_angle,
859 GtkMenubarAngleToggle );
861 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
862 p_intf->p_sys->p_popup ), "popup_angle" ) );
863 GtkRadioMenu( p_intf, p_popup_menu, NULL, "Angle",
864 p_intf->p_input->stream.p_selected_area->i_angle_nb,
865 p_intf->p_input->stream.p_selected_area->i_angle,
866 GtkPopupAngleToggle );
868 p_intf->p_sys->b_angle_update = 0;
871 /* look for selected ES */
875 for( i = 0 ; i < p_intf->p_input->stream.i_selected_es_number ; i++ )
877 if( p_intf->p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES )
879 p_audio_es = p_intf->p_input->stream.pp_selected_es[i];
882 if( p_intf->p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
884 p_spu_es = p_intf->p_input->stream.pp_selected_es[i];
888 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
891 if( p_intf->p_sys->b_audio_update )
893 /* find audio root menu */
894 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
895 p_intf->p_sys->p_window ), "menubar_audio" ) );
897 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
898 p_intf->p_sys->p_popup ), "popup_audio" ) );
900 p_intf->p_sys->b_audio_update = 1;
901 GtkLanguageMenus( p_intf, p_menubar_menu, p_audio_es, AUDIO_ES,
902 GtkMenubarAudioToggle );
903 p_intf->p_sys->b_audio_update = 1;
904 GtkLanguageMenus( p_intf, p_popup_menu, p_audio_es, AUDIO_ES,
905 GtkPopupAudioToggle );
907 p_intf->p_sys->b_audio_update = 0;
910 /* sub picture menus */
911 if( p_intf->p_sys->b_spu_update )
913 /* find spu root menu */
914 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
915 p_intf->p_sys->p_window ), "menubar_subpictures" ) );
917 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
918 p_intf->p_sys->p_popup ), "popup_subpictures" ) );
920 p_intf->p_sys->b_spu_update = 1;
921 GtkLanguageMenus( p_intf, p_menubar_menu, p_spu_es, SPU_ES,
922 GtkMenubarSubtitleToggle );
923 p_intf->p_sys->b_spu_update = 1;
924 GtkLanguageMenus( p_intf, p_popup_menu, p_spu_es, SPU_ES,
925 GtkPopupSubtitleToggle );
927 p_intf->p_sys->b_spu_update = 0;
930 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );