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.4 2002/05/19 17:27:39 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 if( p_input_bank->pp_input[0] != NULL )
209 input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_SLOWER );
211 vlc_mutex_lock( &p_main->p_playlist->change_lock );
212 p_main->p_playlist->b_stopped = 0;
213 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
219 if( p_input_bank->pp_input[0] != NULL )
221 input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_FASTER );
223 vlc_mutex_lock( &p_main->p_playlist->change_lock );
224 p_main->p_playlist->b_stopped = 0;
225 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
231 if( p_aout_bank->pp_aout[0] == NULL ) return;
233 if( p_main->p_intf->p_sys->b_mute )
235 p_aout_bank->pp_aout[0]->i_volume =
236 p_main->p_intf->p_sys->i_saved_volume;
240 p_main->p_intf->p_sys->i_saved_volume =
241 p_aout_bank->pp_aout[0]->i_volume;
242 p_aout_bank->pp_aout[0]->i_volume = 0;
244 p_main->p_intf->p_sys->b_mute = !p_main->p_intf->p_sys->b_mute;
249 if( p_aout_bank->pp_aout[0] == NULL ) return;
251 if( p_main->p_intf->p_sys->b_mute )
253 p_main->p_intf->p_sys->i_saved_volume = VOLUME_MAX;
257 p_aout_bank->pp_aout[0]->i_volume = VOLUME_MAX;
263 if( p_vout_bank->pp_vout[0] != NULL )
265 p_vout_bank->pp_vout[0]->i_changes |= VOUT_FULLSCREEN_CHANGE;
271 /* FIXME : this will only eject the first drive found */
272 NSArray * o_devices = GetEjectableMediaOfClass(kIODVDMediaClass);
273 const char * psz_device;
275 if ( p_input_bank->pp_input[0] != NULL &&
276 (p_input_bank->pp_input[0]->stream.i_method == INPUT_METHOD_VCD ||
277 p_input_bank->pp_input[0]->stream.i_method == INPUT_METHOD_DVD ||
278 p_input_bank->pp_input[0]->stream.i_method == INPUT_METHOD_DISC) )
280 intf_ErrMsg("error: cannot eject the disc while you're reading from it");
284 if ( o_devices == nil )
286 o_devices = GetEjectableMediaOfClass(kIOCDMediaClass);
289 psz_device = [[o_devices objectAtIndex:0] cString];
290 intf_Eject( psz_device );
295 #define p_area p_input_bank->pp_input[0]->stream.p_selected_area
297 - (NSString *)getTimeAsString
299 static char psz_currenttime[ OFFSETTOTIME_MAX_SIZE ];
301 if( p_input_bank->pp_input[0] == NULL )
303 return [NSString stringWithCString:"00:00:00"];
306 input_OffsetToTime( p_input_bank->pp_input[0],
307 psz_currenttime, p_area->i_tell );
309 return( [NSString stringWithCString: psz_currenttime] );
312 - (float)getTimeAsFloat
316 vlc_mutex_lock( &p_input_bank->lock );
318 if( p_input_bank->pp_input[0] != NULL )
320 f_time = (float)p_area->i_tell / (float)p_area->i_size;
323 vlc_mutex_unlock( &p_input_bank->lock );
328 - (void)setTimeAsFloat:(float)f_position
330 vlc_mutex_lock( &p_input_bank->lock );
332 if( p_input_bank->pp_input[0] != NULL )
334 input_Seek( p_input_bank->pp_input[0], p_area->i_size * f_position );
337 vlc_mutex_unlock( &p_input_bank->lock );
342 - (bool)playlistPlaying
344 return( !p_main->p_playlist->b_stopped );
347 - (NSArray *)playlistAsArray
350 NSMutableArray* p_list =
351 [NSMutableArray arrayWithCapacity: p_main->p_playlist->i_size];
353 vlc_mutex_lock( &p_main->p_playlist->change_lock );
355 for( i = 0; i < p_main->p_playlist->i_size; i++ )
357 [p_list addObject: [NSString
358 stringWithCString: p_main->p_playlist->p_item[i].psz_name]];
361 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
363 return( [NSArray arrayWithArray: p_list] );
367 - (int)playlistLength
369 return( p_main->p_playlist->i_size );
372 - (NSString*)playlistItem:(int)i_pos
374 NSString *o_item = nil;
376 vlc_mutex_lock( &p_main->p_playlist->change_lock );
378 if( i_pos < p_main->p_playlist->i_size )
381 stringWithCString: p_main->p_playlist->p_item[i_pos].psz_name];
384 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
389 - (void)playlistPlayItem:(int)i_item
393 vlc_mutex_lock( &p_main->p_playlist->change_lock );
395 if( i_item<p_main->p_playlist->i_size )
397 p_main->p_playlist->i_index--;
400 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
402 [self playlistPlayCurrent];
405 - (void)playlistAdd:(NSString *)o_filename
407 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
408 [o_filename lossyCString] );
411 - (void)clearPlaylist
415 vlc_mutex_lock( &p_main->p_playlist->change_lock );
417 for( i = 0; i < p_main->p_playlist->i_size; i++ )
419 intf_PlaylistDelete( p_main->p_playlist, i );
422 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
426 /* open file/disc/network */
428 - (void)openFiles:(NSArray*)o_files
431 int i_end = p_main->p_playlist->i_size;
432 NSEnumerator *o_enum = [o_files objectEnumerator];
434 while( ( o_file = (NSString *)[o_enum nextObject] ) )
436 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
437 [o_file lossyCString] );
440 /* end current item, select first added item */
441 if( p_input_bank->pp_input[0] != NULL )
443 p_input_bank->pp_input[0]->b_eof = 1;
446 intf_PlaylistJumpto( p_main->p_playlist, i_end - 1 );
449 - (void)openDisc:(NSString*)o_type device:(NSString*)o_device title:(int)i_title chapter:(int)i_chapter
452 int i_end = p_main->p_playlist->i_size;
454 o_source = [NSString stringWithFormat: @"%@:%@@%d,%d",
455 o_type, o_device, i_title, i_chapter];
457 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
458 [o_source lossyCString] );
460 /* stop current item, select added item */
461 if( p_input_bank->pp_input[0] != NULL )
463 p_input_bank->pp_input[0]->b_eof = 1;
466 intf_PlaylistJumpto( p_main->p_playlist, i_end - 1 );
469 - (void)openNet:(NSString*)o_protocol addr:(NSString*)o_addr port:(int)i_port baddr:(NSString*)o_baddr
472 int i_end = p_main->p_playlist->i_size;
474 if( p_input_bank->pp_input[0] != NULL )
476 p_input_bank->pp_input[0]->b_eof = 1;
479 config_PutIntVariable( "network_channel", 0 );
483 o_source = [NSString stringWithFormat: @"%@://%@@:%i/%@",
484 o_protocol, o_addr, i_port, o_baddr];
488 o_source = [NSString stringWithFormat: @"%@://%@@:%i",
489 o_protocol, o_addr, i_port];
492 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
493 [o_source lossyCString] );
495 intf_PlaylistJumpto( p_main->p_playlist, i_end - 1 );
498 - (void)openNetChannel:(NSString*)o_addr port:(int)i_port
500 if( p_input_bank->pp_input[0] != NULL )
502 p_input_bank->pp_input[0]->b_eof = 1;
505 config_PutIntVariable( "network_channel", 1 );
507 if( p_main->p_channel == NULL )
509 network_ChannelCreate();
512 config_PutPszVariable( "channel_server", (char*)[o_addr lossyCString] );
513 config_PutIntVariable( "channel_port", i_port );
516 - (void)toggleProgram:(id)sender
518 NSMenuItem * o_item = (NSMenuItem *)sender;
519 input_thread_t * p_input = p_input_bank->pp_input[0];
521 if( [o_item state] == NSOffState )
523 u16 i_program_id = [o_item tag];
525 input_ChangeProgram( p_input, i_program_id );
527 vlc_mutex_lock( &p_input->stream.stream_lock );
529 vlc_mutex_unlock( &p_input->stream.stream_lock );
531 input_SetStatus( p_input, INPUT_STATUS_PLAY );
535 - (void)toggleTitle:(id)sender
537 NSMenuItem * o_item = (NSMenuItem *)sender;
538 input_thread_t * p_input = p_input_bank->pp_input[0];
540 if( [o_item state] == NSOffState )
542 int i_title = [o_item tag];
544 input_ChangeArea( p_input,
545 p_input->stream.pp_areas[i_title] );
547 vlc_mutex_lock( &p_input->stream.stream_lock );
549 vlc_mutex_unlock( &p_input->stream.stream_lock );
551 input_SetStatus( p_input, INPUT_STATUS_PLAY );
555 - (void)toggleChapter:(id)sender
557 NSMenuItem * o_item = (NSMenuItem *)sender;
558 input_thread_t * p_input = p_input_bank->pp_input[0];
560 if( [o_item state] == NSOffState )
562 int i_chapter = [o_item tag];
564 p_input->stream.p_selected_area->i_part = i_chapter;
565 input_ChangeArea( p_input,
566 p_input->stream.p_selected_area );
568 vlc_mutex_lock( &p_input->stream.stream_lock );
570 vlc_mutex_unlock( &p_input->stream.stream_lock );
572 input_SetStatus( p_input, INPUT_STATUS_PLAY );
576 - (void)toggleLanguage:(id)sender
578 NSMenuItem * o_item = (NSMenuItem *)sender;
579 input_thread_t * p_input = p_input_bank->pp_input[0];
581 int i_es = [o_item tag];
583 if( [o_item state] == NSOnState )
585 /* We just have one ES to disable */
586 input_ToggleES( p_input, p_input->stream.pp_es[i_es], 0 );
590 /* Unselect the selected ES in the same class */
592 vlc_mutex_lock( &p_input->stream.stream_lock );
593 for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
595 if( p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES )
597 vlc_mutex_unlock( &p_input->stream.stream_lock );
598 input_ToggleES( p_input, p_input->stream.pp_selected_es[i], 0 );
599 vlc_mutex_lock( &p_input->stream.stream_lock );
603 vlc_mutex_unlock( &p_input->stream.stream_lock );
605 /* Select the wanted ES */
606 input_ToggleES( p_input, p_input->stream.pp_es[i_es], 1 );
609 vlc_mutex_lock( &p_input->stream.stream_lock );
611 vlc_mutex_unlock( &p_input->stream.stream_lock );
613 input_SetStatus( p_input, INPUT_STATUS_PLAY );
616 - (void)toggleSubtitle:(id)sender
618 NSMenuItem * o_item = (NSMenuItem *)sender;
619 input_thread_t * p_input = p_input_bank->pp_input[0];
621 int i_es = [o_item tag];
623 if( [o_item state] == NSOnState )
625 /* We just have one ES to disable */
626 input_ToggleES( p_input, p_input->stream.pp_es[i_es], 0 );
630 /* Unselect the selected ES in the same class */
632 vlc_mutex_lock( &p_input->stream.stream_lock );
633 for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
635 if( p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
637 vlc_mutex_unlock( &p_input->stream.stream_lock );
638 input_ToggleES( p_input, p_input->stream.pp_selected_es[i], 0 );
639 vlc_mutex_lock( &p_input->stream.stream_lock );
643 vlc_mutex_unlock( &p_input->stream.stream_lock );
645 /* Select the wanted ES */
646 input_ToggleES( p_input, p_input->stream.pp_es[i_es], 1 );
649 vlc_mutex_lock( &p_input->stream.stream_lock );
651 vlc_mutex_unlock( &p_input->stream.stream_lock );
653 input_SetStatus( p_input, INPUT_STATUS_PLAY );
659 NSMenuItem *o_controls_item;
660 NSMenuItem *o_program_item, *o_title_item, *o_chapter_item, *o_language_item,
662 input_thread_t * p_input = p_input_bank->pp_input[0];
664 o_main_menu = [NSApp mainMenu];
665 o_controls_item = [o_main_menu itemWithTitle: @"Controls"];
666 o_program_item = [[o_controls_item submenu] itemWithTitle: @"Program"];
667 o_title_item = [[o_controls_item submenu] itemWithTitle: @"Title"];
668 o_chapter_item = [[o_controls_item submenu] itemWithTitle: @"Chapter"];
669 o_language_item = [[o_controls_item submenu] itemWithTitle: @"Language"];
670 o_subtitle_item = [[o_controls_item submenu] itemWithTitle: @"Subtitles"];
672 if( p_input == NULL )
674 [o_program_item setEnabled:0];
675 [o_title_item setEnabled:0];
676 [o_chapter_item setEnabled:0];
677 [o_language_item setEnabled:0];
678 [o_subtitle_item setEnabled:0];
682 NSMenu *o_program, *o_title, *o_chapter, *o_language, *o_subtitle;
683 SEL pf_toggle_program, pf_toggle_title, pf_toggle_chapter,
684 pf_toggle_language, pf_toggle_subtitle;
687 pgrm_descriptor_t * p_pgrm;
689 /* ----- PROGRAMS ----- */
690 if( p_input->stream.i_pgrm_number < 2 )
692 [o_program_item setEnabled:0];
696 [o_program_item setEnabled:1];
697 o_program = [o_program_item submenu];
698 pf_toggle_program = @selector(toggleProgram:);
700 /* Remove previous program menu */
701 i_nb_items = [o_program numberOfItems];
702 for( i = 0; i < i_nb_items; i++ )
704 [o_program removeItemAtIndex:0];
707 if( p_input->stream.p_new_program )
709 p_pgrm = p_input->stream.p_new_program;
713 p_pgrm = p_input->stream.p_selected_program;
716 /* Create program menu */
717 for( i = 0 ; i < p_input->stream.i_pgrm_number ; i++ )
719 char psz_title[ 256 ];
720 NSString * o_menu_title;
723 snprintf( psz_title, sizeof(psz_title), "id %d",
724 p_input->stream.pp_programs[i]->i_number );
725 psz_title[sizeof(psz_title) - 1] = '\0';
727 o_menu_title = [NSString stringWithCString: psz_title];
729 o_item = [o_program addItemWithTitle: o_menu_title
730 action: pf_toggle_program keyEquivalent: @""];
731 [o_item setTarget: self];
732 [o_item setTag: p_input->stream.pp_programs[i]->i_number];
733 if( p_pgrm == p_input->stream.pp_programs[i] )
735 [o_item setState: 1];
739 vlc_mutex_unlock( &p_input->stream.stream_lock );
740 vlc_mutex_lock( &p_input->stream.stream_lock );
742 /* ----- TITLES ----- */
743 if( p_input->stream.i_area_nb < 2 )
745 [o_title_item setEnabled:0];
749 [o_title_item setEnabled:1];
750 o_title = [o_title_item submenu];
751 pf_toggle_title = @selector(toggleTitle:);
753 /* Remove previous title menu */
754 i_nb_items = [o_title numberOfItems];
755 for( i = 0; i < i_nb_items; i++ )
757 [o_title removeItemAtIndex:0];
760 /* Create title menu */
761 for( i = 1 ; i < p_input->stream.i_area_nb ; i++ )
763 char psz_title[ 256 ];
764 NSString * o_menu_title;
767 snprintf( psz_title, sizeof(psz_title), "Title %d (%d)", i,
768 p_input->stream.pp_areas[i]->i_part_nb );
769 psz_title[sizeof(psz_title) - 1] = '\0';
771 o_menu_title = [NSString stringWithCString: psz_title];
773 o_item = [o_title addItemWithTitle: o_menu_title
774 action: pf_toggle_title keyEquivalent: @""];
776 [o_item setTarget: self];
777 if( ( p_input->stream.pp_areas[i] ==
778 p_input->stream.p_selected_area ) )
780 [o_item setState: 1];
784 vlc_mutex_unlock( &p_input->stream.stream_lock );
785 vlc_mutex_lock( &p_input->stream.stream_lock );
787 /* ----- CHAPTERS ----- */
788 if( p_input->stream.p_selected_area->i_part_nb < 2 )
790 [o_chapter_item setEnabled:0];
794 [o_chapter_item setEnabled:1];
795 o_chapter = [o_chapter_item submenu];
796 pf_toggle_chapter = @selector(toggleChapter:);
798 /* Remove previous chapter menu */
799 i_nb_items = [o_chapter numberOfItems];
800 for( i = 0; i < i_nb_items; i++ )
802 [o_chapter removeItemAtIndex:0];
805 /* Create chapter menu */
806 for( i = 0 ; i < p_input->stream.p_selected_area->i_part_nb ; i++ )
808 char psz_title[ 256 ];
809 NSString * o_menu_title;
812 snprintf( psz_title, sizeof(psz_title), "Chapter %d", i + 1 );
813 psz_title[sizeof(psz_title) - 1] = '\0';
815 o_menu_title = [NSString stringWithCString: psz_title];
817 o_item = [o_chapter addItemWithTitle: o_menu_title
818 action: pf_toggle_chapter keyEquivalent: @""];
820 [o_item setTarget: self];
821 if( ( p_input->stream.p_selected_area->i_part == i + 1 ) )
823 [o_item setState: 1];
827 p_main->p_intf->p_sys->i_part = p_input->stream.p_selected_area->i_part;
828 vlc_mutex_unlock( &p_input->stream.stream_lock );
829 vlc_mutex_lock( &p_input->stream.stream_lock );
831 /* ----- LANGUAGES & SUBTITLES ----- */
832 o_language = [o_language_item submenu];
833 o_subtitle = [o_subtitle_item submenu];
834 pf_toggle_language = @selector(toggleLanguage:);
835 pf_toggle_subtitle = @selector(toggleSubtitle:);
837 /* Remove previous language menu */
838 i_nb_items = [o_language numberOfItems];
839 for( i = 0; i < i_nb_items; i++ )
841 [o_language removeItemAtIndex:0];
844 /* Remove previous subtitle menu */
845 i_nb_items = [o_subtitle numberOfItems];
846 for( i = 0; i < i_nb_items; i++ )
848 [o_subtitle removeItemAtIndex:0];
851 /* Create language & subtitles menus */
852 for( i = 0 ; i < p_input->stream.i_es_number ; i++ )
854 es_descriptor_t * p_es = p_input->stream.pp_es[i];
855 if( p_es->p_pgrm != NULL
856 && p_es->p_pgrm != p_input->stream.p_selected_program )
861 if( p_es->i_cat == AUDIO_ES )
863 NSString * o_menu_title;
866 if( *p_es->psz_desc )
868 o_menu_title = [NSString stringWithCString: p_es->psz_desc];
872 char psz_title[ 256 ];
873 snprintf( psz_title, sizeof(psz_title), "Language 0x%x",
875 psz_title[sizeof(psz_title) - 1] = '\0';
877 o_menu_title = [NSString stringWithCString: psz_title];
880 o_item = [o_language addItemWithTitle: o_menu_title
881 action: pf_toggle_language keyEquivalent: @""];
883 [o_item setTarget: self];
884 if( p_es->p_decoder_fifo != NULL )
886 [o_item setState: 1];
889 else if( p_es->i_cat == SPU_ES )
891 NSString * o_menu_title;
894 if( *p_es->psz_desc )
896 o_menu_title = [NSString stringWithCString: p_es->psz_desc];
900 char psz_title[ 256 ];
901 snprintf( psz_title, sizeof(psz_title), "Subtitle 0x%x",
903 psz_title[sizeof(psz_title) - 1] = '\0';
905 o_menu_title = [NSString stringWithCString: psz_title];
908 o_item = [o_subtitle addItemWithTitle: o_menu_title
909 action: pf_toggle_subtitle keyEquivalent: @""];
911 [o_item setTarget: self];
912 if( p_es->p_decoder_fifo != NULL )
914 [o_item setState: 1];
919 if( [o_language numberOfItems] )
921 [o_language_item setEnabled: 1];
925 [o_language_item setEnabled: 0];
927 if( [o_subtitle numberOfItems] )
929 [o_subtitle_item setEnabled: 1];
933 [o_subtitle_item setEnabled: 0];
935 p_input->stream.b_changed = 0;