]> git.sesse.net Git - vlc/blob - modules/gui/win32/menu.cpp
The win32 interface is preparing for the internationalization.
[vlc] / modules / gui / win32 / menu.cpp
1 /*****************************************************************************\r
2  * menu.cpp: functions to handle menu items\r
3  *****************************************************************************\r
4  * Copyright (C) 2002 VideoLAN\r
5  *\r
6  * Authors: Olivier Teuliere <ipkiss@via.ecp.fr>\r
7  *\r
8  * This program is free software; you can redistribute it and/or modify\r
9  * it under the terms of the GNU General Public License as published by\r
10  * the Free Software Foundation; either version 2 of the License, or\r
11  * (at your option) any later version.\r
12  * \r
13  * This program is distributed in the hope that it will be useful,\r
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
16  * GNU General Public License for more details.\r
17  *\r
18  * You should have received a copy of the GNU General Public License\r
19  * along with this program; if not, write to the Free Software\r
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.\r
21  *****************************************************************************/\r
22 \r
23 #include <vcl.h>\r
24 //#pragma hdrstop\r
25 \r
26 #include <vlc/vlc.h>\r
27 #include <vlc/intf.h>\r
28 \r
29 #include "menu.h"\r
30 #include "win32_common.h"\r
31 \r
32 \r
33 /****************************************************************************\r
34  * Local Prototypes\r
35  ****************************************************************************/\r
36 extern  intf_thread_t *p_intfGlobal;\r
37 \r
38 static TMenuItem *Index2Item( TMenuItem *, int, bool );\r
39 static int Item2Index( TMenuItem *, TMenuItem * );\r
40 static void __fastcall LangChange( TMenuItem *, TMenuItem *, TMenuItem *, int );\r
41 static void __fastcall ProgramChange( TMenuItem *, TMenuItem * );\r
42 \r
43 static void __fastcall RadioMenu( TMenuItem *, AnsiString,\r
44                                   int, int, TNotifyEvent );\r
45 static void __fastcall ProgramMenu( TMenuItem *, pgrm_descriptor_t *,\r
46                                     TNotifyEvent );\r
47 static void __fastcall LanguageMenu( TMenuItem *t, es_descriptor_t *,\r
48                                      int, TNotifyEvent );\r
49 static void __fastcall NavigationMenu( TMenuItem *, TNotifyEvent );\r
50 \r
51 \r
52 static TMenuItem *Index2Item( TMenuItem *Root, int i_index, bool SingleColumn )\r
53 {\r
54     if( SingleColumn || ( i_index < 20 ) )\r
55     {\r
56         return Root->Items[i_index];\r
57     }\r
58     else\r
59     {\r
60         return Root->Items[i_index / 10]->Items[i_index % 10];\r
61     }\r
62 }\r
63 \r
64 static int Item2Index( TMenuItem *Root, TMenuItem *Item )\r
65 {\r
66     if( Item->Parent == Root )\r
67     {\r
68         return Item->MenuIndex;\r
69     }\r
70     else\r
71     {\r
72         return( 10 * Item->Parent->MenuIndex + Item->MenuIndex );\r
73     }\r
74 }\r
75 \r
76 \r
77 /****************************************************************************\r
78  * LangChange: change audio or subtitles languages\r
79  ****************************************************************************\r
80  * Toggle the language, and update the selected menuitems.\r
81  ****************************************************************************/\r
82 static void __fastcall LangChange( TMenuItem *RootCurrent, TMenuItem *Item,\r
83                                    TMenuItem *RootOther, int i_cat )\r
84 {\r
85     intf_thread_t         * p_intf = p_intfGlobal;\r
86     es_descriptor_t       * p_es;\r
87     es_descriptor_t       * p_es_old;\r
88     int                     i_index;\r
89     int                     i_es;\r
90 \r
91     /* find the selected ES */\r
92     i_es = Item->Tag;\r
93 \r
94     /* find selected menu item */\r
95     i_index = Item2Index( RootCurrent, Item ) - 1;\r
96     if( i_index < 0 )\r
97     {\r
98         /* 'None' was selected */\r
99         p_es = NULL;\r
100     }\r
101     else\r
102     {\r
103         vlc_mutex_lock( &p_intfGlobal->p_sys->p_input->stream.stream_lock );\r
104         p_es = p_intfGlobal->p_sys->p_input->stream.pp_es[i_es];\r
105         vlc_mutex_unlock( &p_intfGlobal->p_sys->p_input->stream.stream_lock );\r
106     }\r
107 \r
108     /* find the current ES */\r
109     if( i_cat == AUDIO_ES )\r
110     {\r
111         p_es_old = p_intf->p_sys->p_audio_es_old;\r
112         p_intf->p_sys->p_audio_es_old = p_es;\r
113     }\r
114     else\r
115     {\r
116         p_es_old = p_intf->p_sys->p_spu_es_old;\r
117         p_intf->p_sys->p_spu_es_old = p_es;\r
118     }\r
119 \r
120     /* exchange them */\r
121     input_ToggleES( p_intfGlobal->p_sys->p_input, p_es_old, false );\r
122     input_ToggleES( p_intfGlobal->p_sys->p_input, p_es, true );\r
123 \r
124     Item->Checked = true;\r
125     Index2Item( RootOther, i_index + 1, true )->Checked = true;\r
126 }\r
127 \r
128 \r
129 /****************************************************************************\r
130  * ProgramChange: change the program\r
131  ****************************************************************************\r
132  * Toggle the program, and update the selected menuitems.\r
133  ****************************************************************************/\r
134 static void __fastcall ProgramChange( TMenuItem *Item, TMenuItem *RootOther )\r
135 {\r
136     intf_thread_t * p_intf = p_intfGlobal;\r
137     int             i_program = Item->Tag;\r
138 \r
139     /* toggle the program */\r
140     input_ChangeProgram( p_intfGlobal->p_sys->p_input, (u16)i_program );\r
141 \r
142     /* check selected menu items */\r
143     Item->Checked = true;\r
144     Index2Item( RootOther, i_program - 1, true )->Checked = true;\r
145 \r
146     /* update audio/subtitles menus */\r
147     p_intf->p_sys->b_audio_update = 1;\r
148     p_intf->p_sys->b_spu_update = 1;\r
149     vlc_mutex_lock( &p_intfGlobal->p_sys->p_input->stream.stream_lock );\r
150     SetupMenus( p_intf );\r
151     vlc_mutex_unlock( &p_intfGlobal->p_sys->p_input->stream.stream_lock );\r
152     p_intf->p_sys->b_audio_update = 0;\r
153     p_intf->p_sys->b_spu_update = 0;\r
154 \r
155     input_SetStatus( p_intfGlobal->p_sys->p_input, INPUT_STATUS_PLAY );\r
156 }\r
157 \r
158 \r
159 /****************************************************************************\r
160  * TMainFrameDlg::*Click: callbacks for the menuitems\r
161  ****************************************************************************\r
162  * These functions need to be in a class, or we won't be able to pass them\r
163  * as arguments (since TNotifyEvent uses __closure)\r
164  ****************************************************************************/\r
165 \r
166  /*\r
167  * Audio\r
168  */\r
169 \r
170 void __fastcall TMainFrameDlg::MenuAudioClick( TObject *Sender )\r
171 {\r
172     LangChange( MenuAudio, (TMenuItem *)Sender, PopupAudio, AUDIO_ES );\r
173 }\r
174 \r
175 void __fastcall TMainFrameDlg::PopupAudioClick( TObject *Sender )\r
176 {\r
177     LangChange( PopupAudio, (TMenuItem *)Sender, MenuAudio, AUDIO_ES );\r
178 }\r
179 \r
180 /*\r
181  * Subtitles\r
182  */\r
183 \r
184 void __fastcall TMainFrameDlg::MenuSubtitleClick( TObject *Sender )\r
185 {\r
186     LangChange( MenuSubtitles, (TMenuItem *)Sender, PopupSubtitles, SPU_ES );\r
187 }\r
188 \r
189 void __fastcall TMainFrameDlg::PopupSubtitleClick( TObject *Sender )\r
190 {\r
191     LangChange( PopupSubtitles, (TMenuItem *)Sender, MenuSubtitles, SPU_ES );\r
192 }\r
193 \r
194 /*\r
195  * Program\r
196  */\r
197 \r
198 void __fastcall TMainFrameDlg::MenuProgramClick( TObject *Sender )\r
199 {\r
200     ProgramChange( (TMenuItem *)Sender, PopupProgram );\r
201 }\r
202 \r
203 void __fastcall TMainFrameDlg::PopupProgramClick( TObject *Sender )\r
204 {\r
205     ProgramChange( (TMenuItem *)Sender, MenuProgram );\r
206 }\r
207 \r
208 /*\r
209  * Navigation\r
210  */\r
211 \r
212 void __fastcall TMainFrameDlg::PopupNavigationClick( TObject *Sender )\r
213 {\r
214     TMenuItem     * Item = (TMenuItem *)Sender;\r
215     TMenuItem     * ItemTitle;\r
216     input_area_t  * p_area;\r
217     int             i_title   = DATA2TITLE( Item->Tag );\r
218     int             i_chapter = DATA2CHAPTER( Item->Tag );\r
219 \r
220     p_area = p_intfGlobal->p_sys->p_input->stream.pp_areas[i_title];\r
221     p_area->i_part = i_chapter;\r
222 \r
223     input_ChangeArea( p_intfGlobal->p_sys->p_input, (input_area_t*)p_area );\r
224 \r
225     Item->Checked = true;\r
226     ItemTitle = Index2Item( MenuTitle, i_title - 1, false );\r
227     if( ItemTitle->Checked )\r
228     {\r
229         /* same title, new chapter */\r
230         Index2Item( MenuChapter, i_chapter - 1, false )->Checked = true;\r
231     }\r
232     else\r
233     {\r
234         /* new title => we must rebuild the chapter menu */\r
235         vlc_mutex_lock( &p_intfGlobal->p_sys->p_input->stream.stream_lock );\r
236         RadioMenu( MenuChapter, "Chapter",\r
237                    p_intfGlobal->p_sys->p_input->stream.p_selected_area->i_part_nb,\r
238                    i_chapter, MenuChapterClick );\r
239         vlc_mutex_unlock( &p_intfGlobal->p_sys->p_input->stream.stream_lock );\r
240     }\r
241 \r
242     input_SetStatus( p_intfGlobal->p_sys->p_input, INPUT_STATUS_PLAY );\r
243 }\r
244 \r
245 /*\r
246  * Title\r
247  */\r
248 \r
249 void __fastcall TMainFrameDlg::MenuTitleClick( TObject *Sender )\r
250 {\r
251     TMenuItem     * Item = (TMenuItem *)Sender;\r
252     TMenuItem     * ItemTitle;\r
253     int             i_title = Item->Tag;\r
254 \r
255     input_ChangeArea( p_intfGlobal->p_sys->p_input,\r
256                       p_intfGlobal->p_sys->p_input->stream.pp_areas[i_title] );\r
257     Item->Checked = true;\r
258     ItemTitle = Index2Item( PopupNavigation, i_title - 1, false );\r
259     Index2Item( ItemTitle, 0, false )->Checked = true;\r
260 \r
261     input_SetStatus( p_intfGlobal->p_sys->p_input, INPUT_STATUS_PLAY );\r
262 }\r
263 \r
264 /*\r
265  * Chapter\r
266  */\r
267 \r
268 void __fastcall TMainFrameDlg::MenuChapterClick( TObject *Sender )\r
269 {\r
270     TMenuItem     * Item = (TMenuItem *)Sender;\r
271     TMenuItem     * ItemTitle;\r
272     input_area_t  * p_area;\r
273     int             i_title;\r
274     int             i_chapter = Item->Tag;\r
275 \r
276     p_area = p_intfGlobal->p_sys->p_input->stream.p_selected_area;\r
277     p_area->i_part = i_chapter;\r
278 \r
279     input_ChangeArea( p_intfGlobal->p_sys->p_input, (input_area_t*)p_area );\r
280 \r
281     i_title = p_intfGlobal->p_sys->p_input->stream.p_selected_area->i_id;\r
282     ItemTitle = Index2Item( PopupNavigation, i_title - 1, false );\r
283     Index2Item( ItemTitle, i_chapter - 1, false )->Checked = true;\r
284 \r
285     input_SetStatus( p_intfGlobal->p_sys->p_input, INPUT_STATUS_PLAY );\r
286 }\r
287 \r
288 \r
289 /****************************************************************************\r
290  * Functions to generate menus\r
291  ****************************************************************************/\r
292 \r
293 /*****************************************************************************\r
294  * RadioMenu: update interactive menus of the interface\r
295  *****************************************************************************\r
296  * Sets up menus with information from input\r
297  * Warning: since this function is designed to be called by management\r
298  * function, the interface lock has to be taken\r
299  *****************************************************************************/\r
300 static void __fastcall RadioMenu( TMenuItem * Root, AnsiString ItemName,\r
301                                   int i_nb, int i_selected,\r
302                                   TNotifyEvent MenuItemClick )\r
303 {\r
304     TMenuItem     * ItemGroup;\r
305     TMenuItem     * Item;\r
306     TMenuItem     * ItemActive;\r
307     AnsiString      Name;\r
308     int             i_item;\r
309 \r
310     /* remove previous menu */\r
311     Root->Enabled = false;\r
312     Root->Clear();\r
313 \r
314     ItemActive = NULL;\r
315 \r
316     for( i_item = 0; i_item < i_nb; i_item++ )\r
317     {\r
318         /* we group titles/chapters in packets of ten for small screens */\r
319         if( ( i_item % 10 == 0 ) && ( i_nb > 20 ) )\r
320         {\r
321             if( i_item != 0 )\r
322             {\r
323                 Root->Add( ItemGroup );\r
324             }\r
325 \r
326             Name.sprintf( "%ss %d to %d", ItemName, i_item + 1, i_item + 10 );\r
327             ItemGroup = new TMenuItem( Root );\r
328             ItemGroup->Hint = Name;\r
329 \r
330             /* set the accelerator character */\r
331             Name.Insert( "&", Name.Length() - 1 );\r
332             ItemGroup->Caption = Name;\r
333         }\r
334 \r
335         Name.sprintf( "%s %d", ItemName, i_item + 1 );\r
336         Item = new TMenuItem( Root );\r
337         Item->RadioItem = true;\r
338         Item->Hint = Name;\r
339 \r
340         /* set the accelerator character */\r
341         Name.Insert( "&", Name.Length() );\r
342         Item->Caption = Name;\r
343 \r
344         /* FIXME: temporary hack to save i_item with the Item\r
345          * It will be used in the callback. */\r
346         Item->Tag = i_item + 1;\r
347 \r
348         if( i_selected == i_item + 1 )\r
349         {\r
350             ItemActive = Item;\r
351         }\r
352         \r
353         /* setup signal handling */\r
354         Item->OnClick = MenuItemClick;\r
355 \r
356         if( i_nb > 20 )\r
357         {\r
358             ItemGroup->Add( Item );\r
359         }\r
360         else\r
361         {\r
362             Root->Add( Item );\r
363         }\r
364     }\r
365 \r
366 //  if( ( i_nb > 20 ) && ( i_item % 10 ) )  ?\r
367     if( i_nb > 20 )\r
368     {\r
369         Root->Add( ItemGroup );\r
370     }\r
371 \r
372     /* check currently selected chapter */\r
373     if( ItemActive != NULL )\r
374     {\r
375         ItemActive->Checked = true;\r
376     }\r
377 \r
378     /* be sure that menu is enabled, if there are several items */\r
379     if( i_nb > 1 )\r
380     {\r
381         Root->Enabled = true;\r
382     }\r
383 }\r
384 \r
385 \r
386 /*****************************************************************************\r
387  * ProgramMenu: update the programs menu of the interface\r
388  *****************************************************************************\r
389  * Builds the program menu according to what have been found in the PAT \r
390  * by the input. Useful for multi-programs streams such as DVB ones.\r
391  *****************************************************************************/\r
392 static void __fastcall ProgramMenu( TMenuItem * Root,\r
393                                     pgrm_descriptor_t * p_pgrm,\r
394                                     TNotifyEvent MenuItemClick )\r
395 {\r
396     TMenuItem     * Item;\r
397     TMenuItem     * ItemActive;\r
398     AnsiString      Name;\r
399     int             i;\r
400 \r
401     /* remove previous menu */\r
402     Root->Clear();\r
403     Root->Enabled = false;\r
404 \r
405     ItemActive = NULL;\r
406 \r
407     /* create a set of program buttons and append them to the container */\r
408     for( i = 0; i < p_intfGlobal->p_sys->p_input->stream.i_pgrm_number; i++ )\r
409     {\r
410         Name.sprintf( "id %d",\r
411             p_intfGlobal->p_sys->p_input->stream.pp_programs[i]->i_number );\r
412 \r
413         Item = new TMenuItem( Root );\r
414         Item->Caption = Name;\r
415         Item->Hint = Name;\r
416         Item->RadioItem = true;\r
417         Item->OnClick = MenuItemClick;\r
418 \r
419         /* FIXME: temporary hack to save the program id with the Item\r
420          * It will be used in the callback. */\r
421         Item->Tag = i + 1;\r
422 \r
423         if( p_pgrm == p_intfGlobal->p_sys->p_input->stream.pp_programs[i] )\r
424         {\r
425             /* don't lose Item when we append into menu */\r
426             ItemActive = Item;\r
427         }\r
428 \r
429         /* Add the item to the submenu */\r
430         Root->Add( Item );\r
431     }\r
432 \r
433     /* check currently selected program */\r
434     if( ItemActive != NULL )\r
435     {\r
436         ItemActive->Checked = true;\r
437     }\r
438 \r
439     /* be sure that menu is enabled if more than 1 program */\r
440     if( p_intfGlobal->p_sys->p_input->stream.i_pgrm_number > 1 )\r
441     {\r
442         Root->Enabled = true;\r
443     }\r
444 }\r
445 \r
446 \r
447 /*****************************************************************************\r
448  * LanguageMenus: update interactive menus of the interface\r
449  *****************************************************************************\r
450  * Sets up menus with information from input:\r
451  *  - languages\r
452  *  - sub-pictures\r
453  * Warning: since this function is designed to be called by management\r
454  * function, the interface lock has to be taken\r
455  *****************************************************************************/\r
456 static void __fastcall LanguageMenu( TMenuItem * Root, es_descriptor_t * p_es,\r
457                                       int i_cat, TNotifyEvent MenuItemClick )\r
458 {\r
459     TMenuItem     * Separator;\r
460     TMenuItem     * Item;\r
461     TMenuItem     * ItemActive;\r
462     AnsiString      Name;\r
463     int             i_item;\r
464     int             i;\r
465 \r
466     /* remove previous menu */\r
467     Root->Clear();\r
468     Root->Enabled = false;\r
469 \r
470     /* special case for "off" item */\r
471     Name = "None";\r
472     Item = new TMenuItem( Root );\r
473     Item->RadioItem = true;\r
474     Item->Hint = Name;\r
475     Item->Caption = Name;\r
476     Item->OnClick = MenuItemClick;\r
477     Item->Tag = -1;\r
478     Root->Add( Item );\r
479 \r
480     /* separator item */\r
481     Separator = new TMenuItem( Root );\r
482     Separator->Caption = "-";\r
483     Root->Add( Separator );\r
484 \r
485     ItemActive = NULL;\r
486     i_item = 0;\r
487 \r
488     vlc_mutex_lock( &p_intfGlobal->p_sys->p_input->stream.stream_lock );\r
489 \r
490 #define ES p_intfGlobal->p_sys->p_input->stream.pp_es[i]\r
491     /* create a set of language buttons and append them to the Root */\r
492     for( i = 0; i < p_intfGlobal->p_sys->p_input->stream.i_es_number; i++ )\r
493     {\r
494         if( ( ES->i_cat == i_cat ) &&\r
495             ( !ES->p_pgrm ||\r
496               ES->p_pgrm ==\r
497                  p_intfGlobal->p_sys->p_input->stream.p_selected_program ) )\r
498         {\r
499             i_item++;\r
500             Name = p_intfGlobal->p_sys->p_input->stream.pp_es[i]->psz_desc;\r
501             if( Name.IsEmpty() )\r
502             {\r
503                 Name.sprintf( "Language %d", i_item );\r
504             }\r
505 \r
506             Item = new TMenuItem( Root );\r
507             Item->RadioItem = true;\r
508             Item->Hint = Name;\r
509             Item->Caption = Name;\r
510             Item->Tag = i;\r
511 \r
512             if( p_es == p_intfGlobal->p_sys->p_input->stream.pp_es[i] )\r
513             {\r
514                 /* don't lose Item when we append into menu */\r
515                 ItemActive = Item;\r
516             }\r
517 \r
518             /* setup signal hanling */\r
519             Item->OnClick = MenuItemClick;\r
520             Root->Add( Item );\r
521         }\r
522     }\r
523 #undef ES\r
524 \r
525     vlc_mutex_unlock( &p_intfGlobal->p_sys->p_input->stream.stream_lock );\r
526 \r
527     /* check currently selected item */\r
528     if( ItemActive != NULL )\r
529     {\r
530         ItemActive->Checked = true;\r
531     }\r
532 \r
533     /* be sure that menu is enabled if non empty */\r
534     if( i_item > 0 )\r
535     {\r
536         Root->Enabled = true;\r
537     }\r
538 }\r
539 \r
540 \r
541 /*****************************************************************************\r
542  * NavigationMenu: sets menus for titles and chapters selection\r
543  *****************************************************************************\r
544  * Generates two types of menus:\r
545  *  -simple list of titles\r
546  *  -cascaded lists of chapters for each title\r
547  *****************************************************************************/\r
548 static void __fastcall NavigationMenu( TMenuItem * Root,\r
549                                        TNotifyEvent MenuItemClick )\r
550 {\r
551     TMenuItem     * TitleGroup;\r
552     TMenuItem     * TitleItem;\r
553     TMenuItem     * ItemActive;\r
554     TMenuItem     * ChapterGroup;\r
555     TMenuItem     * ChapterItem;\r
556     AnsiString      Name;\r
557     int             i_title;\r
558     int             i_chapter;\r
559     int             i_title_nb;\r
560     int             i_chapter_nb;\r
561 \r
562 \r
563     /* remove previous menu */\r
564     Root->Enabled = false;\r
565     Root->Clear();\r
566 \r
567     ItemActive = NULL;\r
568     i_title_nb = p_intfGlobal->p_sys->p_input->stream.i_area_nb;\r
569     \r
570     /* loop on titles */\r
571     for( i_title = 1; i_title < i_title_nb; i_title++ )\r
572     {\r
573         /* we group titles in packets of ten for small screens */\r
574         if( ( i_title % 10 == 1 ) && ( i_title_nb > 20 ) )\r
575         {\r
576             if( i_title != 1 )\r
577             {\r
578                 Root->Add( TitleGroup );\r
579             }\r
580 \r
581             Name.sprintf( "%d - %d", i_title, i_title + 9 );\r
582             TitleGroup = new TMenuItem( Root );\r
583             TitleGroup->RadioItem = true;\r
584             TitleGroup->Hint = Name;\r
585             TitleGroup->Caption = Name;\r
586         }\r
587 \r
588         Name.sprintf( "Title %d (%d)", i_title,\r
589             p_intfGlobal->p_sys->p_input->stream.pp_areas[i_title]->i_part_nb );\r
590 \r
591         {\r
592             TitleItem = new TMenuItem( Root );\r
593             TitleItem->RadioItem = true;\r
594             TitleItem->Hint = Name;\r
595             TitleItem->Caption = Name;\r
596 \r
597             i_chapter_nb =\r
598                 p_intfGlobal->p_sys->p_input->stream.pp_areas[i_title]->i_part_nb;\r
599 \r
600             /* loop on chapters */\r
601             for( i_chapter = 0; i_chapter < i_chapter_nb; i_chapter++ )\r
602             {\r
603                 /* we group chapters in packets of ten for small screens */\r
604                 if( ( i_chapter % 10 == 0 ) && ( i_chapter_nb > 20 ) )\r
605                 {\r
606                     if( i_chapter != 0 )\r
607                     {\r
608                         TitleItem->Add( ChapterGroup );\r
609                     }\r
610 \r
611                     Name.sprintf( "%d - %d", i_chapter + 1, i_chapter + 10 );\r
612                     ChapterGroup = new TMenuItem( TitleItem );\r
613                     ChapterGroup->RadioItem = true;\r
614                     ChapterGroup->Hint = Name;\r
615                     ChapterGroup->Caption = Name;\r
616                 }\r
617 \r
618                 Name.sprintf( "Chapter %d", i_chapter + 1 );\r
619 \r
620                 ChapterItem = new TMenuItem( TitleItem );\r
621                 ChapterItem->RadioItem = true;\r
622                 ChapterItem->Hint = Name;\r
623                 ChapterItem->Caption = Name;\r
624 \r
625                 /* FIXME: temporary hack to save i_title and i_chapter with\r
626                  * ChapterItem, since we will need them in the callback */\r
627                  ChapterItem->Tag = (int)POS2DATA( i_title, i_chapter + 1 );\r
628 \r
629 #define p_area p_intfGlobal->p_sys->p_input->stream.pp_areas[i_title]\r
630                 if( ( p_area ==\r
631                         p_intfGlobal->p_sys->p_input->stream.p_selected_area ) &&\r
632                     ( p_area->i_part == i_chapter + 1 ) )\r
633                 {\r
634                     ItemActive = ChapterItem;\r
635                 }\r
636 #undef p_area\r
637 \r
638                 /* setup signal hanling */\r
639                 ChapterItem->OnClick = MenuItemClick;\r
640 \r
641                 if( i_chapter_nb > 20 )\r
642                 {\r
643                     ChapterGroup->Add( ChapterItem );\r
644                 }\r
645                 else\r
646                 {\r
647                     TitleItem->Add( ChapterItem );\r
648                 }\r
649             }\r
650 \r
651             if( i_chapter_nb > 20 )\r
652             {\r
653                 TitleItem->Add( ChapterGroup );\r
654             }\r
655 \r
656             if( p_intfGlobal->p_sys->p_input->stream.pp_areas[i_title]->i_part_nb\r
657                 > 1 )\r
658             {\r
659                 /* be sure that menu is sensitive */\r
660                 Root->Enabled = true;\r
661             }\r
662         }\r
663 \r
664         if( i_title_nb > 20 )\r
665         {\r
666             TitleGroup->Add( TitleItem );\r
667         }\r
668         else\r
669         {\r
670             Root->Add( TitleItem );\r
671         }\r
672     }\r
673 \r
674     if( i_title_nb > 20 )\r
675     {\r
676         Root->Add( TitleGroup );\r
677     }\r
678 \r
679     /* Default selected chapter */\r
680     if( ItemActive != NULL )\r
681     {\r
682         ItemActive->Checked = true;\r
683     }\r
684 \r
685     /* be sure that menu is sensitive */\r
686     Root->Enabled = true;\r
687 }\r
688 \r
689 \r
690 /*****************************************************************************\r
691  * SetupMenus: function that generates title/chapter/audio/subpic\r
692  * menus with help from preceding functions\r
693  *****************************************************************************/\r
694 int __fastcall SetupMenus( intf_thread_t * p_intf )\r
695 {\r
696     TMainFrameDlg     * p_window = p_intf->p_sys->p_window;\r
697     es_descriptor_t   * p_audio_es;\r
698     es_descriptor_t   * p_spu_es;\r
699     int                 i;\r
700 \r
701     p_intf->p_sys->b_chapter_update |= p_intf->p_sys->b_title_update;\r
702     p_intf->p_sys->b_audio_update |= p_intf->p_sys->b_title_update |\r
703                                      p_intf->p_sys->b_program_update;\r
704     p_intf->p_sys->b_spu_update |= p_intf->p_sys->b_title_update |\r
705                                    p_intf->p_sys->b_program_update;\r
706 \r
707     if( p_intf->p_sys->b_program_update )\r
708     { \r
709         pgrm_descriptor_t * p_pgrm;\r
710 \r
711         if( p_intfGlobal->p_sys->p_input->stream.p_new_program )\r
712         {\r
713             p_pgrm = p_intfGlobal->p_sys->p_input->stream.p_new_program;\r
714         }\r
715         else\r
716         {\r
717             p_pgrm = p_intfGlobal->p_sys->p_input->stream.p_selected_program;\r
718         }\r
719 \r
720         ProgramMenu( p_window->MenuProgram, p_pgrm,\r
721                      p_window->MenuProgramClick );\r
722         ProgramMenu( p_window->PopupProgram, p_pgrm,\r
723                      p_window->PopupProgramClick );\r
724 \r
725         p_intf->p_sys->b_program_update = 0;\r
726     }\r
727 \r
728     if( p_intf->p_sys->b_title_update )\r
729     {\r
730         RadioMenu( p_window->MenuTitle, "Title",\r
731 //why "-1" ?\r
732                    p_intfGlobal->p_sys->p_input->stream.i_area_nb - 1,\r
733                    p_intfGlobal->p_sys->p_input->stream.p_selected_area->i_id,\r
734                    p_window->MenuTitleClick );\r
735 \r
736         AnsiString CurrentTitle;\r
737         CurrentTitle.sprintf( "%d",\r
738                     p_intfGlobal->p_sys->p_input->stream.p_selected_area->i_id );\r
739         p_window->LabelTitleCurrent->Caption = CurrentTitle;\r
740 \r
741         p_intf->p_sys->b_title_update = 0;\r
742     }\r
743 \r
744     if( p_intf->p_sys->b_chapter_update )\r
745     {\r
746         RadioMenu( p_window->MenuChapter, "Chapter",\r
747                    p_intfGlobal->p_sys->p_input->stream.p_selected_area->i_part_nb,\r
748                    p_intfGlobal->p_sys->p_input->stream.p_selected_area->i_part,\r
749                    p_window->MenuChapterClick );\r
750 \r
751         NavigationMenu( p_window->PopupNavigation,\r
752                         p_window->PopupNavigationClick );\r
753 \r
754         AnsiString CurrentChapter;\r
755         CurrentChapter.sprintf( "%d",\r
756                     p_intfGlobal->p_sys->p_input->stream.p_selected_area->i_part );\r
757         p_window->LabelChapterCurrent->Caption = CurrentChapter;\r
758 \r
759         p_intf->p_sys->i_part =\r
760                     p_intfGlobal->p_sys->p_input->stream.p_selected_area->i_part;\r
761 \r
762         p_intf->p_sys->b_chapter_update = 0;\r
763     }\r
764 \r
765     /* look for selected ES */\r
766     p_audio_es = NULL;\r
767     p_spu_es = NULL;\r
768 \r
769      for( i = 0; i < p_intfGlobal->p_sys->p_input->stream.i_selected_es_number; i++ )\r
770     {\r
771         if( p_intfGlobal->p_sys->p_input->stream.pp_selected_es[i]->i_cat\r
772             == AUDIO_ES )\r
773         {\r
774             p_audio_es = p_intfGlobal->p_sys->p_input->stream.pp_selected_es[i];\r
775             p_intfGlobal->p_sys->p_audio_es_old = p_audio_es;\r
776         }\r
777 \r
778         if( p_intfGlobal->p_sys->p_input->stream.pp_selected_es[i]->i_cat\r
779             == SPU_ES )\r
780         {\r
781             p_spu_es = p_intfGlobal->p_sys->p_input->stream.pp_selected_es[i];\r
782             p_intfGlobal->p_sys->p_spu_es_old = p_spu_es;\r
783         }\r
784     }\r
785 \r
786     vlc_mutex_unlock( &p_intfGlobal->p_sys->p_input->stream.stream_lock );\r
787 \r
788     /* audio menus */\r
789     if( p_intf->p_sys->b_audio_update )\r
790     {\r
791         LanguageMenu( p_window->MenuAudio, p_audio_es, AUDIO_ES,\r
792                       p_window->MenuAudioClick );\r
793         LanguageMenu( p_window->PopupAudio, p_audio_es, AUDIO_ES,\r
794                       p_window->PopupAudioClick );\r
795 \r
796         p_intf->p_sys->b_audio_update = 0;\r
797     }\r
798 \r
799     /* sub picture menus */\r
800     if( p_intf->p_sys->b_spu_update )\r
801     {\r
802         LanguageMenu( p_window->PopupSubtitles, p_spu_es, SPU_ES,\r
803                       p_window->PopupSubtitleClick );\r
804         LanguageMenu( p_window->MenuSubtitles, p_spu_es, SPU_ES,\r
805                       p_window->MenuSubtitleClick );\r
806 \r
807         p_intf->p_sys->b_spu_update = 0;\r
808     }\r
809 \r
810     vlc_mutex_lock( &p_intfGlobal->p_sys->p_input->stream.stream_lock );\r
811 \r
812     return true;\r
813 }\r
814 \r
815 \r
816 \r