1 /*****************************************************************************
2 * gtk_menu.c : functions to handle menu items.
3 *****************************************************************************
4 * Copyright (C) 2000, 2001 VideoLAN
5 * $Id: gtk_menu.c,v 1.5 2001/05/24 01:24:47 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"
63 static gint GtkLanguageMenus( gpointer , GtkWidget *, es_descriptor_t *, gint,
64 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) );
66 void GtkMenubarAudioToggle ( GtkCheckMenuItem *, gpointer );
67 void GtkPopupAudioToggle ( GtkCheckMenuItem *, gpointer );
68 void GtkMenubarSubtitleToggle( GtkCheckMenuItem *, gpointer );
69 void GtkPopupSubtitleToggle ( GtkCheckMenuItem *, gpointer );
70 static gint GtkTitleMenu( gpointer, GtkWidget *,
71 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) );
72 static gint GtkRadioMenu( intf_thread_t *, GtkWidget *, GSList *,
74 void( *pf_toggle )( GtkCheckMenuItem *, gpointer ) );
75 void GtkMenubarAngleToggle( GtkCheckMenuItem *, gpointer );
76 void GtkPopupAngleToggle( GtkCheckMenuItem *, gpointer );
78 gint GtkSetupMenus( intf_thread_t * p_intf );
80 /****************************************************************************
81 * Gtk*Toggle: callbacks to toggle the value of a checkmenuitem
82 ****************************************************************************
83 * We need separate functions for menubar and popup here since we can't use
84 * user_data to transmit intf_* and we need to refresh the other menu.
85 ****************************************************************************/
87 #define GtkLangToggle( intf, window, menu, type, callback, b_update ) \
88 intf_thread_t * p_intf; \
90 es_descriptor_t * p_es; \
92 p_intf = GetIntf( GTK_WIDGET(menuitem), (intf) ); \
94 if( !p_intf->p_sys->b_update ) \
96 p_menu = GTK_WIDGET( gtk_object_get_data( \
97 GTK_OBJECT( p_intf->p_sys->window ), (menu) ) ); \
98 p_es = (es_descriptor_t*)user_data; \
100 input_ToggleES( p_intf->p_input, p_es, menuitem->active ); \
102 p_intf->p_sys->b_update = menuitem->active; \
104 if( p_intf->p_sys->b_update ) \
106 GtkLanguageMenus( p_intf, p_menu, p_es, type, callback ); \
109 p_intf->p_sys->b_update = 0; \
116 void GtkMenubarAudioToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
118 GtkLangToggle( "intf_window", p_popup, "popup_audio", AUDIO_ES,
119 GtkPopupAudioToggle, b_audio_update );
122 void GtkPopupAudioToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
124 GtkLangToggle( "intf_popup", p_window, "menubar_audio", AUDIO_ES,
125 GtkMenubarAudioToggle, b_audio_update );
132 void GtkMenubarSubtitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
134 GtkLangToggle( "intf_window", p_popup, "popup_subpictures", SPU_ES,
135 GtkPopupSubtitleToggle, b_spu_update );
138 void GtkPopupSubtitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
140 GtkLangToggle( "intf_popup", p_window, "menubar_subpictures", SPU_ES,
141 GtkMenubarSubtitleToggle, b_spu_update );
150 void GtkPopupNavigationToggle( GtkCheckMenuItem * menuitem,
153 intf_thread_t * p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_popup" );
155 if( menuitem->active &&
156 !p_intf->p_sys->b_title_update &&
157 !p_intf->p_sys->b_chapter_update )
159 input_area_t *p_area;
161 gint i_title = DATA2TITLE( user_data );
162 gint i_chapter = DATA2CHAPTER( user_data );
164 p_area = p_intf->p_input->stream.p_selected_area;
166 if( p_area != p_intf->p_input->stream.pp_areas[i_title] )
168 p_area = p_intf->p_input->stream.pp_areas[i_title];
169 p_intf->p_sys->b_title_update = 1;
172 p_area->i_part = i_chapter;
174 input_ChangeArea( p_intf->p_input, (input_area_t*)p_area );
176 p_intf->p_sys->b_chapter_update = 1;
177 GtkSetupMenus( p_intf );
179 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
187 void GtkMenubarTitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
189 intf_thread_t * p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_window" );
191 if( menuitem->active && !p_intf->p_sys->b_title_update )
193 gint i_title = (gint)user_data;
194 input_ChangeArea( p_intf->p_input,
195 p_intf->p_input->stream.pp_areas[i_title] );
197 p_intf->p_sys->b_title_update = 1;
198 GtkSetupMenus( p_intf );
199 p_intf->p_sys->b_title_update = 0;
201 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
210 void GtkMenubarChapterToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
212 intf_thread_t * p_intf;
213 input_area_t * p_area;
216 GtkWidget * p_popup_menu;
218 p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_window" );
219 p_area = p_intf->p_input->stream.p_selected_area;
220 i_chapter = (gint)user_data;
222 if( menuitem->active && !p_intf->p_sys->b_chapter_update )
224 p_area->i_part = i_chapter;
225 input_ChangeArea( p_intf->p_input, (input_area_t*)p_area );
227 snprintf( psz_chapter, 4, "%02d", p_area->i_part );
228 psz_chapter[ 4 ] = '\0';
229 gtk_label_set_text( p_intf->p_sys->p_label_chapter, psz_chapter );
231 p_intf->p_sys->b_chapter_update = 1;
232 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
233 p_intf->p_sys->p_popup ), "popup_navigation" ) );
235 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
236 GtkTitleMenu( p_intf, p_popup_menu, GtkPopupNavigationToggle );
237 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
239 p_intf->p_sys->b_chapter_update = 0;
241 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
250 #define GtkAngleToggle( intf, window, menu, callback ) \
251 intf_thread_t * p_intf; \
252 GtkWidget * p_menu; \
253 input_area_t * p_area; \
255 p_intf = GetIntf( GTK_WIDGET(menuitem), (intf) ); \
257 if( menuitem->active && !p_intf->p_sys->b_angle_update ) \
259 p_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( \
260 p_intf->p_sys->window ), (menu) ) ); \
261 p_area = p_intf->p_input->stream.p_selected_area; \
262 p_area->i_angle = (gint)user_data; \
264 input_ChangeArea( p_intf->p_input, (input_area_t*)p_area ); \
266 p_intf->p_sys->b_angle_update = 1; \
267 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock ); \
268 GtkRadioMenu( p_intf, p_menu, NULL, "Angle", \
269 p_area->i_angle_nb, p_area->i_angle, (callback) ); \
270 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock ); \
271 p_intf->p_sys->b_angle_update = 0; \
274 void GtkMenubarAngleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
276 GtkAngleToggle( "intf_window", p_popup, "popup_angle",
277 GtkPopupAngleToggle );
280 void GtkPopupAngleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
282 GtkAngleToggle( "intf_popup", p_window, "menubar_angle",
283 GtkMenubarAngleToggle );
286 #undef GtkAngleToggle
288 /****************************************************************************
289 * Functions to generate menus
290 ****************************************************************************/
292 /*****************************************************************************
293 * GtkRadioMenu: update interactive menus of the interface
294 *****************************************************************************
295 * Sets up menus with information from input
296 * Warning: since this function is designed to be called by management
297 * function, the interface lock has to be taken
298 *****************************************************************************/
299 static gint GtkRadioMenu( intf_thread_t * p_intf,
300 GtkWidget * p_root, GSList * p_menu_group,
301 char * psz_item_name,
302 int i_nb, int i_selected,
303 void( *pf_toggle )( GtkCheckMenuItem *, gpointer ) )
305 char psz_name[ GTK_MENU_LABEL_SIZE ];
307 GtkWidget * p_submenu;
308 GtkWidget * p_item_group;
310 GtkWidget * p_item_selected;
314 /* temporary hack to avoid blank menu when an open menu is removed */
315 if( GTK_MENU_ITEM(p_root)->submenu != NULL )
317 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
319 /* removes previous menu */
320 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
321 gtk_widget_set_sensitive( p_root, FALSE );
325 p_item_selected = NULL;
326 p_group = p_menu_group;
328 p_menu = gtk_menu_new();
330 for( i_item = 0 ; i_item < i_nb ; i_item++ )
332 /* we group chapters in packets of ten for small screens */
333 if( ( i_item % 10 == 0 ) && ( i_nb > 20 ) )
337 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_item_group ),
339 gtk_menu_append( GTK_MENU( p_menu ), p_item_group );
342 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
343 "%ss %d to %d", psz_item_name, i_item + 1, i_item + 10);
344 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
345 p_item_group = gtk_menu_item_new_with_label( psz_name );
346 gtk_widget_show( p_item_group );
347 p_submenu = gtk_menu_new();
350 snprintf( psz_name, GTK_MENU_LABEL_SIZE, "%s %d",
351 psz_item_name, i_item + 1 );
352 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
354 p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
355 p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
357 if( i_selected == i_item + 1 )
359 p_item_selected = p_item;
362 gtk_widget_show( p_item );
364 /* setup signal hanling */
365 gtk_signal_connect( GTK_OBJECT( p_item ),
367 GTK_SIGNAL_FUNC( pf_toggle ),
368 (gpointer)(i_item + 1) );
372 gtk_menu_append( GTK_MENU( p_submenu ), p_item );
376 gtk_menu_append( GTK_MENU( p_menu ), p_item );
382 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_item_group ), p_submenu );
383 gtk_menu_append( GTK_MENU( p_menu ), p_item_group );
386 /* link the new menu to the title menu item */
387 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
389 /* toggle currently selected chapter
390 * We have to release the lock since input_ToggleES needs it */
391 if( p_item_selected != NULL )
393 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
394 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_selected ),
396 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
399 /* be sure that menu is sensitive, if there are several items */
402 gtk_widget_set_sensitive( p_root, TRUE );
408 /*****************************************************************************
409 * GtkLanguageMenus: update interactive menus of the interface
410 *****************************************************************************
411 * Sets up menus with information from input:
414 * Warning: since this function is designed to be called by management
415 * function, the interface lock has to be taken
416 *****************************************************************************/
417 static gint GtkLanguageMenus( gpointer p_data,
419 es_descriptor_t * p_es,
421 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
423 intf_thread_t * p_intf;
425 GtkWidget * p_separator;
427 GtkWidget * p_item_active;
429 char psz_name[ GTK_MENU_LABEL_SIZE ];
436 p_intf = (intf_thread_t *)p_data;
438 /* temporary hack to avoid blank menu when an open menu is removed */
439 if( GTK_MENU_ITEM(p_root)->submenu != NULL )
441 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
443 /* removes previous menu */
444 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
445 gtk_widget_set_sensitive( p_root, FALSE );
450 p_menu = gtk_menu_new();
452 /* special case for "off" item */
453 snprintf( psz_name, GTK_MENU_LABEL_SIZE, "None" );
454 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
456 p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
457 p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
459 gtk_widget_show( p_item );
461 /* signal hanling for off */
462 gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
463 GTK_SIGNAL_FUNC ( pf_toggle ), NULL );
465 gtk_menu_append( GTK_MENU( p_menu ), p_item );
467 p_separator = gtk_menu_item_new();
468 gtk_widget_set_sensitive( p_separator, FALSE );
469 gtk_widget_show( p_separator );
470 gtk_menu_append( GTK_MENU( p_menu ), p_separator );
472 p_item_active = NULL;
475 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
477 /* create a set of language buttons and append them to the container */
478 for( i = 0 ; i < p_intf->p_input->stream.i_es_number ; i++ )
480 if( p_intf->p_input->stream.pp_es[i]->i_cat == i_cat )
483 strcpy( psz_name, p_intf->p_input->stream.pp_es[i]->psz_desc );
484 if( psz_name[0] == '\0' )
486 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
487 "Language %d", i_item );
488 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
491 p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
493 gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
495 if( p_es == p_intf->p_input->stream.pp_es[i] )
497 /* don't lose p_item when we append into menu */
498 p_item_active = p_item;
501 gtk_widget_show( p_item );
503 /* setup signal hanling */
504 gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
505 GTK_SIGNAL_FUNC( pf_toggle ),
506 (gpointer)( p_intf->p_input->stream.pp_es[i] ) );
508 gtk_menu_append( GTK_MENU( p_menu ), p_item );
512 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
514 /* link the new menu to the menubar item */
515 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
517 /* acitvation will call signals so we can only do it
518 * when submenu is attached to menu - to get intf_window
519 * We have to release the lock since input_ToggleES needs it */
520 if( p_item_active != NULL )
522 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
526 /* be sure that menu is sensitive if non empty */
529 gtk_widget_set_sensitive( p_root, TRUE );
535 /*****************************************************************************
536 * GtkTitleMenu: sets menus for titles and chapters selection
537 *****************************************************************************
538 * Generates two types of menus:
539 * -simple list of titles
540 * -cascaded lists of chapters for each title
541 *****************************************************************************/
542 static gint GtkTitleMenu( gpointer p_data,
543 GtkWidget * p_navigation,
544 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
546 intf_thread_t * p_intf;
547 char psz_name[ GTK_MENU_LABEL_SIZE ];
548 GtkWidget * p_title_menu;
549 GtkWidget * p_title_submenu;
550 GtkWidget * p_title_item;
551 GtkWidget * p_item_active;
552 GtkWidget * p_chapter_menu;
553 GtkWidget * p_chapter_submenu;
554 GtkWidget * p_title_menu_item;
555 GtkWidget * p_chapter_menu_item;
557 GSList * p_title_group;
558 GSList * p_chapter_group;
565 p_intf = (intf_thread_t*)p_data;
567 /* temporary hack to avoid blank menu when an open menu is removed */
568 if( GTK_MENU_ITEM(p_navigation)->submenu != NULL )
570 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_navigation)->submenu ) );
572 /* removes previous menu */
573 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_navigation ) );
574 gtk_widget_set_sensitive( p_navigation, FALSE );
576 p_title_menu = gtk_menu_new();
577 p_title_group = NULL;
578 p_title_submenu = NULL;
579 p_title_menu_item = NULL;
580 p_chapter_group = NULL;
581 p_chapter_submenu = NULL;
582 p_chapter_menu_item = NULL;
583 p_item_active = NULL;
584 i_title_nb = p_intf->p_input->stream.i_area_nb;
587 for( i_title = 1 ; i_title < i_title_nb ; i_title++ )
589 /* we group titles in packets of ten for small screens */
590 if( ( i_title % 10 == 1 ) && ( i_title_nb > 20 ) )
594 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_menu_item ),
596 gtk_menu_append( GTK_MENU( p_title_menu ), p_title_menu_item );
599 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
600 "%d - %d", i_title, i_title + 9 );
601 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
602 p_title_menu_item = gtk_menu_item_new_with_label( psz_name );
603 gtk_widget_show( p_title_menu_item );
604 p_title_submenu = gtk_menu_new();
607 snprintf( psz_name, GTK_MENU_LABEL_SIZE, "Title %d (%d)", i_title,
608 p_intf->p_input->stream.pp_areas[i_title]->i_part_nb );
609 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
611 if( pf_toggle == on_menubar_title_toggle )
613 p_title_item = gtk_radio_menu_item_new_with_label( p_title_group,
616 gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_title_item ) );
618 if( p_intf->p_input->stream.pp_areas[i_title] ==
619 p_intf->p_input->stream.p_selected_area )
621 p_item_active = p_title_item;
624 /* setup signal hanling */
625 gtk_signal_connect( GTK_OBJECT( p_title_item ),
627 GTK_SIGNAL_FUNC( pf_toggle ),
628 (gpointer)(p_intf->p_input->stream.pp_areas[i_title]) );
630 if( p_intf->p_input->stream.i_area_nb > 1 )
632 /* be sure that menu is sensitive */
633 gtk_widget_set_sensitive( p_navigation, TRUE );
639 p_title_item = gtk_menu_item_new_with_label( psz_name );
642 p_chapter_menu = gtk_menu_new();
644 p_intf->p_input->stream.pp_areas[i_title]->i_part_nb;
646 for( i_chapter = 0 ; i_chapter < i_chapter_nb ; i_chapter++ )
648 /* we group chapters in packets of ten for small screens */
649 if( ( i_chapter % 10 == 0 ) && ( i_chapter_nb > 20 ) )
653 gtk_menu_item_set_submenu(
654 GTK_MENU_ITEM( p_chapter_menu_item ),
656 gtk_menu_append( GTK_MENU( p_chapter_menu ),
657 p_chapter_menu_item );
660 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
661 "%d - %d", i_chapter + 1, i_chapter + 10 );
662 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
663 p_chapter_menu_item =
664 gtk_menu_item_new_with_label( psz_name );
665 gtk_widget_show( p_chapter_menu_item );
666 p_chapter_submenu = gtk_menu_new();
669 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
670 "Chapter %d", i_chapter + 1 );
671 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
673 p_item = gtk_radio_menu_item_new_with_label(
674 p_chapter_group, psz_name );
675 p_chapter_group = gtk_radio_menu_item_group(
676 GTK_RADIO_MENU_ITEM( p_item ) );
677 gtk_widget_show( p_item );
679 #define p_area p_intf->p_input->stream.pp_areas[i_title]
680 if( ( p_area == p_intf->p_input->stream.p_selected_area ) &&
681 ( p_area->i_part == i_chapter + 1 ) )
683 p_item_active = p_item;
687 /* setup signal hanling */
688 gtk_signal_connect( GTK_OBJECT( p_item ),
690 GTK_SIGNAL_FUNC( pf_toggle ),
691 (gpointer)POS2DATA( i_title, i_chapter + 1) );
693 if( i_chapter_nb > 20 )
695 gtk_menu_append( GTK_MENU( p_chapter_submenu ), p_item );
699 gtk_menu_append( GTK_MENU( p_chapter_menu ), p_item );
703 if( i_chapter_nb > 20 )
705 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_chapter_menu_item ),
707 gtk_menu_append( GTK_MENU( p_chapter_menu ),
708 p_chapter_menu_item );
711 /* link the new menu to the title menu item */
712 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_item ),
715 if( p_intf->p_input->stream.pp_areas[i_title]->i_part_nb > 1 )
717 /* be sure that menu is sensitive */
718 gtk_widget_set_sensitive( p_navigation, TRUE );
721 GtkRadioMenu( p_intf, p_title_item, p_chapter_group, "Chapter",
722 p_intf->p_input->stream.pp_areas[i_title]->i_part_nb,
724 p_intf->p_input->stream.p_selected_area->i_part +
725 p_intf->p_input->stream.p_selected_area->i_id *100,
730 gtk_widget_show( p_title_item );
732 if( i_title_nb > 20 )
734 gtk_menu_append( GTK_MENU( p_title_submenu ), p_title_item );
738 gtk_menu_append( GTK_MENU( p_title_menu ), p_title_item );
742 if( i_title_nb > 20 )
744 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_menu_item ),
746 gtk_menu_append( GTK_MENU( p_title_menu ), p_title_menu_item );
749 /* be sure that menu is sensitive */
750 gtk_widget_set_sensitive( p_title_menu, TRUE );
752 /* link the new menu to the menubar item */
753 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_navigation ), p_title_menu );
755 /* Default selected chapter
756 * We have to release the lock since input_ToggleES needs it */
757 if( p_item_active != NULL )
759 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
760 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
762 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
765 if( p_intf->p_input->stream.i_area_nb > 1 )
767 /* be sure that menu is sensitive */
768 gtk_widget_set_sensitive( p_navigation, TRUE );
775 /*****************************************************************************
776 * GtkSetupMenus: function that generates title/chapter/audio/subpic
777 * menus with help from preceding functions
778 *****************************************************************************/
779 gint GtkSetupMenus( intf_thread_t * p_intf )
781 es_descriptor_t * p_audio_es;
782 es_descriptor_t * p_spu_es;
783 GtkWidget * p_menubar_menu;
784 GtkWidget * p_popup_menu;
787 p_intf->p_sys->b_chapter_update |= p_intf->p_sys->b_title_update;
788 p_intf->p_sys->b_angle_update |= p_intf->p_sys->b_title_update;
789 p_intf->p_sys->b_audio_update |= p_intf->p_sys->b_title_update;
790 p_intf->p_sys->b_spu_update |= p_intf->p_sys->b_title_update;
792 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
794 if( p_intf->p_sys->b_title_update )
798 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
799 p_intf->p_sys->p_window ), "menubar_title" ) );
800 GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Title",
801 p_intf->p_input->stream.i_area_nb - 1,
802 p_intf->p_input->stream.p_selected_area->i_id,
803 GtkMenubarTitleToggle );
805 snprintf( psz_title, 4, "%d",
806 p_intf->p_input->stream.p_selected_area->i_id );
807 psz_title[ 4 ] = '\0';
808 gtk_label_set_text( p_intf->p_sys->p_label_title, psz_title );
810 p_intf->p_sys->b_title_update = 0;
813 if( p_intf->p_sys->b_chapter_update )
817 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
818 p_intf->p_sys->p_popup ), "popup_navigation" ) );
819 GtkTitleMenu( p_intf, p_popup_menu, GtkPopupNavigationToggle );
821 GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Title",
822 p_intf->p_input->stream.i_area_nb - 1,
823 p_intf->p_input->stream.p_selected_area->i_id,
824 on_menubar_chapter_toggle );
827 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
828 p_intf->p_sys->p_window ), "menubar_chapter" ) );
829 GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Chapter",
830 p_intf->p_input->stream.p_selected_area->i_part_nb,
831 p_intf->p_input->stream.p_selected_area->i_part,
832 GtkMenubarChapterToggle );
835 snprintf( psz_chapter, 4, "%d",
836 p_intf->p_input->stream.p_selected_area->i_part );
837 psz_chapter[ 4 ] = '\0';
838 gtk_label_set_text( p_intf->p_sys->p_label_chapter, psz_chapter );
840 p_intf->p_sys->i_part =
841 p_intf->p_input->stream.p_selected_area->i_part;
843 p_intf->p_sys->b_chapter_update = 0;
846 if( p_intf->p_sys->b_angle_update )
848 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
849 p_intf->p_sys->p_window ), "menubar_angle" ) );
850 GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Angle",
851 p_intf->p_input->stream.p_selected_area->i_angle_nb,
852 p_intf->p_input->stream.p_selected_area->i_angle,
853 GtkMenubarAngleToggle );
855 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
856 p_intf->p_sys->p_popup ), "popup_angle" ) );
857 GtkRadioMenu( p_intf, p_popup_menu, NULL, "Angle",
858 p_intf->p_input->stream.p_selected_area->i_angle_nb,
859 p_intf->p_input->stream.p_selected_area->i_angle,
860 GtkPopupAngleToggle );
862 p_intf->p_sys->b_angle_update = 0;
865 /* look for selected ES */
869 for( i = 0 ; i < p_intf->p_input->stream.i_selected_es_number ; i++ )
871 if( p_intf->p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES )
873 p_audio_es = p_intf->p_input->stream.pp_selected_es[i];
876 if( p_intf->p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
878 p_spu_es = p_intf->p_input->stream.pp_selected_es[i];
882 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
885 if( p_intf->p_sys->b_audio_update )
887 /* find audio root menu */
888 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
889 p_intf->p_sys->p_window ), "menubar_audio" ) );
891 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
892 p_intf->p_sys->p_popup ), "popup_audio" ) );
894 p_intf->p_sys->b_audio_update = 1;
895 GtkLanguageMenus( p_intf, p_menubar_menu, p_audio_es, AUDIO_ES,
896 GtkMenubarAudioToggle );
897 p_intf->p_sys->b_audio_update = 1;
898 GtkLanguageMenus( p_intf, p_popup_menu, p_audio_es, AUDIO_ES,
899 GtkPopupAudioToggle );
901 p_intf->p_sys->b_audio_update = 0;
904 /* sub picture menus */
905 if( p_intf->p_sys->b_spu_update )
907 /* find spu root menu */
908 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
909 p_intf->p_sys->p_window ), "menubar_subpictures" ) );
911 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
912 p_intf->p_sys->p_popup ), "popup_subpictures" ) );
914 p_intf->p_sys->b_spu_update = 1;
915 GtkLanguageMenus( p_intf, p_menubar_menu, p_spu_es, SPU_ES,
916 GtkMenubarSubtitleToggle );
917 p_intf->p_sys->b_spu_update = 1;
918 GtkLanguageMenus( p_intf, p_popup_menu, p_spu_es, SPU_ES,
919 GtkPopupSubtitleToggle );
921 p_intf->p_sys->b_spu_update = 0;