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