]> git.sesse.net Git - vlc/blob - plugins/gtk/gtk_menu.c
1b57c85ccb677dadb3a64ed978fec4222aeb8c73
[vlc] / plugins / gtk / gtk_menu.c
1 /*****************************************************************************
2  * gtk_menu.c : functions to handle menu items.
3  *****************************************************************************
4  * Copyright (C) 2000, 2001 VideoLAN
5  * $Id: gtk_menu.c,v 1.1 2001/05/15 01:01:44 stef Exp $
6  *
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.
14  * 
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.
19  *
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  *****************************************************************************/
24
25 #define MODULE_NAME gtk
26 #include "modules_inner.h"
27
28 /*****************************************************************************
29  * Preamble
30  *****************************************************************************/
31 #include "defs.h"
32 #include <sys/types.h>                                              /* off_t */
33 #include <stdlib.h>
34
35 #include <gtk/gtk.h>
36
37 #include <string.h>
38
39 #include "config.h"
40 #include "common.h"
41 #include "threads.h"
42 #include "mtime.h"
43
44 #include "stream_control.h"
45 #include "input_ext-intf.h"
46
47 #include "interface.h"
48 #include "intf_playlist.h"
49 #include "intf_msg.h"
50
51 #include "video.h"
52 #include "video_output.h"
53 #include "audio_output.h"
54
55 #include "gtk_callbacks.h"
56 #include "gtk_interface.h"
57 #include "gtk_support.h"
58 #include "gtk_playlist.h"
59 #include "intf_gtk.h"
60
61 #include "main.h"
62
63 /****************************************************************************
64  * Gtk*Toggle: callbacks to toggle the value of a checkmenuitem
65  ****************************************************************************
66  * We need separate functions for menubar and popup here since we can't use
67  * user_data to transmit intf_*
68  ****************************************************************************/
69
70 #define GtkLangToggle( b_update )                                   \
71     es_descriptor_t *       p_es;                                   \
72                                                                     \
73     if( !b_update )                                                 \
74     {                                                               \
75         p_es = (es_descriptor_t*)user_data;                         \
76                                                                     \
77         input_ToggleES( p_intf->p_input, p_es, menuitem->active );  \
78                                                                     \
79         b_update = menuitem->active;                                \
80     }                                                               \
81
82 /*
83  * Audio
84  */ 
85
86 void GtkMenubarAudioToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
87 {
88     intf_thread_t * p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_window" );
89
90     GtkLangToggle( p_intf->p_sys->b_audio_update );
91 }
92
93 void GtkPopupAudioToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
94 {
95     intf_thread_t * p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_popup" );
96
97     GtkLangToggle( p_intf->p_sys->b_audio_update );
98 }
99
100 /* 
101  * Subtitles
102  */ 
103
104
105 void GtkMenubarSubtitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
106 {
107     intf_thread_t * p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_window" );
108
109     GtkLangToggle( p_intf->p_sys->b_spu_update );
110 }
111 void GtkPopupSubtitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
112 {
113     intf_thread_t * p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_popup" );
114
115     GtkLangToggle( p_intf->p_sys->b_spu_update );
116 }
117
118 /*
119  * Navigation
120  */
121 void GtkPopupNavigationToggle( GtkCheckMenuItem * menuitem,
122                                gpointer user_data )
123 {
124     intf_thread_t * p_intf = GetIntf( GTK_WIDGET(menuitem), "intf_popup" );
125
126     if( menuitem->active &&
127         !p_intf->p_sys->b_title_update &&
128         !p_intf->p_sys->b_chapter_update )
129     {
130         input_area_t   *p_area = p_intf->p_input->stream.p_selected_area;
131
132         gint i_title   = DATA2TITLE( user_data );
133         gint i_chapter = DATA2CHAPTER( user_data );
134
135         if( p_area != p_intf->p_input->stream.pp_areas[i_title] )
136         {
137             p_area = p_intf->p_input->stream.pp_areas[i_title];
138             p_intf->p_sys->b_title_update = 1;
139         }
140
141         p_area->i_part = i_chapter;
142         p_intf->p_sys->b_chapter_update = 1;
143
144         p_intf->p_input->pf_set_area( p_intf->p_input, (input_area_t*)p_area );
145
146         input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );
147     }
148 }
149
150 /*
151  * Title
152  */
153
154 #define GtkTitleToggle( intf )                                              \
155     intf_thread_t * p_intf = GetIntf( GTK_WIDGET(menuitem), (intf) );       \
156                                                                             \
157     if( menuitem->active && !p_intf->p_sys->b_title_update )                \
158     {                                                                       \
159         gint i_title = (gint)user_data;                                     \
160         p_intf->p_input->pf_set_area( p_intf->p_input,                      \
161             p_intf->p_input->stream.pp_areas[i_title] );                    \
162                                                                             \
163         input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );              \
164                                                                             \
165         p_intf->p_sys->b_title_update = 1;                                  \
166     }
167
168 void GtkMenubarTitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
169 {
170     GtkTitleToggle( "intf_window" );
171 }
172
173 void GtkPopupTitleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
174 {
175     GtkTitleToggle( "intf_popup" );
176 }
177
178 /*
179  * Chapter
180  */
181
182 #define GtkChapterToggle( intf )                                            \
183     intf_thread_t * p_intf;                                                 \
184     input_area_t *  p_area;                                                 \
185     gint            i_chapter;                                              \
186     char            psz_chapter[5];                                         \
187                                                                             \
188     p_intf    = GetIntf( GTK_WIDGET(menuitem), (intf) );                    \
189     p_area    = p_intf->p_input->stream.p_selected_area;                    \
190     i_chapter = (gint)user_data;                                            \
191                                                                             \
192     if( menuitem->active && !p_intf->p_sys->b_chapter_update )              \
193     {                                                                       \
194         p_area->i_part = i_chapter;                                         \
195         p_intf->p_input->pf_set_area( p_intf->p_input,                      \
196                                       (input_area_t*)p_area );              \
197                                                                             \
198         snprintf( psz_chapter, 3, "%02d", p_area->i_part );                 \
199         gtk_label_set_text( p_intf->p_sys->p_label_chapter, psz_chapter );  \
200                                                                             \
201         input_SetStatus( p_intf->p_input, INPUT_STATUS_PLAY );              \
202                                                                             \
203         p_intf->p_sys->b_chapter_update = 1;                                \
204     }
205
206
207 void GtkMenubarChapterToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
208 {
209     GtkChapterToggle( "intf_window" );
210 }
211
212 void GtkPopupChapterToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
213 {
214     GtkChapterToggle( "intf_popup" );
215 }
216
217 /*
218  * Angle
219  */
220
221 #define GtkAngleToggle( intf )                                              \
222     intf_thread_t * p_intf;                                                 \
223     input_area_t *  p_area;                                                 \
224     gint            i_angle;                                                \
225                                                                             \
226     p_intf    = GetIntf( GTK_WIDGET(menuitem), (intf) );                    \
227     p_area    = p_intf->p_input->stream.p_selected_area;                    \
228     i_angle   = (gint)user_data;                                            \
229                                                                             \
230     if( menuitem->active && !p_intf->p_sys->b_angle_update )                \
231     {                                                                       \
232         p_area->i_angle = i_angle;                                          \
233         p_intf->p_input->pf_set_area( p_intf->p_input,                      \
234                                      (input_area_t*)p_area );               \
235                                                                             \
236         p_intf->p_sys->b_angle_update = 1;                                  \
237     }
238
239 void GtkMenubarAngleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
240 {
241     GtkAngleToggle( "intf_window" )
242 }
243
244 void GtkPopupAngleToggle( GtkCheckMenuItem * menuitem, gpointer user_data )
245 {
246     GtkAngleToggle( "intf_popup" )
247 }
248
249 /****************************************************************************
250  * Functions to generate menus
251  ****************************************************************************/
252
253 /*****************************************************************************
254  * GtkRadioMenu: update interactive menus of the interface
255  *****************************************************************************
256  * Sets up menus with information from input
257  * Warning: since this function is designed to be called by management
258  * function, the interface lock has to be taken
259  *****************************************************************************/
260 static gint GtkRadioMenu( intf_thread_t * p_intf,
261                             GtkWidget * p_root, GSList * p_menu_group,
262                             char * psz_item_name,
263                             int i_nb, int i_selected,
264                      void( *pf_toggle )( GtkCheckMenuItem *, gpointer ) )
265 {
266     char                psz_name[ GTK_MENU_LABEL_SIZE ];
267     GtkWidget *         p_menu;
268     GtkWidget *         p_submenu;
269     GtkWidget *         p_item_group;
270     GtkWidget *         p_item;
271     GtkWidget *         p_item_selected;
272     GSList *            p_group;
273     gint                i_item;
274
275     /* temporary hack to avoid blank menu when an open menu is removed */
276     if( GTK_MENU_ITEM(p_root)->submenu != NULL )
277     {
278         gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
279     }
280     /* removes previous menu */
281     gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
282     gtk_widget_set_sensitive( p_root, FALSE );
283
284     p_item_group = NULL;
285     p_submenu = NULL;
286     p_item_selected = NULL;
287     p_group = p_menu_group;
288
289     p_menu = gtk_menu_new();
290
291     for( i_item = 0 ; i_item < i_nb ; i_item++ )
292     {
293         /* we group chapters in packets of ten for small screens */
294         if( ( i_item % 10 == 0 ) && ( i_nb > 20 ) )
295         {
296             if( i_item != 0 )
297             {
298                 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_item_group ),
299                                            p_submenu );
300                 gtk_menu_append( GTK_MENU( p_menu ), p_item_group );
301             }
302
303             snprintf( psz_name, GTK_MENU_LABEL_SIZE,
304                       "%ss %d to %d", psz_item_name, i_item + 1, i_item + 10);
305             psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
306             p_item_group = gtk_menu_item_new_with_label( psz_name );
307             gtk_widget_show( p_item_group );
308             p_submenu = gtk_menu_new();
309         }
310
311         snprintf( psz_name, GTK_MENU_LABEL_SIZE, "%s %d",
312                   psz_item_name, i_item + 1 );
313         psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
314
315         p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
316         p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
317
318         if( i_selected == i_item + 1 )
319         {
320             p_item_selected = p_item;
321         }
322         
323         gtk_widget_show( p_item );
324
325         /* setup signal hanling */
326         gtk_signal_connect( GTK_OBJECT( p_item ),
327                             "toggled",
328                             GTK_SIGNAL_FUNC( pf_toggle ),
329                             (gpointer)(i_item + 1) );
330
331         if( i_nb > 20 )
332         {
333             gtk_menu_append( GTK_MENU( p_submenu ), p_item );
334         }
335         else
336         {
337             gtk_menu_append( GTK_MENU( p_menu ), p_item );
338         }
339     }
340
341     if( i_nb > 20 )
342     {
343         gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_item_group ), p_submenu );
344         gtk_menu_append( GTK_MENU( p_menu ), p_item_group );
345     }
346
347     /* link the new menu to the title menu item */
348     gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
349
350     /* toggle currently selected chapter */
351     if( p_item_selected != NULL )
352     {
353         gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_selected ),
354                                         TRUE );
355     }
356
357     /* be sure that menu is sensitive, if there are several items */
358     if( i_nb > 1 )
359     {
360         gtk_widget_set_sensitive( p_root, TRUE );
361     }
362
363     return TRUE;
364 }
365
366 /*****************************************************************************
367  * GtkLanguageMenus: update interactive menus of the interface
368  *****************************************************************************
369  * Sets up menus with information from input:
370  *  -languages
371  *  -sub-pictures
372  * Warning: since this function is designed to be called by management
373  * function, the interface lock has to be taken
374  *****************************************************************************/
375 static gint GtkLanguageMenus( gpointer          p_data,
376                                 GtkWidget *       p_root,
377                                 es_descriptor_t * p_es,
378                                 gint              i_cat,
379                           void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
380 {
381     intf_thread_t *     p_intf;
382     GtkWidget *         p_menu;
383     GtkWidget *         p_separator;
384     GtkWidget *         p_item;
385     GtkWidget *         p_item_active;
386     GSList *            p_group;
387     char                psz_name[ GTK_MENU_LABEL_SIZE ];
388     gint                i_item;
389     gint                i;
390
391     
392
393     /* cast */
394     p_intf = (intf_thread_t *)p_data;
395
396     /* temporary hack to avoid blank menu when an open menu is removed */
397     if( GTK_MENU_ITEM(p_root)->submenu != NULL )
398     {
399         gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_root)->submenu ) );
400     }
401     /* removes previous menu */
402     gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_root ) );
403     gtk_widget_set_sensitive( p_root, FALSE );
404
405     p_group = NULL;
406
407     /* menu container */
408     p_menu = gtk_menu_new();
409
410     /* special case for "off" item */
411     snprintf( psz_name, GTK_MENU_LABEL_SIZE, "None" );
412     psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
413
414     p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
415     p_group = gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
416
417     gtk_widget_show( p_item );
418
419     /* signal hanling for off */
420     gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
421                         GTK_SIGNAL_FUNC ( pf_toggle ), NULL );
422
423     gtk_menu_append( GTK_MENU( p_menu ), p_item );
424
425     p_separator = gtk_menu_item_new();
426     gtk_widget_set_sensitive( p_separator, FALSE );
427     gtk_widget_show( p_separator );
428     gtk_menu_append( GTK_MENU( p_menu ), p_separator );
429
430     vlc_mutex_lock( &p_intf->p_input->stream.stream_lock );
431     p_item_active = NULL;
432     i_item = 0;
433
434     /* create a set of language buttons and append them to the container */
435     for( i = 0 ; i < p_intf->p_input->stream.i_es_number ; i++ )
436     {
437         if( p_intf->p_input->stream.pp_es[i]->i_cat == i_cat )
438         {
439             i_item++;
440             strcpy( psz_name, p_intf->p_input->stream.pp_es[i]->psz_desc );
441             if( psz_name[0] == '\0' )
442             {
443                 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
444                           "Language %d", i_item );
445                 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
446             }
447
448             p_item = gtk_radio_menu_item_new_with_label( p_group, psz_name );
449             p_group =
450                 gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_item ) );
451
452             if( p_es == p_intf->p_input->stream.pp_es[i] )
453             {
454                 /* don't lose p_item when we append into menu */
455                 p_item_active = p_item;
456             }
457
458             gtk_widget_show( p_item );
459
460             /* setup signal hanling */
461             gtk_signal_connect( GTK_OBJECT( p_item ), "toggled",
462                             GTK_SIGNAL_FUNC( pf_toggle ),
463                             (gpointer)( p_intf->p_input->stream.pp_es[i] ) );
464
465             gtk_menu_append( GTK_MENU( p_menu ), p_item );
466         }
467     }
468
469     vlc_mutex_unlock( &p_intf->p_input->stream.stream_lock );
470
471     /* link the new menu to the menubar item */
472     gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_root ), p_menu );
473
474     /* acitvation will call signals so we can only do it
475      * when submenu is attached to menu - to get intf_window */
476     if( p_item_active != NULL )
477     {
478         gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
479                                         TRUE );
480     }
481
482     /* be sure that menu is sensitive if non empty */
483     if( i_item > 0 )
484     {
485         gtk_widget_set_sensitive( p_root, TRUE );
486     }
487
488     return TRUE;
489 }
490 #if 1
491 /*****************************************************************************
492  * GtkTitleMenu: sets menus for titles and chapters selection
493  *****************************************************************************
494  * Generates two types of menus:
495  *  -simple list of titles
496  *  -cascaded lists of chapters for each title
497  *****************************************************************************/
498 static gint GtkTitleMenu( gpointer       p_data,
499                             GtkWidget *    p_navigation, 
500                             void(*pf_toggle )( GtkCheckMenuItem *, gpointer ) )
501 {
502     intf_thread_t *     p_intf;
503     char                psz_name[ GTK_MENU_LABEL_SIZE ];
504     GtkWidget *         p_title_menu;
505     GtkWidget *         p_title_submenu;
506     GtkWidget *         p_title_item;
507     GtkWidget *         p_item_active;
508     GtkWidget *         p_chapter_menu;
509     GtkWidget *         p_chapter_submenu;
510     GtkWidget *         p_title_menu_item;
511     GtkWidget *         p_chapter_menu_item;
512     GtkWidget *         p_item;
513     GSList *            p_title_group;
514     GSList *            p_chapter_group;
515     gint                i_title;
516     gint                i_chapter;
517     gint                i_title_nb;
518     gint                i_chapter_nb;
519
520     /* cast */
521     p_intf = (intf_thread_t*)p_data;
522
523     /* temporary hack to avoid blank menu when an open menu is removed */
524     if( GTK_MENU_ITEM(p_navigation)->submenu != NULL )
525     {
526         gtk_menu_popdown( GTK_MENU( GTK_MENU_ITEM(p_navigation)->submenu ) );
527     }
528     /* removes previous menu */
529     gtk_menu_item_remove_submenu( GTK_MENU_ITEM( p_navigation ) );
530     gtk_widget_set_sensitive( p_navigation, FALSE );
531
532     p_title_menu = gtk_menu_new();
533     p_title_group = NULL;
534     p_title_submenu = NULL;
535     p_title_menu_item = NULL;
536     p_chapter_group = NULL;
537     p_chapter_submenu = NULL;
538     p_chapter_menu_item = NULL;
539     p_item_active = NULL;
540     i_title_nb = p_intf->p_input->stream.i_area_nb;
541
542     /* loop on titles */
543     for( i_title = 1 ; i_title < i_title_nb ; i_title++ )
544     {
545         /* we group titles in packets of ten for small screens */
546         if( ( i_title % 10 == 1 ) && ( i_title_nb > 20 ) )
547         {
548             if( i_title != 1 )
549             {
550                 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_menu_item ),
551                                            p_title_submenu );
552                 gtk_menu_append( GTK_MENU( p_title_menu ), p_title_menu_item );
553             }
554
555             snprintf( psz_name, GTK_MENU_LABEL_SIZE,
556                       "%d - %d", i_title, i_title + 9 );
557             psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
558             p_title_menu_item = gtk_menu_item_new_with_label( psz_name );
559             gtk_widget_show( p_title_menu_item );
560             p_title_submenu = gtk_menu_new();
561         }
562
563         snprintf( psz_name, GTK_MENU_LABEL_SIZE, "Title %d (%d)", i_title,
564                   p_intf->p_input->stream.pp_areas[i_title]->i_part_nb );
565         psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
566 #if 0
567         if( pf_toggle == on_menubar_title_toggle )
568         {
569             p_title_item = gtk_radio_menu_item_new_with_label( p_title_group,
570                                                            psz_name );
571             p_title_group =
572               gtk_radio_menu_item_group( GTK_RADIO_MENU_ITEM( p_title_item ) );
573
574             if( p_intf->p_input->stream.pp_areas[i_title] ==
575                          p_intf->p_input->stream.p_selected_area )
576             {
577                 p_item_active = p_title_item;
578             }
579
580             /* setup signal hanling */
581             gtk_signal_connect( GTK_OBJECT( p_title_item ),
582                      "toggled",
583                      GTK_SIGNAL_FUNC( pf_toggle ),
584                      (gpointer)(p_intf->p_input->stream.pp_areas[i_title]) );
585
586             if( p_intf->p_input->stream.i_area_nb > 1 )
587             {
588                 /* be sure that menu is sensitive */
589                 gtk_widget_set_sensitive( p_navigation, TRUE );
590             }
591         }
592         else
593 #endif
594         {
595             p_title_item = gtk_menu_item_new_with_label( psz_name );
596
597 #if 1    
598             p_chapter_menu = gtk_menu_new();
599             i_chapter_nb =
600                     p_intf->p_input->stream.pp_areas[i_title]->i_part_nb;
601     
602             for( i_chapter = 0 ; i_chapter < i_chapter_nb ; i_chapter++ )
603             {
604                 /* we group chapters in packets of ten for small screens */
605                 if( ( i_chapter % 10 == 0 ) && ( i_chapter_nb > 20 ) )
606                 {
607                     if( i_chapter != 0 )
608                     {
609                         gtk_menu_item_set_submenu(
610                                     GTK_MENU_ITEM( p_chapter_menu_item ),
611                                     p_chapter_submenu );
612                         gtk_menu_append( GTK_MENU( p_chapter_menu ),
613                                          p_chapter_menu_item );
614                     }
615
616                     snprintf( psz_name, GTK_MENU_LABEL_SIZE,
617                               "%d - %d", i_chapter + 1, i_chapter + 10 );
618                     psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
619                     p_chapter_menu_item =
620                             gtk_menu_item_new_with_label( psz_name );
621                     gtk_widget_show( p_chapter_menu_item );
622                     p_chapter_submenu = gtk_menu_new();
623                 }
624
625                 snprintf( psz_name, GTK_MENU_LABEL_SIZE,
626                           "Chapter %d", i_chapter + 1 );
627                 psz_name[ GTK_MENU_LABEL_SIZE - 1 ] = '\0';
628     
629                 p_item = gtk_radio_menu_item_new_with_label(
630                                                 p_chapter_group, psz_name );
631                 p_chapter_group = gtk_radio_menu_item_group(
632                                                 GTK_RADIO_MENU_ITEM( p_item ) );
633                 gtk_widget_show( p_item );
634
635 #define p_area p_intf->p_input->stream.pp_areas[i_title]
636                 if( ( p_area == p_intf->p_input->stream.p_selected_area ) &&
637                     ( p_area->i_part == i_chapter + 1 ) )
638                 {
639                     p_item_active = p_item;
640                 }
641 #undef p_area
642
643                 /* setup signal hanling */
644                 gtk_signal_connect( GTK_OBJECT( p_item ),
645                            "toggled",
646                            GTK_SIGNAL_FUNC( pf_toggle ),
647                            (gpointer)POS2DATA( i_title, i_chapter + 1) );
648
649                 if( i_chapter_nb > 20 )
650                 {
651                     gtk_menu_append( GTK_MENU( p_chapter_submenu ), p_item );
652                 }
653                 else
654                 {
655                     gtk_menu_append( GTK_MENU( p_chapter_menu ), p_item );
656                 }
657             }
658
659             if( i_chapter_nb > 20 )
660             {
661                 gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_chapter_menu_item ),
662                                            p_chapter_submenu );
663                 gtk_menu_append( GTK_MENU( p_chapter_menu ),
664                                  p_chapter_menu_item );
665             }
666
667             /* link the new menu to the title menu item */
668             gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_item ),
669                                        p_chapter_menu );
670
671             if( p_intf->p_input->stream.pp_areas[i_title]->i_part_nb > 1 )
672             {
673                 /* be sure that menu is sensitive */
674                 gtk_widget_set_sensitive( p_navigation, TRUE );
675             }
676 #else
677         GtkRadioMenu( p_intf, p_title_item, p_chapter_group, "Chapter",
678                         p_intf->p_input->stream.pp_areas[i_title]->i_part_nb,
679                         i_title * 100,
680                         p_intf->p_input->stream.p_selected_area->i_part +
681                             p_intf->p_input->stream.p_selected_area->i_id *100,
682                         pf_toggle );
683
684 #endif
685         }
686         gtk_widget_show( p_title_item );
687
688         if( i_title_nb > 20 )
689         {
690             gtk_menu_append( GTK_MENU( p_title_submenu ), p_title_item );
691         }
692         else
693         {
694             gtk_menu_append( GTK_MENU( p_title_menu ), p_title_item );
695         }
696     }
697
698     if( i_title_nb > 20 )
699     {
700         gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_title_menu_item ),
701                                    p_title_submenu );
702         gtk_menu_append( GTK_MENU( p_title_menu ), p_title_menu_item );
703     }
704
705     /* be sure that menu is sensitive */
706     gtk_widget_set_sensitive( p_title_menu, TRUE );
707
708     /* link the new menu to the menubar item */
709     gtk_menu_item_set_submenu( GTK_MENU_ITEM( p_navigation ), p_title_menu );
710
711     if( p_item_active != NULL )
712     {
713         gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_item_active ),
714                                         TRUE );
715     }
716 #if 0
717     if( p_intf->p_input->stream.i_area_nb > 1 )
718     {
719         /* be sure that menu is sensitive */
720         gtk_widget_set_sensitive( p_navigation, TRUE );
721     }
722 #endif
723
724     return TRUE;
725 }
726 #endif
727 /*****************************************************************************
728  * GtkSetupMenu: function that generates title/chapter/audio/subpic
729  * menus with help from preceding functions
730  *****************************************************************************/
731 gint GtkSetupMenu( intf_thread_t * p_intf )
732 {
733     es_descriptor_t *   p_audio_es;
734     es_descriptor_t *   p_spu_es;
735     GtkWidget *         p_menubar_menu;
736     GtkWidget *         p_popup_menu;
737     gint                i;
738
739     p_intf->p_sys->b_chapter_update |= p_intf->p_sys->b_title_update;
740     p_intf->p_sys->b_angle_update |= p_intf->p_sys->b_title_update;
741     p_intf->p_sys->b_audio_update |= p_intf->p_sys->b_title_update;
742     p_intf->p_sys->b_spu_update |= p_intf->p_sys->b_title_update;
743
744     if( p_intf->p_sys->b_title_update )
745     { 
746         char            psz_title[5];
747
748         p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( 
749                             p_intf->p_sys->p_window ), "menubar_title" ) );
750         GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Title",
751                         p_intf->p_input->stream.i_area_nb - 1,
752                         p_intf->p_input->stream.p_selected_area->i_id,
753                         GtkMenubarTitleToggle );
754
755         snprintf( psz_title, 4, "%d",
756                   p_intf->p_input->stream.p_selected_area->i_id );
757         psz_title[ 4 ] = '\0';
758         gtk_label_set_text( p_intf->p_sys->p_label_title, psz_title );
759
760         p_intf->p_sys->b_title_update = 0;
761     }
762
763     if( p_intf->p_sys->b_chapter_update )
764     {
765         char            psz_chapter[5];
766
767         p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( 
768                              p_intf->p_sys->p_popup ), "popup_navigation" ) );
769         GtkTitleMenu( p_intf, p_popup_menu, GtkPopupNavigationToggle );
770 #if 0
771         GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Title",
772                         p_intf->p_input->stream.i_area_nb - 1,
773                         p_intf->p_input->stream.p_selected_area->i_id,
774                         on_menubar_chapter_toggle );
775 #endif
776
777         p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( 
778                              p_intf->p_sys->p_window ), "menubar_chapter" ) );
779         GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Chapter",
780                         p_intf->p_input->stream.p_selected_area->i_part_nb,
781                         p_intf->p_input->stream.p_selected_area->i_part,
782                         GtkMenubarChapterToggle );
783
784
785         snprintf( psz_chapter, 4, "%d", 
786                   p_intf->p_input->stream.p_selected_area->i_part );
787         psz_chapter[ 4 ] = '\0';
788         gtk_label_set_text( p_intf->p_sys->p_label_chapter, psz_chapter );
789
790         p_intf->p_sys->i_part =
791                 p_intf->p_input->stream.p_selected_area->i_part;
792
793         p_intf->p_sys->b_chapter_update = 0;
794     }
795
796     if( p_intf->p_sys->b_angle_update )
797     {
798         p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( 
799                              p_intf->p_sys->p_window ), "menubar_angle" ) );
800         GtkRadioMenu( p_intf, p_menubar_menu, NULL, "Angle",
801                         p_intf->p_input->stream.p_selected_area->i_angle_nb,
802                         p_intf->p_input->stream.p_selected_area->i_angle,
803                         GtkMenubarAngleToggle );
804
805         p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( 
806                              p_intf->p_sys->p_popup ), "popup_angle" ) );
807         GtkRadioMenu( p_intf, p_popup_menu, NULL, "Angle",
808                         p_intf->p_input->stream.p_selected_area->i_angle_nb,
809                         p_intf->p_input->stream.p_selected_area->i_angle,
810                         GtkPopupAngleToggle );
811
812         p_intf->p_sys->b_angle_update = 0;
813     }
814     
815     /* look for selected ES */
816     p_audio_es = NULL;
817     p_spu_es = NULL;
818
819     for( i = 0 ; i < p_intf->p_input->stream.i_selected_es_number ; i++ )
820     {
821         if( p_intf->p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES )
822         {
823             p_audio_es = p_intf->p_input->stream.pp_selected_es[i];
824         }
825
826         if( p_intf->p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
827         {
828             p_spu_es = p_intf->p_input->stream.pp_selected_es[i];
829         }
830     }
831
832     /* audio menus */
833     if( p_intf->p_sys->b_audio_update )
834     {
835         /* find audio root menu */
836         p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
837                              p_intf->p_sys->p_window ), "menubar_audio" ) );
838     
839         p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( 
840                      p_intf->p_sys->p_popup ), "popup_audio" ) );
841     
842         GtkLanguageMenus( p_intf, p_menubar_menu, p_audio_es, AUDIO_ES,
843                             GtkMenubarAudioToggle );
844         GtkLanguageMenus( p_intf, p_popup_menu, p_audio_es, AUDIO_ES,
845                             GtkPopupAudioToggle );
846
847         p_intf->p_sys->b_audio_update = 0;
848     }
849     
850     /* sub picture menus */
851     if( p_intf->p_sys->b_spu_update )
852     {
853         /* find spu root menu */
854         p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
855                           p_intf->p_sys->p_window ), "menubar_subpictures" ) );
856     
857         p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( 
858                      p_intf->p_sys->p_popup ), "popup_subpictures" ) );
859     
860         GtkLanguageMenus( p_intf, p_menubar_menu, p_spu_es, SPU_ES,
861                             GtkMenubarSubtitleToggle  );
862         GtkLanguageMenus( p_intf, p_popup_menu, p_spu_es, SPU_ES,
863                             GtkPopupSubtitleToggle );
864
865         p_intf->p_sys->b_spu_update = 0;
866     }
867
868     /* handle fullscreen check items */
869     if( p_vout_bank->i_count )
870     {
871         p_menubar_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT(
872                           p_intf->p_sys->p_window ), "menubar_fullscreen" ) );
873     
874         p_popup_menu = GTK_WIDGET( gtk_object_get_data( GTK_OBJECT( 
875                      p_intf->p_sys->p_popup ), "popup_fullscreen" ) );
876
877         gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_menubar_menu ),
878                                         p_vout_bank->pp_vout[0]->b_fullscreen );
879         gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM( p_popup_menu ),
880                                         p_vout_bank->pp_vout[0]->b_fullscreen );
881
882     }
883
884     return TRUE;
885 }
886