From bf680e8fb64910e8d968addce71139d135a9b33f Mon Sep 17 00:00:00 2001 From: Derk-Jan Hartman Date: Mon, 5 Jul 2004 01:27:35 +0000 Subject: [PATCH] * OSX lowlevel work - The VLCApplication is now launched at the vlc.c level instead of at the module level. Allows VLC to be a more valid Mac application, also removes the vout intf dependancy (use ncurses to disp. video :). This wasn't done at the libvlc level, because a mozilla plugin would no longer be able to function properly. - Some functionality of the macosx vout may not work without the OS X GUI, and not all of this is checked yet. - There is a symlink in VLC.app/Contents/Mac called clivlc that will force it back to a fullblown cli app when you want, so it can still be run by a user who isn't logged in via GUI. - there are some autorelease leaks which need to be tackled. - moved a lot of the VLCApplication func. to the VLCMain class. - VLCMain is a +sharedInstance now. - the complete OS X interface is still badly broken because of the many API changes lately. any volunteers? Examples: VLC.app/Contents/MacOS/VLC [-I macosx] launches VLC as before (requires you to be logged in via GUI) VLC.app/Contents/MacOS/VLC -I ncurses launch vlc with a ncurses intf and display video on your mac (requires you to be logged in via GUI) VLC.app/Contents/MacOS/clivlc -I telnet -d launch vlm remotely trough ssh in daemon mode, on a GUI'less server for instance, and stream your vids Now how is that for combining GUI and cli in one application on the mac?!!? :) jlj? I finally understand now how the OS X interface works ! --- Makefile.am | 1 + TODO | 7 + configure.ac | 2 +- .../English.lproj/MainMenu.nib/info.nib | 6 +- .../English.lproj/MainMenu.nib/objects.nib | Bin 52299 -> 53103 bytes modules/gui/macosx/applescript.m | 4 +- modules/gui/macosx/controls.m | 46 +-- modules/gui/macosx/intf.h | 37 +- modules/gui/macosx/intf.m | 353 ++++++++---------- modules/gui/macosx/misc.m | 7 +- modules/gui/macosx/open.m | 4 +- modules/gui/macosx/output.m | 2 +- modules/gui/macosx/playlist.m | 38 +- modules/gui/macosx/playlistinfo.m | 34 +- modules/gui/macosx/prefs.m | 59 +-- modules/gui/macosx/vout.m | 27 +- src/interface/interface.c | 49 ++- src/vlc.c | 94 ++++- 18 files changed, 433 insertions(+), 337 deletions(-) diff --git a/Makefile.am b/Makefile.am index b138d674a7..79d2a61252 100644 --- a/Makefile.am +++ b/Makefile.am @@ -492,6 +492,7 @@ VLC.app: vlc $(INSTALL) -d $(top_builddir)/VLC.app/Contents/MacOS $(INSTALL) $(top_builddir)/vlc \ $(top_builddir)/VLC.app/Contents/MacOS/VLC + ln -sf ./VLC $(top_builddir)/VLC.app/Contents/MacOS/clivlc $(INSTALL) -d $(top_builddir)/VLC.app/Contents/MacOS/modules for i in "" `$(VLC_CONFIG) --target plugin` ; do \ if test -n "$$i" ; \ diff --git a/TODO b/TODO index a68e63f67f..1db3c5fb5a 100644 --- a/TODO +++ b/TODO @@ -183,6 +183,13 @@ Description: DVB info in NIT We need to get the information of a DVB stream that are in the NIT (current program, next program, ...) Status: Todo +Task +Difficulty: Medium +Urgency: Wishlist +Platform: any +Description: IceCast/ShoutCast serving +This would be a nice thing for the sake of completeness of VLC's streaming capabilities. +Status: Todo Task Difficulty: Hard diff --git a/configure.ac b/configure.ac index 57f2028994..d3f2901578 100644 --- a/configure.ac +++ b/configure.ac @@ -120,6 +120,7 @@ case "${target_os}" in OBJCFLAGS_save="${OBJCFLAGS_save} -no-cpp-precomp -D_INTL_REDIRECT_MACROS"; OBJCFLAGS="${OBJCFLAGS_save}" VLC_ADD_LDFLAGS([vlc ffmpeg],[-all_load]) VLC_ADD_LDFLAGS([mp4], [-framework IOKit -framework CoreFoundation]) + VLC_ADD_CFLAGS([vlc],[-x objective-c]) VLC_ADD_LDFLAGS([vlc],[-Wl,-multiply_defined,suppress]) ;; *mingw32* | *cygwin*) @@ -1237,7 +1238,6 @@ then ],[ if test -n "${enable_dvdread}" then - AC_MSG_WARN([Please get libdvdread from http://www.dtek.chalmers.se/groups/dvd/downloads.shtml]) AC_MSG_ERROR([cannot find libdvdread headers]) fi ]) diff --git a/extras/MacOSX/Resources/English.lproj/MainMenu.nib/info.nib b/extras/MacOSX/Resources/English.lproj/MainMenu.nib/info.nib index c3a05743c5..d281f309e7 100644 --- a/extras/MacOSX/Resources/English.lproj/MainMenu.nib/info.nib +++ b/extras/MacOSX/Resources/English.lproj/MainMenu.nib/info.nib @@ -21,12 +21,12 @@ IBOpenObjects - 29 - 1617 21 + 1617 1647 + 29 IBSystem Version - 7F44 + 7H63 diff --git a/extras/MacOSX/Resources/English.lproj/MainMenu.nib/objects.nib b/extras/MacOSX/Resources/English.lproj/MainMenu.nib/objects.nib index f19413d666edc2d6d426ac51c14b43f844b53cbc..fda4eaf3677532e51b7731206c844bd9663e42e7 100644 GIT binary patch literal 53103 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 LsM*8dRMr0nQhKsq literal 52299 zcmeIb33Ob=mH7RZey?R&UgQOc*_tH=vlwj55)X?v%;pVb95N7uEVXT6SuLcNZMMW$ zNFrpLj01`t7(y761QJ442qAz;f>{D&ATTULAYp(cgfQ7yh79)qcdOp(ey>}yMgHHM z^L^)hB<`nI%dK1Y-nw<`)~$M(k;RKU@-1D(&V17v@qgRv&g$*$9lfaGv^k5HUzl$$ z&TA?*iSw)8-kL=XHpS`NXp7A4?kX16*u*JU_jt>QKgP_TAU!@_)f_i4ra8u7k#wZaT-k~oiC-J5BhHEWhb;usRU zi%rYh@)6ukn`##qSLHjGwdU7#^-}_DqY|?_JDV=1QkG`TpI2}8H}-yUh6llxS`uWT0?{UUDPS3}8?AYP<0dVZ12HUr@@?C}Q&gT4-s|P3t)YH~9 zt;}m3#R}}_uF5yBUenaMy1&1#_bUTmC5OtIv#@o2zNMkqRLuAH_trOd6gtlC&=zMm zD zoKu`me%tvwPkndAs9v|(xz)YZxi!<@*9Uk--pBylO`s3k4ErsbaA5>wq{Yrc+Z5Bh zGK{}QE^2_T9fkIme5V87@7UP4+3BrQJXb{j_1>^KRDqz=4b9YV)2iaUbjQX!H}{O& z;5gr-M4%;*qPcCY9hyJ$j*WM1?s2x-Tvv0EjJa)1U0n_9nmRi2orkE99-!P?wqWj( zwx)~QTDyu`6)6I%r7C3ldcy4+@7e5puaEy6N8I0uyDWZgyoavyKjgEyd6wfkeZ3MKd=nj1aC_acvG?9IZudjUK38Ga8_4w=?*i)m`mZ;bHLJO~8A!<6 z+(KIcBHbGH`m_S(VZ+5;NRf)*Zq1gsbDEl0uk0*zx3`$m{k;$0>i2ppR$Ot?A-8

V>gX8f!6y0{yTcqeMmu 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 diff --git a/modules/gui/macosx/applescript.m b/modules/gui/macosx/applescript.m index 5cade7ae5c..af3fbba641 100644 --- a/modules/gui/macosx/applescript.m +++ b/modules/gui/macosx/applescript.m @@ -41,7 +41,7 @@ if ( [o_command isEqualToString:@"GetURL"] || [o_command isEqualToString:@"OpenURL"] ) { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if( p_playlist == NULL ) @@ -84,7 +84,7 @@ - (id)performDefaultImplementation { NSString *o_command = [[self commandDescription] commandName]; - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if( p_playlist == NULL ) diff --git a/modules/gui/macosx/controls.m b/modules/gui/macosx/controls.m index b355a43294..fa0e67b8e9 100644 --- a/modules/gui/macosx/controls.m +++ b/modules/gui/macosx/controls.m @@ -45,7 +45,7 @@ { vlc_value_t val; playlist_t * p_playlist; - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; input_thread_t * p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE ); @@ -87,7 +87,7 @@ - (IBAction)stop:(id)sender { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if( p_playlist != NULL ) @@ -100,7 +100,7 @@ - (IBAction)faster:(id)sender { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; input_thread_t * p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE ); if( p_input != NULL ) @@ -115,7 +115,7 @@ - (IBAction)slower:(id)sender { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; input_thread_t * p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE ); if( p_input != NULL ) @@ -130,7 +130,7 @@ - (IBAction)prev:(id)sender { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if( p_playlist ) @@ -143,7 +143,7 @@ - (IBAction)next:(id)sender { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if( p_playlist ) @@ -156,7 +156,7 @@ - (IBAction)random:(id)sender { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; vlc_value_t val; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); @@ -184,7 +184,7 @@ - (IBAction)repeat:(id)sender { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; vlc_value_t val; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); @@ -216,7 +216,7 @@ - (IBAction)loop:(id)sender { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; vlc_value_t val; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); @@ -248,7 +248,7 @@ - (IBAction)forward:(id)sender { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; input_thread_t * p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE ); if( p_input != NULL ) @@ -263,7 +263,7 @@ - (IBAction)backward:(id)sender { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; input_thread_t * p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE ); if( p_input != NULL ) @@ -279,7 +279,7 @@ - (IBAction)volumeUp:(id)sender { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; if( p_intf->p_sys->b_mute ) { @@ -293,7 +293,7 @@ - (IBAction)volumeDown:(id)sender { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; if( p_intf->p_sys->b_mute ) { @@ -307,7 +307,7 @@ - (IBAction)mute:(id)sender { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; audio_volume_t i_volume; aout_VolumeMute( p_intf, &i_volume ); @@ -318,7 +318,7 @@ - (IBAction)volumeSliderUpdated:(id)sender { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; audio_volume_t i_volume = (audio_volume_t)[sender intValue]; aout_VolumeSet( p_intf, i_volume * AOUT_VOLUME_STEP ); @@ -326,7 +326,7 @@ - (void)updateVolumeSlider { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; audio_volume_t i_volume; aout_VolumeGet( p_intf, &i_volume ); @@ -343,7 +343,7 @@ NSString *o_title = [sender title]; NSArray *o_windows = [NSApp orderedWindows]; NSEnumerator *o_enumerator = [o_windows objectEnumerator]; - vout_thread_t *p_vout = vlc_object_find( [NSApp getIntf], VLC_OBJECT_VOUT, + vout_thread_t *p_vout = vlc_object_find( VLCIntf, VLC_OBJECT_VOUT, FIND_ANYWHERE ); if( p_vout != NULL ) @@ -408,7 +408,7 @@ /* Get the descriptive name of the variable */ var_Change( p_object, psz_variable, VLC_VAR_GETTEXT, &text, NULL ); - [o_mi setTitle: [NSApp localizedString: text.psz_string ? + [o_mi setTitle: [[VLCMain sharedInstance] localizedString: text.psz_string ? text.psz_string : strdup( psz_variable ) ]]; var_Get( p_object, psz_variable, &val ); @@ -523,7 +523,7 @@ another_val.psz_string = strdup(val_list.p_list->p_values[i].psz_string); - o_title = [NSApp localizedString: text_list.p_list->p_values[i].psz_string ? + o_title = [[VLCMain sharedInstance] localizedString: text_list.p_list->p_values[i].psz_string ? text_list.p_list->p_values[i].psz_string : val_list.p_list->p_values[i].psz_string ]; o_lmi = [o_menu addItemWithTitle: o_title action: pf_callback keyEquivalent: @""]; @@ -540,7 +540,7 @@ case VLC_VAR_INTEGER: o_title = text_list.p_list->p_values[i].psz_string ? - [NSApp localizedString: strdup( text_list.p_list->p_values[i].psz_string )] : + [[VLCMain sharedInstance] localizedString: strdup( text_list.p_list->p_values[i].psz_string )] : [NSString stringWithFormat: @"%d", val_list.p_list->p_values[i].i_int]; @@ -580,9 +580,9 @@ NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init]; VLCMenuExt *o_data = (VLCMenuExt *)_o_data; - vlc_thread_set_priority( [NSApp getIntf] , VLC_THREAD_PRIORITY_LOW ); + vlc_thread_set_priority( VLCIntf , VLC_THREAD_PRIORITY_LOW ); - p_object = (vlc_object_t *)vlc_object_get( [NSApp getIntf], + p_object = (vlc_object_t *)vlc_object_get( VLCIntf, [o_data objectID] ); if( p_object != NULL ) @@ -604,7 +604,7 @@ { BOOL bEnabled = TRUE; vlc_value_t val; - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); diff --git a/modules/gui/macosx/intf.h b/modules/gui/macosx/intf.h index c57ef7661f..f5890b4838 100644 --- a/modules/gui/macosx/intf.h +++ b/modules/gui/macosx/intf.h @@ -31,33 +31,18 @@ #include /***************************************************************************** - * VLCApplication interface + * Local prototypes. *****************************************************************************/ -@interface VLCApplication : NSApplication -{ - intf_thread_t *p_intf; -} - -- (NSString *)localizedString:(char *)psz; -- (char *)delocalizeString:(NSString *)psz; -- (NSString *)wrapString: (NSString *)o_in_string toWidth: (int)i_width; - -- (void)setIntf:(intf_thread_t *)p_intf; -- (intf_thread_t *)getIntf; -- (BOOL)hasDefinedShortcutKey:(NSEvent *)o_event; +int ExecuteOnMainThread( id target, SEL sel, void * p_arg ); +unsigned int CocoaKeyToVLC( unichar i_key ); -@end +#define VLCIntf [[VLCMain sharedInstance] getIntf] -#define _NS(s) [NSApp localizedString: _(s)] +#define _NS(s) [[VLCMain sharedInstance] localizedString: _(s)] /* Get an alternate version of the string. * This string is stored as '1:string' but when displayed it only displays * the translated string. the translation should be '1:translatedstring' though */ -#define _ANS(s) [[NSApp localizedString: _(s)] substringFromIndex:2] - -int ExecuteOnMainThread( id target, SEL sel, void * p_arg ); -int PlaylistChanged( vlc_object_t *p_this, const char *psz_variable, - vlc_value_t old_val, vlc_value_t new_val, void *param ); -unsigned int CocoaKeyToVLC( unichar i_key ); +#define _ANS(s) [[[VLCMain sharedInstance] localizedString: _(s)] substringFromIndex:2] /***************************************************************************** * intf_sys_t: description and status of the interface @@ -92,6 +77,7 @@ struct intf_sys_t *****************************************************************************/ @interface VLCMain : NSObject { + intf_thread_t *p_intf; /* The main intf object */ id o_prefs; /* VLCPrefs */ IBOutlet id o_window; /* main window */ @@ -238,10 +224,19 @@ struct intf_sys_t IBOutlet id o_dmi_mute; } ++ (VLCMain *)sharedInstance; + +- (intf_thread_t *)getIntf; +- (void)setIntf:(intf_thread_t *)p_mainintf; + - (id)getControls; - (id)getPlaylist; - (id)getInfo; - (void)terminate; +- (NSString *)localizedString:(char *)psz; +- (char *)delocalizeString:(NSString *)psz; +- (NSString *)wrapString: (NSString *)o_in_string toWidth: (int)i_width; +- (BOOL)hasDefinedShortcutKey:(NSEvent *)o_event; - (void)initStrings; diff --git a/modules/gui/macosx/intf.m b/modules/gui/macosx/intf.m index 8a1f567abf..377d5f8a5f 100644 --- a/modules/gui/macosx/intf.m +++ b/modules/gui/macosx/intf.m @@ -70,10 +70,7 @@ int E_(OpenIntf) ( vlc_object_t *p_this ) p_intf->b_play = VLC_TRUE; p_intf->pf_run = Run; - [VLCApplication sharedApplication]; - [NSApp setIntf: p_intf]; - - [NSBundle loadNibNamed: @"MainMenu" owner: NSApp]; + [[VLCMain sharedInstance] setIntf: p_intf]; return( 0 ); } @@ -102,162 +99,9 @@ static void Run( intf_thread_t *p_intf ) * fails to go to real-time priority with the first launched thread * (???) --Meuuh */ vlc_thread_set_priority( p_intf, VLC_THREAD_PRIORITY_LOW ); - - [NSApp run]; -} - -/***************************************************************************** - * VLCApplication implementation - *****************************************************************************/ -@implementation VLCApplication - -- (NSString *)localizedString:(char *)psz -{ - NSString * o_str = nil; - - if( psz != NULL ) - { - o_str = [[[NSString alloc] initWithUTF8String: psz] autorelease]; - } - if ( o_str == NULL ) - { - msg_Err( p_intf, "could not translate: %s", psz ); - } - - return( o_str ); -} - -- (char *)delocalizeString:(NSString *)id -{ - NSData * o_data = [id dataUsingEncoding: NSUTF8StringEncoding - allowLossyConversion: NO]; - char * psz_string; - - if ( o_data == nil ) - { - o_data = [id dataUsingEncoding: NSUTF8StringEncoding - allowLossyConversion: YES]; - psz_string = malloc( [o_data length] + 1 ); - [o_data getBytes: psz_string]; - psz_string[ [o_data length] ] = '\0'; - msg_Err( p_intf, "cannot convert to wanted encoding: %s", - psz_string ); - } - else - { - psz_string = malloc( [o_data length] + 1 ); - [o_data getBytes: psz_string]; - psz_string[ [o_data length] ] = '\0'; - } - - return psz_string; -} - -/* i_width is in pixels */ -- (NSString *)wrapString: (NSString *)o_in_string toWidth: (int) i_width -{ - NSMutableString *o_wrapped; - NSString *o_out_string; - NSRange glyphRange, effectiveRange, charRange; - NSRect lineFragmentRect; - unsigned glyphIndex, breaksInserted = 0; - - NSTextStorage *o_storage = [[NSTextStorage alloc] initWithString: o_in_string - attributes: [NSDictionary dictionaryWithObjectsAndKeys: - [NSFont labelFontOfSize: 0.0], NSFontAttributeName, nil]]; - NSLayoutManager *o_layout_manager = [[NSLayoutManager alloc] init]; - NSTextContainer *o_container = [[NSTextContainer alloc] - initWithContainerSize: NSMakeSize(i_width, 2000)]; - - [o_layout_manager addTextContainer: o_container]; - [o_container release]; - [o_storage addLayoutManager: o_layout_manager]; - [o_layout_manager release]; - - o_wrapped = [o_in_string mutableCopy]; - glyphRange = [o_layout_manager glyphRangeForTextContainer: o_container]; - - for( glyphIndex = glyphRange.location ; glyphIndex < NSMaxRange(glyphRange) ; - glyphIndex += effectiveRange.length) { - lineFragmentRect = [o_layout_manager lineFragmentRectForGlyphAtIndex: glyphIndex - effectiveRange: &effectiveRange]; - charRange = [o_layout_manager characterRangeForGlyphRange: effectiveRange - actualGlyphRange: &effectiveRange]; - if ([o_wrapped lineRangeForRange: - NSMakeRange(charRange.location + breaksInserted, charRange.length)].length > charRange.length) { - [o_wrapped insertString: @"\n" atIndex: NSMaxRange(charRange) + breaksInserted]; - breaksInserted++; - } - } - o_out_string = [NSString stringWithString: o_wrapped]; - [o_wrapped release]; - [o_storage release]; - - return o_out_string; -} - -- (void)setIntf:(intf_thread_t *)_p_intf -{ - p_intf = _p_intf; -} - -- (intf_thread_t *)getIntf -{ - return( p_intf ); -} - -- (void)terminate:(id)sender -{ - p_intf->p_vlc->b_die = VLC_TRUE; - [super terminate:sender]; -} - - -/***************************************************************************** - * hasDefinedShortcutKey: Check to see if the key press is a defined VLC - * shortcut key. If it is, pass it off to VLC for handling and return YES, - * otherwise ignore it and return NO (where it will get handled by Cocoa). - *****************************************************************************/ -- (BOOL)hasDefinedShortcutKey:(NSEvent *)o_event -{ - unichar key = 0; - vlc_value_t val; - unsigned int i_pressed_modifiers = 0; - struct hotkey *p_hotkeys; - int i; - - val.i_int = 0; - p_hotkeys = p_intf->p_vlc->p_hotkeys; - - i_pressed_modifiers = [o_event modifierFlags]; - - if( i_pressed_modifiers & NSShiftKeyMask ) - val.i_int |= KEY_MODIFIER_SHIFT; - if( i_pressed_modifiers & NSControlKeyMask ) - val.i_int |= KEY_MODIFIER_CTRL; - if( i_pressed_modifiers & NSAlternateKeyMask ) - val.i_int |= KEY_MODIFIER_ALT; - if( i_pressed_modifiers & NSCommandKeyMask ) - val.i_int |= KEY_MODIFIER_COMMAND; - - key = [[o_event charactersIgnoringModifiers] characterAtIndex: 0]; - - val.i_int |= CocoaKeyToVLC( key ); - - for( i = 0; p_hotkeys[i].psz_action != NULL; i++ ) - { - if( p_hotkeys[i].i_key == val.i_int ) - { - var_Set( p_intf->p_vlc, "key-pressed", val ); - return YES; - } - } - - return NO; + [NSBundle loadNibNamed: @"MainMenu" owner: NSApp]; } -@end - int ExecuteOnMainThread( id target, SEL sel, void * p_arg ) { int i_ret = 0; @@ -271,7 +115,7 @@ int ExecuteOnMainThread( id target, SEL sel, void * p_arg ) withObject: [NSValue valueWithPointer: p_arg] waitUntilDone: YES]; } - else if( NSApp != nil && [NSApp respondsToSelector: @selector(getIntf)] ) + else if( NSApp != nil && [[VLCMain sharedInstance] respondsToSelector: @selector(getIntf)] ) { NSValue * o_v1; NSValue * o_v2; @@ -285,7 +129,7 @@ int ExecuteOnMainThread( id target, SEL sel, void * p_arg ) id * val[] = { &o_lock, &o_v2 }; - p_intf = (intf_thread_t *)[NSApp getIntf]; + p_intf = (intf_thread_t *)VLCIntf; o_recv_port = [[NSPort port] retain]; o_v1 = [NSValue valueWithPointer: val]; @@ -329,7 +173,7 @@ int ExecuteOnMainThread( id target, SEL sel, void * p_arg ) int PlaylistChanged( vlc_object_t *p_this, const char *psz_variable, vlc_value_t old_val, vlc_value_t new_val, void *param ) { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; p_intf->p_sys->b_playlist_update = TRUE; p_intf->p_sys->b_intf_update = TRUE; return VLC_SUCCESS; @@ -417,10 +261,36 @@ unsigned int VLCModifiersToCocoa( unsigned int i_key ) *****************************************************************************/ @implementation VLCMain +static VLCMain *_o_sharedMainInstance = nil; + ++ (VLCMain *)sharedInstance +{ + return _o_sharedMainInstance ? _o_sharedMainInstance : [[self alloc] init]; +} + +- (id)init +{ + if (_o_sharedMainInstance) { + [self dealloc]; + } else { + _o_sharedMainInstance = [super init]; + } + + return _o_sharedMainInstance; +} + +- (void)setIntf: (intf_thread_t *)p_mainintf { + p_intf = p_mainintf; +} + +- (intf_thread_t *)getIntf { + return p_intf; +} + - (void)awakeFromNib { unsigned int i_key = 0; - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t *p_playlist; vlc_value_t val; @@ -632,8 +502,6 @@ unsigned int VLCModifiersToCocoa( unsigned int i_key ) - (void)applicationWillFinishLaunching:(NSNotification *)o_notification { - intf_thread_t * p_intf = [NSApp getIntf]; - o_msg_lock = [[NSLock alloc] init]; o_msg_arr = [[NSMutableArray arrayWithCapacity: 200] retain]; @@ -659,7 +527,7 @@ unsigned int VLCModifiersToCocoa( unsigned int i_key ) vlc_thread_set_priority( p_intf, VLC_THREAD_PRIORITY_LOW ); } - +/* - (BOOL)application:(NSApplication *)o_app openFile:(NSString *)o_filename { NSDictionary *o_dic = [NSDictionary dictionaryWithObjectsAndKeys: o_filename, @"ITEM_URL", nil]; @@ -668,6 +536,135 @@ unsigned int VLCModifiersToCocoa( unsigned int i_key ) return( TRUE ); } +*/ +- (NSString *)localizedString:(char *)psz +{ + NSString * o_str = nil; + + if( psz != NULL ) + { + o_str = [[[NSString alloc] initWithUTF8String: psz] autorelease]; + } + if ( o_str == NULL ) + { + msg_Err( VLCIntf, "could not translate: %s", psz ); + } + + return( o_str ); +} + +- (char *)delocalizeString:(NSString *)id +{ + NSData * o_data = [id dataUsingEncoding: NSUTF8StringEncoding + allowLossyConversion: NO]; + char * psz_string; + + if ( o_data == nil ) + { + o_data = [id dataUsingEncoding: NSUTF8StringEncoding + allowLossyConversion: YES]; + psz_string = malloc( [o_data length] + 1 ); + [o_data getBytes: psz_string]; + psz_string[ [o_data length] ] = '\0'; + msg_Err( VLCIntf, "cannot convert to wanted encoding: %s", + psz_string ); + } + else + { + psz_string = malloc( [o_data length] + 1 ); + [o_data getBytes: psz_string]; + psz_string[ [o_data length] ] = '\0'; + } + + return psz_string; +} + +/* i_width is in pixels */ +- (NSString *)wrapString: (NSString *)o_in_string toWidth: (int) i_width +{ + NSMutableString *o_wrapped; + NSString *o_out_string; + NSRange glyphRange, effectiveRange, charRange; + NSRect lineFragmentRect; + unsigned glyphIndex, breaksInserted = 0; + + NSTextStorage *o_storage = [[NSTextStorage alloc] initWithString: o_in_string + attributes: [NSDictionary dictionaryWithObjectsAndKeys: + [NSFont labelFontOfSize: 0.0], NSFontAttributeName, nil]]; + NSLayoutManager *o_layout_manager = [[NSLayoutManager alloc] init]; + NSTextContainer *o_container = [[NSTextContainer alloc] + initWithContainerSize: NSMakeSize(i_width, 2000)]; + + [o_layout_manager addTextContainer: o_container]; + [o_container release]; + [o_storage addLayoutManager: o_layout_manager]; + [o_layout_manager release]; + + o_wrapped = [o_in_string mutableCopy]; + glyphRange = [o_layout_manager glyphRangeForTextContainer: o_container]; + + for( glyphIndex = glyphRange.location ; glyphIndex < NSMaxRange(glyphRange) ; + glyphIndex += effectiveRange.length) { + lineFragmentRect = [o_layout_manager lineFragmentRectForGlyphAtIndex: glyphIndex + effectiveRange: &effectiveRange]; + charRange = [o_layout_manager characterRangeForGlyphRange: effectiveRange + actualGlyphRange: &effectiveRange]; + if ([o_wrapped lineRangeForRange: + NSMakeRange(charRange.location + breaksInserted, charRange.length)].length > charRange.length) { + [o_wrapped insertString: @"\n" atIndex: NSMaxRange(charRange) + breaksInserted]; + breaksInserted++; + } + } + o_out_string = [NSString stringWithString: o_wrapped]; + [o_wrapped release]; + [o_storage release]; + + return o_out_string; +} + + +/***************************************************************************** + * hasDefinedShortcutKey: Check to see if the key press is a defined VLC + * shortcut key. If it is, pass it off to VLC for handling and return YES, + * otherwise ignore it and return NO (where it will get handled by Cocoa). + *****************************************************************************/ +- (BOOL)hasDefinedShortcutKey:(NSEvent *)o_event +{ + unichar key = 0; + vlc_value_t val; + unsigned int i_pressed_modifiers = 0; + struct hotkey *p_hotkeys; + int i; + + val.i_int = 0; + p_hotkeys = VLCIntf->p_vlc->p_hotkeys; + + i_pressed_modifiers = [o_event modifierFlags]; + + if( i_pressed_modifiers & NSShiftKeyMask ) + val.i_int |= KEY_MODIFIER_SHIFT; + if( i_pressed_modifiers & NSControlKeyMask ) + val.i_int |= KEY_MODIFIER_CTRL; + if( i_pressed_modifiers & NSAlternateKeyMask ) + val.i_int |= KEY_MODIFIER_ALT; + if( i_pressed_modifiers & NSCommandKeyMask ) + val.i_int |= KEY_MODIFIER_COMMAND; + + key = [[o_event charactersIgnoringModifiers] characterAtIndex: 0]; + + val.i_int |= CocoaKeyToVLC( key ); + + for( i = 0; p_hotkeys[i].psz_action != NULL; i++ ) + { + if( p_hotkeys[i].i_key == val.i_int ) + { + var_Set( VLCIntf->p_vlc, "key-pressed", val ); + return YES; + } + } + + return NO; +} - (id)getControls { @@ -699,7 +696,6 @@ unsigned int VLCModifiersToCocoa( unsigned int i_key ) - (void)manage { NSDate * o_sleep_date; - intf_thread_t * p_intf = [NSApp getIntf]; NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init]; vlc_thread_set_priority( p_intf, VLC_THREAD_PRIORITY_LOW ); @@ -769,8 +765,6 @@ unsigned int VLCModifiersToCocoa( unsigned int i_key ) - (void)manageIntf:(NSTimer *)o_timer { - intf_thread_t * p_intf = [NSApp getIntf]; - if( p_intf->p_vlc->b_die == VLC_TRUE ) { [o_timer invalidate]; @@ -950,7 +944,6 @@ unsigned int VLCModifiersToCocoa( unsigned int i_key ) - (void)setupMenus { - intf_thread_t * p_intf = [NSApp getIntf]; playlist_t *p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); @@ -1013,7 +1006,6 @@ unsigned int VLCModifiersToCocoa( unsigned int i_key ) - (void)updateMessageArray { int i_start, i_stop; - intf_thread_t * p_intf = [NSApp getIntf]; vlc_value_t quiet; vlc_mutex_lock( p_intf->p_sys->p_sub->p_lock ); @@ -1131,7 +1123,6 @@ unsigned int VLCModifiersToCocoa( unsigned int i_key ) - (void)manageVolumeSlider { audio_volume_t i_volume; - intf_thread_t * p_intf = [NSApp getIntf]; aout_VolumeGet( p_intf, &i_volume ); @@ -1159,7 +1150,6 @@ unsigned int VLCModifiersToCocoa( unsigned int i_key ) return; } - p_intf = [NSApp getIntf]; p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE ); @@ -1194,10 +1184,8 @@ unsigned int VLCModifiersToCocoa( unsigned int i_key ) - (void)terminate { - NSEvent * o_event; playlist_t * p_playlist; vout_thread_t * p_vout; - intf_thread_t * p_intf = [NSApp getIntf]; /* Stop playback */ if( ( p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, @@ -1257,19 +1245,11 @@ unsigned int VLCModifiersToCocoa( unsigned int i_key ) o_msg_lock = nil; } - [NSApp stop: nil]; - [NSApp terminate: nil]; - /* write cached user defaults to disk */ [[NSUserDefaults standardUserDefaults] synchronize]; - - /* send a dummy event to break out of the event loop */ - o_event = [NSEvent mouseEventWithType: NSLeftMouseDown - location: NSMakePoint( 1, 1 ) modifierFlags: 0 - timestamp: 1 windowNumber: [[NSApp mainWindow] windowNumber] - context: [NSGraphicsContext currentContext] eventNumber: 1 - clickCount: 1 pressure: 0.0]; - [NSApp postEvent: o_event atStart: YES]; + + p_intf->b_die = VLC_TRUE; + [NSApp stop:NULL]; } - (IBAction)clearRecentItems:(id)sender @@ -1291,8 +1271,7 @@ unsigned int VLCModifiersToCocoa( unsigned int i_key ) - (IBAction)closeError:(id)sender { vlc_value_t val; - intf_thread_t * p_intf = [NSApp getIntf]; - + if( [o_err_ckbk_surpress state] == NSOnState ) { val.i_int = -1; diff --git a/modules/gui/macosx/misc.m b/modules/gui/macosx/misc.m index 276370d6fc..7bcfbc4125 100644 --- a/modules/gui/macosx/misc.m +++ b/modules/gui/macosx/misc.m @@ -44,8 +44,7 @@ - (BOOL)performKeyEquivalent:(NSEvent *)o_event { - return [( (VLCApplication *) [VLCApplication sharedApplication] ) - hasDefinedShortcutKey:o_event]; + return [[VLCMain sharedInstance] hasDefinedShortcutKey:o_event]; } @end @@ -110,7 +109,7 @@ o_dic = [NSDictionary dictionaryWithObject:[o_values objectAtIndex:i] forKey:@"ITEM_URL"]; o_array = [o_array arrayByAddingObject: o_dic]; } - [(VLCPlaylist *)[[NSApp delegate] getPlaylist] appendArray: o_array atPos: -1 enqueue:NO]; + [(VLCPlaylist *)[[VLCMain sharedInstance] getPlaylist] appendArray: o_array atPos: -1 enqueue:NO]; return YES; } } @@ -188,7 +187,7 @@ o_dic = [NSDictionary dictionaryWithObject:[o_values objectAtIndex:i] forKey:@"ITEM_URL"]; o_array = [o_array arrayByAddingObject: o_dic]; } - [(VLCPlaylist *)[[NSApp delegate] getPlaylist] appendArray: o_array atPos: -1 enqueue:NO]; + [[[VLCMain sharedInstance] getPlaylist] appendArray: o_array atPos: -1 enqueue:NO]; return YES; } } diff --git a/modules/gui/macosx/open.m b/modules/gui/macosx/open.m index 0f393197e9..69faebb0d6 100644 --- a/modules/gui/macosx/open.m +++ b/modules/gui/macosx/open.m @@ -130,7 +130,7 @@ NSArray *GetEjectableMediaOfClass( const char *psz_class ) - (void)awakeFromNib { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; [o_panel setTitle: _NS("Open Source")]; [o_mrl_lbl setTitle: _NS("Media Resource Locator (MRL)")]; @@ -573,7 +573,7 @@ NSArray *GetEjectableMediaOfClass( const char *psz_class ) { NSString *o_mode; NSString *o_mrl_string = [NSString string]; - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; o_mode = [[o_net_mode selectedCell] title]; diff --git a/modules/gui/macosx/output.m b/modules/gui/macosx/output.m index 0aa917ef1e..c3214deaef 100644 --- a/modules/gui/macosx/output.m +++ b/modules/gui/macosx/output.m @@ -397,7 +397,7 @@ - (void)TTLChanged:(NSNotification *)o_notification { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; config_PutInt( p_intf, "ttl", [o_stream_ttl intValue] ); } diff --git a/modules/gui/macosx/playlist.m b/modules/gui/macosx/playlist.m index fb73965d8c..984b18731d 100644 --- a/modules/gui/macosx/playlist.m +++ b/modules/gui/macosx/playlist.m @@ -56,7 +56,7 @@ NSNumber *o_number; playlist_t * p_playlist; - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; if( [[o_event characters] length] ) { @@ -191,7 +191,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ - (void) tableView:(NSTableView*)o_tv didClickTableColumn:(NSTableColumn *)o_tc { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t *p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); @@ -264,7 +264,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ - (NSMenu *)menuForEvent:(NSEvent *)o_event { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); @@ -316,7 +316,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ - (IBAction)savePlaylist:(id)sender { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); @@ -335,7 +335,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ - (IBAction)playItem:(id)sender { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); @@ -352,7 +352,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ NSMutableArray *o_to_delete; NSNumber *o_number; - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); @@ -392,7 +392,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ NSMutableArray *o_selected; NSNumber *o_number; - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); @@ -434,7 +434,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ - (IBAction)enableGroup:(id)sender { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); @@ -448,7 +448,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ - (IBAction)disableGroup:(id)sender { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); @@ -472,7 +472,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ NSString *o_current_name; NSString *o_current_author; - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); @@ -528,7 +528,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ - (IBAction)handlePopUp:(id)sender { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; vlc_value_t val1,val2; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); @@ -576,7 +576,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ - (void)appendArray:(NSArray*)o_array atPos:(int)i_position enqueue:(BOOL)b_enqueue { int i_item; - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); @@ -667,7 +667,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ - (void)playlistUpdated { vlc_value_t val1, val2; - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if( p_playlist != NULL ) @@ -698,7 +698,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ { int i_row; - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); @@ -728,7 +728,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ - (void)deleteGroup:(int)i_id { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); int i; @@ -833,7 +833,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ - (int)numberOfRowsInTableView:(NSTableView *)o_tv { int i_count = 0; - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); @@ -853,7 +853,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ row:(int)i_row { id o_value = nil; - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); @@ -922,7 +922,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ forTableColumn:(NSTableColumn *)o_tc row:(int)i_rows { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if (p_playlist) @@ -998,7 +998,7 @@ belongs to an Apple hidden private API, and then can "disapear" at any time*/ { if (i_moveRow != -1 && i_proposed_row != -1) { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); diff --git a/modules/gui/macosx/playlistinfo.m b/modules/gui/macosx/playlistinfo.m index 86f0c038c6..04b6b210d8 100644 --- a/modules/gui/macosx/playlistinfo.m +++ b/modules/gui/macosx/playlistinfo.m @@ -76,8 +76,8 @@ } else { - i_item = [[[NSApp delegate] getPlaylist] selectedPlaylistItem]; - o_selected = [[[NSApp delegate] getPlaylist] selectedPlaylistItemsList]; + i_item = [[[VLCMain sharedInstance] getPlaylist] selectedPlaylistItem]; + o_selected = [[[VLCMain sharedInstance] getPlaylist] selectedPlaylistItemsList]; [o_selected retain]; [self initPanel:sender]; } @@ -91,7 +91,7 @@ } else { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); @@ -109,7 +109,7 @@ - (void)initPanel:(id)sender { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist; p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, @@ -161,7 +161,7 @@ - (IBAction)infoOk:(id)sender { int i,i_row,c; - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); vlc_value_t val; @@ -219,7 +219,7 @@ - (IBAction)handleGroup:(id)sender { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); @@ -228,13 +228,13 @@ if ([[o_group_cbx stringValue] isEqual: [o_group_cbx objectValueOfSelectedItem]]) { - [o_group_color setBackgroundColor:[[[NSApp delegate] getPlaylist] + [o_group_color setBackgroundColor:[[[VLCMain sharedInstance] getPlaylist] getColor: p_playlist->pp_groups[ [o_group_cbx indexOfSelectedItem]]->i_id]]; } else { - [o_group_color setBackgroundColor:[[[NSApp delegate] getPlaylist] + [o_group_color setBackgroundColor:[[[VLCMain sharedInstance] getPlaylist] getColor:p_playlist->pp_groups[ [o_group_cbx numberOfItems] - 1]->i_id + 1]]; } @@ -244,7 +244,7 @@ - (IBAction)deleteOutlineGroup:(id)sender { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); @@ -253,7 +253,7 @@ if ([[o_group_cbx stringValue] isEqual: [o_group_cbx objectValueOfSelectedItem]]) { - [[[NSApp delegate] getPlaylist] deleteGroup:p_playlist->pp_groups[ + [[[VLCMain sharedInstance] getPlaylist] deleteGroup:p_playlist->pp_groups[ [o_group_cbx indexOfSelectedItem]]->i_id]; [self createComboBox]; [self handleGroup:self]; @@ -269,7 +269,7 @@ - (IBAction)createOutlineGroup:(id)sender; { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); if(p_playlist) @@ -278,14 +278,14 @@ strdup([[o_group_cbx stringValue] cString])); [self createComboBox]; [o_group_cbx reloadData]; - [[[NSApp delegate] getPlaylist] playlistUpdated]; + [[[VLCMain sharedInstance] getPlaylist] playlistUpdated]; vlc_object_release(p_playlist); } } -(void)createComboBox { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); int i; @@ -322,7 +322,7 @@ { BOOL bEnabled = TRUE; - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; input_thread_t * p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE ); @@ -387,7 +387,7 @@ static VLCInfoTreeItem *o_root_item = nil; o_value = [o_item_value copy]; i_object_id = i_id; o_parent = o_parent_item; - i_item = [[[NSApp delegate] getInfo] getItem]; + i_item = [[[VLCMain sharedInstance] getInfo] getItem]; } return( self ); } @@ -410,7 +410,7 @@ static VLCInfoTreeItem *o_root_item = nil; { if (o_children == NULL) { - intf_thread_t * p_intf = [NSApp getIntf]; + intf_thread_t * p_intf = VLCIntf; playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); int i; @@ -491,7 +491,7 @@ static VLCInfoTreeItem *o_root_item = nil; */ - (void)refresh { - i_item = [[[NSApp delegate] getInfo] getItem]; + i_item = [[[VLCMain sharedInstance] getInfo] getItem]; if (o_children != NULL) { [o_children release]; diff --git a/modules/gui/macosx/prefs.m b/modules/gui/macosx/prefs.m index a6c53b1f68..34b46c6586 100644 --- a/modules/gui/macosx/prefs.m +++ b/modules/gui/macosx/prefs.m @@ -60,7 +60,7 @@ - (void)awakeFromNib { - p_intf = [NSApp getIntf]; + p_intf = VLCIntf; b_advanced = config_GetInt( p_intf, "advanced" ); [self initStrings]; @@ -338,7 +338,7 @@ if ( label ) \ { \ [o_text_field setStringValue: \ - [NSApp localizedString: label]]; \ + [[VLCMain sharedInstance] localizedString: label]]; \ } \ [o_text_field sizeToFit]; \ [o_view addSubview: [o_text_field autorelease]]; \ @@ -359,7 +359,7 @@ [o_text_field msg: param]; \ if ( psz_duptip != NULL ) \ { \ - [o_text_field setToolTip: [NSApp wrapString: [NSApp localizedString: \ + [o_text_field setToolTip: [[VLCMain sharedInstance] wrapString: [[VLCMain sharedInstance] localizedString: \ psz_duptip] toWidth: PREFS_WRAP ]]; \ free(psz_duptip);\ } \ @@ -393,7 +393,7 @@ if( p_item->i_type == CONFIG_HINT_CATEGORY ) { if( !strcmp( p_parser->psz_object_name, "main" ) && - [o_item_name isEqualToString: [NSApp localizedString: p_item->psz_text]] ) + [o_item_name isEqualToString: [[VLCMain sharedInstance] localizedString: p_item->psz_text]] ) { b_right_cat = TRUE; } else if( strcmp( p_parser->psz_object_name, "main" ) ) @@ -435,7 +435,7 @@ if ( psz_duptip != NULL ) { - [o_modules setToolTip: [NSApp wrapString: [NSApp localizedString: psz_duptip] toWidth: PREFS_WRAP]]; + [o_modules setToolTip: [[VLCMain sharedInstance] wrapString: [[VLCMain sharedInstance] localizedString: psz_duptip] toWidth: PREFS_WRAP]]; free( psz_duptip ); } [o_view addSubview: [o_modules autorelease]]; @@ -453,7 +453,7 @@ if( !strcmp( p_a_module->psz_capability, p_item->psz_type ) ) { - NSString *o_description = [NSApp + NSString *o_description = [[VLCMain sharedInstance] localizedString: p_a_module->psz_longname]; [o_modules addItemWithTitle: o_description]; [[o_modules lastItem] setTag: p_a_module->i_object_id]; @@ -510,10 +510,10 @@ o_text_field = [[VLCTextField alloc] initWithFrame: s_rc]; CONTROL_CONFIG( o_text_field, o_module_name, CONFIG_ITEM_STRING , p_item->psz_name ); - [o_text_field setStringValue: [NSApp localizedString: psz_value]]; + [o_text_field setStringValue: [[VLCMain sharedInstance] localizedString: psz_value]]; if ( psz_duptip != NULL ) { - [o_text_field setToolTip: [NSApp wrapString: [NSApp localizedString: + [o_text_field setToolTip: [[VLCMain sharedInstance] wrapString: [[VLCMain sharedInstance] localizedString: psz_duptip] toWidth: PREFS_WRAP ]]; free(psz_duptip); } @@ -540,7 +540,7 @@ p_item->psz_value : ""; INPUT_FIELD_STRING( p_item->psz_name, p_item->psz_text, 200, - [NSApp localizedString: psz_value], + [[VLCMain sharedInstance] localizedString: psz_value], p_item->psz_longtext ); } else @@ -570,7 +570,7 @@ if ( psz_duptip != NULL ) { - [o_combo_box setToolTip: [NSApp wrapString: [NSApp localizedString: psz_duptip] toWidth: PREFS_WRAP]]; + [o_combo_box setToolTip: [[VLCMain sharedInstance] wrapString: [[VLCMain sharedInstance] localizedString: psz_duptip] toWidth: PREFS_WRAP]]; free( psz_duptip ); } [o_view addSubview: [o_combo_box autorelease]]; @@ -578,9 +578,9 @@ for( i=0; p_item->ppsz_list[i]; i++ ) { [o_combo_box addItemWithObjectValue: - [NSApp localizedString: p_item->ppsz_list[i]]]; + [[VLCMain sharedInstance] localizedString: p_item->ppsz_list[i]]]; } - [o_combo_box setStringValue: [NSApp localizedString: + [o_combo_box setStringValue: [[VLCMain sharedInstance] localizedString: p_item->psz_value ? p_item->psz_value : ""]]; CONTROL_LABEL( p_item->psz_text ); @@ -620,7 +620,7 @@ if ( psz_duptip != NULL ) { - [o_slider setToolTip: [NSApp wrapString: [NSApp localizedString: psz_duptip] toWidth: PREFS_WRAP]]; + [o_slider setToolTip: [[VLCMain sharedInstance] wrapString: [[VLCMain sharedInstance] localizedString: psz_duptip] toWidth: PREFS_WRAP]]; free( psz_duptip ); } [o_slider setTarget: self]; @@ -665,7 +665,7 @@ if ( psz_duptip != NULL ) { - [o_slider setToolTip: [NSApp wrapString: [NSApp localizedString: psz_duptip] toWidth: PREFS_WRAP]]; + [o_slider setToolTip: [[VLCMain sharedInstance] wrapString: [[VLCMain sharedInstance] localizedString: psz_duptip] toWidth: PREFS_WRAP]]; free( psz_duptip ); } [o_slider setTarget: self]; @@ -699,10 +699,10 @@ o_btn_bool = [[VLCButton alloc] initWithFrame: s_rc]; [o_btn_bool setButtonType: NSSwitchButton]; [o_btn_bool setIntValue: p_item->i_value]; - [o_btn_bool setTitle: [NSApp localizedString: p_item->psz_text]]; + [o_btn_bool setTitle: [[VLCMain sharedInstance] localizedString: p_item->psz_text]]; if ( psz_duptip != NULL ) { - [o_btn_bool setToolTip: [NSApp wrapString: [NSApp localizedString: psz_duptip] toWidth: PREFS_WRAP]]; + [o_btn_bool setToolTip: [[VLCMain sharedInstance] wrapString: [[VLCMain sharedInstance] localizedString: psz_duptip] toWidth: PREFS_WRAP]]; free( psz_duptip ); } [o_btn_bool setTarget: self]; @@ -742,7 +742,7 @@ [o_current_cell setControlSize: NSSmallControlSize]; if( psz_duptip != NULL ) { - [o_matrix setToolTip: [NSApp wrapString: [NSApp localizedString: psz_duptip] toWidth: PREFS_WRAP] forCell: o_current_cell]; + [o_matrix setToolTip: [[VLCMain sharedInstance] wrapString: [[VLCMain sharedInstance] localizedString: psz_duptip] toWidth: PREFS_WRAP] forCell: o_current_cell]; } switch( i ) { @@ -791,7 +791,7 @@ if ( psz_duptip != NULL ) { - [o_combo_box setToolTip: [NSApp wrapString: [NSApp localizedString: psz_duptip] toWidth: PREFS_WRAP]]; + [o_combo_box setToolTip: [[VLCMain sharedInstance] wrapString: [[VLCMain sharedInstance] localizedString: psz_duptip] toWidth: PREFS_WRAP]]; } [o_view addSubview: [o_combo_box autorelease]]; @@ -799,10 +799,10 @@ { if( vlc_keys[i].psz_key_string && *vlc_keys[i].psz_key_string ) - [o_combo_box addItemWithObjectValue: [NSApp localizedString:vlc_keys[i].psz_key_string]]; + [o_combo_box addItemWithObjectValue: [[VLCMain sharedInstance] localizedString:vlc_keys[i].psz_key_string]]; } - [o_combo_box setStringValue: [NSApp localizedString:KeyToString(( ((unsigned int)p_item->i_value) & ~KEY_MODIFIER ))]]; + [o_combo_box setStringValue: [[VLCMain sharedInstance] localizedString:KeyToString(( ((unsigned int)p_item->i_value) & ~KEY_MODIFIER ))]]; s_rc.origin.y += s_rc.size.height; s_rc.origin.x = X_ORIGIN; @@ -886,7 +886,7 @@ static VLCTreeItem *o_root_item = nil; * Loads children incrementally */ - (NSArray *)children { if (o_children == NULL) { - intf_thread_t *p_intf = [NSApp getIntf]; + intf_thread_t *p_intf = VLCIntf; vlc_list_t *p_list; module_t *p_module = NULL; module_config_t *p_item; @@ -928,7 +928,7 @@ static VLCTreeItem *o_root_item = nil; switch( p_item->i_type ) { case CONFIG_HINT_CATEGORY: - o_child_name = [NSApp localizedString: p_item->psz_text]; + o_child_name = [[VLCMain sharedInstance] localizedString: p_item->psz_text]; [o_children addObject:[[VLCTreeItem alloc] initWithName: o_child_name ID: p_module->i_object_id parent:self]]; break; @@ -970,7 +970,7 @@ static VLCTreeItem *o_root_item = nil; /* Create the capability tree if it doesn't already exist */ NSString *o_capability; - o_capability = [NSApp localizedString: p_module->psz_capability]; + o_capability = [[VLCMain sharedInstance] localizedString: p_module->psz_capability]; if( !p_module->psz_capability || !*p_module->psz_capability ) { /* Empty capability ? Let's look at the submodules */ @@ -980,7 +980,7 @@ static VLCTreeItem *o_root_item = nil; p_submodule = (module_t*)p_module->pp_children[ j ]; if( p_submodule->psz_capability && *p_submodule->psz_capability ) { - o_capability = [NSApp localizedString: p_submodule->psz_capability]; + o_capability = [[VLCMain sharedInstance] localizedString: p_submodule->psz_capability]; BOOL b_found = FALSE; for( j = 0; j < (int)[o_children count]; j++ ) { @@ -1040,7 +1040,7 @@ static VLCTreeItem *o_root_item = nil; /* Check the capability */ NSString *o_capability; - o_capability = [NSApp localizedString: p_module->psz_capability]; + o_capability = [[VLCMain sharedInstance] localizedString: p_module->psz_capability]; if( !p_module->psz_capability || !*p_module->psz_capability ) { /* Empty capability ? Let's look at the submodules */ @@ -1050,11 +1050,11 @@ static VLCTreeItem *o_root_item = nil; p_submodule = (module_t*)p_module->pp_children[ j ]; if( p_submodule->psz_capability && *p_submodule->psz_capability ) { - o_capability = [NSApp localizedString: p_submodule->psz_capability]; + o_capability = [[VLCMain sharedInstance] localizedString: p_submodule->psz_capability]; if( [o_capability isEqualToString: [self getName]] ) { [o_children addObject:[[VLCTreeItem alloc] initWithName: - [NSApp localizedString: p_module->psz_object_name ] + [[VLCMain sharedInstance] localizedString: p_module->psz_object_name ] ID: p_module->i_object_id parent:self]]; } } @@ -1063,7 +1063,7 @@ static VLCTreeItem *o_root_item = nil; else if( [o_capability isEqualToString: [self getName]] ) { [o_children addObject:[[VLCTreeItem alloc] initWithName: - [NSApp localizedString: p_module->psz_object_name ] + [[VLCMain sharedInstance] localizedString: p_module->psz_object_name ] ID: p_module->i_object_id parent:self]]; } } @@ -1092,13 +1092,14 @@ static VLCTreeItem *o_root_item = nil; } - (int)numberOfChildren { + return 0; id i_tmp = [self children]; return (i_tmp == IsALeafNode) ? (-1) : (int)[i_tmp count]; } - (BOOL)hasPrefs:(NSString *)o_module_name { - intf_thread_t *p_intf = [NSApp getIntf]; + intf_thread_t *p_intf = VLCIntf; module_t *p_parser; vlc_list_t *p_list; char *psz_module_name; diff --git a/modules/gui/macosx/vout.m b/modules/gui/macosx/vout.m index e87959626d..eb787c66a8 100644 --- a/modules/gui/macosx/vout.m +++ b/modules/gui/macosx/vout.m @@ -119,26 +119,6 @@ int E_(OpenVideo) ( vlc_object_t *p_this ) return( 1 ); } - if( [NSApp respondsToSelector: @selector(getIntf)] ) - { - intf_thread_t * p_intf; - - for( i_timeout = 10 ; i_timeout-- ; ) - { - if( ( p_intf = [NSApp getIntf] ) == NULL ) - { - msleep( INTF_IDLE_SLEEP ); - } - } - - if( p_intf == NULL ) - { - msg_Err( p_vout, "MacOS X intf has getIntf, but is NULL" ); - free( p_vout->p_sys ); - return( 1 ); - } - } - p_vout->p_sys->b_mouse_moved = VLC_TRUE; p_vout->p_sys->i_time_mouse_last_moved = mdate(); @@ -613,12 +593,12 @@ static int CoSendRequest( vout_thread_t *p_vout, SEL sel ) interface. We do not check if this interface exists, since it has already been done before.*/ - p_intf = [NSApp getIntf]; + /*p_intf = VLCIntf; val.b_bool = VLC_TRUE; var_Create(p_intf,"intf-change",VLC_VAR_BOOL); var_Set(p_intf, "intf-change",val); - +*/ return( i_ret ); } @@ -1036,8 +1016,7 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic ) - (BOOL)performKeyEquivalent:(NSEvent *)o_event { - return [(VLCApplication *) [VLCApplication sharedApplication] - hasDefinedShortcutKey:o_event]; + return [[VLCMain sharedInstance] hasDefinedShortcutKey:o_event]; } - (void)keyDown:(NSEvent *)o_event diff --git a/src/interface/interface.c b/src/interface/interface.c index 458431d2da..f729444aa2 100644 --- a/src/interface/interface.c +++ b/src/interface/interface.c @@ -42,10 +42,13 @@ #include "audio_output.h" #include "vlc_interface.h" - #include "vlc_video.h" #include "video_output.h" +#ifdef SYS_DARWIN +# include "Cocoa/Cocoa.h" +#endif /* SYS_DARWIN */ + /***************************************************************************** * Local prototypes *****************************************************************************/ @@ -127,8 +130,10 @@ intf_thread_t* __intf_Create( vlc_object_t *p_this, const char *psz_module ) */ int intf_RunThread( intf_thread_t *p_intf ) { +#ifdef SYS_DARWIN if( p_intf->b_block ) { + /* This is the primary intf */ /* Run a manager thread, launch the interface, kill the manager */ if( vlc_thread_create( p_intf, "manager", Manager, VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) ) @@ -136,15 +141,49 @@ int intf_RunThread( intf_thread_t *p_intf ) msg_Err( p_intf, "cannot spawn manager thread" ); return VLC_EGENERIC; } + } - RunInterface( p_intf ); + if( p_intf->b_block && !strncmp( p_intf->p_module->psz_shortname, "macosx" , 6 ) ) + { + /* this is OSX, we are cheating :) + This is NOT I REPEAT NOT blocking since [NSApp run] is */ + p_intf->b_block = VLC_FALSE; + RunInterface( p_intf ); + p_intf->b_block = VLC_TRUE; + } + else if( p_intf->b_block && !strncmp( p_intf->p_vlc->psz_object_name, "clivlc", 6 ) ) + { + /* VLC OS X in cli mode ( no blocking [NSApp run] ) + this is equal to running in normal non-OSX primary intf mode */ + RunInterface( p_intf ); p_intf->b_die = VLC_TRUE; + } + else + { + /* If anything else is the primary intf and we are not in cli mode, + then don't make it blocking ([NSApp run] will be blocking) + but run it in a seperate thread. */ + p_intf->b_block = VLC_FALSE; +#else + if( p_intf->b_block ) + { + /* Run a manager thread, launch the interface, kill the manager */ + if( vlc_thread_create( p_intf, "manager", Manager, + VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) ) + { + msg_Err( p_intf, "cannot spawn manager thread" ); + return VLC_EGENERIC; + } + + RunInterface( p_intf ); + p_intf->b_die = VLC_TRUE; /* Do not join the thread... intf_StopThread will do it for us */ } else { +#endif /* Run the interface in a separate thread */ if( vlc_thread_create( p_intf, "interface", RunInterface, VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) ) @@ -228,6 +267,12 @@ static void Manager( intf_thread_t *p_intf ) if( p_intf->p_vlc->b_die ) { p_intf->b_die = VLC_TRUE; +#ifdef SYS_DARWIN + if( strncmp( p_intf->p_vlc->psz_object_name, "clivlc", 6 ) ) + { + [NSApp stop: NULL]; + } +#endif return; } } diff --git a/src/vlc.c b/src/vlc.c index 6aedd11dc0..36cf1f322c 100644 --- a/src/vlc.c +++ b/src/vlc.c @@ -7,6 +7,7 @@ * Authors: Vincent Seguin * Samuel Hocevar * Gildas Bazin + * Derk-Jan Hartman * Lots of other people, see the libvlc AUTHORS file * * This program is free software; you can redistribute it and/or modify @@ -34,9 +35,16 @@ #ifdef HAVE_TIME_H # include /* time() */ #endif +#ifdef HAVE_STRINGS_H +# include /* strncmp() */ +#endif #include +#ifdef SYS_DARWIN +#include +#endif + /***************************************************************************** * Local prototypes. *****************************************************************************/ @@ -44,14 +52,58 @@ static void SigHandler ( int i_signal ); #endif +#ifdef SYS_DARWIN +/***************************************************************************** + * VLCApplication interface + *****************************************************************************/ +@interface VLCApplication : NSApplication +{ +} + +@end + +/***************************************************************************** + * VLCApplication implementation + *****************************************************************************/ +@implementation VLCApplication + +- (void)stop: (id)sender +{ + NSEvent *o_event; + [super stop:sender]; + + /* send a dummy event to break out of the event loop */ + o_event = [NSEvent mouseEventWithType: NSLeftMouseDown + location: NSMakePoint( 1, 1 ) modifierFlags: 0 + timestamp: 1 windowNumber: [[NSApp mainWindow] windowNumber] + context: [NSGraphicsContext currentContext] eventNumber: 1 + clickCount: 1 pressure: 0.0]; + [NSApp postEvent: o_event atStart: YES]; +} + +- (void)terminate: (id)sender +{ + if( [NSApp isRunning] ) + [NSApp stop:sender]; + [super terminate: sender]; +} + +@end + +#endif /* SYS_DARWIN */ + /***************************************************************************** - * main: parse command line, start interface and spawn threads + * main: parse command line, start interface and spawn threads. *****************************************************************************/ int main( int i_argc, char *ppsz_argv[] ) { int i_ret; + int b_cli = VLC_FALSE ; +#ifndef SYS_DARWIN + /* This clutters OSX GUI error logs */ fprintf( stderr, "VLC media player %s\n", VLC_Version() ); +#endif #ifdef HAVE_PUTENV # ifdef DEBUG @@ -98,8 +150,39 @@ int main( int i_argc, char *ppsz_argv[] ) return i_ret; } - /* Add a blocking interface, start playing, and keep the return value */ +#ifdef HAVE_STRINGS_H + /* if first 3 chars of argv[0] are cli, then this is clivlc + * We detect this specifically for Mac OS X, so you can launch vlc + * from the commandline even if you are not logged in on the GUI */ + if( i_argc > 0 ) + { + char *psz_temp; + char *psz_program = psz_temp = ppsz_argv[0]; + while( *psz_temp ) + { + if( *psz_temp == '/' ) psz_program = ++psz_temp; + else ++psz_temp; + } + b_cli = !strncmp( psz_program, "cli", 3 ); + } +#endif + +#ifdef SYS_DARWIN + if( !b_cli ) + { + [VLCApplication sharedApplication]; + } + + i_ret = VLC_AddIntf( 0, NULL, VLC_TRUE, VLC_TRUE ); + + if( !b_cli ) + { + /* This is a blocking call */ + [NSApp run]; + } +#else i_ret = VLC_AddIntf( 0, NULL, VLC_TRUE, VLC_TRUE ); +#endif /* SYS_DARWIN */ /* Finish the threads */ VLC_CleanUp( 0 ); @@ -107,6 +190,13 @@ int main( int i_argc, char *ppsz_argv[] ) /* Destroy the libvlc structure */ VLC_Destroy( 0 ); +#ifdef SYS_DARWIN + if( !b_cli ) + { + [NSApp terminate:NULL]; + } +#endif /* SYS_DARWIN */ + return i_ret; } -- 2.39.2