* DirectX plugin by Gildas Bazin <gbazin@netcourrier.com>.
[vlc.git] / plugins / gtk / gtk_menu.c
blobcefa5e44860d54e594cd1869e9263e5bf8150622
1 /*****************************************************************************
2 * gtk_menu.c : functions to handle menu items.
3 *****************************************************************************
4 * Copyright (C) 2000, 2001 VideoLAN
5 * $Id: gtk_menu.c,v 1.9 2001/06/02 01:09:03 sam Exp $
7 * Authors: Samuel Hocevar <sam@zoy.org>
8 * Stéphane Borel <stef@via.ecp.fr>
9 *
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 /*****************************************************************************
26 * Preamble
27 *****************************************************************************/
28 #include "defs.h"
29 #include <sys/types.h> /* off_t */
30 #include <stdlib.h>
32 #include <gtk/gtk.h>
34 #include <string.h>
36 #include "config.h"
37 #include "common.h"
38 #include "threads.h"
39 #include "mtime.h"
41 #include "stream_control.h"
42 #include "input_ext-intf.h"
44 #include "interface.h"
45 #include "intf_playlist.h"
46 #include "intf_msg.h"
48 #include "video.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"
56 #include "intf_gtk.h"
58 #include "main.h"
60 #include "modules_export.h"
62 #ifdef WIN32
63 #ifndef snprintf
64 #define snprintf _snprintf
65 #endif
66 #endif
69 * Local Prototypes
71 static gint GtkLanguageMenus( gpointer , GtkWidget *, es_descriptor_t *, gint,
72 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) );
74 void GtkMenubarAudioToggle ( GtkCheckMenuItem *, gpointer );
75 void GtkPopupAudioToggle ( GtkCheckMenuItem *, gpointer );
76 void GtkMenubarSubtitleToggle( GtkCheckMenuItem *, gpointer );
77 void GtkPopupSubtitleToggle ( GtkCheckMenuItem *, gpointer );
78 static gint GtkTitleMenu( gpointer, GtkWidget *,
79 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) );
80 static gint GtkRadioMenu( intf_thread_t *, GtkWidget *, GSList *,
81 char *, int, int,
82 void( *pf_toggle )( GtkCheckMenuItem *, gpointer ) );
83 void GtkMenubarAngleToggle( GtkCheckMenuItem *, gpointer );
84 void GtkPopupAngleToggle( GtkCheckMenuItem *, gpointer );
86 gint GtkSetupMenus( intf_thread_t * p_intf );
88 /****************************************************************************
89 * Gtk*Toggle: callbacks to toggle the value of a checkmenuitem
90 ****************************************************************************
91 * We need separate functions for menubar and popup here since we can't use
92 * user_data to transmit intf_* and we need to refresh the other menu.
93 ****************************************************************************/
95 #define GtkLangToggle( intf, window, menu, type, callback, b_update ) \
96 intf_thread_t * p_intf; \
97 GtkWidget * p_menu; \
98 es_descriptor_t * p_es; \
100 p_intf = GetIntf( GTK_WIDGET(menuitem), (intf) ); \
102 if( !p_intf->p_sys->b_update ) \
104 p_menu = GTK_WIDGET( gtk_object_get_data( \
105 GTK_OBJECT( p_intf->p_sys->window ), (menu) ) ); \
106 p_es = (es_descriptor_t*)user_data; \
108 input_ToggleES( p_intf->p_input, p_es, menuitem->active ); \
110 p_intf->p_sys->b_update = menuitem->active; \
112 if( p_intf->p_sys->b_update ) \
114 GtkLanguageMenus( p_intf, p_menu, p_es, type, callback ); \
117 p_intf->p_sys->b_update = 0; \
121 * Audio
124 void GtkMenubarAudioToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
126 GtkLangToggle( "intf_window", p_popup, "popup_audio", AUDIO_ES,
127 GtkPopupAudioToggle, b_audio_update );
130 void GtkPopupAudioToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
132 GtkLangToggle( "intf_popup", p_window, "menubar_audio", AUDIO_ES,
133 GtkMenubarAudioToggle, b_audio_update );
137 * Subtitles
140 void GtkMenubarSubtitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
142 GtkLangToggle( "intf_window", p_popup, "popup_subpictures", SPU_ES,
143 GtkPopupSubtitleToggle, b_spu_update );
146 void GtkPopupSubtitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
148 GtkLangToggle( "intf_popup", p_window, "menubar_subpictures", SPU_ES,
149 GtkMenubarSubtitleToggle, b_spu_update );
152 #undef GtkLangToggle
155 * Navigation
158 void GtkPopupNavigationToggle( GtkCheckMenuItem * menuitem,
159 gpointer user_data )
161 intf_thread_t * p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_popup" );
163 if( menuitem->active &&
164 !p_intf->p_sys->b_title_update &&
165 !p_intf->p_sys->b_chapter_update )
167 input_area_t *p_area;
169 gint i_title = DATA2TITLE( user_data );
170 gint i_chapter = DATA2CHAPTER( user_data );
172 p_area = p_intf->p_input->stream.p_selected_area;
174 if( p_area != p_intf->p_input->stream.pp_areas[i_title] )
176 p_area = p_intf->p_input->stream.pp_areas[i_title];
177 p_intf->p_sys->b_title_update = 1;
180 p_area->i_part = i_chapter;
182 input_ChangeArea( p_intf->p_input, (input_area_t*)p_area );
184 p_intf->p_sys->b_chapter_update = 1;
185 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
186 GtkSetupMenus( p_intf );
187 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
189 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
194 * Title
197 void GtkMenubarTitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
199 intf_thread_t * p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_window" );
201 if( menuitem->active && !p_intf->p_sys->b_title_update )
203 gint i_title = (gint)user_data;
204 input_ChangeArea( p_intf->p_input,
205 p_intf->p_input->stream.pp_areas[i_title] );
207 p_intf->p_sys->b_title_update = 1;
208 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
209 GtkSetupMenus( p_intf );
210 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
211 p_intf->p_sys->b_title_update = 0;
213 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
219 * Chapter
222 void GtkMenubarChapterToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
224 intf_thread_t * p_intf;
225 input_area_t * p_area;
226 gint i_chapter;
227 char psz_chapter[5];
228 GtkWidget * p_popup_menu;
230 p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_window" );
231 p_area = p_intf->p_input->stream.p_selected_area;
232 i_chapter = (gint)user_data;
234 if( menuitem->active && !p_intf->p_sys->b_chapter_update )
236 p_area->i_part = i_chapter;
237 input_ChangeArea( p_intf->p_input, (input_area_t*)p_area );
239 snprintf( psz_chapter, 4, "%02d", p_area->i_part );
240 psz_chapter[ 4 ] = '\0';
241 gtk_label_set_text( p_intf->p_sys->p_label_chapter, psz_chapter );
243 p_intf->p_sys->b_chapter_update = 1;
244 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
245 p_intf->p_sys->p_popup ), "popup_navigation" ) );
247 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
248 GtkTitleMenu( p_intf, p_popup_menu, GtkPopupNavigationToggle );
249 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
251 p_intf->p_sys->b_chapter_update = 0;
253 input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
259 * Angle
262 #define GtkAngleToggle( intf, window, menu, callback ) \
263 intf_thread_t * p_intf; \
264 GtkWidget * p_menu; \
265 input_area_t * p_area; \
267 p_intf = GetIntf( GTK_WIDGET(menuitem), (intf) ); \
269 if( menuitem->active && !p_intf->p_sys->b_angle_update ) \
271 p_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( \
272 p_intf->p_sys->window ), (menu) ) ); \
273 p_area = p_intf->p_input->stream.p_selected_area; \
274 p_area->i_angle = (gint)user_data; \
276 input_ChangeArea( p_intf->p_input, (input_area_t*)p_area ); \
278 p_intf->p_sys->b_angle_update = 1; \
279 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock ); \
280 GtkRadioMenu( p_intf, p_menu, NULL, "Angle", \
281 p_area->i_angle_nb, p_area->i_angle, (callback) ); \
282 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock ); \
283 p_intf->p_sys->b_angle_update = 0; \
286 void GtkMenubarAngleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
288 GtkAngleToggle( "intf_window", p_popup, "popup_angle",
289 GtkPopupAngleToggle );
292 void GtkPopupAngleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
294 GtkAngleToggle( "intf_popup", p_window, "menubar_angle",
295 GtkMenubarAngleToggle );
298 #undef GtkAngleToggle
300 /****************************************************************************
301 * Functions to generate menus
302 ****************************************************************************/
304 /*****************************************************************************
305 * GtkRadioMenu: update interactive menus of the interface
306 *****************************************************************************
307 * Sets up menus with information from input
308 * Warning: since this function is designed to be called by management
309 * function, the interface lock has to be taken
310 *****************************************************************************/
311 static gint GtkRadioMenu( intf_thread_t * p_intf,
312 GtkWidget * p_root, GSList * p_menu_group,
313 char * psz_item_name,
314 int i_nb, int i_selected,
315 void( *pf_toggle )( GtkCheckMenuItem *, gpointer ) )
317 char psz_name[ GTK_MENU_LABEL_SIZE ];
318 GtkWidget * p_menu;
319 GtkWidget * p_submenu;
320 GtkWidget * p_item_group;
321 GtkWidget * p_item;
322 GtkWidget * p_item_selected;
323 GSList * p_group;
324 gint i_item;
326 /* temporary hack to avoid blank menu when an open menu is removed */
327 if( GTK_MENU_ITEM(p_root)->submenu != NULL )
329 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
331 /* removes previous menu */
332 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
333 gtk_widget_set_sensitive( p_root, FALSE );
335 p_item_group = NULL;
336 p_submenu = NULL;
337 p_item_selected = NULL;
338 p_group = p_menu_group;
340 p_menu = gtk_menu_new();
342 for( i_item = 0 ; i_item < i_nb ; i_item++ )
344 /* we group chapters in packets of ten for small screens */
345 if( ( i_item % 10 == 0 ) && ( i_nb > 20 ) )
347 if( i_item != 0 )
349 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_item_group ),
350 p_submenu );
351 gtk_menu_append( GTK_MENU( p_menu ), p_item_group );
354 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
355 "%ss %d to %d", psz_item_name, i_item + 1, i_item + 10);
356 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
357 p_item_group = gtk_menu_item_new_with_label( psz_name );
358 gtk_widget_show( p_item_group );
359 p_submenu = gtk_menu_new();
362 snprintf( psz_name, GTK_MENU_LABEL_SIZE, "%s %d",
363 psz_item_name, i_item + 1 );
364 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
366 p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
367 p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
369 if( i_selected == i_item + 1 )
371 p_item_selected = p_item;
374 gtk_widget_show( p_item );
376 /* setup signal hanling */
377 gtk_signal_connect( GTK_OBJECT( p_item ),
378 "toggled",
379 GTK_SIGNAL_FUNC( pf_toggle ),
380 (gpointer)(i_item + 1) );
382 if( i_nb > 20 )
384 gtk_menu_append( GTK_MENU( p_submenu ), p_item );
386 else
388 gtk_menu_append( GTK_MENU( p_menu ), p_item );
392 if( i_nb > 20 )
394 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_item_group ), p_submenu );
395 gtk_menu_append( GTK_MENU( p_menu ), p_item_group );
398 /* link the new menu to the title menu item */
399 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
401 /* toggle currently selected chapter
402 * We have to release the lock since input_ToggleES needs it */
403 if( p_item_selected != NULL )
405 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
406 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_selected ),
407 TRUE );
408 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
411 /* be sure that menu is sensitive, if there are several items */
412 if( i_nb > 1 )
414 gtk_widget_set_sensitive( p_root, TRUE );
417 return TRUE;
420 /*****************************************************************************
421 * GtkLanguageMenus: update interactive menus of the interface
422 *****************************************************************************
423 * Sets up menus with information from input:
424 * -languages
425 * -sub-pictures
426 * Warning: since this function is designed to be called by management
427 * function, the interface lock has to be taken
428 *****************************************************************************/
429 static gint GtkLanguageMenus( gpointer p_data,
430 GtkWidget * p_root,
431 es_descriptor_t * p_es,
432 gint i_cat,
433 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
435 intf_thread_t * p_intf;
436 GtkWidget * p_menu;
437 GtkWidget * p_separator;
438 GtkWidget * p_item;
439 GtkWidget * p_item_active;
440 GSList * p_group;
441 char psz_name[ GTK_MENU_LABEL_SIZE ];
442 gint i_item;
443 gint i;
447 /* cast */
448 p_intf = (intf_thread_t *)p_data;
450 /* temporary hack to avoid blank menu when an open menu is removed */
451 if( GTK_MENU_ITEM(p_root)->submenu != NULL )
453 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
455 /* removes previous menu */
456 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
457 gtk_widget_set_sensitive( p_root, FALSE );
459 p_group = NULL;
461 /* menu container */
462 p_menu = gtk_menu_new();
464 /* special case for "off" item */
465 snprintf( psz_name, GTK_MENU_LABEL_SIZE, "None" );
466 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
468 p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
469 p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
471 gtk_widget_show( p_item );
473 /* signal hanling for off */
474 gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
475 GTK_SIGNAL_FUNC ( pf_toggle ), NULL );
477 gtk_menu_append( GTK_MENU( p_menu ), p_item );
479 p_separator = gtk_menu_item_new();
480 gtk_widget_set_sensitive( p_separator, FALSE );
481 gtk_widget_show( p_separator );
482 gtk_menu_append( GTK_MENU( p_menu ), p_separator );
484 p_item_active = NULL;
485 i_item = 0;
487 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
489 /* create a set of language buttons and append them to the container */
490 for( i = 0 ; i < p_intf->p_input->stream.i_es_number ; i++ )
492 if( p_intf->p_input->stream.pp_es[i]->i_cat == i_cat )
494 i_item++;
495 strcpy( psz_name, p_intf->p_input->stream.pp_es[i]->psz_desc );
496 if( psz_name[0] == '\0' )
498 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
499 "Language %d", i_item );
500 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
503 p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
504 p_group =
505 gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
507 if( p_es == p_intf->p_input->stream.pp_es[i] )
509 /* don't lose p_item when we append into menu */
510 p_item_active = p_item;
513 gtk_widget_show( p_item );
515 /* setup signal hanling */
516 gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
517 GTK_SIGNAL_FUNC( pf_toggle ),
518 (gpointer)( p_intf->p_input->stream.pp_es[i] ) );
520 gtk_menu_append( GTK_MENU( p_menu ), p_item );
524 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
526 /* link the new menu to the menubar item */
527 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
529 /* acitvation will call signals so we can only do it
530 * when submenu is attached to menu - to get intf_window
531 * We have to release the lock since input_ToggleES needs it */
532 if( p_item_active != NULL )
534 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
535 TRUE );
538 /* be sure that menu is sensitive if non empty */
539 if( i_item > 0 )
541 gtk_widget_set_sensitive( p_root, TRUE );
544 return TRUE;
547 /*****************************************************************************
548 * GtkTitleMenu: sets menus for titles and chapters selection
549 *****************************************************************************
550 * Generates two types of menus:
551 * -simple list of titles
552 * -cascaded lists of chapters for each title
553 *****************************************************************************/
554 static gint GtkTitleMenu( gpointer p_data,
555 GtkWidget * p_navigation,
556 void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
558 intf_thread_t * p_intf;
559 char psz_name[ GTK_MENU_LABEL_SIZE ];
560 GtkWidget * p_title_menu;
561 GtkWidget * p_title_submenu;
562 GtkWidget * p_title_item;
563 GtkWidget * p_item_active;
564 GtkWidget * p_chapter_menu;
565 GtkWidget * p_chapter_submenu;
566 GtkWidget * p_title_menu_item;
567 GtkWidget * p_chapter_menu_item;
568 GtkWidget * p_item;
569 GSList * p_title_group;
570 GSList * p_chapter_group;
571 gint i_title;
572 gint i_chapter;
573 gint i_title_nb;
574 gint i_chapter_nb;
576 /* cast */
577 p_intf = (intf_thread_t*)p_data;
579 /* temporary hack to avoid blank menu when an open menu is removed */
580 if( GTK_MENU_ITEM(p_navigation)->submenu != NULL )
582 gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_navigation)->submenu ) );
584 /* removes previous menu */
585 gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_navigation ) );
586 gtk_widget_set_sensitive( p_navigation, FALSE );
588 p_title_menu = gtk_menu_new();
589 p_title_group = NULL;
590 p_title_submenu = NULL;
591 p_title_menu_item = NULL;
592 p_chapter_group = NULL;
593 p_chapter_submenu = NULL;
594 p_chapter_menu_item = NULL;
595 p_item_active = NULL;
596 i_title_nb = p_intf->p_input->stream.i_area_nb;
598 /* loop on titles */
599 for( i_title = 1 ; i_title < i_title_nb ; i_title++ )
601 /* we group titles in packets of ten for small screens */
602 if( ( i_title % 10 == 1 ) && ( i_title_nb > 20 ) )
604 if( i_title != 1 )
606 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_menu_item ),
607 p_title_submenu );
608 gtk_menu_append( GTK_MENU( p_title_menu ), p_title_menu_item );
611 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
612 "%d - %d", i_title, i_title + 9 );
613 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
614 p_title_menu_item = gtk_menu_item_new_with_label( psz_name );
615 gtk_widget_show( p_title_menu_item );
616 p_title_submenu = gtk_menu_new();
619 snprintf( psz_name, GTK_MENU_LABEL_SIZE, "Title %d (%d)", i_title,
620 p_intf->p_input->stream.pp_areas[i_title]->i_part_nb );
621 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
622 #if 0
623 if( pf_toggle == on_menubar_title_toggle )
625 p_title_item = gtk_radio_menu_item_new_with_label( p_title_group,
626 psz_name );
627 p_title_group =
628 gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_title_item ) );
630 if( p_intf->p_input->stream.pp_areas[i_title] ==
631 p_intf->p_input->stream.p_selected_area )
633 p_item_active = p_title_item;
636 /* setup signal hanling */
637 gtk_signal_connect( GTK_OBJECT( p_title_item ),
638 "toggled",
639 GTK_SIGNAL_FUNC( pf_toggle ),
640 (gpointer)(p_intf->p_input->stream.pp_areas[i_title]) );
642 if( p_intf->p_input->stream.i_area_nb > 1 )
644 /* be sure that menu is sensitive */
645 gtk_widget_set_sensitive( p_navigation, TRUE );
648 else
649 #endif
651 p_title_item = gtk_menu_item_new_with_label( psz_name );
653 #if 1
654 p_chapter_menu = gtk_menu_new();
655 i_chapter_nb =
656 p_intf->p_input->stream.pp_areas[i_title]->i_part_nb;
658 for( i_chapter = 0 ; i_chapter < i_chapter_nb ; i_chapter++ )
660 /* we group chapters in packets of ten for small screens */
661 if( ( i_chapter % 10 == 0 ) && ( i_chapter_nb > 20 ) )
663 if( i_chapter != 0 )
665 gtk_menu_item_set_submenu(
666 GTK_MENU_ITEM( p_chapter_menu_item ),
667 p_chapter_submenu );
668 gtk_menu_append( GTK_MENU( p_chapter_menu ),
669 p_chapter_menu_item );
672 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
673 "%d - %d", i_chapter + 1, i_chapter + 10 );
674 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
675 p_chapter_menu_item =
676 gtk_menu_item_new_with_label( psz_name );
677 gtk_widget_show( p_chapter_menu_item );
678 p_chapter_submenu = gtk_menu_new();
681 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
682 "Chapter %d", i_chapter + 1 );
683 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
685 p_item = gtk_radio_menu_item_new_with_label(
686 p_chapter_group, psz_name );
687 p_chapter_group = gtk_radio_menu_item_group(
688 GTK_RADIO_MENU_ITEM( p_item ) );
689 gtk_widget_show( p_item );
691 #define p_area p_intf->p_input->stream.pp_areas[i_title]
692 if( ( p_area == p_intf->p_input->stream.p_selected_area ) &&
693 ( p_area->i_part == i_chapter + 1 ) )
695 p_item_active = p_item;
697 #undef p_area
699 /* setup signal hanling */
700 gtk_signal_connect( GTK_OBJECT( p_item ),
701 "toggled",
702 GTK_SIGNAL_FUNC( pf_toggle ),
703 (gpointer)POS2DATA( i_title, i_chapter + 1) );
705 if( i_chapter_nb > 20 )
707 gtk_menu_append( GTK_MENU( p_chapter_submenu ), p_item );
709 else
711 gtk_menu_append( GTK_MENU( p_chapter_menu ), p_item );
715 if( i_chapter_nb > 20 )
717 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_chapter_menu_item ),
718 p_chapter_submenu );
719 gtk_menu_append( GTK_MENU( p_chapter_menu ),
720 p_chapter_menu_item );
723 /* link the new menu to the title menu item */
724 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_item ),
725 p_chapter_menu );
727 if( p_intf->p_input->stream.pp_areas[i_title]->i_part_nb > 1 )
729 /* be sure that menu is sensitive */
730 gtk_widget_set_sensitive( p_navigation, TRUE );
732 #else
733 GtkRadioMenu( p_intf, p_title_item, p_chapter_group, "Chapter",
734 p_intf->p_input->stream.pp_areas[i_title]->i_part_nb,
735 i_title * 100,
736 p_intf->p_input->stream.p_selected_area->i_part +
737 p_intf->p_input->stream.p_selected_area->i_id *100,
738 pf_toggle );
740 #endif
742 gtk_widget_show( p_title_item );
744 if( i_title_nb > 20 )
746 gtk_menu_append( GTK_MENU( p_title_submenu ), p_title_item );
748 else
750 gtk_menu_append( GTK_MENU( p_title_menu ), p_title_item );
754 if( i_title_nb > 20 )
756 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_menu_item ),
757 p_title_submenu );
758 gtk_menu_append( GTK_MENU( p_title_menu ), p_title_menu_item );
761 /* be sure that menu is sensitive */
762 gtk_widget_set_sensitive( p_title_menu, TRUE );
764 /* link the new menu to the menubar item */
765 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_navigation ), p_title_menu );
767 /* Default selected chapter
768 * We have to release the lock since input_ToggleES needs it */
769 if( p_item_active != NULL )
771 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
772 gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
773 TRUE );
774 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
776 #if 0
777 if( p_intf->p_input->stream.i_area_nb > 1 )
779 /* be sure that menu is sensitive */
780 gtk_widget_set_sensitive( p_navigation, TRUE );
782 #endif
784 return TRUE;
787 /*****************************************************************************
788 * GtkSetupMenus: function that generates title/chapter/audio/subpic
789 * menus with help from preceding functions
790 *****************************************************************************/
791 gint GtkSetupMenus( intf_thread_t * p_intf )
793 es_descriptor_t * p_audio_es;
794 es_descriptor_t * p_spu_es;
795 GtkWidget * p_menubar_menu;
796 GtkWidget * p_popup_menu;
797 gint i;
799 p_intf->p_sys->b_chapter_update |= p_intf->p_sys->b_title_update;
800 p_intf->p_sys->b_angle_update |= p_intf->p_sys->b_title_update;
801 p_intf->p_sys->b_audio_update |= p_intf->p_sys->b_title_update;
802 p_intf->p_sys->b_spu_update |= p_intf->p_sys->b_title_update;
804 // vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
806 if( p_intf->p_sys->b_title_update )
808 char psz_title[5];
810 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
811 p_intf->p_sys->p_window ), "menubar_title" ) );
812 GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Title",
813 p_intf->p_input->stream.i_area_nb - 1,
814 p_intf->p_input->stream.p_selected_area->i_id,
815 GtkMenubarTitleToggle );
817 snprintf( psz_title, 4, "%d",
818 p_intf->p_input->stream.p_selected_area->i_id );
819 psz_title[ 4 ] = '\0';
820 gtk_label_set_text( p_intf->p_sys->p_label_title, psz_title );
822 p_intf->p_sys->b_title_update = 0;
825 if( p_intf->p_sys->b_chapter_update )
827 char psz_chapter[5];
829 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
830 p_intf->p_sys->p_popup ), "popup_navigation" ) );
831 GtkTitleMenu( p_intf, p_popup_menu, GtkPopupNavigationToggle );
832 #if 0
833 GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Title",
834 p_intf->p_input->stream.i_area_nb - 1,
835 p_intf->p_input->stream.p_selected_area->i_id,
836 on_menubar_chapter_toggle );
837 #endif
839 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
840 p_intf->p_sys->p_window ), "menubar_chapter" ) );
841 GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Chapter",
842 p_intf->p_input->stream.p_selected_area->i_part_nb,
843 p_intf->p_input->stream.p_selected_area->i_part,
844 GtkMenubarChapterToggle );
847 snprintf( psz_chapter, 4, "%d",
848 p_intf->p_input->stream.p_selected_area->i_part );
849 psz_chapter[ 4 ] = '\0';
850 gtk_label_set_text( p_intf->p_sys->p_label_chapter, psz_chapter );
852 p_intf->p_sys->i_part =
853 p_intf->p_input->stream.p_selected_area->i_part;
855 p_intf->p_sys->b_chapter_update = 0;
858 if( p_intf->p_sys->b_angle_update )
860 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
861 p_intf->p_sys->p_window ), "menubar_angle" ) );
862 GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Angle",
863 p_intf->p_input->stream.p_selected_area->i_angle_nb,
864 p_intf->p_input->stream.p_selected_area->i_angle,
865 GtkMenubarAngleToggle );
867 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
868 p_intf->p_sys->p_popup ), "popup_angle" ) );
869 GtkRadioMenu( p_intf, p_popup_menu, NULL, "Angle",
870 p_intf->p_input->stream.p_selected_area->i_angle_nb,
871 p_intf->p_input->stream.p_selected_area->i_angle,
872 GtkPopupAngleToggle );
874 p_intf->p_sys->b_angle_update = 0;
877 /* look for selected ES */
878 p_audio_es = NULL;
879 p_spu_es = NULL;
881 for( i = 0 ; i < p_intf->p_input->stream.i_selected_es_number ; i++ )
883 if( p_intf->p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES )
885 p_audio_es = p_intf->p_input->stream.pp_selected_es[i];
888 if( p_intf->p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
890 p_spu_es = p_intf->p_input->stream.pp_selected_es[i];
894 vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
896 /* audio menus */
897 if( p_intf->p_sys->b_audio_update )
899 /* find audio root menu */
900 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
901 p_intf->p_sys->p_window ), "menubar_audio" ) );
903 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
904 p_intf->p_sys->p_popup ), "popup_audio" ) );
906 p_intf->p_sys->b_audio_update = 1;
907 GtkLanguageMenus( p_intf, p_menubar_menu, p_audio_es, AUDIO_ES,
908 GtkMenubarAudioToggle );
909 p_intf->p_sys->b_audio_update = 1;
910 GtkLanguageMenus( p_intf, p_popup_menu, p_audio_es, AUDIO_ES,
911 GtkPopupAudioToggle );
913 p_intf->p_sys->b_audio_update = 0;
916 /* sub picture menus */
917 if( p_intf->p_sys->b_spu_update )
919 /* find spu root menu */
920 p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
921 p_intf->p_sys->p_window ), "menubar_subpictures" ) );
923 p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
924 p_intf->p_sys->p_popup ), "popup_subpictures" ) );
926 p_intf->p_sys->b_spu_update = 1;
927 GtkLanguageMenus( p_intf, p_menubar_menu, p_spu_es, SPU_ES,
928 GtkMenubarSubtitleToggle );
929 p_intf->p_sys->b_spu_update = 1;
930 GtkLanguageMenus( p_intf, p_popup_menu, p_spu_es, SPU_ES,
931 GtkPopupSubtitleToggle );
933 p_intf->p_sys->b_spu_update = 0;
936 vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
938 return TRUE;