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.3 2002/05/18 13:33:44 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 )
104 vlc_mutex_unlock( &p_input_bank->pp_input[0]->stream.stream_lock );
106 else if ( !p_main->p_intf->p_sys->b_disabled_menus )
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 if( p_input_bank->pp_input[0] != NULL )
207 input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_SLOWER );
209 vlc_mutex_lock( &p_main->p_playlist->change_lock );
210 p_main->p_playlist->b_stopped = 0;
211 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
217 if( p_input_bank->pp_input[0] != NULL )
219 input_SetStatus( p_input_bank->pp_input[0], INPUT_STATUS_FASTER );
221 vlc_mutex_lock( &p_main->p_playlist->change_lock );
222 p_main->p_playlist->b_stopped = 0;
223 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
229 if( p_aout_bank->pp_aout[0] == NULL ) return;
231 if( p_main->p_intf->p_sys->b_mute )
233 p_aout_bank->pp_aout[0]->i_volume =
234 p_main->p_intf->p_sys->i_saved_volume;
238 p_main->p_intf->p_sys->i_saved_volume =
239 p_aout_bank->pp_aout[0]->i_volume;
240 p_aout_bank->pp_aout[0]->i_volume = 0;
242 p_main->p_intf->p_sys->b_mute = !p_main->p_intf->p_sys->b_mute;
247 if( p_aout_bank->pp_aout[0] == NULL ) return;
249 if( p_main->p_intf->p_sys->b_mute )
251 p_main->p_intf->p_sys->i_saved_volume = VOLUME_MAX;
255 p_aout_bank->pp_aout[0]->i_volume = VOLUME_MAX;
261 if( p_vout_bank->pp_vout[0] != NULL )
263 p_vout_bank->pp_vout[0]->i_changes |= VOUT_FULLSCREEN_CHANGE;
269 /* FIXME : this will only eject the first drive found */
270 NSArray * o_devices = GetEjectableMediaOfClass(kIODVDMediaClass);
271 const char * psz_device;
273 if ( p_input_bank->pp_input[0] != NULL &&
274 (p_input_bank->pp_input[0]->stream.i_method == INPUT_METHOD_VCD ||
275 p_input_bank->pp_input[0]->stream.i_method == INPUT_METHOD_DVD ||
276 p_input_bank->pp_input[0]->stream.i_method == INPUT_METHOD_DISC) )
278 intf_ErrMsg("error: cannot eject the disc while you're reading from it");
282 if ( o_devices == nil )
284 o_devices = GetEjectableMediaOfClass(kIOCDMediaClass);
287 psz_device = [[o_devices objectAtIndex:0] cString];
288 intf_Eject( psz_device );
293 #define p_area p_input_bank->pp_input[0]->stream.p_selected_area
295 - (NSString *)getTimeAsString
297 static char psz_currenttime[ OFFSETTOTIME_MAX_SIZE ];
299 if( p_input_bank->pp_input[0] == NULL )
301 return [NSString stringWithCString:"00:00:00"];
304 input_OffsetToTime( p_input_bank->pp_input[0],
305 psz_currenttime, p_area->i_tell );
307 return( [NSString stringWithCString: psz_currenttime] );
310 - (float)getTimeAsFloat
314 vlc_mutex_lock( &p_input_bank->lock );
316 if( p_input_bank->pp_input[0] != NULL )
318 f_time = (float)p_area->i_tell / (float)p_area->i_size;
321 vlc_mutex_unlock( &p_input_bank->lock );
326 - (void)setTimeAsFloat:(float)f_position
328 vlc_mutex_lock( &p_input_bank->lock );
330 if( p_input_bank->pp_input[0] != NULL )
332 input_Seek( p_input_bank->pp_input[0], p_area->i_size * f_position );
335 vlc_mutex_unlock( &p_input_bank->lock );
340 - (bool)playlistPlaying
342 return( !p_main->p_playlist->b_stopped );
345 - (NSArray *)playlistAsArray
348 NSMutableArray* p_list =
349 [NSMutableArray arrayWithCapacity: p_main->p_playlist->i_size];
351 vlc_mutex_lock( &p_main->p_playlist->change_lock );
353 for( i = 0; i < p_main->p_playlist->i_size; i++ )
355 [p_list addObject: [NSString
356 stringWithCString: p_main->p_playlist->p_item[i].psz_name]];
359 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
361 return( [NSArray arrayWithArray: p_list] );
365 - (int)playlistLength
367 return( p_main->p_playlist->i_size );
370 - (NSString*)playlistItem:(int)i_pos
372 NSString *o_item = nil;
374 vlc_mutex_lock( &p_main->p_playlist->change_lock );
376 if( i_pos < p_main->p_playlist->i_size )
379 stringWithCString: p_main->p_playlist->p_item[i_pos].psz_name];
382 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
387 - (void)playlistPlayItem:(int)i_item
391 vlc_mutex_lock( &p_main->p_playlist->change_lock );
393 if( i_item<p_main->p_playlist->i_size )
395 p_main->p_playlist->i_index--;
398 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
400 [self playlistPlayCurrent];
403 - (void)playlistAdd:(NSString *)o_filename
405 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
406 [o_filename lossyCString] );
409 - (void)clearPlaylist
413 vlc_mutex_lock( &p_main->p_playlist->change_lock );
415 for( i = 0; i < p_main->p_playlist->i_size; i++ )
417 intf_PlaylistDelete( p_main->p_playlist, i );
420 vlc_mutex_unlock( &p_main->p_playlist->change_lock );
424 /* open file/disc/network */
426 - (void)openFiles:(NSArray*)o_files
429 int i_end = p_main->p_playlist->i_size;
430 NSEnumerator *o_enum = [o_files objectEnumerator];
432 while( ( o_file = (NSString *)[o_enum nextObject] ) )
434 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
435 [o_file lossyCString] );
438 /* end current item, select first added item */
439 if( p_input_bank->pp_input[0] != NULL )
441 p_input_bank->pp_input[0]->b_eof = 1;
444 intf_PlaylistJumpto( p_main->p_playlist, i_end - 1 );
447 - (void)openDisc:(NSString*)o_type device:(NSString*)o_device title:(int)i_title chapter:(int)i_chapter
450 int i_end = p_main->p_playlist->i_size;
452 o_source = [NSString stringWithFormat: @"%@:%@@%d,%d",
453 o_type, o_device, i_title, i_chapter];
455 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
456 [o_source lossyCString] );
458 /* stop current item, select added item */
459 if( p_input_bank->pp_input[0] != NULL )
461 p_input_bank->pp_input[0]->b_eof = 1;
464 intf_PlaylistJumpto( p_main->p_playlist, i_end - 1 );
467 - (void)openNet:(NSString*)o_protocol addr:(NSString*)o_addr port:(int)i_port baddr:(NSString*)o_baddr
470 int i_end = p_main->p_playlist->i_size;
472 if( p_input_bank->pp_input[0] != NULL )
474 p_input_bank->pp_input[0]->b_eof = 1;
477 config_PutIntVariable( "network_channel", 0 );
481 o_source = [NSString stringWithFormat: @"%@://%@@:%i/%@",
482 o_protocol, o_addr, i_port, o_baddr];
486 o_source = [NSString stringWithFormat: @"%@://%@@:%i",
487 o_protocol, o_addr, i_port];
490 intf_PlaylistAdd( p_main->p_playlist, PLAYLIST_END,
491 [o_source lossyCString] );
493 intf_PlaylistJumpto( p_main->p_playlist, i_end - 1 );
496 - (void)openNetChannel:(NSString*)o_addr port:(int)i_port
498 if( p_input_bank->pp_input[0] != NULL )
500 p_input_bank->pp_input[0]->b_eof = 1;
503 config_PutIntVariable( "network_channel", 1 );
505 if( p_main->p_channel == NULL )
507 network_ChannelCreate();
510 config_PutPszVariable( "channel_server", (char*)[o_addr lossyCString] );
511 config_PutIntVariable( "channel_port", i_port );
514 - (void)toggleProgram:(id)sender
516 NSMenuItem * o_item = (NSMenuItem *)sender;
517 input_thread_t * p_input = p_input_bank->pp_input[0];
519 if( [o_item state] == NSOffState )
521 u16 i_program_id = [o_item tag];
523 input_ChangeProgram( p_input, i_program_id );
525 vlc_mutex_lock( &p_input->stream.stream_lock );
527 vlc_mutex_unlock( &p_input->stream.stream_lock );
529 input_SetStatus( p_input, INPUT_STATUS_PLAY );
533 - (void)toggleTitle:(id)sender
535 NSMenuItem * o_item = (NSMenuItem *)sender;
536 input_thread_t * p_input = p_input_bank->pp_input[0];
538 if( [o_item state] == NSOffState )
540 int i_title = [o_item tag];
542 input_ChangeArea( p_input,
543 p_input->stream.pp_areas[i_title] );
545 vlc_mutex_lock( &p_input->stream.stream_lock );
547 vlc_mutex_unlock( &p_input->stream.stream_lock );
549 input_SetStatus( p_input, INPUT_STATUS_PLAY );
553 - (void)toggleChapter:(id)sender
555 NSMenuItem * o_item = (NSMenuItem *)sender;
556 input_thread_t * p_input = p_input_bank->pp_input[0];
558 if( [o_item state] == NSOffState )
560 int i_chapter = [o_item tag];
562 p_input->stream.p_selected_area->i_part = i_chapter;
563 input_ChangeArea( p_input,
564 p_input->stream.p_selected_area );
566 vlc_mutex_lock( &p_input->stream.stream_lock );
568 vlc_mutex_unlock( &p_input->stream.stream_lock );
570 input_SetStatus( p_input, INPUT_STATUS_PLAY );
574 - (void)toggleLanguage:(id)sender
576 NSMenuItem * o_item = (NSMenuItem *)sender;
577 input_thread_t * p_input = p_input_bank->pp_input[0];
579 int i_es = [o_item tag];
581 if( [o_item state] == NSOnState )
583 /* We just have one ES to disable */
584 input_ToggleES( p_input, p_input->stream.pp_es[i_es], 0 );
588 /* Unselect the selected ES in the same class */
590 vlc_mutex_lock( &p_input->stream.stream_lock );
591 for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
593 if( p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES )
595 vlc_mutex_unlock( &p_input->stream.stream_lock );
596 input_ToggleES( p_input, p_input->stream.pp_selected_es[i], 0 );
597 vlc_mutex_lock( &p_input->stream.stream_lock );
601 vlc_mutex_unlock( &p_input->stream.stream_lock );
603 /* Select the wanted ES */
604 input_ToggleES( p_input, p_input->stream.pp_es[i_es], 1 );
607 vlc_mutex_lock( &p_input->stream.stream_lock );
609 vlc_mutex_unlock( &p_input->stream.stream_lock );
611 input_SetStatus( p_input, INPUT_STATUS_PLAY );
614 - (void)toggleSubtitle:(id)sender
616 NSMenuItem * o_item = (NSMenuItem *)sender;
617 input_thread_t * p_input = p_input_bank->pp_input[0];
619 int i_es = [o_item tag];
621 if( [o_item state] == NSOnState )
623 /* We just have one ES to disable */
624 input_ToggleES( p_input, p_input->stream.pp_es[i_es], 0 );
628 /* Unselect the selected ES in the same class */
630 vlc_mutex_lock( &p_input->stream.stream_lock );
631 for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
633 if( p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
635 vlc_mutex_unlock( &p_input->stream.stream_lock );
636 input_ToggleES( p_input, p_input->stream.pp_selected_es[i], 0 );
637 vlc_mutex_lock( &p_input->stream.stream_lock );
641 vlc_mutex_unlock( &p_input->stream.stream_lock );
643 /* Select the wanted ES */
644 input_ToggleES( p_input, p_input->stream.pp_es[i_es], 1 );
647 vlc_mutex_lock( &p_input->stream.stream_lock );
649 vlc_mutex_unlock( &p_input->stream.stream_lock );
651 input_SetStatus( p_input, INPUT_STATUS_PLAY );
657 NSMenuItem *o_controls_item;
658 NSMenuItem *o_program_item, *o_title_item, *o_chapter_item, *o_language_item,
660 input_thread_t * p_input = p_input_bank->pp_input[0];
662 o_main_menu = [NSApp mainMenu];
663 o_controls_item = [o_main_menu itemWithTitle: @"Controls"];
664 o_program_item = [[o_controls_item submenu] itemWithTitle: @"Program"];
665 o_title_item = [[o_controls_item submenu] itemWithTitle: @"Title"];
666 o_chapter_item = [[o_controls_item submenu] itemWithTitle: @"Chapter"];
667 o_language_item = [[o_controls_item submenu] itemWithTitle: @"Language"];
668 o_subtitle_item = [[o_controls_item submenu] itemWithTitle: @"Subtitles"];
670 if( p_input == NULL )
672 [o_program_item setEnabled:0];
673 [o_title_item setEnabled:0];
674 [o_chapter_item setEnabled:0];
675 [o_language_item setEnabled:0];
676 [o_subtitle_item setEnabled:0];
680 NSMenu *o_program, *o_title, *o_chapter, *o_language, *o_subtitle;
681 SEL pf_toggle_program, pf_toggle_title, pf_toggle_chapter,
682 pf_toggle_language, pf_toggle_subtitle;
685 pgrm_descriptor_t * p_pgrm;
687 /* ----- PROGRAMS ----- */
688 if( p_input->stream.i_pgrm_number < 2 )
690 [o_program_item setEnabled:0];
694 [o_program_item setEnabled:1];
695 o_program = [o_program_item submenu];
696 pf_toggle_program = @selector(toggleProgram:);
698 /* Remove previous program menu */
699 i_nb_items = [o_program numberOfItems];
700 for( i = 0; i < i_nb_items; i++ )
702 [o_program removeItemAtIndex:0];
705 if( p_input->stream.p_new_program )
707 p_pgrm = p_input->stream.p_new_program;
711 p_pgrm = p_input->stream.p_selected_program;
714 /* Create program menu */
715 for( i = 0 ; i < p_input->stream.i_pgrm_number ; i++ )
717 char psz_title[ 256 ];
718 NSString * o_menu_title;
721 snprintf( psz_title, sizeof(psz_title), "id %d",
722 p_input->stream.pp_programs[i]->i_number );
723 psz_title[sizeof(psz_title) - 1] = '\0';
725 o_menu_title = [NSString stringWithCString: psz_title];
727 o_item = [o_program addItemWithTitle: o_menu_title
728 action: pf_toggle_program keyEquivalent: @""];
729 [o_item setTarget: self];
730 [o_item setTag: p_input->stream.pp_programs[i]->i_number];
731 if( p_pgrm == p_input->stream.pp_programs[i] )
733 [o_item setState: 1];
737 vlc_mutex_unlock( &p_input->stream.stream_lock );
738 vlc_mutex_lock( &p_input->stream.stream_lock );
740 /* ----- TITLES ----- */
741 if( p_input->stream.i_area_nb < 2 )
743 [o_title_item setEnabled:0];
747 [o_title_item setEnabled:1];
748 o_title = [o_title_item submenu];
749 pf_toggle_title = @selector(toggleTitle:);
751 /* Remove previous title menu */
752 i_nb_items = [o_title numberOfItems];
753 for( i = 0; i < i_nb_items; i++ )
755 [o_title removeItemAtIndex:0];
758 /* Create title menu */
759 for( i = 1 ; i < p_input->stream.i_area_nb ; i++ )
761 char psz_title[ 256 ];
762 NSString * o_menu_title;
765 snprintf( psz_title, sizeof(psz_title), "Title %d (%d)", i,
766 p_input->stream.pp_areas[i]->i_part_nb );
767 psz_title[sizeof(psz_title) - 1] = '\0';
769 o_menu_title = [NSString stringWithCString: psz_title];
771 o_item = [o_title addItemWithTitle: o_menu_title
772 action: pf_toggle_title keyEquivalent: @""];
774 [o_item setTarget: self];
775 if( ( p_input->stream.pp_areas[i] ==
776 p_input->stream.p_selected_area ) )
778 [o_item setState: 1];
782 vlc_mutex_unlock( &p_input->stream.stream_lock );
783 vlc_mutex_lock( &p_input->stream.stream_lock );
785 /* ----- CHAPTERS ----- */
786 if( p_input->stream.p_selected_area->i_part_nb < 2 )
788 [o_chapter_item setEnabled:0];
792 [o_chapter_item setEnabled:1];
793 o_chapter = [o_chapter_item submenu];
794 pf_toggle_chapter = @selector(toggleChapter:);
796 /* Remove previous chapter menu */
797 i_nb_items = [o_chapter numberOfItems];
798 for( i = 0; i < i_nb_items; i++ )
800 [o_chapter removeItemAtIndex:0];
803 /* Create chapter menu */
804 for( i = 0 ; i < p_input->stream.p_selected_area->i_part_nb ; i++ )
806 char psz_title[ 256 ];
807 NSString * o_menu_title;
810 snprintf( psz_title, sizeof(psz_title), "Chapter %d", i + 1 );
811 psz_title[sizeof(psz_title) - 1] = '\0';
813 o_menu_title = [NSString stringWithCString: psz_title];
815 o_item = [o_chapter addItemWithTitle: o_menu_title
816 action: pf_toggle_chapter keyEquivalent: @""];
818 [o_item setTarget: self];
819 if( ( p_input->stream.p_selected_area->i_part == i + 1 ) )
821 [o_item setState: 1];
825 p_main->p_intf->p_sys->i_part = p_input->stream.p_selected_area->i_part;
826 vlc_mutex_unlock( &p_input->stream.stream_lock );
827 vlc_mutex_lock( &p_input->stream.stream_lock );
829 /* ----- LANGUAGES & SUBTITLES ----- */
830 o_language = [o_language_item submenu];
831 o_subtitle = [o_subtitle_item submenu];
832 pf_toggle_language = @selector(toggleLanguage:);
833 pf_toggle_subtitle = @selector(toggleSubtitle:);
835 /* Remove previous language menu */
836 i_nb_items = [o_language numberOfItems];
837 for( i = 0; i < i_nb_items; i++ )
839 [o_language removeItemAtIndex:0];
842 /* Remove previous subtitle menu */
843 i_nb_items = [o_subtitle numberOfItems];
844 for( i = 0; i < i_nb_items; i++ )
846 [o_subtitle removeItemAtIndex:0];
849 /* Create language & subtitles menus */
850 for( i = 0 ; i < p_input->stream.i_es_number ; i++ )
852 es_descriptor_t * p_es = p_input->stream.pp_es[i];
853 if( p_es->p_pgrm != NULL
854 && p_es->p_pgrm != p_input->stream.p_selected_program )
859 if( p_es->i_cat == AUDIO_ES )
861 NSString * o_menu_title;
864 if( *p_es->psz_desc )
866 o_menu_title = [NSString stringWithCString: p_es->psz_desc];
870 char psz_title[ 256 ];
871 snprintf( psz_title, sizeof(psz_title), "Language 0x%x",
873 psz_title[sizeof(psz_title) - 1] = '\0';
875 o_menu_title = [NSString stringWithCString: psz_title];
878 o_item = [o_language addItemWithTitle: o_menu_title
879 action: pf_toggle_language keyEquivalent: @""];
881 [o_item setTarget: self];
882 if( p_es->p_decoder_fifo != NULL )
884 [o_item setState: 1];
887 else if( p_es->i_cat == SPU_ES )
889 NSString * o_menu_title;
892 if( *p_es->psz_desc )
894 o_menu_title = [NSString stringWithCString: p_es->psz_desc];
898 char psz_title[ 256 ];
899 snprintf( psz_title, sizeof(psz_title), "Subtitle 0x%x",
901 psz_title[sizeof(psz_title) - 1] = '\0';
903 o_menu_title = [NSString stringWithCString: psz_title];
906 o_item = [o_subtitle addItemWithTitle: o_menu_title
907 action: pf_toggle_subtitle keyEquivalent: @""];
909 [o_item setTarget: self];
910 if( p_es->p_decoder_fifo != NULL )
912 [o_item setState: 1];
917 if( [o_language numberOfItems] )
919 [o_language_item setEnabled: 1];
923 [o_language_item setEnabled: 0];
925 if( [o_subtitle numberOfItems] )
927 [o_subtitle_item setEnabled: 1];
931 [o_subtitle_item setEnabled: 0];
933 p_input->stream.b_changed = 0;
936 p_main->p_intf->p_sys->b_disabled_menus = 1;