1 /*****************************************************************************
2 * gtk_menu.c : functions to handle menu items.
3 *****************************************************************************
4 * Copyright (C) 2000, 2001 VideoLAN
5 * $Id: gtk_menu.c,v 1.6 2001/05/30 17:03:12 sam 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 GtkSetupMenus( p_intf );
181 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
189 void GtkMenubarTitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
191 intf_thread_t * p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_window" );
193 if( menuitem->active && !p_intf->p_sys->b_title_update )
195 gint i_title = (gint)user_data;
196 input_ChangeArea( p_intf->p_input,
197 p_intf->p_input->stream.pp_areas[i_title] );
199 p_intf->p_sys->b_title_update = 1;
200 GtkSetupMenus( p_intf );
201 p_intf->p_sys->b_title_update = 0;
203 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
212 void GtkMenubarChapterToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
214 intf_thread_t * p_intf;
215 input_area_t * p_area;
218 GtkWidget * p_popup_menu;
220 p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_window" );
221 p_area = p_intf->p_input->stream.p_selected_area;
222 i_chapter = (gint)user_data;
224 if( menuitem->active && !p_intf->p_sys->b_chapter_update )
226 p_area->i_part = i_chapter;
227 input_ChangeArea( p_intf->p_input, (input_area_t*)p_area );
229 snprintf( psz_chapter, 4, "%02d", p_area->i_part );
230 psz_chapter[ 4 ] = '\0';
231 gtk_label_set_text( p_intf->p_sys->p_label_chapter, psz_chapter );
233 p_intf->p_sys->b_chapter_update = 1;
234 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
235 p_intf->p_sys->p_popup ), "popup_navigation" ) );
237 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
238 GtkTitleMenu( p_intf, p_popup_menu, GtkPopupNavigationToggle );
239 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
241 p_intf->p_sys->b_chapter_update = 0;
243 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
252 #define GtkAngleToggle( intf, window, menu, callback ) \
253 intf_thread_t * p_intf; \
254 GtkWidget * p_menu; \
255 input_area_t * p_area; \
257 p_intf = GetIntf( GTK_WIDGET(menuitem), (intf) ); \
259 if( menuitem->active && !p_intf->p_sys->b_angle_update ) \
261 p_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( \
262 p_intf->p_sys->window ), (menu) ) ); \
263 p_area = p_intf->p_input->stream.p_selected_area; \
264 p_area->i_angle = (gint)user_data; \
266 input_ChangeArea( p_intf->p_input, (input_area_t*)p_area ); \
268 p_intf->p_sys->b_angle_update = 1; \
269 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock ); \
270 GtkRadioMenu( p_intf, p_menu, NULL, "Angle", \
271 p_area->i_angle_nb, p_area->i_angle, (callback) ); \
272 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock ); \
273 p_intf->p_sys->b_angle_update = 0; \
276 void GtkMenubarAngleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
278 GtkAngleToggle( "intf_window", p_popup, "popup_angle",
279 GtkPopupAngleToggle );
282 void GtkPopupAngleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
284 GtkAngleToggle( "intf_popup", p_window, "menubar_angle",
285 GtkMenubarAngleToggle );
288 #undef GtkAngleToggle
290 /****************************************************************************
291 * Functions to generate menus
292 ****************************************************************************/
294 /*****************************************************************************
295 * GtkRadioMenu: update interactive menus of the interface
296 *****************************************************************************
297 * Sets up menus with information from input
298 * Warning: since this function is designed to be called by management
299 * function, the interface lock has to be taken
300 *****************************************************************************/
301 static gint GtkRadioMenu( intf_thread_t * p_intf,
302 GtkWidget * p_root, GSList * p_menu_group,
303 char * psz_item_name,
304 int i_nb, int i_selected,
305 void( *pf_toggle )( GtkCheckMenuItem *, gpointer ) )
307 char psz_name[ GTK_MENU_LABEL_SIZE ];
309 GtkWidget * p_submenu;
310 GtkWidget * p_item_group;
312 GtkWidget * p_item_selected;
316 /* temporary hack to avoid blank menu when an open menu is removed */
317 if( GTK_MENU_ITEM(p_root)->submenu != NULL )
319 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
321 /* removes previous menu */
322 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
323 gtk_widget_set_sensitive( p_root, FALSE );
327 p_item_selected = NULL;
328 p_group = p_menu_group;
330 p_menu = gtk_menu_new();
332 for( i_item = 0 ; i_item < i_nb ; i_item++ )
334 /* we group chapters in packets of ten for small screens */
335 if( ( i_item % 10 == 0 ) && ( i_nb > 20 ) )
339 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_item_group ),
341 gtk_menu_append( GTK_MENU( p_menu ), p_item_group );
344 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
345 "%ss %d to %d", psz_item_name, i_item + 1, i_item + 10);
346 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
347 p_item_group = gtk_menu_item_new_with_label( psz_name );
348 gtk_widget_show( p_item_group );
349 p_submenu = gtk_menu_new();
352 snprintf( psz_name, GTK_MENU_LABEL_SIZE, "%s %d",
353 psz_item_name, i_item + 1 );
354 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
356 p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
357 p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
359 if( i_selected == i_item + 1 )
361 p_item_selected = p_item;
364 gtk_widget_show( p_item );
366 /* setup signal hanling */
367 gtk_signal_connect( GTK_OBJECT( p_item ),
369 GTK_SIGNAL_FUNC( pf_toggle ),
370 (gpointer)(i_item + 1) );
374 gtk_menu_append( GTK_MENU( p_submenu ), p_item );
378 gtk_menu_append( GTK_MENU( p_menu ), p_item );
384 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_item_group ), p_submenu );
385 gtk_menu_append( GTK_MENU( p_menu ), p_item_group );
388 /* link the new menu to the title menu item */
389 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
391 /* toggle currently selected chapter
392 * We have to release the lock since input_ToggleES needs it */
393 if( p_item_selected != NULL )
395 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
396 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_selected ),
398 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
401 /* be sure that menu is sensitive, if there are several items */
404 gtk_widget_set_sensitive( p_root, TRUE );
410 /*****************************************************************************
411 * GtkLanguageMenus: update interactive menus of the interface
412 *****************************************************************************
413 * Sets up menus with information from input:
416 * Warning: since this function is designed to be called by management
417 * function, the interface lock has to be taken
418 *****************************************************************************/
419 static gint GtkLanguageMenus( gpointer p_data,
421 es_descriptor_t * p_es,
423 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
425 intf_thread_t * p_intf;
427 GtkWidget * p_separator;
429 GtkWidget * p_item_active;
431 char psz_name[ GTK_MENU_LABEL_SIZE ];
438 p_intf = (intf_thread_t *)p_data;
440 /* temporary hack to avoid blank menu when an open menu is removed */
441 if( GTK_MENU_ITEM(p_root)->submenu != NULL )
443 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
445 /* removes previous menu */
446 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
447 gtk_widget_set_sensitive( p_root, FALSE );
452 p_menu = gtk_menu_new();
454 /* special case for "off" item */
455 snprintf( psz_name, GTK_MENU_LABEL_SIZE, "None" );
456 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
458 p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
459 p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
461 gtk_widget_show( p_item );
463 /* signal hanling for off */
464 gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
465 GTK_SIGNAL_FUNC ( pf_toggle ), NULL );
467 gtk_menu_append( GTK_MENU( p_menu ), p_item );
469 p_separator = gtk_menu_item_new();
470 gtk_widget_set_sensitive( p_separator, FALSE );
471 gtk_widget_show( p_separator );
472 gtk_menu_append( GTK_MENU( p_menu ), p_separator );
474 p_item_active = NULL;
477 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
479 /* create a set of language buttons and append them to the container */
480 for( i = 0 ; i < p_intf->p_input->stream.i_es_number ; i++ )
482 if( p_intf->p_input->stream.pp_es[i]->i_cat == i_cat )
485 strcpy( psz_name, p_intf->p_input->stream.pp_es[i]->psz_desc );
486 if( psz_name[0] == '\0' )
488 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
489 "Language %d", i_item );
490 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
493 p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
495 gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
497 if( p_es == p_intf->p_input->stream.pp_es[i] )
499 /* don't lose p_item when we append into menu */
500 p_item_active = p_item;
503 gtk_widget_show( p_item );
505 /* setup signal hanling */
506 gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
507 GTK_SIGNAL_FUNC( pf_toggle ),
508 (gpointer)( p_intf->p_input->stream.pp_es[i] ) );
510 gtk_menu_append( GTK_MENU( p_menu ), p_item );
514 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
516 /* link the new menu to the menubar item */
517 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
519 /* acitvation will call signals so we can only do it
520 * when submenu is attached to menu - to get intf_window
521 * We have to release the lock since input_ToggleES needs it */
522 if( p_item_active != NULL )
524 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
528 /* be sure that menu is sensitive if non empty */
531 gtk_widget_set_sensitive( p_root, TRUE );
537 /*****************************************************************************
538 * GtkTitleMenu: sets menus for titles and chapters selection
539 *****************************************************************************
540 * Generates two types of menus:
541 * -simple list of titles
542 * -cascaded lists of chapters for each title
543 *****************************************************************************/
544 static gint GtkTitleMenu( gpointer p_data,
545 GtkWidget * p_navigation,
546 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
548 intf_thread_t * p_intf;
549 char psz_name[ GTK_MENU_LABEL_SIZE ];
550 GtkWidget * p_title_menu;
551 GtkWidget * p_title_submenu;
552 GtkWidget * p_title_item;
553 GtkWidget * p_item_active;
554 GtkWidget * p_chapter_menu;
555 GtkWidget * p_chapter_submenu;
556 GtkWidget * p_title_menu_item;
557 GtkWidget * p_chapter_menu_item;
559 GSList * p_title_group;
560 GSList * p_chapter_group;
567 p_intf = (intf_thread_t*)p_data;
569 /* temporary hack to avoid blank menu when an open menu is removed */
570 if( GTK_MENU_ITEM(p_navigation)->submenu != NULL )
572 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_navigation)->submenu ) );
574 /* removes previous menu */
575 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_navigation ) );
576 gtk_widget_set_sensitive( p_navigation, FALSE );
578 p_title_menu = gtk_menu_new();
579 p_title_group = NULL;
580 p_title_submenu = NULL;
581 p_title_menu_item = NULL;
582 p_chapter_group = NULL;
583 p_chapter_submenu = NULL;
584 p_chapter_menu_item = NULL;
585 p_item_active = NULL;
586 i_title_nb = p_intf->p_input->stream.i_area_nb;
589 for( i_title = 1 ; i_title < i_title_nb ; i_title++ )
591 /* we group titles in packets of ten for small screens */
592 if( ( i_title % 10 == 1 ) && ( i_title_nb > 20 ) )
596 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_menu_item ),
598 gtk_menu_append( GTK_MENU( p_title_menu ), p_title_menu_item );
601 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
602 "%d - %d", i_title, i_title + 9 );
603 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
604 p_title_menu_item = gtk_menu_item_new_with_label( psz_name );
605 gtk_widget_show( p_title_menu_item );
606 p_title_submenu = gtk_menu_new();
609 snprintf( psz_name, GTK_MENU_LABEL_SIZE, "Title %d (%d)", i_title,
610 p_intf->p_input->stream.pp_areas[i_title]->i_part_nb );
611 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
613 if( pf_toggle == on_menubar_title_toggle )
615 p_title_item = gtk_radio_menu_item_new_with_label( p_title_group,
618 gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_title_item ) );
620 if( p_intf->p_input->stream.pp_areas[i_title] ==
621 p_intf->p_input->stream.p_selected_area )
623 p_item_active = p_title_item;
626 /* setup signal hanling */
627 gtk_signal_connect( GTK_OBJECT( p_title_item ),
629 GTK_SIGNAL_FUNC( pf_toggle ),
630 (gpointer)(p_intf->p_input->stream.pp_areas[i_title]) );
632 if( p_intf->p_input->stream.i_area_nb > 1 )
634 /* be sure that menu is sensitive */
635 gtk_widget_set_sensitive( p_navigation, TRUE );
641 p_title_item = gtk_menu_item_new_with_label( psz_name );
644 p_chapter_menu = gtk_menu_new();
646 p_intf->p_input->stream.pp_areas[i_title]->i_part_nb;
648 for( i_chapter = 0 ; i_chapter < i_chapter_nb ; i_chapter++ )
650 /* we group chapters in packets of ten for small screens */
651 if( ( i_chapter % 10 == 0 ) && ( i_chapter_nb > 20 ) )
655 gtk_menu_item_set_submenu(
656 GTK_MENU_ITEM( p_chapter_menu_item ),
658 gtk_menu_append( GTK_MENU( p_chapter_menu ),
659 p_chapter_menu_item );
662 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
663 "%d - %d", i_chapter + 1, i_chapter + 10 );
664 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
665 p_chapter_menu_item =
666 gtk_menu_item_new_with_label( psz_name );
667 gtk_widget_show( p_chapter_menu_item );
668 p_chapter_submenu = gtk_menu_new();
671 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
672 "Chapter %d", i_chapter + 1 );
673 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
675 p_item = gtk_radio_menu_item_new_with_label(
676 p_chapter_group, psz_name );
677 p_chapter_group = gtk_radio_menu_item_group(
678 GTK_RADIO_MENU_ITEM( p_item ) );
679 gtk_widget_show( p_item );
681 #define p_area p_intf->p_input->stream.pp_areas[i_title]
682 if( ( p_area == p_intf->p_input->stream.p_selected_area ) &&
683 ( p_area->i_part == i_chapter + 1 ) )
685 p_item_active = p_item;
689 /* setup signal hanling */
690 gtk_signal_connect( GTK_OBJECT( p_item ),
692 GTK_SIGNAL_FUNC( pf_toggle ),
693 (gpointer)POS2DATA( i_title, i_chapter + 1) );
695 if( i_chapter_nb > 20 )
697 gtk_menu_append( GTK_MENU( p_chapter_submenu ), p_item );
701 gtk_menu_append( GTK_MENU( p_chapter_menu ), p_item );
705 if( i_chapter_nb > 20 )
707 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_chapter_menu_item ),
709 gtk_menu_append( GTK_MENU( p_chapter_menu ),
710 p_chapter_menu_item );
713 /* link the new menu to the title menu item */
714 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_item ),
717 if( p_intf->p_input->stream.pp_areas[i_title]->i_part_nb > 1 )
719 /* be sure that menu is sensitive */
720 gtk_widget_set_sensitive( p_navigation, TRUE );
723 GtkRadioMenu( p_intf, p_title_item, p_chapter_group, "Chapter",
724 p_intf->p_input->stream.pp_areas[i_title]->i_part_nb,
726 p_intf->p_input->stream.p_selected_area->i_part +
727 p_intf->p_input->stream.p_selected_area->i_id *100,
732 gtk_widget_show( p_title_item );
734 if( i_title_nb > 20 )
736 gtk_menu_append( GTK_MENU( p_title_submenu ), p_title_item );
740 gtk_menu_append( GTK_MENU( p_title_menu ), p_title_item );
744 if( i_title_nb > 20 )
746 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_menu_item ),
748 gtk_menu_append( GTK_MENU( p_title_menu ), p_title_menu_item );
751 /* be sure that menu is sensitive */
752 gtk_widget_set_sensitive( p_title_menu, TRUE );
754 /* link the new menu to the menubar item */
755 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_navigation ), p_title_menu );
757 /* Default selected chapter
758 * We have to release the lock since input_ToggleES needs it */
759 if( p_item_active != NULL )
761 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
762 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
764 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
767 if( p_intf->p_input->stream.i_area_nb > 1 )
769 /* be sure that menu is sensitive */
770 gtk_widget_set_sensitive( p_navigation, TRUE );
777 /*****************************************************************************
778 * GtkSetupMenus: function that generates title/chapter/audio/subpic
779 * menus with help from preceding functions
780 *****************************************************************************/
781 gint GtkSetupMenus( intf_thread_t * p_intf )
783 es_descriptor_t * p_audio_es;
784 es_descriptor_t * p_spu_es;
785 GtkWidget * p_menubar_menu;
786 GtkWidget * p_popup_menu;
789 p_intf->p_sys->b_chapter_update |= p_intf->p_sys->b_title_update;
790 p_intf->p_sys->b_angle_update |= p_intf->p_sys->b_title_update;
791 p_intf->p_sys->b_audio_update |= p_intf->p_sys->b_title_update;
792 p_intf->p_sys->b_spu_update |= p_intf->p_sys->b_title_update;
794 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
796 if( p_intf->p_sys->b_title_update )
800 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
801 p_intf->p_sys->p_window ), "menubar_title" ) );
802 GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Title",
803 p_intf->p_input->stream.i_area_nb - 1,
804 p_intf->p_input->stream.p_selected_area->i_id,
805 GtkMenubarTitleToggle );
807 snprintf( psz_title, 4, "%d",
808 p_intf->p_input->stream.p_selected_area->i_id );
809 psz_title[ 4 ] = '\0';
810 gtk_label_set_text( p_intf->p_sys->p_label_title, psz_title );
812 p_intf->p_sys->b_title_update = 0;
815 if( p_intf->p_sys->b_chapter_update )
819 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
820 p_intf->p_sys->p_popup ), "popup_navigation" ) );
821 GtkTitleMenu( p_intf, p_popup_menu, GtkPopupNavigationToggle );
823 GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Title",
824 p_intf->p_input->stream.i_area_nb - 1,
825 p_intf->p_input->stream.p_selected_area->i_id,
826 on_menubar_chapter_toggle );
829 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
830 p_intf->p_sys->p_window ), "menubar_chapter" ) );
831 GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Chapter",
832 p_intf->p_input->stream.p_selected_area->i_part_nb,
833 p_intf->p_input->stream.p_selected_area->i_part,
834 GtkMenubarChapterToggle );
837 snprintf( psz_chapter, 4, "%d",
838 p_intf->p_input->stream.p_selected_area->i_part );
839 psz_chapter[ 4 ] = '\0';
840 gtk_label_set_text( p_intf->p_sys->p_label_chapter, psz_chapter );
842 p_intf->p_sys->i_part =
843 p_intf->p_input->stream.p_selected_area->i_part;
845 p_intf->p_sys->b_chapter_update = 0;
848 if( p_intf->p_sys->b_angle_update )
850 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
851 p_intf->p_sys->p_window ), "menubar_angle" ) );
852 GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Angle",
853 p_intf->p_input->stream.p_selected_area->i_angle_nb,
854 p_intf->p_input->stream.p_selected_area->i_angle,
855 GtkMenubarAngleToggle );
857 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
858 p_intf->p_sys->p_popup ), "popup_angle" ) );
859 GtkRadioMenu( p_intf, p_popup_menu, NULL, "Angle",
860 p_intf->p_input->stream.p_selected_area->i_angle_nb,
861 p_intf->p_input->stream.p_selected_area->i_angle,
862 GtkPopupAngleToggle );
864 p_intf->p_sys->b_angle_update = 0;
867 /* look for selected ES */
871 for( i = 0 ; i < p_intf->p_input->stream.i_selected_es_number ; i++ )
873 if( p_intf->p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES )
875 p_audio_es = p_intf->p_input->stream.pp_selected_es[i];
878 if( p_intf->p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
880 p_spu_es = p_intf->p_input->stream.pp_selected_es[i];
884 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
887 if( p_intf->p_sys->b_audio_update )
889 /* find audio root menu */
890 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
891 p_intf->p_sys->p_window ), "menubar_audio" ) );
893 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
894 p_intf->p_sys->p_popup ), "popup_audio" ) );
896 p_intf->p_sys->b_audio_update = 1;
897 GtkLanguageMenus( p_intf, p_menubar_menu, p_audio_es, AUDIO_ES,
898 GtkMenubarAudioToggle );
899 p_intf->p_sys->b_audio_update = 1;
900 GtkLanguageMenus( p_intf, p_popup_menu, p_audio_es, AUDIO_ES,
901 GtkPopupAudioToggle );
903 p_intf->p_sys->b_audio_update = 0;
906 /* sub picture menus */
907 if( p_intf->p_sys->b_spu_update )
909 /* find spu root menu */
910 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
911 p_intf->p_sys->p_window ), "menubar_subpictures" ) );
913 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
914 p_intf->p_sys->p_popup ), "popup_subpictures" ) );
916 p_intf->p_sys->b_spu_update = 1;
917 GtkLanguageMenus( p_intf, p_menubar_menu, p_spu_es, SPU_ES,
918 GtkMenubarSubtitleToggle );
919 p_intf->p_sys->b_spu_update = 1;
920 GtkLanguageMenus( p_intf, p_popup_menu, p_spu_es, SPU_ES,
921 GtkPopupSubtitleToggle );
923 p_intf->p_sys->b_spu_update = 0;