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