1 /*****************************************************************************
2 * gtk_menu.c : functions to handle menu items.
3 *****************************************************************************
4 * Copyright (C) 2000, 2001 VideoLAN
5 * $Id: gtk_menu.c,v 1.17 2001/12/30 07:09:55 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 *****************************************************************************/
28 #include <sys/types.h> /* off_t */
31 #include <videolan/vlc.h>
33 #ifdef MODULE_NAME_IS_gnome
41 #include "stream_control.h"
42 #include "input_ext-intf.h"
44 #include "interface.h"
45 #include "intf_playlist.h"
48 #include "video_output.h"
49 #include "audio_output.h"
51 #include "gtk_callbacks.h"
52 #include "gtk_interface.h"
53 #include "gtk_support.h"
54 #include "gtk_playlist.h"
55 #include "gtk_common.h"
60 static gint GtkLanguageMenus( gpointer , GtkWidget *, es_descriptor_t *, gint,
61 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) );
63 void GtkMenubarAudioToggle ( GtkCheckMenuItem *, gpointer );
64 void GtkPopupAudioToggle ( GtkCheckMenuItem *, gpointer );
65 void GtkMenubarSubtitleToggle( GtkCheckMenuItem *, gpointer );
66 void GtkPopupSubtitleToggle ( GtkCheckMenuItem *, gpointer );
67 static gint GtkTitleMenu( gpointer, GtkWidget *,
68 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) );
69 static gint GtkRadioMenu( intf_thread_t *, GtkWidget *, GSList *,
71 void( *pf_toggle )( GtkCheckMenuItem *, gpointer ) );
72 void GtkMenubarAngleToggle( GtkCheckMenuItem *, gpointer );
73 void GtkPopupAngleToggle( 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( intf, window, menu, type, callback, b_update ) \
85 intf_thread_t * p_intf; \
87 es_descriptor_t * p_es; \
89 p_intf = GetIntf( GTK_WIDGET(menuitem), (intf) ); \
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_input, p_es, menuitem->active ); \
99 p_intf->p_sys->b_update = menuitem->active; \
101 if( p_intf->p_sys->b_update ) \
103 GtkLanguageMenus( p_intf, p_menu, p_es, type, callback ); \
106 p_intf->p_sys->b_update = 0; \
113 void GtkMenubarAudioToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
115 GTKLANGTOGGLE( "intf_window", p_popup, "popup_audio", AUDIO_ES,
116 GtkPopupAudioToggle, b_audio_update );
119 void GtkPopupAudioToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
121 GTKLANGTOGGLE( "intf_popup", p_window, "menubar_audio", AUDIO_ES,
122 GtkMenubarAudioToggle, b_audio_update );
129 void GtkMenubarSubtitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
131 GTKLANGTOGGLE( "intf_window", p_popup, "popup_subpictures", SPU_ES,
132 GtkPopupSubtitleToggle, b_spu_update );
135 void GtkPopupSubtitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
137 GTKLANGTOGGLE( "intf_popup", p_window, "menubar_subpictures", SPU_ES,
138 GtkMenubarSubtitleToggle, b_spu_update );
147 void GtkPopupNavigationToggle( GtkCheckMenuItem * menuitem,
150 intf_thread_t * p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_popup" );
152 if( menuitem->active &&
153 !p_intf->p_sys->b_title_update &&
154 !p_intf->p_sys->b_chapter_update )
156 input_area_t *p_area;
158 gint i_title = DATA2TITLE( user_data );
159 gint i_chapter = DATA2CHAPTER( user_data );
161 p_area = p_intf->p_input->stream.p_selected_area;
163 if( p_area != p_intf->p_input->stream.pp_areas[i_title] )
165 p_area = p_intf->p_input->stream.pp_areas[i_title];
166 p_intf->p_sys->b_title_update = 1;
169 p_area->i_part = i_chapter;
171 input_ChangeArea( p_intf->p_input, (input_area_t*)p_area );
173 p_intf->p_sys->b_chapter_update = 1;
174 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
175 GtkSetupMenus( p_intf );
176 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
178 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
186 void GtkMenubarTitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
188 intf_thread_t * p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_window" );
190 if( menuitem->active && !p_intf->p_sys->b_title_update )
192 gint i_title = (gint)((long)user_data);
193 input_ChangeArea( p_intf->p_input,
194 p_intf->p_input->stream.pp_areas[i_title] );
196 p_intf->p_sys->b_title_update = 1;
197 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
198 GtkSetupMenus( p_intf );
199 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
200 p_intf->p_sys->b_title_update = 0;
202 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
211 void GtkMenubarChapterToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
213 intf_thread_t * p_intf;
214 input_area_t * p_area;
217 GtkWidget * p_popup_menu;
219 p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_window" );
220 p_area = p_intf->p_input->stream.p_selected_area;
221 i_chapter = (gint)((long)user_data);
223 if( menuitem->active && !p_intf->p_sys->b_chapter_update )
225 p_area->i_part = i_chapter;
226 input_ChangeArea( p_intf->p_input, (input_area_t*)p_area );
228 snprintf( psz_chapter, 4, "%02d", p_area->i_part );
229 psz_chapter[ 4 ] = '\0';
230 gtk_label_set_text( p_intf->p_sys->p_label_chapter, psz_chapter );
232 p_intf->p_sys->b_chapter_update = 1;
233 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
234 p_intf->p_sys->p_popup ), "popup_navigation" ) );
236 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
237 GtkTitleMenu( p_intf, p_popup_menu, GtkPopupNavigationToggle );
238 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
240 p_intf->p_sys->b_chapter_update = 0;
242 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
251 #define GTKANGLETOGGLE( intf, window, menu, callback ) \
252 intf_thread_t * p_intf; \
253 GtkWidget * p_menu; \
254 input_area_t * p_area; \
256 p_intf = GetIntf( GTK_WIDGET(menuitem), (intf) ); \
258 if( menuitem->active && !p_intf->p_sys->b_angle_update ) \
260 p_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( \
261 p_intf->p_sys->window ), (menu) ) ); \
262 p_area = p_intf->p_input->stream.p_selected_area; \
263 p_area->i_angle = (gint)((long)user_data); \
265 input_ChangeArea( p_intf->p_input, (input_area_t*)p_area ); \
267 p_intf->p_sys->b_angle_update = 1; \
268 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock ); \
269 GtkRadioMenu( p_intf, p_menu, NULL, "Angle", \
270 p_area->i_angle_nb, p_area->i_angle, (callback) ); \
271 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock ); \
272 p_intf->p_sys->b_angle_update = 0; \
275 void GtkMenubarAngleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
277 GTKANGLETOGGLE( "intf_window", p_popup, "popup_angle",
278 GtkPopupAngleToggle );
281 void GtkPopupAngleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
283 GTKANGLETOGGLE( "intf_popup", p_window, "menubar_angle",
284 GtkMenubarAngleToggle );
287 #undef GTKANGLETOGGLE
289 /****************************************************************************
290 * Functions to generate menus
291 ****************************************************************************/
293 /*****************************************************************************
294 * GtkRadioMenu: update interactive menus of the interface
295 *****************************************************************************
296 * Sets up menus with information from input
297 * Warning: since this function is designed to be called by management
298 * function, the interface lock has to be taken
299 *****************************************************************************/
300 static gint GtkRadioMenu( intf_thread_t * p_intf,
301 GtkWidget * p_root, GSList * p_menu_group,
302 char * psz_item_name,
303 int i_nb, int i_selected,
304 void( *pf_toggle )( GtkCheckMenuItem *, gpointer ) )
306 char psz_name[ GTK_MENU_LABEL_SIZE ];
308 GtkWidget * p_submenu;
309 GtkWidget * p_item_group;
311 GtkWidget * p_item_selected;
315 /* temporary hack to avoid blank menu when an open menu is removed */
316 if( GTK_MENU_ITEM(p_root)->submenu != NULL )
318 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
320 /* removes previous menu */
321 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
322 gtk_widget_set_sensitive( p_root, FALSE );
326 p_item_selected = NULL;
327 p_group = p_menu_group;
329 p_menu = gtk_menu_new();
331 for( i_item = 0 ; i_item < i_nb ; i_item++ )
333 /* we group chapters in packets of ten for small screens */
334 if( ( i_item % 10 == 0 ) && ( i_nb > 20 ) )
338 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_item_group ),
340 gtk_menu_append( GTK_MENU( p_menu ), p_item_group );
343 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
344 "%ss %d to %d", psz_item_name, i_item + 1, i_item + 10);
345 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
346 p_item_group = gtk_menu_item_new_with_label( psz_name );
347 gtk_widget_show( p_item_group );
348 p_submenu = gtk_menu_new();
351 snprintf( psz_name, GTK_MENU_LABEL_SIZE, "%s %d",
352 psz_item_name, i_item + 1 );
353 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
355 p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
356 p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
358 if( i_selected == i_item + 1 )
360 p_item_selected = p_item;
363 gtk_widget_show( p_item );
365 /* setup signal hanling */
366 gtk_signal_connect( GTK_OBJECT( p_item ),
368 GTK_SIGNAL_FUNC( pf_toggle ),
369 (gpointer)((long)(i_item + 1)) );
373 gtk_menu_append( GTK_MENU( p_submenu ), p_item );
377 gtk_menu_append( GTK_MENU( p_menu ), p_item );
383 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_item_group ), p_submenu );
384 gtk_menu_append( GTK_MENU( p_menu ), p_item_group );
387 /* link the new menu to the title menu item */
388 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
390 /* toggle currently selected chapter
391 * We have to release the lock since input_ToggleES needs it */
392 if( p_item_selected != NULL )
394 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
395 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_selected ),
397 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
400 /* be sure that menu is sensitive, if there are several items */
403 gtk_widget_set_sensitive( p_root, TRUE );
409 /*****************************************************************************
410 * GtkLanguageMenus: update interactive menus of the interface
411 *****************************************************************************
412 * Sets up menus with information from input:
415 * Warning: since this function is designed to be called by management
416 * function, the interface lock has to be taken
417 *****************************************************************************/
418 static gint GtkLanguageMenus( gpointer p_data,
420 es_descriptor_t * p_es,
422 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
424 intf_thread_t * p_intf;
426 GtkWidget * p_separator;
428 GtkWidget * p_item_active;
430 char psz_name[ GTK_MENU_LABEL_SIZE ];
437 p_intf = (intf_thread_t *)p_data;
439 /* temporary hack to avoid blank menu when an open menu is removed */
440 if( GTK_MENU_ITEM(p_root)->submenu != NULL )
442 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
444 /* removes previous menu */
445 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
446 gtk_widget_set_sensitive( p_root, FALSE );
451 p_menu = gtk_menu_new();
453 /* special case for "off" item */
454 snprintf( psz_name, GTK_MENU_LABEL_SIZE, "None" );
455 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
457 p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
458 p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
460 gtk_widget_show( p_item );
462 /* signal hanling for off */
463 gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
464 GTK_SIGNAL_FUNC ( pf_toggle ), NULL );
466 gtk_menu_append( GTK_MENU( p_menu ), p_item );
468 p_separator = gtk_menu_item_new();
469 gtk_widget_set_sensitive( p_separator, FALSE );
470 gtk_widget_show( p_separator );
471 gtk_menu_append( GTK_MENU( p_menu ), p_separator );
473 p_item_active = NULL;
476 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
478 /* create a set of language buttons and append them to the container */
479 for( i = 0 ; i < p_intf->p_input->stream.i_es_number ; i++ )
481 if( p_intf->p_input->stream.pp_es[i]->i_cat == i_cat )
484 strcpy( psz_name, p_intf->p_input->stream.pp_es[i]->psz_desc );
485 if( psz_name[0] == '\0' )
487 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
488 "Language %d", i_item );
489 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
492 p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
494 gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
496 if( p_es == p_intf->p_input->stream.pp_es[i] )
498 /* don't lose p_item when we append into menu */
499 p_item_active = p_item;
502 gtk_widget_show( p_item );
504 /* setup signal hanling */
505 gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
506 GTK_SIGNAL_FUNC( pf_toggle ),
507 (gpointer)( p_intf->p_input->stream.pp_es[i] ) );
509 gtk_menu_append( GTK_MENU( p_menu ), p_item );
513 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
515 /* link the new menu to the menubar item */
516 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
518 /* acitvation will call signals so we can only do it
519 * when submenu is attached to menu - to get intf_window
520 * We have to release the lock since input_ToggleES needs it */
521 if( p_item_active != NULL )
523 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
527 /* be sure that menu is sensitive if non empty */
530 gtk_widget_set_sensitive( p_root, TRUE );
536 /*****************************************************************************
537 * GtkTitleMenu: sets menus for titles and chapters selection
538 *****************************************************************************
539 * Generates two types of menus:
540 * -simple list of titles
541 * -cascaded lists of chapters for each title
542 *****************************************************************************/
543 static gint GtkTitleMenu( gpointer p_data,
544 GtkWidget * p_navigation,
545 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
547 intf_thread_t * p_intf;
548 char psz_name[ GTK_MENU_LABEL_SIZE ];
549 GtkWidget * p_title_menu;
550 GtkWidget * p_title_submenu;
551 GtkWidget * p_title_item;
552 GtkWidget * p_item_active;
553 GtkWidget * p_chapter_menu;
554 GtkWidget * p_chapter_submenu;
555 GtkWidget * p_title_menu_item;
556 GtkWidget * p_chapter_menu_item;
558 GSList * p_title_group;
559 GSList * p_chapter_group;
566 p_intf = (intf_thread_t*)p_data;
568 /* temporary hack to avoid blank menu when an open menu is removed */
569 if( GTK_MENU_ITEM(p_navigation)->submenu != NULL )
571 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_navigation)->submenu ) );
573 /* removes previous menu */
574 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_navigation ) );
575 gtk_widget_set_sensitive( p_navigation, FALSE );
577 p_title_menu = gtk_menu_new();
578 p_title_group = NULL;
579 p_title_submenu = NULL;
580 p_title_menu_item = NULL;
581 p_chapter_group = NULL;
582 p_chapter_submenu = NULL;
583 p_chapter_menu_item = NULL;
584 p_item_active = NULL;
585 i_title_nb = p_intf->p_input->stream.i_area_nb;
588 for( i_title = 1 ; i_title < i_title_nb ; i_title++ )
590 /* we group titles in packets of ten for small screens */
591 if( ( i_title % 10 == 1 ) && ( i_title_nb > 20 ) )
595 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_menu_item ),
597 gtk_menu_append( GTK_MENU( p_title_menu ), p_title_menu_item );
600 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
601 "%d - %d", i_title, i_title + 9 );
602 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
603 p_title_menu_item = gtk_menu_item_new_with_label( psz_name );
604 gtk_widget_show( p_title_menu_item );
605 p_title_submenu = gtk_menu_new();
608 snprintf( psz_name, GTK_MENU_LABEL_SIZE, "Title %d (%d)", i_title,
609 p_intf->p_input->stream.pp_areas[i_title]->i_part_nb );
610 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
612 if( pf_toggle == on_menubar_title_toggle )
614 p_title_item = gtk_radio_menu_item_new_with_label( p_title_group,
617 gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_title_item ) );
619 if( p_intf->p_input->stream.pp_areas[i_title] ==
620 p_intf->p_input->stream.p_selected_area )
622 p_item_active = p_title_item;
625 /* setup signal hanling */
626 gtk_signal_connect( GTK_OBJECT( p_title_item ),
628 GTK_SIGNAL_FUNC( pf_toggle ),
629 (gpointer)(p_intf->p_input->stream.pp_areas[i_title]) );
631 if( p_intf->p_input->stream.i_area_nb > 1 )
633 /* be sure that menu is sensitive */
634 gtk_widget_set_sensitive( p_navigation, TRUE );
640 p_title_item = gtk_menu_item_new_with_label( psz_name );
643 p_chapter_menu = gtk_menu_new();
645 p_intf->p_input->stream.pp_areas[i_title]->i_part_nb;
647 for( i_chapter = 0 ; i_chapter < i_chapter_nb ; i_chapter++ )
649 /* we group chapters in packets of ten for small screens */
650 if( ( i_chapter % 10 == 0 ) && ( i_chapter_nb > 20 ) )
654 gtk_menu_item_set_submenu(
655 GTK_MENU_ITEM( p_chapter_menu_item ),
657 gtk_menu_append( GTK_MENU( p_chapter_menu ),
658 p_chapter_menu_item );
661 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
662 "%d - %d", i_chapter + 1, i_chapter + 10 );
663 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
664 p_chapter_menu_item =
665 gtk_menu_item_new_with_label( psz_name );
666 gtk_widget_show( p_chapter_menu_item );
667 p_chapter_submenu = gtk_menu_new();
670 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
671 "Chapter %d", i_chapter + 1 );
672 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
674 p_item = gtk_radio_menu_item_new_with_label(
675 p_chapter_group, psz_name );
676 p_chapter_group = gtk_radio_menu_item_group(
677 GTK_RADIO_MENU_ITEM( p_item ) );
678 gtk_widget_show( p_item );
680 #define p_area p_intf->p_input->stream.pp_areas[i_title]
681 if( ( p_area == p_intf->p_input->stream.p_selected_area ) &&
682 ( p_area->i_part == i_chapter + 1 ) )
684 p_item_active = p_item;
688 /* setup signal hanling */
689 gtk_signal_connect( GTK_OBJECT( p_item ),
691 GTK_SIGNAL_FUNC( pf_toggle ),
692 (gpointer)POS2DATA( i_title, i_chapter + 1) );
694 if( i_chapter_nb > 20 )
696 gtk_menu_append( GTK_MENU( p_chapter_submenu ), p_item );
700 gtk_menu_append( GTK_MENU( p_chapter_menu ), p_item );
704 if( i_chapter_nb > 20 )
706 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_chapter_menu_item ),
708 gtk_menu_append( GTK_MENU( p_chapter_menu ),
709 p_chapter_menu_item );
712 /* link the new menu to the title menu item */
713 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_item ),
716 if( p_intf->p_input->stream.pp_areas[i_title]->i_part_nb > 1 )
718 /* be sure that menu is sensitive */
719 gtk_widget_set_sensitive( p_navigation, TRUE );
722 GtkRadioMenu( p_intf, p_title_item, p_chapter_group, "Chapter",
723 p_intf->p_input->stream.pp_areas[i_title]->i_part_nb,
725 p_intf->p_input->stream.p_selected_area->i_part +
726 p_intf->p_input->stream.p_selected_area->i_id *100,
731 gtk_widget_show( p_title_item );
733 if( i_title_nb > 20 )
735 gtk_menu_append( GTK_MENU( p_title_submenu ), p_title_item );
739 gtk_menu_append( GTK_MENU( p_title_menu ), p_title_item );
743 if( i_title_nb > 20 )
745 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_menu_item ),
747 gtk_menu_append( GTK_MENU( p_title_menu ), p_title_menu_item );
750 /* be sure that menu is sensitive */
751 gtk_widget_set_sensitive( p_title_menu, TRUE );
753 /* link the new menu to the menubar item */
754 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_navigation ), p_title_menu );
756 /* Default selected chapter
757 * We have to release the lock since input_ToggleES needs it */
758 if( p_item_active != NULL )
760 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
761 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
763 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
766 if( p_intf->p_input->stream.i_area_nb > 1 )
768 /* be sure that menu is sensitive */
769 gtk_widget_set_sensitive( p_navigation, TRUE );
776 /*****************************************************************************
777 * GtkSetupMenus: function that generates title/chapter/audio/subpic
778 * menus with help from preceding functions
779 *****************************************************************************/
780 gint GtkSetupMenus( intf_thread_t * p_intf )
782 es_descriptor_t * p_audio_es;
783 es_descriptor_t * p_spu_es;
784 GtkWidget * p_menubar_menu;
785 GtkWidget * p_popup_menu;
788 p_intf->p_sys->b_chapter_update |= p_intf->p_sys->b_title_update;
789 p_intf->p_sys->b_angle_update |= p_intf->p_sys->b_title_update;
790 p_intf->p_sys->b_audio_update |= p_intf->p_sys->b_title_update;
791 p_intf->p_sys->b_spu_update |= p_intf->p_sys->b_title_update;
793 // vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
795 if( p_intf->p_sys->b_title_update )
799 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
800 p_intf->p_sys->p_window ), "menubar_title" ) );
801 GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Title",
802 p_intf->p_input->stream.i_area_nb - 1,
803 p_intf->p_input->stream.p_selected_area->i_id,
804 GtkMenubarTitleToggle );
806 snprintf( psz_title, 4, "%d",
807 p_intf->p_input->stream.p_selected_area->i_id );
808 psz_title[ 4 ] = '\0';
809 gtk_label_set_text( p_intf->p_sys->p_label_title, psz_title );
811 p_intf->p_sys->b_title_update = 0;
814 if( p_intf->p_sys->b_chapter_update )
818 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
819 p_intf->p_sys->p_popup ), "popup_navigation" ) );
820 GtkTitleMenu( p_intf, p_popup_menu, GtkPopupNavigationToggle );
822 GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Title",
823 p_intf->p_input->stream.i_area_nb - 1,
824 p_intf->p_input->stream.p_selected_area->i_id,
825 on_menubar_chapter_toggle );
828 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
829 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;
926 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );