1 /*****************************************************************************
2 * menu.cpp: functions to handle menu items
3 *****************************************************************************
4 * Copyright (C) 2002-2003 VideoLAN
5 * $Id: menu.cpp,v 1.13 2003/02/06 23:59:40 sam Exp $
7 * Authors: Olivier Teuliere <ipkiss@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
30 #include "win32_common.h"
32 /*****************************************************************************
33 * TMenusGen::*Click: callbacks for the menuitems
34 ****************************************************************************/
40 /* variables of the audio output */
41 void __fastcall TMenusGen::AoutVarClick( TObject *Sender )
43 TMenuItem * Item = (TMenuItem *)Sender;
45 vlc_object_t * p_aout;
46 p_aout = (vlc_object_t *)vlc_object_find( p_intf, VLC_OBJECT_AOUT,
50 msg_Warn( p_intf, "cannot set variable (%s)", Item->Caption.c_str() );
54 if( Item->Parent == MenuADevice || Item->Parent == PopupADevice )
56 VarChange( p_aout, "audio-device", MenuADevice, PopupADevice, Item );
58 else if( Item->Parent == MenuChannel || Item->Parent == PopupChannel )
60 VarChange( p_aout, "audio-channels", MenuChannel, PopupChannel, Item );
63 vlc_object_release( p_aout );
66 /* variables of the video output */
67 void __fastcall TMenusGen::VoutVarClick( TObject *Sender )
69 TMenuItem * Item = (TMenuItem *)Sender;
71 vlc_object_t * p_vout;
72 p_vout = (vlc_object_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
76 msg_Warn( p_intf, "cannot set variable (%s)", Item->Caption.c_str() );
80 if( Item->Parent == MenuVDevice || Item->Parent == PopupVDevice )
82 VarChange( p_vout, "video-device", MenuVDevice, PopupVDevice, Item );
85 vlc_object_release( p_vout );
92 /* Interface modules: we spawn a new interface */
93 void __fastcall TMenusGen::InterfaceModuleClick( TObject *Sender )
95 TMenuItem * Item = (TMenuItem *)Sender;
97 AnsiString IntfName = CleanCaption( Item->Caption );
99 intf_thread_t *p_newintf;
101 p_newintf = intf_Create( p_intf->p_vlc, IntfName.c_str() );
105 p_newintf->b_block = VLC_FALSE;
106 if( intf_RunThread( p_newintf ) )
108 vlc_object_detach( p_newintf );
109 intf_Destroy( p_newintf );
118 void __fastcall TMenusGen::MenuLanguageClick( TObject *Sender )
120 LangChange( MenuLanguage, (TMenuItem *)Sender, PopupLanguage, AUDIO_ES );
123 void __fastcall TMenusGen::PopupLanguageClick( TObject *Sender )
125 LangChange( PopupLanguage, (TMenuItem *)Sender, MenuLanguage, AUDIO_ES );
132 void __fastcall TMenusGen::MenuSubtitleClick( TObject *Sender )
134 LangChange( MenuSubtitles, (TMenuItem *)Sender, PopupSubtitles, SPU_ES );
137 void __fastcall TMenusGen::PopupSubtitleClick( TObject *Sender )
139 LangChange( PopupSubtitles, (TMenuItem *)Sender, MenuSubtitles, SPU_ES );
146 void __fastcall TMenusGen::MenuProgramClick( TObject *Sender )
148 ProgramChange( (TMenuItem *)Sender, PopupProgram );
151 void __fastcall TMenusGen::PopupProgramClick( TObject *Sender )
153 ProgramChange( (TMenuItem *)Sender, MenuProgram );
160 void __fastcall TMenusGen::MenuTitleClick( TObject *Sender )
162 TMenuItem * Item = (TMenuItem *)Sender;
163 TMenuItem * ItemTitle;
164 input_area_t * p_area;
165 unsigned int i_title = Item->Tag;
167 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
168 i_title = __MIN( i_title,
169 p_intf->p_sys->p_input->stream.i_area_nb - 1 );
170 i_title = __MAX( i_title, 1 );
171 p_area = p_intf->p_sys->p_input->stream.pp_areas[i_title];
172 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
174 input_ChangeArea( p_intf->p_sys->p_input, p_area );
176 Item->Checked = true;
177 ItemTitle = Index2Item( PopupNavigation, i_title - 1, false );
178 Index2Item( ItemTitle, 0, false )->Checked = true;
180 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
187 void __fastcall TMenusGen::MenuChapterClick( TObject *Sender )
189 TMenuItem * Item = (TMenuItem *)Sender;
190 TMenuItem * ItemTitle;
191 input_area_t * p_area;
192 unsigned int i_title;
193 unsigned int i_chapter = Item->Tag;
195 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
196 p_area = p_intf->p_sys->p_input->stream.p_selected_area;
197 i_chapter = __MIN( i_chapter, p_area->i_part_nb - 1 );
198 i_chapter = __MAX( i_chapter, 1 );
199 p_area->i_part = i_chapter;
200 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
202 input_ChangeArea( p_intf->p_sys->p_input, p_area );
204 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
205 i_title = p_intf->p_sys->p_input->stream.p_selected_area->i_id;
206 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
208 ItemTitle = Index2Item( PopupNavigation, i_title, false );
209 Index2Item( ItemTitle, i_chapter, false )->Checked = true;
211 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
218 void __fastcall TMenusGen::PopupNavigationClick( TObject *Sender )
220 TMenuItem * Item = (TMenuItem *)Sender;
221 TMenuItem * ItemTitle;
222 input_area_t * p_area;
223 unsigned int i_title = Data2Title( Item->Tag );
224 unsigned int i_chapter = Data2Chapter( Item->Tag );
226 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
227 i_title = __MIN( i_title,
228 p_intf->p_sys->p_input->stream.i_area_nb - 1 );
229 i_title = __MAX( i_title, 1 );
230 p_area = p_intf->p_sys->p_input->stream.pp_areas[i_title];
231 i_chapter = __MIN( i_chapter, p_area->i_part_nb - 1 );
232 i_chapter = __MAX( i_chapter, 1 );
233 p_area->i_part = i_chapter;
234 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
236 input_ChangeArea( p_intf->p_sys->p_input, p_area );
238 Item->Checked = true;
239 ItemTitle = Index2Item( MenuTitle, i_title, false );
240 if( ItemTitle->Checked )
242 /* same title, new chapter */
243 Index2Item( MenuChapter, i_chapter, false )->Checked = true;
247 /* new title => we must rebuild the chapter menu */
248 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
250 MenuChapter, "Chapter",
251 p_intf->p_sys->p_input->stream.p_selected_area->i_part_nb,
252 i_chapter, MenuChapterClick );
253 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
256 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
260 __fastcall TMenusGen::TMenusGen( intf_thread_t *_p_intf ) : TObject()
264 /* Initialize local pointers to menu items of the main window */
265 TMainFrameDlg * p_window = p_intf->p_sys->p_window;
266 if( p_window == NULL )
268 msg_Warn( p_intf, "Main window wasn't created, expect problems..." );
272 MenuChannel = p_window->MenuChannel;
273 PopupChannel = p_window->PopupChannel;
274 MenuADevice = p_window->MenuADevice;
275 PopupADevice = p_window->PopupADevice;
276 MenuVDevice = p_window->MenuVDevice;
277 PopupVDevice = p_window->PopupVDevice;
278 MenuLanguage = p_window->MenuLanguage;
279 PopupLanguage = p_window->PopupLanguage;
280 MenuSubtitles = p_window->MenuSubtitles;
281 PopupSubtitles = p_window->PopupSubtitles;
282 MenuProgram = p_window->MenuProgram;
283 PopupProgram = p_window->PopupProgram;
284 MenuTitle = p_window->MenuTitle;
285 MenuChapter = p_window->MenuChapter;
286 PopupNavigation = p_window->PopupNavigation;
287 MenuAddInterface = p_window->MenuAddInterface;
289 /* Create the "Add interface" menu */
290 SetupModuleMenu( "interface", MenuAddInterface, InterfaceModuleClick );
294 /*****************************************************************************
295 * SetupMenus: This function dynamically generates some menus
296 *****************************************************************************
297 * The lock on p_input->stream must be taken before you call this function
298 *****************************************************************************/
299 void __fastcall TMenusGen::SetupMenus()
301 TMainFrameDlg * p_window = p_intf->p_sys->p_window;
302 input_thread_t * p_input = p_intf->p_sys->p_input;
303 es_descriptor_t * p_audio_es;
304 es_descriptor_t * p_spu_es;
306 p_intf->p_sys->b_chapter_update |= p_intf->p_sys->b_title_update;
307 p_intf->p_sys->b_audio_update |= p_intf->p_sys->b_program_update |
308 p_intf->p_sys->b_title_update;
309 p_intf->p_sys->b_spu_update |= p_intf->p_sys->b_program_update |
310 p_intf->p_sys->b_title_update;
312 if( p_intf->p_sys->b_program_update )
314 pgrm_descriptor_t * p_pgrm;
316 if( p_input->stream.p_new_program )
318 p_pgrm = p_input->stream.p_new_program;
322 p_pgrm = p_input->stream.p_selected_program;
325 ProgramMenu( MenuProgram, p_pgrm, MenuProgramClick );
326 ProgramMenu( PopupProgram, p_pgrm, PopupProgramClick );
328 p_intf->p_sys->b_program_update = VLC_FALSE;
331 if( p_intf->p_sys->b_title_update )
334 // because if the titles go from 1 to X-1, there are X-1 titles
335 RadioMenu( MenuTitle, "Title",
336 p_input->stream.i_area_nb - 1,
337 p_input->stream.p_selected_area->i_id,
340 AnsiString CurrentTitle;
341 CurrentTitle.sprintf( "%d", p_input->stream.p_selected_area->i_id );
342 p_window->LabelTitleCurrent->Caption = CurrentTitle;
344 p_intf->p_sys->b_title_update = VLC_FALSE;
347 if( p_intf->p_sys->b_chapter_update )
349 RadioMenu( MenuChapter, "Chapter",
350 p_input->stream.p_selected_area->i_part_nb - 1,
351 p_input->stream.p_selected_area->i_part,
354 NavigationMenu( PopupNavigation, PopupNavigationClick );
356 AnsiString CurrentChapter;
357 CurrentChapter.sprintf( "%d", p_input->stream.p_selected_area->i_part );
358 p_window->LabelChapterCurrent->Caption = CurrentChapter;
360 p_intf->p_sys->i_part = p_input->stream.p_selected_area->i_part;
362 p_intf->p_sys->b_chapter_update = VLC_FALSE;
365 /* look for selected ES */
369 for( unsigned int i = 0; i < p_input->stream.i_selected_es_number; i++ )
371 if( p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES )
373 p_audio_es = p_input->stream.pp_selected_es[i];
376 if( p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
378 p_spu_es = p_input->stream.pp_selected_es[i];
381 this->p_audio_es_old = p_audio_es;
382 this->p_spu_es_old = p_spu_es;
384 vlc_mutex_unlock( &p_input->stream.stream_lock );
387 if( p_intf->p_sys->b_audio_update )
389 LanguageMenu( MenuLanguage, p_audio_es, AUDIO_ES, MenuLanguageClick );
390 LanguageMenu( PopupLanguage, p_audio_es, AUDIO_ES, PopupLanguageClick );
392 p_intf->p_sys->b_audio_update = VLC_FALSE;
395 /* sub picture menus */
396 if( p_intf->p_sys->b_spu_update )
398 LanguageMenu( PopupSubtitles, p_spu_es, SPU_ES, PopupSubtitleClick );
399 LanguageMenu( MenuSubtitles, p_spu_es, SPU_ES, MenuSubtitleClick );
401 p_intf->p_sys->b_spu_update = VLC_FALSE;
404 if( p_intf->p_sys->b_aout_update )
406 aout_instance_t * p_aout;
407 p_aout = (aout_instance_t *)vlc_object_find( p_intf, VLC_OBJECT_AOUT,
413 val.b_bool = VLC_FALSE;
415 var_Set( (vlc_object_t *)p_aout, "intf-change", val );
417 SetupVarMenu( (vlc_object_t *)p_aout, "audio-channels",
418 MenuChannel, AoutVarClick );
419 SetupVarMenu( (vlc_object_t *)p_aout, "audio-channels",
420 PopupChannel, AoutVarClick );
422 SetupVarMenu( (vlc_object_t *)p_aout, "audio-device",
423 MenuADevice, AoutVarClick );
424 SetupVarMenu( (vlc_object_t *)p_aout, "audio-device",
425 PopupADevice, AoutVarClick );
427 vlc_object_release( (vlc_object_t *)p_aout );
430 p_intf->p_sys->b_aout_update = VLC_FALSE;
433 if( p_intf->p_sys->b_vout_update )
435 vout_thread_t * p_vout;
436 p_vout = (vout_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
442 val.b_bool = VLC_FALSE;
444 var_Set( (vlc_object_t *)p_vout, "intf-change", val );
446 SetupVarMenu( (vlc_object_t *)p_vout, "video-device",
447 MenuVDevice, VoutVarClick );
448 SetupVarMenu( (vlc_object_t *)p_vout, "video-device",
449 PopupVDevice, VoutVarClick );
451 vlc_object_release( (vlc_object_t *)p_vout );
454 p_intf->p_sys->b_vout_update = VLC_FALSE;
457 vlc_mutex_lock( &p_input->stream.stream_lock );
461 /*****************************************************************************
463 *****************************************************************************/
464 TMenuItem * TMenusGen::Index2Item( TMenuItem *Root, int i_index,
467 if( SingleColumn || ( i_index < 20 ) )
468 return Root->Items[i_index];
470 return Root->Items[i_index / 10]->Items[i_index % 10];
473 int TMenusGen::Item2Index( TMenuItem *Root, TMenuItem *Item )
475 if( Item->Parent == Root )
476 return Item->MenuIndex;
478 return( 10 * Item->Parent->MenuIndex + Item->MenuIndex );
481 int __fastcall TMenusGen::Data2Title( int data )
483 return (int) (data >> 16 );
486 int __fastcall TMenusGen::Data2Chapter( int data )
488 return (int) (data & 0xffff);
491 int __fastcall TMenusGen::Pos2Data( int title, int chapter )
493 return (int) (( title << 16 ) | ( chapter & 0xffff ));
496 /* This function deletes all the '&' characters in the caption string,
497 * because Borland automatically adds one when (and only when!) you click on
498 * the menuitem. Grrrrr... */
499 AnsiString __fastcall TMenusGen::CleanCaption( AnsiString Caption )
501 while( Caption.LastDelimiter( "&" ) != 0 )
503 Caption.Delete( Caption.LastDelimiter( "&" ), 1 );
509 /****************************************************************************
510 * VarChange: change a variable in a vlc_object_t
511 ****************************************************************************
512 * Change the variable and update the menuitems.
513 ****************************************************************************/
514 void __fastcall TMenusGen::VarChange( vlc_object_t *p_object,
515 const char *psz_variable, TMenuItem *RootMenu, TMenuItem *RootPopup,
521 AnsiString Caption = CleanCaption( Item->Caption );
522 val.psz_string = Caption.c_str();
524 /* set the new value */
525 if( var_Set( p_object, psz_variable, val ) < 0 )
527 msg_Warn( p_object, "cannot set variable (%s)", val.psz_string );
530 i_index = Item->MenuIndex;
531 RootMenu->Items[i_index]->Checked = true;
532 RootPopup->Items[i_index]->Checked = true;
535 /****************************************************************************
536 * LangChange: change audio or subtitles languages
537 ****************************************************************************
538 * Toggle the language, and update the selected menuitems.
539 ****************************************************************************/
540 void __fastcall TMenusGen::LangChange( TMenuItem *RootCurrent, TMenuItem *Item,
541 TMenuItem *RootOther, int i_cat )
543 es_descriptor_t * p_es;
544 es_descriptor_t * p_es_old;
548 /* find the selected ES */
551 /* find selected menu item */
552 i_index = Item2Index( RootCurrent, Item ) - 1;
555 /* 'None' was selected */
560 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
561 p_es = p_intf->p_sys->p_input->stream.pp_es[i_es];
562 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
565 /* find the current ES */
566 if( i_cat == AUDIO_ES )
568 p_es_old = this->p_audio_es_old;
569 this->p_audio_es_old = p_es;
573 p_es_old = this->p_spu_es_old;
574 this->p_spu_es_old = p_es;
578 input_ToggleES( p_intf->p_sys->p_input, p_es_old, false );
579 input_ToggleES( p_intf->p_sys->p_input, p_es, true );
581 Item->Checked = true;
582 Index2Item( RootOther, i_index + 1, true )->Checked = true;
585 /****************************************************************************
586 * ProgramChange: change the program
587 ****************************************************************************
588 * Toggle the program, and update the selected menuitems.
589 ****************************************************************************/
590 void __fastcall TMenusGen::ProgramChange( TMenuItem *Item,
591 TMenuItem *RootOther )
593 int i_program = Item->Tag;
595 /* toggle the program */
596 input_ChangeProgram( p_intf->p_sys->p_input, (uint16_t)i_program );
598 /* check selected menu items */
599 Item->Checked = true;
600 Index2Item( RootOther, i_program - 1, true )->Checked = true;
602 /* update audio/subtitles menus */
603 p_intf->p_sys->b_audio_update = VLC_TRUE;
604 p_intf->p_sys->b_spu_update = VLC_TRUE;
605 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
607 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
608 p_intf->p_sys->b_audio_update = VLC_FALSE;
609 p_intf->p_sys->b_spu_update = VLC_FALSE;
611 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
614 /*****************************************************************************
615 * SetupVarMenu: build a menu allowing to change a variable
616 *****************************************************************************/
617 void __fastcall TMenusGen::SetupVarMenu( vlc_object_t *p_object,
618 const char *psz_variable, TMenuItem *Root, TNotifyEvent MenuItemClick )
622 char * psz_value = NULL;
625 /* remove previous menu */
628 /* get the current value */
629 if( var_Get( p_object, psz_variable, &val ) < 0 )
633 psz_value = val.psz_string;
635 if( var_Change( p_object, psz_variable, VLC_VAR_GETLIST, &val ) < 0 )
641 /* append a menuitem for each option */
642 for( i = 0; i < val.p_list->i_count; i++ )
644 Item = new TMenuItem( Root );
645 Item->Caption = val.p_list->p_values[i].psz_string;
646 Item->Hint = val.p_list->p_values[i].psz_string;
647 Item->RadioItem = true;
648 Item->OnClick = MenuItemClick;
649 if( !strcmp( psz_value, val.p_list->p_values[i].psz_string ) )
650 Item->Checked = true;
652 /* Add the item to the submenu */
656 /* enable the menu if there is at least 1 item */
657 Root->Enabled = ( val.p_list->i_count > 0 );
659 /* clean up everything */
660 var_Change( p_object, psz_variable, VLC_VAR_FREELIST, &val );
661 // free( psz_value );
664 /*****************************************************************************
665 * SetupModuleMenu: build a menu listing all the modules of a given
667 *****************************************************************************/
668 void __fastcall TMenusGen::SetupModuleMenu( const char *psz_capability,
669 TMenuItem *Root, TNotifyEvent MenuItemClick )
675 /* remove previous menu */
677 Root->Enabled = false;
679 p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
680 for( i_index = 0; i_index < p_list->i_count; i_index++ )
682 p_parser = (module_t *)p_list->p_values[i_index].p_object ;
684 if( !strcmp( p_parser->psz_capability, psz_capability ) )
686 TMenuItem *Item = new TMenuItem( Root );
687 Item->Caption = p_parser->psz_object_name;
688 Item->Hint = Item->Caption;
689 Item->OnClick = MenuItemClick;
694 vlc_list_release( p_list );
696 /* be sure that menu is enabled, if there is at least one item */
698 Root->Enabled = true;
701 /*****************************************************************************
702 * ProgramMenu: update the programs menu of the interface
703 *****************************************************************************
704 * Builds the program menu according to what have been found in the PAT
705 * by the input. Useful for multi-programs streams such as DVB ones.
706 *****************************************************************************/
707 void __fastcall TMenusGen::ProgramMenu( TMenuItem *Root,
708 pgrm_descriptor_t *p_pgrm, TNotifyEvent MenuItemClick )
712 /* remove previous menu */
714 Root->Enabled = false;
716 /* create a set of program buttons and append them to the container */
717 for( unsigned int i = 0; i < p_intf->p_sys->p_input->stream.i_pgrm_number;
721 Name.sprintf( "id %d",
722 p_intf->p_sys->p_input->stream.pp_programs[i]->i_number );
724 Item = new TMenuItem( Root );
725 Item->Caption = Name;
727 Item->RadioItem = true;
728 Item->OnClick = MenuItemClick;
730 /* FIXME: temporary hack to save the program id with the Item
731 * It will be used in the callback. */
734 /* check the currently selected program */
735 if( p_pgrm == p_intf->p_sys->p_input->stream.pp_programs[i] )
736 Item->Checked = true;
738 /* add the item to the submenu */
742 /* be sure that menu is enabled if more than 1 program */
743 if( p_intf->p_sys->p_input->stream.i_pgrm_number > 1 )
744 Root->Enabled = true;
747 /*****************************************************************************
748 * RadioMenu: update interactive menus of the interface
749 *****************************************************************************
750 * Sets up menus with information from input
751 * Warning: since this function is designed to be called by management
752 * function, the interface lock has to be taken
753 *****************************************************************************/
754 void __fastcall TMenusGen::RadioMenu( TMenuItem *Root, AnsiString ItemName,
755 int i_nb, int i_selected, TNotifyEvent MenuItemClick )
757 TMenuItem * ItemGroup;
761 /* remove previous menu */
762 Root->Enabled = false;
765 for( int i_item = 1; i_item <= i_nb; i_item++ )
767 /* we group titles/chapters in packets of ten for small screens */
768 if( ( i_item % 10 == 1 ) && ( i_nb > 20 ) )
771 Root->Add( ItemGroup );
773 Name.sprintf( "%ss %d to %d", ItemName, i_item, i_item + 9 );
774 ItemGroup = new TMenuItem( Root );
775 ItemGroup->Hint = Name;
776 ItemGroup->RadioItem = true;
778 /* set the accelerator character */
779 Name.Insert( "&", Name.Length() - 1 );
780 ItemGroup->Caption = Name;
783 Name.sprintf( "%s %d", ItemName, i_item );
784 Item = new TMenuItem( Root );
785 Item->RadioItem = true;
788 /* set the accelerator character */
789 Name.Insert( "&", Name.Length() );
790 Item->Caption = Name;
792 /* FIXME: temporary hack to save i_item with the Item
793 * It will be used in the callback. */
796 /* check the currently selected chapter */
797 if( i_selected == i_item )
798 Item->Checked = true;
800 /* setup signal handling */
801 Item->OnClick = MenuItemClick;
804 ItemGroup->Add( Item );
809 // if( ( i_nb > 20 ) && ( i_item % 10 ) ) ?
811 Root->Add( ItemGroup );
813 /* be sure that menu is enabled, if there are several items */
815 Root->Enabled = true;
818 /*****************************************************************************
819 * LanguageMenus: update interactive menus of the interface
820 *****************************************************************************
821 * Sets up menus with information from input:
824 * Warning: since this function is designed to be called by management
825 * function, the interface lock has to be taken
826 *****************************************************************************/
827 void __fastcall TMenusGen::LanguageMenu( TMenuItem *Root, es_descriptor_t *p_es,
828 int i_cat, TNotifyEvent MenuItemClick )
830 TMenuItem * Separator;
834 /* remove previous menu */
836 Root->Enabled = false;
838 /* special case for "off" item */
840 Item = new TMenuItem( Root );
841 Item->RadioItem = true;
843 Item->Caption = Name;
844 Item->OnClick = MenuItemClick;
849 Separator = new TMenuItem( Root );
850 Separator->Caption = "-";
851 Root->Add( Separator );
855 vlc_mutex_lock( &p_intf->p_sys->p_input->stream.stream_lock );
857 #define ES p_intf->p_sys->p_input->stream.pp_es[i]
858 /* create a set of language buttons and append them to the Root */
859 for( unsigned int i = 0; i < p_intf->p_sys->p_input->stream.i_es_number;
862 if( ( ES->i_cat == i_cat ) &&
865 p_intf->p_sys->p_input->stream.p_selected_program ) )
868 Name = p_intf->p_sys->p_input->stream.pp_es[i]->psz_desc;
870 Name.sprintf( "Language %d", i_item );
872 Item = new TMenuItem( Root );
873 Item->RadioItem = true;
875 Item->Caption = Name;
878 /* check the currently selected item */
879 if( p_es == p_intf->p_sys->p_input->stream.pp_es[i] )
880 Item->Checked = true;
882 /* setup signal hanling */
883 Item->OnClick = MenuItemClick;
889 vlc_mutex_unlock( &p_intf->p_sys->p_input->stream.stream_lock );
891 /* be sure that menu is enabled if non empty */
893 Root->Enabled = true;
896 /*****************************************************************************
897 * NavigationMenu: sets menus for titles and chapters selection
898 *****************************************************************************
899 * Generates two types of menus:
900 * -simple list of titles
901 * -cascaded lists of chapters for each title
902 *****************************************************************************/
903 void __fastcall TMenusGen::NavigationMenu( TMenuItem *Root,
904 TNotifyEvent MenuItemClick )
906 TMenuItem * TitleGroup;
907 TMenuItem * TitleItem;
908 TMenuItem * ChapterGroup;
909 TMenuItem * ChapterItem;
911 unsigned int i_title_nb;
912 unsigned int i_chapter_nb;
915 /* remove previous menu */
916 Root->Enabled = false;
919 i_title_nb = p_intf->p_sys->p_input->stream.i_area_nb - 1;
922 for( unsigned int i_title = 1; i_title <= i_title_nb; i_title++ )
924 /* we group titles in packets of ten for small screens */
925 if( ( i_title % 10 == 1 ) && ( i_title_nb > 20 ) )
928 Root->Add( TitleGroup );
930 Name.sprintf( "%d - %d", i_title, i_title + 9 );
931 TitleGroup = new TMenuItem( Root );
932 TitleGroup->RadioItem = true;
933 TitleGroup->Hint = Name;
934 TitleGroup->Caption = Name;
937 Name.sprintf( "Title %d (%d)", i_title,
938 p_intf->p_sys->p_input->stream.pp_areas[i_title]->i_part_nb - 1 );
940 TitleItem = new TMenuItem( Root );
941 TitleItem->RadioItem = true;
942 TitleItem->Hint = Name;
943 TitleItem->Caption = Name;
946 p_intf->p_sys->p_input->stream.pp_areas[i_title]->i_part_nb - 1;
948 /* loop on chapters */
949 for( unsigned int i_chapter = 1; i_chapter <= i_chapter_nb;
952 /* we group chapters in packets of ten for small screens */
953 if( ( i_chapter % 10 == 1 ) && ( i_chapter_nb > 20 ) )
956 TitleItem->Add( ChapterGroup );
958 Name.sprintf( "%d - %d", i_chapter, i_chapter + 9 );
959 ChapterGroup = new TMenuItem( TitleItem );
960 ChapterGroup->RadioItem = true;
961 ChapterGroup->Hint = Name;
962 ChapterGroup->Caption = Name;
965 Name.sprintf( "Chapter %d", i_chapter );
967 ChapterItem = new TMenuItem( TitleItem );
968 ChapterItem->RadioItem = true;
969 ChapterItem->Hint = Name;
970 ChapterItem->Caption = Name;
972 /* FIXME: temporary hack to save i_title and i_chapter with
973 * ChapterItem, since we will need them in the callback */
974 ChapterItem->Tag = Pos2Data( i_title, i_chapter );
976 #define p_area p_intf->p_sys->p_input->stream.pp_areas[i_title]
977 /* check the currently selected chapter */
979 p_intf->p_sys->p_input->stream.p_selected_area ) &&
980 ( p_area->i_part == i_chapter ) )
982 ChapterItem->Checked = true;
986 /* setup signal handling */
987 ChapterItem->OnClick = MenuItemClick;
989 if( i_chapter_nb > 20 )
990 ChapterGroup->Add( ChapterItem );
992 TitleItem->Add( ChapterItem );
995 if( i_chapter_nb > 20 )
997 TitleItem->Add( ChapterGroup );
1000 if( p_intf->p_sys->p_input->stream.pp_areas[i_title]->i_part_nb
1003 /* be sure that menu is sensitive */
1004 Root->Enabled = true;
1008 if( i_title_nb > 20 )
1009 TitleGroup->Add( TitleItem );
1011 Root->Add( TitleItem );
1014 if( i_title_nb > 20 )
1015 Root->Add( TitleGroup );
1017 /* be sure that menu is sensitive */
1018 Root->Enabled = true;