1 /*****************************************************************************
2 * intf_vlc_wrapper.m: MacOS X plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: intf_vlc_wrapper.m,v 1.15 2002/06/18 23:18:40 massiot Exp $
7 * Authors: Florian G. Pflug <fgp@phlo.org>
8 * Jon Lech Johansen <jon-vl@nanocrew.net>
9 * Christophe Massiot <massiot@via.ecp.fr>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
24 *****************************************************************************/
26 #include <stdlib.h> /* malloc(), free() */
27 #include <sys/param.h> /* for MAXPATHLEN */
30 #include <IOKit/storage/IOCDMedia.h>
31 #include <IOKit/storage/IODVDMedia.h>
33 #include <videolan/vlc.h>
35 #include "interface.h"
36 #include "vlc_playlist.h"
37 #include "intf_eject.h"
40 #include "video_output.h"
41 #include "audio_output.h"
43 #include "stream_control.h"
44 #include "input_ext-intf.h"
47 #include "intf_open.h"
48 #include "intf_vlc_wrapper.h"
52 @implementation Intf_VLCWrapper
54 static Intf_VLCWrapper *o_intf = nil;
58 + (Intf_VLCWrapper *)instance
62 o_intf = [[[Intf_VLCWrapper alloc] init] autorelease];
76 if( p_main->p_intf->b_die )
78 /* Vout depends on intf */
87 if( p_input_bank->pp_input[0] != NULL )
89 vlc_mutex_lock( &p_input_bank->pp_input[0]->stream.stream_lock );
91 if( !p_input_bank->pp_input[0]->b_die )
93 /* New input or stream map change */
94 if( p_input_bank->pp_input[0]->stream.b_changed ||
95 p_main->p_intf->p_sys->i_part !=
96 p_input_bank->pp_input[0]->stream.p_selected_area->i_part )
99 p_main->p_intf->p_sys->b_disabled_menus = 0;
103 vlc_mutex_unlock( &p_input_bank->pp_input[0]->stream.stream_lock );
105 else if ( !p_main->p_intf->p_sys->b_disabled_menus )
108 p_main->p_intf->p_sys->b_disabled_menus = 1;
116 p_main->p_intf->b_die = 1;
119 /* playlist control */
123 if( p_input_bank->pp_input[0] != NULL )
125 input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_PLAY );
126 p_main->p_playlist->b_stopped = 0;
130 vlc_mutex_lock( &p_main->p_playlist->change_lock );
132 if( p_main->p_playlist->b_stopped )
134 if( p_main->p_playlist->i_size )
136 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
137 intf_PlaylistJumpto( p_main->p_playlist,
138 p_main->p_playlist->i_index );
142 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
143 [[Intf_Open instance] openFile: nil];
148 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
155 - (void)playlistPause
157 if ( p_input_bank->pp_input[0] != NULL )
159 input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_PAUSE );
161 vlc_mutex_lock( &p_main->p_playlist->change_lock );
162 p_main->p_playlist->b_stopped = 0;
163 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
169 if( p_input_bank->pp_input[0] != NULL )
171 /* end playing item */
172 p_input_bank->pp_input[0]->b_eof = 1;
174 /* update playlist */
175 vlc_mutex_lock( &p_main->p_playlist->change_lock );
177 p_main->p_playlist->i_index--;
178 p_main->p_playlist->b_stopped = 1;
180 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
186 if( p_input_bank->pp_input[0] != NULL )
188 p_input_bank->pp_input[0]->b_eof = 1;
194 if( p_input_bank->pp_input[0] != NULL )
196 /* FIXME: temporary hack */
197 intf_PlaylistPrev( p_main->p_playlist );
198 intf_PlaylistPrev( p_main->p_playlist );
199 p_input_bank->pp_input[0]->b_eof = 1;
205 intf_thread_t * p_intf = p_main->p_intf;
207 p_intf->p_sys->i_channel++;
209 intf_WarnMsg( 3, "intf info: joining channel %d", p_intf->p_sys->i_channel );
211 vlc_mutex_lock( &p_intf->change_lock );
212 if( p_input_bank->pp_input[0] != NULL )
214 /* end playing item */
215 p_input_bank->pp_input[0]->b_eof = 1;
217 /* update playlist */
218 vlc_mutex_lock( &p_main->p_playlist->change_lock );
220 p_main->p_playlist->i_index--;
221 p_main->p_playlist->b_stopped = 1;
223 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
225 /* FIXME: ugly hack to close input and outputs */
226 p_intf->pf_manage( p_intf );
229 network_ChannelJoin( p_intf->p_sys->i_channel );
232 p_main->p_playlist->b_stopped = 0;
233 p_intf->pf_manage( p_intf );
235 vlc_mutex_unlock( &p_intf->change_lock );
240 intf_thread_t * p_intf = p_main->p_intf;
242 if ( p_intf->p_sys->i_channel )
244 p_intf->p_sys->i_channel--;
247 intf_WarnMsg( 3, "intf info: joining channel %d", p_intf->p_sys->i_channel );
249 vlc_mutex_lock( &p_intf->change_lock );
250 if( p_input_bank->pp_input[0] != NULL )
252 /* end playing item */
253 p_input_bank->pp_input[0]->b_eof = 1;
255 /* update playlist */
256 vlc_mutex_lock( &p_main->p_playlist->change_lock );
258 p_main->p_playlist->i_index--;
259 p_main->p_playlist->b_stopped = 1;
261 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
263 /* FIXME: ugly hack to close input and outputs */
264 p_intf->pf_manage( p_intf );
267 network_ChannelJoin( p_intf->p_sys->i_channel );
270 p_main->p_playlist->b_stopped = 0;
271 p_intf->pf_manage( p_intf );
273 vlc_mutex_unlock( &p_intf->change_lock );
278 intf_thread_t * p_intf = p_main->p_intf;
280 if ( p_intf->p_sys->b_loop )
282 intf_PlaylistDelete( p_main->p_playlist,
283 p_main->p_playlist->i_size - 1 );
287 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
290 p_intf->p_sys->b_loop = !p_intf->p_sys->b_loop;
295 if( p_input_bank->pp_input[0] != NULL )
297 input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_SLOWER );
299 vlc_mutex_lock( &p_main->p_playlist->change_lock );
300 p_main->p_playlist->b_stopped = 0;
301 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
307 if( p_input_bank->pp_input[0] != NULL )
309 input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_FASTER );
311 vlc_mutex_lock( &p_main->p_playlist->change_lock );
312 p_main->p_playlist->b_stopped = 0;
313 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
319 if( p_aout_bank->pp_aout[0] == NULL ) return;
321 if( p_main->p_intf->p_sys->b_mute )
323 p_aout_bank->pp_aout[0]->i_volume =
324 p_main->p_intf->p_sys->i_saved_volume;
328 p_main->p_intf->p_sys->i_saved_volume =
329 p_aout_bank->pp_aout[0]->i_volume;
330 p_aout_bank->pp_aout[0]->i_volume = 0;
332 p_main->p_intf->p_sys->b_mute = !p_main->p_intf->p_sys->b_mute;
337 if( p_aout_bank->pp_aout[0] == NULL ) return;
339 if( p_main->p_intf->p_sys->b_mute )
341 p_main->p_intf->p_sys->i_saved_volume = VOLUME_MAX;
345 p_aout_bank->pp_aout[0]->i_volume = VOLUME_MAX;
351 if( p_vout_bank->pp_vout[0] != NULL )
353 p_vout_bank->pp_vout[0]->i_changes |= VOUT_FULLSCREEN_CHANGE;
359 /* FIXME : this will only eject the first drive found */
360 NSArray * o_devices = GetEjectableMediaOfClass(kIODVDMediaClass);
361 const char * psz_device;
363 if ( p_input_bank->pp_input[0] != NULL &&
364 (p_input_bank->pp_input[0]->stream.i_method == INPUT_METHOD_VCD ||
365 p_input_bank->pp_input[0]->stream.i_method == INPUT_METHOD_DVD ||
366 p_input_bank->pp_input[0]->stream.i_method == INPUT_METHOD_DISC) )
368 intf_ErrMsg("error: cannot eject the disc while you're reading from it");
372 if ( o_devices == nil )
374 o_devices = GetEjectableMediaOfClass(kIOCDMediaClass);
377 if ( o_devices != nil && [o_devices count] )
379 psz_device = [[o_devices objectAtIndex:0] cString];
380 intf_Eject( psz_device );
386 #define p_area p_input_bank->pp_input[0]->stream.p_selected_area
388 - (NSString *)getTimeAsString
390 static char psz_currenttime[ OFFSETTOTIME_MAX_SIZE ];
392 if( p_input_bank->pp_input[0] == NULL )
394 return [NSString stringWithCString:"00:00:00"];
397 input_OffsetToTime( p_input_bank->pp_input[0],
398 psz_currenttime, p_area->i_tell );
400 return( [NSString stringWithCString: psz_currenttime] );
403 - (float)getTimeAsFloat
407 if( p_input_bank->pp_input[0] != NULL )
409 f_time = (float)p_area->i_tell / (float)p_area->i_size;
415 - (void)setTimeAsFloat:(float)f_position
417 if( p_input_bank->pp_input[0] != NULL )
419 input_Seek( p_input_bank->pp_input[0]->p_this,
420 p_area->i_size * f_position, INPUT_SEEK_SET );
426 - (bool)playlistPlaying
428 return( !p_main->p_playlist->b_stopped );
431 - (NSArray *)playlistAsArray
434 NSMutableArray* p_list =
435 [NSMutableArray arrayWithCapacity: p_main->p_playlist->i_size];
437 vlc_mutex_lock( &p_main->p_playlist->change_lock );
439 for( i = 0; i < p_main->p_playlist->i_size; i++ )
441 [p_list addObject: [NSString
442 stringWithCString: p_main->p_playlist->p_item[i].psz_name]];
445 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
447 return( [NSArray arrayWithArray: p_list] );
451 - (int)playlistLength
453 return( p_main->p_playlist->i_size );
456 - (NSString*)playlistItem:(int)i_pos
458 NSString *o_item = nil;
460 vlc_mutex_lock( &p_main->p_playlist->change_lock );
462 if( i_pos < p_main->p_playlist->i_size )
465 stringWithCString: p_main->p_playlist->p_item[i_pos].psz_name];
468 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
473 - (void)playlistPlayItem:(int)i_item
477 vlc_mutex_lock( &p_main->p_playlist->change_lock );
479 if( i_item<p_main->p_playlist->i_size )
481 p_main->p_playlist->i_index--;
484 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
486 [self playlistPlayCurrent];
489 - (void)playlistAdd:(NSString *)o_filename
491 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
492 [o_filename fileSystemRepresentation] );
495 - (void)clearPlaylist
499 vlc_mutex_lock( &p_main->p_playlist->change_lock );
501 for( i = 0; i < p_main->p_playlist->i_size; i++ )
503 intf_PlaylistDelete( p_main->p_playlist, i );
506 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
510 /* open file/disc/network */
512 - (void)openFiles:(NSArray*)o_files
515 int i_end = p_main->p_playlist->i_size;
516 NSEnumerator *o_enum = [o_files objectEnumerator];
517 intf_thread_t * p_intf = p_main->p_intf;
519 if ( p_intf->p_sys->b_loop )
521 intf_PlaylistDelete( p_main->p_playlist,
522 p_main->p_playlist->i_size - 1 );
525 while( ( o_file = (NSString *)[o_enum nextObject] ) )
527 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
528 [o_file fileSystemRepresentation] );
531 /* end current item, select first added item */
532 if( p_input_bank->pp_input[0] != NULL )
534 p_input_bank->pp_input[0]->b_eof = 1;
537 intf_PlaylistJumpto( p_main->p_playlist, i_end - 1 );
539 if ( p_intf->p_sys->b_loop )
541 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
546 - (void)openDisc:(NSString*)o_type device:(NSString*)o_device title:(int)i_title chapter:(int)i_chapter
549 int i_end = p_main->p_playlist->i_size;
550 intf_thread_t * p_intf = p_main->p_intf;
552 o_source = [NSString stringWithFormat: @"%@:%@@%d,%d",
553 o_type, o_device, i_title, i_chapter];
555 if ( p_intf->p_sys->b_loop )
557 intf_PlaylistDelete( p_main->p_playlist,
558 p_main->p_playlist->i_size - 1 );
561 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
562 [o_source fileSystemRepresentation] );
564 /* stop current item, select added item */
565 if( p_input_bank->pp_input[0] != NULL )
567 p_input_bank->pp_input[0]->b_eof = 1;
570 intf_PlaylistJumpto( p_main->p_playlist, i_end - 1 );
572 if ( p_intf->p_sys->b_loop )
574 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
579 - (void)openNet:(NSString*)o_addr port:(int)i_port
582 int i_end = p_main->p_playlist->i_size;
583 intf_thread_t * p_intf = p_main->p_intf;
585 if( p_input_bank->pp_input[0] != NULL )
587 p_input_bank->pp_input[0]->b_eof = 1;
590 config_PutIntVariable( "network-channel", 0 );
592 o_source = [NSString stringWithFormat: @"udpstream:@%@:%i",
595 if ( p_intf->p_sys->b_loop )
597 intf_PlaylistDelete( p_main->p_playlist,
598 p_main->p_playlist->i_size - 1 );
601 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
602 [o_source fileSystemRepresentation] );
604 intf_PlaylistJumpto( p_main->p_playlist, i_end - 1 );
606 if ( p_intf->p_sys->b_loop )
608 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
613 - (void)openNetChannel:(NSString*)o_addr port:(int)i_port
615 if( p_input_bank->pp_input[0] != NULL )
617 p_input_bank->pp_input[0]->b_eof = 1;
620 config_PutIntVariable( "network-channel", 1 );
622 if( p_main->p_channel == NULL )
624 network_ChannelCreate();
627 config_PutPszVariable( "channel-server", (char*)[o_addr lossyCString] );
628 config_PutIntVariable( "channel-port", i_port );
631 - (void)openNetHTTP:(NSString*)o_addr
633 int i_end = p_main->p_playlist->i_size;
634 intf_thread_t * p_intf = p_main->p_intf;
636 if( p_input_bank->pp_input[0] != NULL )
638 p_input_bank->pp_input[0]->b_eof = 1;
641 config_PutIntVariable( "network-channel", 0 );
643 if ( p_intf->p_sys->b_loop )
645 intf_PlaylistDelete( p_main->p_playlist,
646 p_main->p_playlist->i_size - 1 );
649 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
650 [o_addr fileSystemRepresentation] );
652 intf_PlaylistJumpto( p_main->p_playlist, i_end - 1 );
654 if ( p_intf->p_sys->b_loop )
656 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
661 - (void)toggleProgram:(id)sender
663 NSMenuItem * o_item = (NSMenuItem *)sender;
664 input_thread_t * p_input = p_input_bank->pp_input[0];
666 if( [o_item state] == NSOffState )
668 u16 i_program_id = [o_item tag];
670 input_ChangeProgram( p_input, i_program_id );
672 vlc_mutex_lock( &p_input->stream.stream_lock );
674 vlc_mutex_unlock( &p_input->stream.stream_lock );
676 input_SetStatus( p_input, INPUT_STATUS_PLAY );
680 - (void)toggleTitle:(id)sender
682 NSMenuItem * o_item = (NSMenuItem *)sender;
683 input_thread_t * p_input = p_input_bank->pp_input[0];
685 if( [o_item state] == NSOffState )
687 int i_title = [o_item tag];
689 input_ChangeArea( p_input,
690 p_input->stream.pp_areas[i_title] );
692 vlc_mutex_lock( &p_input->stream.stream_lock );
694 vlc_mutex_unlock( &p_input->stream.stream_lock );
696 input_SetStatus( p_input, INPUT_STATUS_PLAY );
700 - (void)toggleChapter:(id)sender
702 NSMenuItem * o_item = (NSMenuItem *)sender;
703 input_thread_t * p_input = p_input_bank->pp_input[0];
705 if( [o_item state] == NSOffState )
707 int i_chapter = [o_item tag];
709 p_input->stream.p_selected_area->i_part = i_chapter;
710 input_ChangeArea( p_input,
711 p_input->stream.p_selected_area );
713 vlc_mutex_lock( &p_input->stream.stream_lock );
715 vlc_mutex_unlock( &p_input->stream.stream_lock );
717 input_SetStatus( p_input, INPUT_STATUS_PLAY );
721 - (void)toggleLanguage:(id)sender
723 NSMenuItem * o_item = (NSMenuItem *)sender;
724 input_thread_t * p_input = p_input_bank->pp_input[0];
726 int i_es = [o_item tag];
728 if( [o_item state] == NSOnState )
730 /* We just have one ES to disable */
731 input_ToggleES( p_input, p_input->stream.pp_es[i_es], 0 );
735 /* Unselect the selected ES in the same class */
737 vlc_mutex_lock( &p_input->stream.stream_lock );
738 for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
740 if( p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES )
742 vlc_mutex_unlock( &p_input->stream.stream_lock );
743 input_ToggleES( p_input, p_input->stream.pp_selected_es[i], 0 );
744 vlc_mutex_lock( &p_input->stream.stream_lock );
748 vlc_mutex_unlock( &p_input->stream.stream_lock );
750 /* Select the wanted ES */
751 input_ToggleES( p_input, p_input->stream.pp_es[i_es], 1 );
754 vlc_mutex_lock( &p_input->stream.stream_lock );
756 vlc_mutex_unlock( &p_input->stream.stream_lock );
758 input_SetStatus( p_input, INPUT_STATUS_PLAY );
761 - (void)toggleSubtitle:(id)sender
763 NSMenuItem * o_item = (NSMenuItem *)sender;
764 input_thread_t * p_input = p_input_bank->pp_input[0];
766 int i_es = [o_item tag];
768 if( [o_item state] == NSOnState )
770 /* We just have one ES to disable */
771 input_ToggleES( p_input, p_input->stream.pp_es[i_es], 0 );
775 /* Unselect the selected ES in the same class */
777 vlc_mutex_lock( &p_input->stream.stream_lock );
778 for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
780 if( p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
782 vlc_mutex_unlock( &p_input->stream.stream_lock );
783 input_ToggleES( p_input, p_input->stream.pp_selected_es[i], 0 );
784 vlc_mutex_lock( &p_input->stream.stream_lock );
788 vlc_mutex_unlock( &p_input->stream.stream_lock );
790 /* Select the wanted ES */
791 input_ToggleES( p_input, p_input->stream.pp_es[i_es], 1 );
794 vlc_mutex_lock( &p_input->stream.stream_lock );
796 vlc_mutex_unlock( &p_input->stream.stream_lock );
798 input_SetStatus( p_input, INPUT_STATUS_PLAY );
804 NSMenuItem *o_controls_item;
805 NSMenuItem *o_program_item, *o_title_item, *o_chapter_item, *o_language_item,
806 *o_subtitle_item, *o_next_channel_item, *o_prev_channel_item;
807 input_thread_t * p_input = p_input_bank->pp_input[0];
809 o_main_menu = [NSApp mainMenu];
810 o_controls_item = [o_main_menu itemWithTitle: @"Controls"];
811 o_program_item = [[o_controls_item submenu] itemWithTitle: @"Program"];
812 o_title_item = [[o_controls_item submenu] itemWithTitle: @"Title"];
813 o_chapter_item = [[o_controls_item submenu] itemWithTitle: @"Chapter"];
814 o_language_item = [[o_controls_item submenu] itemWithTitle: @"Language"];
815 o_subtitle_item = [[o_controls_item submenu] itemWithTitle: @"Subtitles"];
816 o_next_channel_item = [[o_controls_item submenu] itemWithTag: 13];
817 o_prev_channel_item = [[o_controls_item submenu] itemWithTag: 12];
819 if( p_input == NULL )
821 [o_program_item setEnabled:0];
822 [o_title_item setEnabled:0];
823 [o_chapter_item setEnabled:0];
824 [o_language_item setEnabled:0];
825 [o_subtitle_item setEnabled:0];
829 NSMenu *o_program, *o_title, *o_chapter, *o_language, *o_subtitle;
830 SEL pf_toggle_program, pf_toggle_title, pf_toggle_chapter,
831 pf_toggle_language, pf_toggle_subtitle;
834 pgrm_descriptor_t * p_pgrm;
836 /* ----- PROGRAMS ----- */
837 if( p_input->stream.i_pgrm_number < 2 )
839 [o_program_item setEnabled:0];
843 [o_program_item setEnabled:1];
844 o_program = [o_program_item submenu];
845 pf_toggle_program = @selector(toggleProgram:);
847 /* Remove previous program menu */
848 i_nb_items = [o_program numberOfItems];
849 for( i = 0; i < i_nb_items; i++ )
851 [o_program removeItemAtIndex:0];
854 if( p_input->stream.p_new_program )
856 p_pgrm = p_input->stream.p_new_program;
860 p_pgrm = p_input->stream.p_selected_program;
863 /* Create program menu */
864 for( i = 0 ; i < p_input->stream.i_pgrm_number ; i++ )
866 char psz_title[ 256 ];
867 NSString * o_menu_title;
870 snprintf( psz_title, sizeof(psz_title), "id %d",
871 p_input->stream.pp_programs[i]->i_number );
872 psz_title[sizeof(psz_title) - 1] = '\0';
874 o_menu_title = [NSString stringWithCString: psz_title];
876 o_item = [o_program addItemWithTitle: o_menu_title
877 action: pf_toggle_program keyEquivalent: @""];
878 [o_item setTarget: self];
879 [o_item setTag: p_input->stream.pp_programs[i]->i_number];
880 if( p_pgrm == p_input->stream.pp_programs[i] )
882 [o_item setState: 1];
886 vlc_mutex_unlock( &p_input->stream.stream_lock );
887 vlc_mutex_lock( &p_input->stream.stream_lock );
889 /* ----- TITLES ----- */
890 if( p_input->stream.i_area_nb < 2 )
892 [o_title_item setEnabled:0];
896 [o_title_item setEnabled:1];
897 o_title = [o_title_item submenu];
898 pf_toggle_title = @selector(toggleTitle:);
900 /* Remove previous title menu */
901 i_nb_items = [o_title numberOfItems];
902 for( i = 0; i < i_nb_items; i++ )
904 [o_title removeItemAtIndex:0];
907 /* Create title menu */
908 for( i = 1 ; i < p_input->stream.i_area_nb ; i++ )
910 char psz_title[ 256 ];
911 NSString * o_menu_title;
914 snprintf( psz_title, sizeof(psz_title), "Title %d (%d)", i,
915 p_input->stream.pp_areas[i]->i_part_nb );
916 psz_title[sizeof(psz_title) - 1] = '\0';
918 o_menu_title = [NSString stringWithCString: psz_title];
920 o_item = [o_title addItemWithTitle: o_menu_title
921 action: pf_toggle_title keyEquivalent: @""];
923 [o_item setTarget: self];
924 if( ( p_input->stream.pp_areas[i] ==
925 p_input->stream.p_selected_area ) )
927 [o_item setState: 1];
931 vlc_mutex_unlock( &p_input->stream.stream_lock );
932 vlc_mutex_lock( &p_input->stream.stream_lock );
934 /* ----- CHAPTERS ----- */
935 if( p_input->stream.p_selected_area->i_part_nb < 2 )
937 [o_chapter_item setEnabled:0];
941 [o_chapter_item setEnabled:1];
942 o_chapter = [o_chapter_item submenu];
943 pf_toggle_chapter = @selector(toggleChapter:);
945 /* Remove previous chapter menu */
946 i_nb_items = [o_chapter numberOfItems];
947 for( i = 0; i < i_nb_items; i++ )
949 [o_chapter removeItemAtIndex:0];
952 /* Create chapter menu */
953 for( i = 0 ; i < p_input->stream.p_selected_area->i_part_nb ; i++ )
955 char psz_title[ 256 ];
956 NSString * o_menu_title;
959 snprintf( psz_title, sizeof(psz_title), "Chapter %d", i + 1 );
960 psz_title[sizeof(psz_title) - 1] = '\0';
962 o_menu_title = [NSString stringWithCString: psz_title];
964 o_item = [o_chapter addItemWithTitle: o_menu_title
965 action: pf_toggle_chapter keyEquivalent: @""];
966 [o_item setTag: i + 1];
967 [o_item setTarget: self];
968 if( ( p_input->stream.p_selected_area->i_part == i + 1 ) )
970 [o_item setState: 1];
974 p_main->p_intf->p_sys->i_part = p_input->stream.p_selected_area->i_part;
975 vlc_mutex_unlock( &p_input->stream.stream_lock );
976 vlc_mutex_lock( &p_input->stream.stream_lock );
978 /* ----- LANGUAGES & SUBTITLES ----- */
979 o_language = [o_language_item submenu];
980 o_subtitle = [o_subtitle_item submenu];
981 pf_toggle_language = @selector(toggleLanguage:);
982 pf_toggle_subtitle = @selector(toggleSubtitle:);
984 /* Remove previous language menu */
985 i_nb_items = [o_language numberOfItems];
986 for( i = 0; i < i_nb_items; i++ )
988 [o_language removeItemAtIndex:0];
991 /* Remove previous subtitle menu */
992 i_nb_items = [o_subtitle numberOfItems];
993 for( i = 0; i < i_nb_items; i++ )
995 [o_subtitle removeItemAtIndex:0];
998 [o_language_item setEnabled: 1];
999 [o_subtitle_item setEnabled: 1];
1001 /* Create language & subtitles menus */
1002 for( i = 0 ; i < p_input->stream.i_es_number ; i++ )
1004 es_descriptor_t * p_es = p_input->stream.pp_es[i];
1005 if( p_es->p_pgrm != NULL
1006 && p_es->p_pgrm != p_input->stream.p_selected_program )
1011 if( p_es->i_cat == AUDIO_ES )
1013 NSString * o_menu_title;
1014 NSMenuItem * o_item;
1016 if( *p_es->psz_desc )
1018 o_menu_title = [NSString stringWithCString: p_es->psz_desc];
1022 char psz_title[ 256 ];
1023 snprintf( psz_title, sizeof(psz_title), "Language 0x%x",
1025 psz_title[sizeof(psz_title) - 1] = '\0';
1027 o_menu_title = [NSString stringWithCString: psz_title];
1030 o_item = [o_language addItemWithTitle: o_menu_title
1031 action: pf_toggle_language keyEquivalent: @""];
1033 [o_item setTarget: self];
1034 [o_item setEnabled: 1];
1035 if( p_es->p_decoder_fifo != NULL )
1037 [o_item setState: 1];
1040 else if( p_es->i_cat == SPU_ES )
1042 NSString * o_menu_title;
1043 NSMenuItem * o_item;
1045 if( *p_es->psz_desc )
1047 o_menu_title = [NSString stringWithCString: p_es->psz_desc];
1051 char psz_title[ 256 ];
1052 snprintf( psz_title, sizeof(psz_title), "Subtitle 0x%x",
1054 psz_title[sizeof(psz_title) - 1] = '\0';
1056 o_menu_title = [NSString stringWithCString: psz_title];
1059 o_item = [o_subtitle addItemWithTitle: o_menu_title
1060 action: pf_toggle_subtitle keyEquivalent: @""];
1062 [o_item setTarget: self];
1063 [o_item setEnabled: 1];
1064 if( p_es->p_decoder_fifo != NULL )
1066 [o_item setState: 1];
1071 if( [o_language numberOfItems] )
1073 [o_language_item setEnabled: 1];
1077 [o_language_item setEnabled: 0];
1079 if( [o_subtitle numberOfItems] )
1081 [o_subtitle_item setEnabled: 1];
1085 [o_subtitle_item setEnabled: 0];
1087 p_input->stream.b_changed = 0;