1 /*****************************************************************************
2 * intf_vlc_wrapper.c: MacOS X plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2001 VideoLAN
5 * $Id: intf_vlc_wrapper.m,v 1.11 2002/06/02 12:16:31 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 "intf_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 p_main->p_intf->pf_manage( p_main->p_intf );
78 if( p_main->p_intf->b_die )
80 /* Vout depends on intf */
89 if( p_input_bank->pp_input[0] != NULL )
91 vlc_mutex_lock( &p_input_bank->pp_input[0]->stream.stream_lock );
93 if( !p_input_bank->pp_input[0]->b_die )
95 /* New input or stream map change */
96 if( p_input_bank->pp_input[0]->stream.b_changed ||
97 p_main->p_intf->p_sys->i_part !=
98 p_input_bank->pp_input[0]->stream.p_selected_area->i_part )
101 p_main->p_intf->p_sys->b_disabled_menus = 0;
105 vlc_mutex_unlock( &p_input_bank->pp_input[0]->stream.stream_lock );
107 else if ( !p_main->p_intf->p_sys->b_disabled_menus )
110 p_main->p_intf->p_sys->b_disabled_menus = 1;
118 p_main->p_intf->b_die = 1;
121 /* playlist control */
125 if( p_input_bank->pp_input[0] != NULL )
127 input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_PLAY );
128 p_main->p_playlist->b_stopped = 0;
132 vlc_mutex_lock( &p_main->p_playlist->change_lock );
134 if( p_main->p_playlist->b_stopped )
136 if( p_main->p_playlist->i_size )
138 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
139 intf_PlaylistJumpto( p_main->p_playlist,
140 p_main->p_playlist->i_index );
144 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
145 [[Intf_Open instance] openFile: nil];
150 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
157 - (void)playlistPause
159 if ( p_input_bank->pp_input[0] != NULL )
161 input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_PAUSE );
163 vlc_mutex_lock( &p_main->p_playlist->change_lock );
164 p_main->p_playlist->b_stopped = 0;
165 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
171 if( p_input_bank->pp_input[0] != NULL )
173 /* end playing item */
174 p_input_bank->pp_input[0]->b_eof = 1;
176 /* update playlist */
177 vlc_mutex_lock( &p_main->p_playlist->change_lock );
179 p_main->p_playlist->i_index--;
180 p_main->p_playlist->b_stopped = 1;
182 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
188 if( p_input_bank->pp_input[0] != NULL )
190 p_input_bank->pp_input[0]->b_eof = 1;
196 if( p_input_bank->pp_input[0] != NULL )
198 /* FIXME: temporary hack */
199 intf_PlaylistPrev( p_main->p_playlist );
200 intf_PlaylistPrev( p_main->p_playlist );
201 p_input_bank->pp_input[0]->b_eof = 1;
207 intf_thread_t * p_intf = p_main->p_intf;
209 p_intf->p_sys->i_channel++;
211 intf_WarnMsg( 3, "intf info: joining channel %d", p_intf->p_sys->i_channel );
213 vlc_mutex_lock( &p_intf->change_lock );
214 if( p_input_bank->pp_input[0] != NULL )
216 /* end playing item */
217 p_input_bank->pp_input[0]->b_eof = 1;
219 /* update playlist */
220 vlc_mutex_lock( &p_main->p_playlist->change_lock );
222 p_main->p_playlist->i_index--;
223 p_main->p_playlist->b_stopped = 1;
225 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
227 /* FIXME: ugly hack to close input and outputs */
228 p_intf->pf_manage( p_intf );
231 network_ChannelJoin( p_intf->p_sys->i_channel );
234 p_main->p_playlist->b_stopped = 0;
235 p_intf->pf_manage( p_intf );
237 vlc_mutex_unlock( &p_intf->change_lock );
242 intf_thread_t * p_intf = p_main->p_intf;
244 if ( p_intf->p_sys->i_channel )
246 p_intf->p_sys->i_channel--;
249 intf_WarnMsg( 3, "intf info: joining channel %d", p_intf->p_sys->i_channel );
251 vlc_mutex_lock( &p_intf->change_lock );
252 if( p_input_bank->pp_input[0] != NULL )
254 /* end playing item */
255 p_input_bank->pp_input[0]->b_eof = 1;
257 /* update playlist */
258 vlc_mutex_lock( &p_main->p_playlist->change_lock );
260 p_main->p_playlist->i_index--;
261 p_main->p_playlist->b_stopped = 1;
263 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
265 /* FIXME: ugly hack to close input and outputs */
266 p_intf->pf_manage( p_intf );
269 network_ChannelJoin( p_intf->p_sys->i_channel );
272 p_main->p_playlist->b_stopped = 0;
273 p_intf->pf_manage( p_intf );
275 vlc_mutex_unlock( &p_intf->change_lock );
280 intf_thread_t * p_intf = p_main->p_intf;
282 if ( p_intf->p_sys->b_loop )
284 intf_PlaylistDelete( p_main->p_playlist,
285 p_main->p_playlist->i_size - 1 );
289 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
292 p_intf->p_sys->b_loop = !p_intf->p_sys->b_loop;
297 if( p_input_bank->pp_input[0] != NULL )
299 input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_SLOWER );
301 vlc_mutex_lock( &p_main->p_playlist->change_lock );
302 p_main->p_playlist->b_stopped = 0;
303 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
309 if( p_input_bank->pp_input[0] != NULL )
311 input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_FASTER );
313 vlc_mutex_lock( &p_main->p_playlist->change_lock );
314 p_main->p_playlist->b_stopped = 0;
315 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
321 if( p_aout_bank->pp_aout[0] == NULL ) return;
323 if( p_main->p_intf->p_sys->b_mute )
325 p_aout_bank->pp_aout[0]->i_volume =
326 p_main->p_intf->p_sys->i_saved_volume;
330 p_main->p_intf->p_sys->i_saved_volume =
331 p_aout_bank->pp_aout[0]->i_volume;
332 p_aout_bank->pp_aout[0]->i_volume = 0;
334 p_main->p_intf->p_sys->b_mute = !p_main->p_intf->p_sys->b_mute;
339 if( p_aout_bank->pp_aout[0] == NULL ) return;
341 if( p_main->p_intf->p_sys->b_mute )
343 p_main->p_intf->p_sys->i_saved_volume = VOLUME_MAX;
347 p_aout_bank->pp_aout[0]->i_volume = VOLUME_MAX;
353 if( p_vout_bank->pp_vout[0] != NULL )
355 p_vout_bank->pp_vout[0]->i_changes |= VOUT_FULLSCREEN_CHANGE;
361 /* FIXME : this will only eject the first drive found */
362 NSArray * o_devices = GetEjectableMediaOfClass(kIODVDMediaClass);
363 const char * psz_device;
365 if ( p_input_bank->pp_input[0] != NULL &&
366 (p_input_bank->pp_input[0]->stream.i_method == INPUT_METHOD_VCD ||
367 p_input_bank->pp_input[0]->stream.i_method == INPUT_METHOD_DVD ||
368 p_input_bank->pp_input[0]->stream.i_method == INPUT_METHOD_DISC) )
370 intf_ErrMsg("error: cannot eject the disc while you're reading from it");
374 if ( o_devices == nil )
376 o_devices = GetEjectableMediaOfClass(kIOCDMediaClass);
379 if ( o_devices != nil && [o_devices count] )
381 psz_device = [[o_devices objectAtIndex:0] cString];
382 intf_Eject( psz_device );
388 #define p_area p_input_bank->pp_input[0]->stream.p_selected_area
390 - (NSString *)getTimeAsString
392 static char psz_currenttime[ OFFSETTOTIME_MAX_SIZE ];
394 if( p_input_bank->pp_input[0] == NULL )
396 return [NSString stringWithCString:"00:00:00"];
399 input_OffsetToTime( p_input_bank->pp_input[0],
400 psz_currenttime, p_area->i_tell );
402 return( [NSString stringWithCString: psz_currenttime] );
405 - (float)getTimeAsFloat
409 if( p_input_bank->pp_input[0] != NULL )
411 f_time = (float)p_area->i_tell / (float)p_area->i_size;
417 - (void)setTimeAsFloat:(float)f_position
419 if( p_input_bank->pp_input[0] != NULL )
421 input_Seek( p_input_bank->pp_input[0]->p_this,
422 p_area->i_size * f_position, INPUT_SEEK_SET );
428 - (bool)playlistPlaying
430 return( !p_main->p_playlist->b_stopped );
433 - (NSArray *)playlistAsArray
436 NSMutableArray* p_list =
437 [NSMutableArray arrayWithCapacity: p_main->p_playlist->i_size];
439 vlc_mutex_lock( &p_main->p_playlist->change_lock );
441 for( i = 0; i < p_main->p_playlist->i_size; i++ )
443 [p_list addObject: [NSString
444 stringWithCString: p_main->p_playlist->p_item[i].psz_name]];
447 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
449 return( [NSArray arrayWithArray: p_list] );
453 - (int)playlistLength
455 return( p_main->p_playlist->i_size );
458 - (NSString*)playlistItem:(int)i_pos
460 NSString *o_item = nil;
462 vlc_mutex_lock( &p_main->p_playlist->change_lock );
464 if( i_pos < p_main->p_playlist->i_size )
467 stringWithCString: p_main->p_playlist->p_item[i_pos].psz_name];
470 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
475 - (void)playlistPlayItem:(int)i_item
479 vlc_mutex_lock( &p_main->p_playlist->change_lock );
481 if( i_item<p_main->p_playlist->i_size )
483 p_main->p_playlist->i_index--;
486 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
488 [self playlistPlayCurrent];
491 - (void)playlistAdd:(NSString *)o_filename
493 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
494 [o_filename fileSystemRepresentation] );
497 - (void)clearPlaylist
501 vlc_mutex_lock( &p_main->p_playlist->change_lock );
503 for( i = 0; i < p_main->p_playlist->i_size; i++ )
505 intf_PlaylistDelete( p_main->p_playlist, i );
508 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
512 /* open file/disc/network */
514 - (void)openFiles:(NSArray*)o_files
517 int i_end = p_main->p_playlist->i_size;
518 NSEnumerator *o_enum = [o_files objectEnumerator];
519 intf_thread_t * p_intf = p_main->p_intf;
521 if ( p_intf->p_sys->b_loop )
523 intf_PlaylistDelete( p_main->p_playlist,
524 p_main->p_playlist->i_size - 1 );
527 while( ( o_file = (NSString *)[o_enum nextObject] ) )
529 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
530 [o_file fileSystemRepresentation] );
533 /* end current item, select first added item */
534 if( p_input_bank->pp_input[0] != NULL )
536 p_input_bank->pp_input[0]->b_eof = 1;
539 intf_PlaylistJumpto( p_main->p_playlist, i_end - 1 );
541 if ( p_intf->p_sys->b_loop )
543 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
548 - (void)openDisc:(NSString*)o_type device:(NSString*)o_device title:(int)i_title chapter:(int)i_chapter
551 int i_end = p_main->p_playlist->i_size;
552 intf_thread_t * p_intf = p_main->p_intf;
554 o_source = [NSString stringWithFormat: @"%@:%@@%d,%d",
555 o_type, o_device, i_title, i_chapter];
557 if ( p_intf->p_sys->b_loop )
559 intf_PlaylistDelete( p_main->p_playlist,
560 p_main->p_playlist->i_size - 1 );
563 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
564 [o_source fileSystemRepresentation] );
566 /* stop current item, select added item */
567 if( p_input_bank->pp_input[0] != NULL )
569 p_input_bank->pp_input[0]->b_eof = 1;
572 intf_PlaylistJumpto( p_main->p_playlist, i_end - 1 );
574 if ( p_intf->p_sys->b_loop )
576 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
581 - (void)openNet:(NSString*)o_protocol addr:(NSString*)o_addr port:(int)i_port baddr:(NSString*)o_baddr
584 int i_end = p_main->p_playlist->i_size;
585 intf_thread_t * p_intf = p_main->p_intf;
587 if( p_input_bank->pp_input[0] != NULL )
589 p_input_bank->pp_input[0]->b_eof = 1;
592 config_PutIntVariable( "network_channel", 0 );
596 o_source = [NSString stringWithFormat: @"%@://%@@:%i/%@",
597 o_protocol, o_addr, i_port, o_baddr];
601 o_source = [NSString stringWithFormat: @"%@://%@@:%i",
602 o_protocol, o_addr, i_port];
605 if ( p_intf->p_sys->b_loop )
607 intf_PlaylistDelete( p_main->p_playlist,
608 p_main->p_playlist->i_size - 1 );
611 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
612 [o_source fileSystemRepresentation] );
614 intf_PlaylistJumpto( p_main->p_playlist, i_end - 1 );
616 if ( p_intf->p_sys->b_loop )
618 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
623 - (void)openNetChannel:(NSString*)o_addr port:(int)i_port
625 if( p_input_bank->pp_input[0] != NULL )
627 p_input_bank->pp_input[0]->b_eof = 1;
630 config_PutIntVariable( "network_channel", 1 );
632 if( p_main->p_channel == NULL )
634 network_ChannelCreate();
637 config_PutPszVariable( "channel_server", (char*)[o_addr lossyCString] );
638 config_PutIntVariable( "channel_port", i_port );
641 - (void)toggleProgram:(id)sender
643 NSMenuItem * o_item = (NSMenuItem *)sender;
644 input_thread_t * p_input = p_input_bank->pp_input[0];
646 if( [o_item state] == NSOffState )
648 u16 i_program_id = [o_item tag];
650 input_ChangeProgram( p_input, i_program_id );
652 vlc_mutex_lock( &p_input->stream.stream_lock );
654 vlc_mutex_unlock( &p_input->stream.stream_lock );
656 input_SetStatus( p_input, INPUT_STATUS_PLAY );
660 - (void)toggleTitle:(id)sender
662 NSMenuItem * o_item = (NSMenuItem *)sender;
663 input_thread_t * p_input = p_input_bank->pp_input[0];
665 if( [o_item state] == NSOffState )
667 int i_title = [o_item tag];
669 input_ChangeArea( p_input,
670 p_input->stream.pp_areas[i_title] );
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)toggleChapter:(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_chapter = [o_item tag];
689 p_input->stream.p_selected_area->i_part = i_chapter;
690 input_ChangeArea( p_input,
691 p_input->stream.p_selected_area );
693 vlc_mutex_lock( &p_input->stream.stream_lock );
695 vlc_mutex_unlock( &p_input->stream.stream_lock );
697 input_SetStatus( p_input, INPUT_STATUS_PLAY );
701 - (void)toggleLanguage:(id)sender
703 NSMenuItem * o_item = (NSMenuItem *)sender;
704 input_thread_t * p_input = p_input_bank->pp_input[0];
706 int i_es = [o_item tag];
708 if( [o_item state] == NSOnState )
710 /* We just have one ES to disable */
711 input_ToggleES( p_input, p_input->stream.pp_es[i_es], 0 );
715 /* Unselect the selected ES in the same class */
717 vlc_mutex_lock( &p_input->stream.stream_lock );
718 for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
720 if( p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES )
722 vlc_mutex_unlock( &p_input->stream.stream_lock );
723 input_ToggleES( p_input, p_input->stream.pp_selected_es[i], 0 );
724 vlc_mutex_lock( &p_input->stream.stream_lock );
728 vlc_mutex_unlock( &p_input->stream.stream_lock );
730 /* Select the wanted ES */
731 input_ToggleES( p_input, p_input->stream.pp_es[i_es], 1 );
734 vlc_mutex_lock( &p_input->stream.stream_lock );
736 vlc_mutex_unlock( &p_input->stream.stream_lock );
738 input_SetStatus( p_input, INPUT_STATUS_PLAY );
741 - (void)toggleSubtitle:(id)sender
743 NSMenuItem * o_item = (NSMenuItem *)sender;
744 input_thread_t * p_input = p_input_bank->pp_input[0];
746 int i_es = [o_item tag];
748 if( [o_item state] == NSOnState )
750 /* We just have one ES to disable */
751 input_ToggleES( p_input, p_input->stream.pp_es[i_es], 0 );
755 /* Unselect the selected ES in the same class */
757 vlc_mutex_lock( &p_input->stream.stream_lock );
758 for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
760 if( p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
762 vlc_mutex_unlock( &p_input->stream.stream_lock );
763 input_ToggleES( p_input, p_input->stream.pp_selected_es[i], 0 );
764 vlc_mutex_lock( &p_input->stream.stream_lock );
768 vlc_mutex_unlock( &p_input->stream.stream_lock );
770 /* Select the wanted ES */
771 input_ToggleES( p_input, p_input->stream.pp_es[i_es], 1 );
774 vlc_mutex_lock( &p_input->stream.stream_lock );
776 vlc_mutex_unlock( &p_input->stream.stream_lock );
778 input_SetStatus( p_input, INPUT_STATUS_PLAY );
784 NSMenuItem *o_controls_item;
785 NSMenuItem *o_program_item, *o_title_item, *o_chapter_item, *o_language_item,
786 *o_subtitle_item, *o_next_channel_item, *o_prev_channel_item;
787 input_thread_t * p_input = p_input_bank->pp_input[0];
789 o_main_menu = [NSApp mainMenu];
790 o_controls_item = [o_main_menu itemWithTitle: @"Controls"];
791 o_program_item = [[o_controls_item submenu] itemWithTitle: @"Program"];
792 o_title_item = [[o_controls_item submenu] itemWithTitle: @"Title"];
793 o_chapter_item = [[o_controls_item submenu] itemWithTitle: @"Chapter"];
794 o_language_item = [[o_controls_item submenu] itemWithTitle: @"Language"];
795 o_subtitle_item = [[o_controls_item submenu] itemWithTitle: @"Subtitles"];
796 o_next_channel_item = [[o_controls_item submenu] itemWithTag: 13];
797 o_prev_channel_item = [[o_controls_item submenu] itemWithTag: 12];
799 if( p_input == NULL )
801 [o_program_item setEnabled:0];
802 [o_title_item setEnabled:0];
803 [o_chapter_item setEnabled:0];
804 [o_language_item setEnabled:0];
805 [o_subtitle_item setEnabled:0];
809 NSMenu *o_program, *o_title, *o_chapter, *o_language, *o_subtitle;
810 SEL pf_toggle_program, pf_toggle_title, pf_toggle_chapter,
811 pf_toggle_language, pf_toggle_subtitle;
814 pgrm_descriptor_t * p_pgrm;
816 /* ----- PROGRAMS ----- */
817 if( p_input->stream.i_pgrm_number < 2 )
819 [o_program_item setEnabled:0];
823 [o_program_item setEnabled:1];
824 o_program = [o_program_item submenu];
825 pf_toggle_program = @selector(toggleProgram:);
827 /* Remove previous program menu */
828 i_nb_items = [o_program numberOfItems];
829 for( i = 0; i < i_nb_items; i++ )
831 [o_program removeItemAtIndex:0];
834 if( p_input->stream.p_new_program )
836 p_pgrm = p_input->stream.p_new_program;
840 p_pgrm = p_input->stream.p_selected_program;
843 /* Create program menu */
844 for( i = 0 ; i < p_input->stream.i_pgrm_number ; i++ )
846 char psz_title[ 256 ];
847 NSString * o_menu_title;
850 snprintf( psz_title, sizeof(psz_title), "id %d",
851 p_input->stream.pp_programs[i]->i_number );
852 psz_title[sizeof(psz_title) - 1] = '\0';
854 o_menu_title = [NSString stringWithCString: psz_title];
856 o_item = [o_program addItemWithTitle: o_menu_title
857 action: pf_toggle_program keyEquivalent: @""];
858 [o_item setTarget: self];
859 [o_item setTag: p_input->stream.pp_programs[i]->i_number];
860 if( p_pgrm == p_input->stream.pp_programs[i] )
862 [o_item setState: 1];
866 vlc_mutex_unlock( &p_input->stream.stream_lock );
867 vlc_mutex_lock( &p_input->stream.stream_lock );
869 /* ----- TITLES ----- */
870 if( p_input->stream.i_area_nb < 2 )
872 [o_title_item setEnabled:0];
876 [o_title_item setEnabled:1];
877 o_title = [o_title_item submenu];
878 pf_toggle_title = @selector(toggleTitle:);
880 /* Remove previous title menu */
881 i_nb_items = [o_title numberOfItems];
882 for( i = 0; i < i_nb_items; i++ )
884 [o_title removeItemAtIndex:0];
887 /* Create title menu */
888 for( i = 1 ; i < p_input->stream.i_area_nb ; i++ )
890 char psz_title[ 256 ];
891 NSString * o_menu_title;
894 snprintf( psz_title, sizeof(psz_title), "Title %d (%d)", i,
895 p_input->stream.pp_areas[i]->i_part_nb );
896 psz_title[sizeof(psz_title) - 1] = '\0';
898 o_menu_title = [NSString stringWithCString: psz_title];
900 o_item = [o_title addItemWithTitle: o_menu_title
901 action: pf_toggle_title keyEquivalent: @""];
903 [o_item setTarget: self];
904 if( ( p_input->stream.pp_areas[i] ==
905 p_input->stream.p_selected_area ) )
907 [o_item setState: 1];
911 vlc_mutex_unlock( &p_input->stream.stream_lock );
912 vlc_mutex_lock( &p_input->stream.stream_lock );
914 /* ----- CHAPTERS ----- */
915 if( p_input->stream.p_selected_area->i_part_nb < 2 )
917 [o_chapter_item setEnabled:0];
921 [o_chapter_item setEnabled:1];
922 o_chapter = [o_chapter_item submenu];
923 pf_toggle_chapter = @selector(toggleChapter:);
925 /* Remove previous chapter menu */
926 i_nb_items = [o_chapter numberOfItems];
927 for( i = 0; i < i_nb_items; i++ )
929 [o_chapter removeItemAtIndex:0];
932 /* Create chapter menu */
933 for( i = 0 ; i < p_input->stream.p_selected_area->i_part_nb ; i++ )
935 char psz_title[ 256 ];
936 NSString * o_menu_title;
939 snprintf( psz_title, sizeof(psz_title), "Chapter %d", i + 1 );
940 psz_title[sizeof(psz_title) - 1] = '\0';
942 o_menu_title = [NSString stringWithCString: psz_title];
944 o_item = [o_chapter addItemWithTitle: o_menu_title
945 action: pf_toggle_chapter keyEquivalent: @""];
946 [o_item setTag: i + 1];
947 [o_item setTarget: self];
948 if( ( p_input->stream.p_selected_area->i_part == i + 1 ) )
950 [o_item setState: 1];
954 p_main->p_intf->p_sys->i_part = p_input->stream.p_selected_area->i_part;
955 vlc_mutex_unlock( &p_input->stream.stream_lock );
956 vlc_mutex_lock( &p_input->stream.stream_lock );
958 /* ----- LANGUAGES & SUBTITLES ----- */
959 o_language = [o_language_item submenu];
960 o_subtitle = [o_subtitle_item submenu];
961 pf_toggle_language = @selector(toggleLanguage:);
962 pf_toggle_subtitle = @selector(toggleSubtitle:);
964 /* Remove previous language menu */
965 i_nb_items = [o_language numberOfItems];
966 for( i = 0; i < i_nb_items; i++ )
968 [o_language removeItemAtIndex:0];
971 /* Remove previous subtitle menu */
972 i_nb_items = [o_subtitle numberOfItems];
973 for( i = 0; i < i_nb_items; i++ )
975 [o_subtitle removeItemAtIndex:0];
978 /* Create language & subtitles menus */
979 for( i = 0 ; i < p_input->stream.i_es_number ; i++ )
981 es_descriptor_t * p_es = p_input->stream.pp_es[i];
982 if( p_es->p_pgrm != NULL
983 && p_es->p_pgrm != p_input->stream.p_selected_program )
988 if( p_es->i_cat == AUDIO_ES )
990 NSString * o_menu_title;
993 if( *p_es->psz_desc )
995 o_menu_title = [NSString stringWithCString: p_es->psz_desc];
999 char psz_title[ 256 ];
1000 snprintf( psz_title, sizeof(psz_title), "Language 0x%x",
1002 psz_title[sizeof(psz_title) - 1] = '\0';
1004 o_menu_title = [NSString stringWithCString: psz_title];
1007 o_item = [o_language addItemWithTitle: o_menu_title
1008 action: pf_toggle_language keyEquivalent: @""];
1010 [o_item setTarget: self];
1011 [o_item setEnabled: 1];
1012 if( p_es->p_decoder_fifo != NULL )
1014 [o_item setState: 1];
1017 else if( p_es->i_cat == SPU_ES )
1019 NSString * o_menu_title;
1020 NSMenuItem * o_item;
1022 if( *p_es->psz_desc )
1024 o_menu_title = [NSString stringWithCString: p_es->psz_desc];
1028 char psz_title[ 256 ];
1029 snprintf( psz_title, sizeof(psz_title), "Subtitle 0x%x",
1031 psz_title[sizeof(psz_title) - 1] = '\0';
1033 o_menu_title = [NSString stringWithCString: psz_title];
1036 o_item = [o_subtitle addItemWithTitle: o_menu_title
1037 action: pf_toggle_subtitle keyEquivalent: @""];
1039 [o_item setTarget: self];
1040 [o_item setEnabled: 1];
1041 if( p_es->p_decoder_fifo != NULL )
1043 [o_item setState: 1];
1048 if( [o_language numberOfItems] )
1050 [o_language_item setEnabled: 1];
1054 [o_language_item setEnabled: 0];
1056 if( [o_subtitle numberOfItems] )
1058 [o_subtitle_item setEnabled: 1];
1062 [o_subtitle_item setEnabled: 0];
1064 p_input->stream.b_changed = 0;