X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fgui%2Fmacosx%2Fintf.m;h=f7e36d751283fbe11ef23fb0713b6fef958929c3;hb=8548e873e73f7e2838fee5e758eeb31ce158f5bb;hp=54ae70f347b146c4ff9a783c11fa1801c1a099ed;hpb=6e70470eb262951fda0963b91c3668d1982c1cfc;p=vlc diff --git a/modules/gui/macosx/intf.m b/modules/gui/macosx/intf.m index 54ae70f347..f7e36d7512 100644 --- a/modules/gui/macosx/intf.m +++ b/modules/gui/macosx/intf.m @@ -1,7 +1,7 @@ /***************************************************************************** * intf.m: MacOS X interface module ***************************************************************************** - * Copyright (C) 2002-2011 the VideoLAN team + * Copyright (C) 2002-2012 VLC authors and VideoLAN * $Id$ * * Authors: Jon Lech Johansen @@ -27,6 +27,10 @@ /***************************************************************************** * Preamble *****************************************************************************/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include /* malloc(), free() */ #include /* for MAXPATHLEN */ #include @@ -35,14 +39,15 @@ #include #include #include +#include #include #include #include /* execl() */ +#import "CompatibilityFixes.h" #import "intf.h" #import "MainMenu.h" -#import "MainWindow.h" -#import "vout.h" +#import "VideoView.h" #import "prefs.h" #import "playlist.h" #import "playlistinfo.h" @@ -51,7 +56,6 @@ #import "wizard.h" #import "bookmarks.h" #import "coredialogs.h" -#import "embeddedwindow.h" #import "AppleRemote.h" #import "eyetv.h" #import "simple_prefs.h" @@ -70,7 +74,7 @@ static void updateProgressPanel (void *, const char *, float); static bool checkProgressPanel (void *); static void destroyProgressPanel (void *); -static void MsgCallback( msg_cb_data_t *, const msg_item_t * ); +static void MsgCallback( void *data, int type, const msg_item_t *item, const char *format, va_list ap ); static int InputEvent( vlc_object_t *, const char *, vlc_value_t, vlc_value_t, void * ); @@ -93,6 +97,7 @@ int OpenIntf ( vlc_object_t *p_this ) { NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init]; [VLCApplication sharedApplication]; + intf_thread_t *p_intf = (intf_thread_t*) p_this; p_intf->p_sys = malloc( sizeof( intf_sys_t ) ); @@ -102,9 +107,9 @@ int OpenIntf ( vlc_object_t *p_this ) memset( p_intf->p_sys, 0, sizeof( *p_intf->p_sys ) ); /* subscribe to LibVLCCore's messages */ - p_intf->p_sys->p_sub = msg_Subscribe( p_intf->p_libvlc, MsgCallback, NULL ); - p_intf->pf_run = Run; - p_intf->b_should_run_on_first_thread = true; + vlc_Subscribe( &p_intf->p_sys->sub, MsgCallback, NULL ); + + Run( p_intf ); [o_pool release]; return VLC_SUCCESS; @@ -155,18 +160,22 @@ static int WindowControl( vout_window_t *p_wnd, int i_query, va_list args ) { /* TODO */ if( i_query == VOUT_WINDOW_SET_STATE ) - NSLog( @"WindowControl:VOUT_WINDOW_SET_STATE" ); + msg_Dbg( p_wnd, "WindowControl:VOUT_WINDOW_SET_STATE" ); else if( i_query == VOUT_WINDOW_SET_SIZE ) { - NSLog( @"WindowControl:VOUT_WINDOW_SET_SIZE" ); unsigned int i_width = va_arg( args, unsigned int ); unsigned int i_height = va_arg( args, unsigned int ); [[VLCMain sharedInstance] setNativeVideoSize:NSMakeSize( i_width, i_height )]; } else if( i_query == VOUT_WINDOW_SET_FULLSCREEN ) - NSLog( @"WindowControl:VOUT_WINDOW_SET_FULLSCREEN" ); + { + NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init]; + // we already have our playlist "fullscreen" callback, do not repeat the same call here + //[[VLCMain sharedInstance] performSelectorOnMainThread:@selector(fullscreenChanged) withObject: nil waitUntilDone: NO]; + [o_pool release]; + } else - NSLog( @"WindowControl: unknown query" ); + msg_Dbg( p_wnd, "WindowControl: unknown query" ); return VLC_SUCCESS; } @@ -174,8 +183,7 @@ void WindowClose( vout_window_t *p_wnd ) { NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init]; [[VLCMain sharedInstance] setActiveVideoPlayback:NO]; - NSLog( @"Window Close" ); - // tell the interface to get rid of the video, TODO + [o_pool release]; } @@ -183,20 +191,9 @@ void WindowClose( vout_window_t *p_wnd ) * Run: main loop *****************************************************************************/ static NSLock * o_appLock = nil; // controls access to f_appExit -static int f_appExit = 0; // set to 1 when application termination signaled static void Run( intf_thread_t *p_intf ) { - sigset_t set; - - /* Make sure the "force quit" menu item does quit instantly. - * VLC overrides SIGTERM which is sent by the "force quit" - * menu item to make sure daemon mode quits gracefully, so - * we un-override SIGTERM here. */ - sigemptyset( &set ); - sigaddset( &set, SIGTERM ); - pthread_sigmask( SIG_UNBLOCK, &set, NULL ); - NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init]; [VLCApplication sharedApplication]; @@ -209,6 +206,8 @@ static void Run( intf_thread_t *p_intf ) [[VLCMain sharedInstance] applicationWillTerminate:nil]; [o_appLock release]; [o_pool release]; + + raise(SIGTERM); } #pragma mark - @@ -219,19 +218,23 @@ static void Run( intf_thread_t *p_intf ) * ready to be displayed. We store everything in a NSArray in our Cocoa part * of this file. *****************************************************************************/ -static void MsgCallback( msg_cb_data_t *data, const msg_item_t *item ) +static void MsgCallback( void *data, int type, const msg_item_t *item, const char *format, va_list ap ) { int canc = vlc_savecancel(); + char *str; - /* this may happen from time to time, let's bail out as info would be useless anyway */ - if( !item->psz_module || !item->psz_msg ) + if (vasprintf( &str, format, ap ) == -1) + { + vlc_restorecancel( canc ); return; + } NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init]; - [[VLCMain sharedInstance] processReceivedlibvlcMessage: item]; + [[VLCMain sharedInstance] processReceivedlibvlcMessage: item ofType: type withStr: str]; [o_pool release]; vlc_restorecancel( canc ); + free( str ); } static int InputEvent( vlc_object_t *p_this, const char *psz_var, @@ -240,19 +243,20 @@ static int InputEvent( vlc_object_t *p_this, const char *psz_var, NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init]; switch (new_val.i_int) { case INPUT_EVENT_STATE: - [[VLCMain sharedInstance] playbackStatusUpdated]; + [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(playbackStatusUpdated) withObject: nil waitUntilDone:NO]; break; case INPUT_EVENT_RATE: - [[VLCMainMenu sharedInstance] performSelectorOnMainThread:@selector(updatePlaybackRate) withObject: nil waitUntilDone:NO]; + [[[VLCMain sharedInstance] mainMenu] performSelectorOnMainThread:@selector(updatePlaybackRate) withObject: nil waitUntilDone:NO]; break; case INPUT_EVENT_POSITION: - [[VLCMain sharedInstance] updatePlaybackPosition]; + [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(updatePlaybackPosition) withObject: nil waitUntilDone:NO]; break; case INPUT_EVENT_TITLE: case INPUT_EVENT_CHAPTER: + [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(updateMainMenu) withObject: nil waitUntilDone:NO]; break; case INPUT_EVENT_CACHE: - [[VLCMain sharedInstance] updateMainWindow]; + [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(updateMainWindow) withObject: nil waitUntilDone: NO]; break; case INPUT_EVENT_STATISTICS: [[[VLCMain sharedInstance] info] performSelectorOnMainThread:@selector(updateStatistics) withObject: nil waitUntilDone: NO]; @@ -260,7 +264,6 @@ static int InputEvent( vlc_object_t *p_this, const char *psz_var, case INPUT_EVENT_ES: break; case INPUT_EVENT_TELETEXT: - NSLog( @"teletext" ); break; case INPUT_EVENT_AOUT: break; @@ -268,14 +271,17 @@ static int InputEvent( vlc_object_t *p_this, const char *psz_var, break; case INPUT_EVENT_ITEM_META: case INPUT_EVENT_ITEM_INFO: - [[VLCMain sharedInstance] updateName]; - [[VLCMain sharedInstance] updateInfoandMetaPanel]; + [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(updateMainMenu) withObject: nil waitUntilDone:NO]; + [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(updateName) withObject: nil waitUntilDone:NO]; + [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(updateInfoandMetaPanel) withObject: nil waitUntilDone:NO]; break; case INPUT_EVENT_BOOKMARK: break; case INPUT_EVENT_RECORD: + [[VLCMain sharedInstance] updateRecordState: var_GetBool( p_this, "record" )]; break; case INPUT_EVENT_PROGRAM: + [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(updateMainMenu) withObject: nil waitUntilDone:NO]; break; case INPUT_EVENT_ITEM_EPG: break; @@ -283,21 +289,23 @@ static int InputEvent( vlc_object_t *p_this, const char *psz_var, break; case INPUT_EVENT_ITEM_NAME: - [[VLCMain sharedInstance] updateName]; - [[VLCMain sharedInstance] playlistUpdated]; + [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(updateName) withObject: nil waitUntilDone:NO]; + [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(playlistUpdated) withObject: nil waitUntilDone:NO]; break; case INPUT_EVENT_AUDIO_DELAY: case INPUT_EVENT_SUBTITLE_DELAY: - [[VLCMain sharedInstance] updateDelays]; + [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(updateDelays) withObject:nil waitUntilDone:NO]; break; case INPUT_EVENT_DEAD: - [[VLCMain sharedInstance] updateName]; - [[VLCMain sharedInstance] updatePlaybackPosition]; + [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(updateName) withObject: nil waitUntilDone:NO]; + [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(updatePlaybackPosition) withObject:nil waitUntilDone:NO]; break; case INPUT_EVENT_ABORT: + [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(updateName) withObject: nil waitUntilDone:NO]; + [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(updatePlaybackPosition) withObject:nil waitUntilDone:NO]; break; default: @@ -333,7 +341,7 @@ static int PlaybackModeUpdated( vlc_object_t *p_this, const char *psz_var, vlc_value_t oldval, vlc_value_t new_val, void *param ) { NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init]; - [[VLCMain sharedInstance] playbackModeUpdated]; + [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(playbackModeUpdated) withObject:nil waitUntilDone:NO]; [o_pool release]; return VLC_SUCCESS; @@ -360,7 +368,16 @@ static int ShowController( vlc_object_t *p_this, const char *psz_variable, intf_thread_t * p_intf = VLCIntf; if( p_intf && p_intf->p_sys ) { -// [[[VLCMain sharedInstance] fspanel] makeKeyAndOrderFront: nil]; + playlist_t * p_playlist = pl_Get( p_intf ); + BOOL b_fullscreen = var_GetBool( p_playlist, "fullscreen" ); + if( strcmp(psz_variable, "intf-toggle-fscontrol") || b_fullscreen ) + { + [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(showFullscreenController) withObject:nil waitUntilDone:NO]; + } + else + { + [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(showMainWindow) withObject:nil waitUntilDone:NO]; + } } return VLC_SUCCESS; } @@ -376,7 +393,7 @@ static int FullscreenChanged( vlc_object_t *p_this, const char *psz_variable, if (p_intf) { NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init]; - [[VLCMain sharedInstance] fullscreenChanged]; + [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(fullscreenChanged) withObject:nil waitUntilDone:NO]; [o_pool release]; } return VLC_SUCCESS; @@ -427,7 +444,7 @@ void updateProgressPanel (void *priv, const char *text, float value) void destroyProgressPanel (void *priv) { NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init]; - [[[VLCMain sharedInstance] coreDialogProvider] destroyProgressPanel]; + [[[VLCMain sharedInstance] coreDialogProvider] performSelectorOnMainThread:@selector(destroyProgressPanel) withObject:nil waitUntilDone:NO]; [o_pool release]; } @@ -502,6 +519,7 @@ static VLCMain *_o_sharedMainInstance = nil; _o_sharedMainInstance = [super init]; p_intf = NULL; + p_current_input = NULL; o_msg_lock = [[NSLock alloc] init]; o_msg_arr = [[NSMutableArray arrayWithCapacity: 600] retain]; @@ -520,6 +538,11 @@ static VLCMain *_o_sharedMainInstance = nil; object: @"VLCEyeTVSupport" userInfo: NULL deliverImmediately: YES]; + + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + NSDictionary *appDefaults = [NSDictionary dictionaryWithObject:@"NO" forKey:@"LiveUpdateTheMessagesPanel"]; + [defaults registerDefaults:appDefaults]; + return _o_sharedMainInstance; } @@ -549,9 +572,10 @@ static VLCMain *_o_sharedMainInstance = nil; val.b_bool = false; - var_AddCallback( p_playlist, "fullscreen", FullscreenChanged, self); + var_AddCallback(p_playlist, "fullscreen", FullscreenChanged, self); + var_AddCallback( p_intf->p_libvlc, "intf-toggle-fscontrol", ShowController, self); var_AddCallback( p_intf->p_libvlc, "intf-show", ShowController, self); -// var_AddCallback(p_playlist, "item-change", PLItemChanged, self); + // var_AddCallback(p_playlist, "item-change", PLItemChanged, self); var_AddCallback(p_playlist, "item-current", PLItemChanged, self); var_AddCallback(p_playlist, "activity", PLItemChanged, self); var_AddCallback(p_playlist, "leaf-to-parent", PlaylistUpdated, self); @@ -563,6 +587,12 @@ static VLCMain *_o_sharedMainInstance = nil; var_AddCallback(p_playlist, "volume", VolumeUpdated, self); var_AddCallback(p_playlist, "mute", VolumeUpdated, self); + if (OSX_LION) + { + if ([NSApp currentSystemPresentationOptions] & NSApplicationPresentationFullScreen) + var_SetBool( p_playlist, "fullscreen", YES ); + } + /* load our Core Dialogs nib */ nib_coredialogs_loaded = [NSBundle loadNibNamed:@"CoreDialogs" owner: NSApp]; @@ -579,14 +609,41 @@ static VLCMain *_o_sharedMainInstance = nil; var_AddCallback( p_intf, "dialog-progress-bar", DialogCallback, self ); dialog_Register( p_intf ); - [self playbackModeUpdated]; - /* init Apple Remote support */ o_remote = [[AppleRemote alloc] init]; [o_remote setClickCountEnabledButtons: kRemoteButtonPlay]; [o_remote setDelegate: _o_sharedMainInstance]; + [o_msgs_refresh_btn setImage: [NSImage imageNamed: NSImageNameRefreshTemplate]]; + /* yeah, we are done */ + b_nativeFullscreenMode = NO; +#ifdef MAC_OS_X_VERSION_10_7 + if( OSX_LION ) + b_nativeFullscreenMode = config_GetInt( p_intf, "macosx-nativefullscreenmode" ); +#endif + + /* recover stored audio device, if set + * in case it was unplugged in the meantime, auhal will fall back on the default */ + int i_value = config_GetInt( p_intf, "macosx-audio-device" ); + if (i_value > 0) + var_SetInteger( pl_Get( VLCIntf ), "audio-device", i_value ); + + if (config_GetInt( VLCIntf, "macosx-icon-change")) + { + /* After day 354 of the year, the usual VLC cone is replaced by another cone + * wearing a Father Xmas hat. + * Note: this icon doesn't represent an endorsement of The Coca-Cola Company. + */ + NSCalendar *gregorian = + [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; + NSUInteger dayOfYear = [gregorian ordinalityOfUnit:NSDayCalendarUnit inUnit:NSYearCalendarUnit forDate:[NSDate date]]; + [gregorian release]; + + if (dayOfYear >= 354) + [[VLCApplication sharedApplication] setApplicationIconImage: [NSImage imageNamed:@"vlc-xmas"]]; + } + nib_main_loaded = TRUE; } @@ -594,6 +651,13 @@ static VLCMain *_o_sharedMainInstance = nil; { if( !p_intf ) return; + [self updateCurrentlyUsedHotkeys]; + + [o_mainwindow updateWindow]; + [o_mainwindow updateTimeSlider]; + [o_mainwindow updateVolumeSlider]; + [o_mainwindow makeKeyAndOrderFront: self]; + /* init media key support */ b_mediaKeySupport = config_GetInt( VLCIntf, "macosx-mediakeys" ); if( b_mediaKeySupport ) @@ -608,16 +672,15 @@ static VLCMain *_o_sharedMainInstance = nil; [self _removeOldPreferences]; - [o_mainwindow updateWindow]; - [o_mainwindow updateTimeSlider]; - [o_mainwindow updateVolumeSlider]; - [o_mainwindow makeKeyAndOrderFront: self]; - /* Handle sleep notification */ [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(computerWillSleep:) name:NSWorkspaceWillSleepNotification object:nil]; - [NSThread detachNewThreadSelector:@selector(lookForCrashLog) toTarget:self withObject:nil]; + [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(lookForCrashLog) withObject:nil waitUntilDone:NO]; + + /* we will need this, so let's load it here so the interface appears to be more responsive */ + nib_open_loaded = [NSBundle loadNibNamed:@"Open" owner: NSApp]; + [self initStrings]; } - (void)initStrings @@ -644,29 +707,38 @@ static VLCMain *_o_sharedMainInstance = nil; - (void)applicationWillTerminate:(NSNotification *)notification { - playlist_t * p_playlist; - vout_thread_t * p_vout; - int returnedValue = 0; - - if( !p_intf ) - return; - - // don't allow a double termination call. If the user has - // already invoked the quit then simply return this time. - int isTerminating = false; + /* don't allow a double termination call. If the user has + * already invoked the quit then simply return this time. */ + static bool f_appExit = false; + bool isTerminating; [o_appLock lock]; - isTerminating = (f_appExit++ > 0 ? 1 : 0); + isTerminating = f_appExit; + f_appExit = true; [o_appLock unlock]; if (isTerminating) return; - msg_Dbg( p_intf, "Terminating" ); + if (notification == nil) + [[NSNotificationCenter defaultCenter] postNotificationName: NSApplicationWillTerminateNotification object: nil]; - /* Make sure the intf object is getting killed */ - vlc_object_kill( p_intf ); - p_playlist = pl_Get( p_intf ); + playlist_t * p_playlist = pl_Get( p_intf ); + int returnedValue = 0; + + /* always exit fullscreen on quit, otherwise we get ugly artifacts on the next launch */ + if (b_nativeFullscreenMode) + { + [o_mainwindow toggleFullScreen: self]; + [NSApp setPresentationOptions:(NSApplicationPresentationDefault)]; + } + + /* Save some interface state in configuration, at module quit */ + config_PutInt( p_intf, "random", var_GetBool( p_playlist, "random" ) ); + config_PutInt( p_intf, "loop", var_GetBool( p_playlist, "loop" ) ); + config_PutInt( p_intf, "repeat", var_GetBool( p_playlist, "repeat" ) ); + + msg_Dbg( p_intf, "Terminating" ); /* unsubscribe from the interactive dialogues */ dialog_Unregister( p_intf ); @@ -686,6 +758,16 @@ static VLCMain *_o_sharedMainInstance = nil; var_DelCallback(p_playlist, "loop", PlaybackModeUpdated, self); var_DelCallback(p_playlist, "volume", VolumeUpdated, self); var_DelCallback(p_playlist, "mute", VolumeUpdated, self); + var_DelCallback(p_playlist, "fullscreen", FullscreenChanged, self); + var_DelCallback(p_intf->p_libvlc, "intf-toggle-fscontrol", ShowController, self); + var_DelCallback(p_intf->p_libvlc, "intf-show", ShowController, self); + + if( p_current_input ) + { + var_DelCallback( p_current_input, "intf-event", InputEvent, [VLCMain sharedInstance] ); + vlc_object_release( p_current_input ); + p_current_input = NULL; + } /* remove global observer watching for vout device changes correctly */ [[NSNotificationCenter defaultCenter] removeObserver: self]; @@ -712,13 +794,13 @@ static VLCMain *_o_sharedMainInstance = nil; [o_embedded_list release]; [o_coredialogs release]; [o_eyetv release]; - [o_mainwindow release]; /* unsubscribe from libvlc's debug messages */ - msg_Unsubscribe( p_intf->p_sys->p_sub ); + vlc_Unsubscribe( &p_intf->p_sys->sub ); [o_msg_arr removeAllObjects]; [o_msg_arr release]; + o_msg_arr = NULL; [o_msg_lock release]; @@ -730,11 +812,11 @@ static VLCMain *_o_sharedMainInstance = nil; [o_mainmenu releaseRepresentedObjects:[NSApp mainMenu]]; [o_mainmenu release]; - /* Kill the playlist, so that it doesn't accept new request - * such as the play request from vlc.c (we are a blocking interface). */ - vlc_object_kill( p_playlist ); libvlc_Quit( p_intf->p_libvlc ); + [o_mainwindow release]; + o_mainwindow = NULL; + [self setIntf:nil]; } @@ -745,7 +827,7 @@ static VLCMain *_o_sharedMainInstance = nil; { [NSApp activateIgnoringOtherApps:YES]; [o_remote stopListening: self]; - var_SetInteger( p_intf->p_libvlc, "key-action", ACTIONID_STOP ); + [[VLCCoreInteraction sharedInstance] stop]; } #pragma mark - @@ -763,15 +845,15 @@ static VLCMain *_o_sharedMainInstance = nil; int keyRepeat = (keyFlags & 0x1); if( keyCode == NX_KEYTYPE_PLAY && keyState == 0 ) - var_SetInteger( p_intf->p_libvlc, "key-action", ACTIONID_PLAY_PAUSE ); + [[VLCCoreInteraction sharedInstance] play]; - if( keyCode == NX_KEYTYPE_FAST && !b_mediakeyJustJumped ) + if( (keyCode == NX_KEYTYPE_FAST || keyCode == NX_KEYTYPE_NEXT) && !b_mediakeyJustJumped ) { if( keyState == 0 && keyRepeat == 0 ) - var_SetInteger( p_intf->p_libvlc, "key-action", ACTIONID_NEXT ); + [[VLCCoreInteraction sharedInstance] next]; else if( keyRepeat == 1 ) { - var_SetInteger( p_intf->p_libvlc, "key-action", ACTIONID_JUMP_FORWARD_SHORT ); + [[VLCCoreInteraction sharedInstance] forwardShort]; b_mediakeyJustJumped = YES; [self performSelector:@selector(resetMediaKeyJump) withObject: NULL @@ -779,13 +861,13 @@ static VLCMain *_o_sharedMainInstance = nil; } } - if( keyCode == NX_KEYTYPE_REWIND && !b_mediakeyJustJumped ) + if( (keyCode == NX_KEYTYPE_REWIND || keyCode == NX_KEYTYPE_PREVIOUS) && !b_mediakeyJustJumped ) { if( keyState == 0 && keyRepeat == 0 ) - var_SetInteger( p_intf->p_libvlc, "key-action", ACTIONID_PREV ); + [[VLCCoreInteraction sharedInstance] previous]; else if( keyRepeat == 1 ) { - var_SetInteger( p_intf->p_libvlc, "key-action", ACTIONID_JUMP_BACKWARD_SHORT ); + [[VLCCoreInteraction sharedInstance] backwardShort]; b_mediakeyJustJumped = YES; [self performSelector:@selector(resetMediaKeyJump) withObject: NULL @@ -803,8 +885,8 @@ static VLCMain *_o_sharedMainInstance = nil; - (void)applicationDidBecomeActive:(NSNotification *)aNotification { if( !p_intf ) return; - if( config_GetInt( p_intf, "macosx-appleremote" ) == YES ) - [o_remote startListening: self]; + if( config_GetInt( p_intf, "macosx-appleremote" ) == YES ) + [o_remote startListening: self]; } - (void)applicationDidResignActive:(NSNotification *)aNotification { @@ -815,16 +897,7 @@ static VLCMain *_o_sharedMainInstance = nil; /* Triggered when the computer goes to sleep */ - (void)computerWillSleep: (NSNotification *)notification { - input_thread_t * p_input; - - p_input = pl_CurrentInput( p_intf ); - if( p_input ) - { - int state = var_GetInteger( p_input, "state" ); - if( state == PLAYING_S ) - var_SetInteger( p_intf->p_libvlc, "key-action", ACTIONID_PLAY_PAUSE ); - vlc_object_release( p_input ); - } + [[VLCCoreInteraction sharedInstance] pause]; } #pragma mark - @@ -837,6 +910,22 @@ static VLCMain *_o_sharedMainInstance = nil; if( !psz_uri ) return( FALSE ); + input_thread_t * p_input = pl_CurrentInput( VLCIntf ); + BOOL b_returned = NO; + + if (p_input) + { + b_returned = input_AddSubtitle( p_input, psz_uri, true ); + vlc_object_release( p_input ); + if(!b_returned) + { + free( psz_uri ); + return YES; + } + } + else if( p_input ) + vlc_object_release( p_input ); + NSDictionary *o_dic = [NSDictionary dictionaryWithObject:[NSString stringWithCString:psz_uri encoding:NSUTF8StringEncoding] forKey:@"ITEM_URL"]; free( psz_uri ); @@ -956,7 +1045,7 @@ static VLCMain *_o_sharedMainInstance = nil; if( psz != NULL ) { - o_str = [NSString stringWithCString: psz encoding:NSUTF8StringEncoding]; + o_str = [NSString stringWithCString: _(psz) encoding:NSUTF8StringEncoding]; if( o_str == NULL ) { @@ -1080,6 +1169,7 @@ static struct { NSCarriageReturnCharacter, KEY_ENTER }, { NSEnterCharacter, KEY_ENTER }, { NSBackspaceCharacter, KEY_BACKSPACE }, + { NSDeleteCharacter, KEY_DELETE }, {0,0} }; @@ -1115,13 +1205,82 @@ unsigned int CocoaKeyToVLC( unichar i_key ) - (NSString *)VLCKeyToString:(NSString *)theString { if (![theString isEqualToString:@""]) { + if ([theString characterAtIndex:([theString length] - 1)] != 0x2b) + theString = [theString stringByReplacingOccurrencesOfString:@"+" withString:@""]; + else + { + theString = [theString stringByReplacingOccurrencesOfString:@"+" withString:@""]; + theString = [NSString stringWithFormat:@"%@+", theString]; + } + if ([theString characterAtIndex:([theString length] - 1)] != 0x2d) + theString = [theString stringByReplacingOccurrencesOfString:@"-" withString:@""]; + else + { + theString = [theString stringByReplacingOccurrencesOfString:@"-" withString:@""]; + theString = [NSString stringWithFormat:@"%@-", theString]; + } theString = [theString stringByReplacingOccurrencesOfString:@"Command" withString:@""]; theString = [theString stringByReplacingOccurrencesOfString:@"Alt" withString:@""]; theString = [theString stringByReplacingOccurrencesOfString:@"Shift" withString:@""]; theString = [theString stringByReplacingOccurrencesOfString:@"Ctrl" withString:@""]; - theString = [theString stringByReplacingOccurrencesOfString:@"+" withString:@""]; - theString = [theString stringByReplacingOccurrencesOfString:@"-" withString:@""]; } + if ([theString length] > 1) + { + if([theString rangeOfString:@"Up"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSUpArrowFunctionKey]; + else if([theString rangeOfString:@"Down"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSDownArrowFunctionKey]; + else if([theString rangeOfString:@"Right"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSRightArrowFunctionKey]; + else if([theString rangeOfString:@"Left"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSLeftArrowFunctionKey]; + else if([theString rangeOfString:@"Enter"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSEnterCharacter]; // we treat NSCarriageReturnCharacter as aquivalent + else if([theString rangeOfString:@"Insert"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSInsertFunctionKey]; + else if([theString rangeOfString:@"Home"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSHomeFunctionKey]; + else if([theString rangeOfString:@"End"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSEndFunctionKey]; + else if([theString rangeOfString:@"Pageup"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSPageUpFunctionKey]; + else if([theString rangeOfString:@"Pagedown"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSPageDownFunctionKey]; + else if([theString rangeOfString:@"Menu"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSMenuFunctionKey]; + else if([theString rangeOfString:@"Tab"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSTabCharacter]; + else if([theString rangeOfString:@"Backspace"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSBackspaceCharacter]; + else if([theString rangeOfString:@"Delete"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSDeleteCharacter]; + else if([theString rangeOfString:@"F12"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSF12FunctionKey]; + else if([theString rangeOfString:@"F11"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSF11FunctionKey]; + else if([theString rangeOfString:@"F10"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSF10FunctionKey]; + else if([theString rangeOfString:@"F9"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSF9FunctionKey]; + else if([theString rangeOfString:@"F8"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSF8FunctionKey]; + else if([theString rangeOfString:@"F7"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSF7FunctionKey]; + else if([theString rangeOfString:@"F6"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSF6FunctionKey]; + else if([theString rangeOfString:@"F5"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSF5FunctionKey]; + else if([theString rangeOfString:@"F4"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSF4FunctionKey]; + else if([theString rangeOfString:@"F3"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSF3FunctionKey]; + else if([theString rangeOfString:@"F2"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSF2FunctionKey]; + else if([theString rangeOfString:@"F1"].location != NSNotFound) + return [NSString stringWithFormat:@"%C", NSF1FunctionKey]; + /* note that we don't support esc here, since it is reserved for leaving fullscreen */ + } + return theString; } @@ -1138,8 +1297,8 @@ unsigned int CocoaKeyToVLC( unichar i_key ) unsigned int i_pressed_modifiers = 0; const struct hotkey *p_hotkeys; int i; - NSMutableString *tempString = [[[NSMutableString alloc] init] autorelease]; - NSMutableString *tempStringPlus = [[[NSMutableString alloc] init] autorelease]; + NSMutableString *tempString = [[NSMutableString alloc] init]; + NSMutableString *tempStringPlus = [[NSMutableString alloc] init]; val.i_int = 0; p_hotkeys = p_intf->p_libvlc->p_hotkeys; @@ -1172,6 +1331,15 @@ unsigned int CocoaKeyToVLC( unichar i_key ) key = [[o_event charactersIgnoringModifiers] characterAtIndex: 0]; + /* handle Lion's default key combo for fullscreen-toggle in addition to our own hotkeys */ + if( key == 'f' && i_pressed_modifiers & NSControlKeyMask && i_pressed_modifiers & NSCommandKeyMask ) + { + [[VLCCoreInteraction sharedInstance] toggleFullscreen]; + [tempString release]; + [tempStringPlus release]; + return YES; + } + switch( key ) { case NSDeleteCharacter: @@ -1184,17 +1352,31 @@ unsigned int CocoaKeyToVLC( unichar i_key ) case NSLeftArrowFunctionKey: case NSEnterCharacter: case NSCarriageReturnCharacter: + [tempString release]; + [tempStringPlus release]; return NO; } + if( key == 0x0020 ) // space key + { + [[VLCCoreInteraction sharedInstance] play]; + [tempString release]; + [tempStringPlus release]; + return YES; + } + val.i_int |= CocoaKeyToVLC( key ); if( [o_usedHotkeys indexOfObject: tempString] != NSNotFound || [o_usedHotkeys indexOfObject: tempStringPlus] != NSNotFound ) { var_SetInteger( p_intf->p_libvlc, "key-pressed", val.i_int ); + [tempString release]; + [tempStringPlus release]; return YES; } + [tempString release]; + [tempStringPlus release]; return NO; } @@ -1222,36 +1404,81 @@ unsigned int CocoaKeyToVLC( unichar i_key ) } } module_config_free (p_config); - o_usedHotkeys = [[NSArray alloc] initWithArray: o_usedHotkeys copyItems: YES]; + o_usedHotkeys = [[NSArray alloc] initWithArray: o_tempArray copyItems: YES]; + [o_tempArray release]; } #pragma mark - #pragma mark Interface updaters - (void)fullscreenChanged { - if(! [o_mainwindow isFullscreen] ) - [o_mainwindow performSelectorOnMainThread:@selector(enterFullscreen) withObject:nil waitUntilDone:NO]; + playlist_t * p_playlist = pl_Get( VLCIntf ); + BOOL b_fullscreen = var_GetBool( p_playlist, "fullscreen" ); + + if (b_nativeFullscreenMode) + { + // this is called twice in certain situations, so only toogle if we really need to + if( ( b_fullscreen && !([NSApp currentSystemPresentationOptions] & NSApplicationPresentationFullScreen) ) || + ( !b_fullscreen && ([NSApp currentSystemPresentationOptions] & NSApplicationPresentationFullScreen) ) ) + [o_mainwindow toggleFullScreen: self]; + + if(b_fullscreen) + [NSApp setPresentationOptions:(NSApplicationPresentationFullScreen | NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar)]; + else + [NSApp setPresentationOptions:(NSApplicationPresentationDefault)]; + } else - [o_mainwindow performSelectorOnMainThread:@selector(leaveFullscreen) withObject:nil waitUntilDone:NO]; + { + if( b_fullscreen ) + { + input_thread_t * p_input = pl_CurrentInput( VLCIntf ); + if( p_input != NULL && [self activeVideoPlayback] ) + { + [o_mainwindow performSelectorOnMainThread:@selector(enterFullscreen) withObject:nil waitUntilDone:NO]; + } + if (p_input) + vlc_object_release( p_input ); + } + else + { + // leaving fullscreen is always allowed + [o_mainwindow performSelectorOnMainThread:@selector(leaveFullscreen) withObject:nil waitUntilDone:NO]; + } + } } - (void)PlaylistItemChanged { - input_thread_t * p_input; + if( p_current_input && ( p_current_input->b_dead || !vlc_object_alive( p_current_input ) )) + { + var_DelCallback( p_current_input, "intf-event", InputEvent, [VLCMain sharedInstance] ); + vlc_object_release( p_current_input ); + p_current_input = NULL; - p_input = playlist_CurrentInput( pl_Get(VLCIntf) ); - if( p_input && !( p_input->b_dead || !vlc_object_alive(p_input) ) ) + [o_mainmenu setRateControlsEnabled: NO]; + } + else if( !p_current_input ) { - var_AddCallback( p_input, "intf-event", InputEvent, [VLCMain sharedInstance] ); - [o_mainmenu setRateControlsEnabled: YES]; - vlc_object_release( p_input ); + // object is hold here and released then it is dead + p_current_input = playlist_CurrentInput( pl_Get( VLCIntf )); + if( p_current_input ) + { + var_AddCallback( p_current_input, "intf-event", InputEvent, [VLCMain sharedInstance] ); + [self playbackStatusUpdated]; + [o_mainmenu setRateControlsEnabled: YES]; + if ( [self activeVideoPlayback] && [[o_mainwindow videoView] isHidden] ) + [o_mainwindow performSelectorOnMainThread:@selector(togglePlaylist:) withObject: nil waitUntilDone:NO]; + } } - else - [o_mainmenu setRateControlsEnabled: NO]; [o_playlist updateRowSelection]; [o_mainwindow updateWindow]; - [o_mainwindow updateName]; + [self updateDelays]; + [self updateMainMenu]; +} + +- (void)updateMainMenu +{ [o_mainmenu setupMenus]; [o_mainmenu updatePlaybackRate]; } @@ -1261,9 +1488,14 @@ unsigned int CocoaKeyToVLC( unichar i_key ) [o_mainwindow updateWindow]; } +- (void)showMainWindow +{ + [o_mainwindow performSelectorOnMainThread:@selector(makeKeyAndOrderFront:) withObject:nil waitUntilDone:NO]; +} + - (void)showFullscreenController { - [o_mainwindow showFullscreenController]; + [o_mainwindow performSelectorOnMainThread:@selector(showFullscreenController) withObject:nil waitUntilDone:NO]; } - (void)updateDelays @@ -1284,7 +1516,7 @@ unsigned int CocoaKeyToVLC( unichar i_key ) p_input = pl_CurrentInput( p_intf ); if( p_input ) { - if( var_GetInteger( p_input, "state" ) == PLAYING_S ) + if( var_GetInteger( p_input, "state" ) == PLAYING_S && [self activeVideoPlayback] ) UpdateSystemActivity( UsrActivity ); vlc_object_release( p_input ); } @@ -1300,6 +1532,12 @@ unsigned int CocoaKeyToVLC( unichar i_key ) [self playbackStatusUpdated]; [o_playlist playlistUpdated]; [o_mainwindow updateWindow]; + [o_mainwindow updateName]; +} + +- (void)updateRecordState: (BOOL)b_value +{ + [o_mainmenu updateRecordState:b_value]; } - (void)updateInfoandMetaPanel @@ -1329,6 +1567,17 @@ unsigned int CocoaKeyToVLC( unichar i_key ) } vlc_object_release( p_input ); } + + [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(updateMainWindow) withObject: nil waitUntilDone: NO]; + [self performSelectorOnMainThread:@selector(sendDistributedNotificationWithUpdatedPlaybackStatus) withObject: nil waitUntilDone: NO]; +} + +- (void)sendDistributedNotificationWithUpdatedPlaybackStatus +{ + [[NSDistributedNotificationCenter defaultCenter] postNotificationName:@"VLCPlayerStateDidChange" + object:nil + userInfo:nil + deliverImmediately:YES]; } - (void)playbackModeUpdated @@ -1361,6 +1610,11 @@ unsigned int CocoaKeyToVLC( unichar i_key ) return o_mainmenu; } +- (id)mainWindow +{ + return o_mainwindow; +} + - (id)controls { if( o_controls ) @@ -1447,16 +1701,16 @@ unsigned int CocoaKeyToVLC( unichar i_key ) - (id)getVideoViewAtPositionX: (int *)pi_x Y: (int *)pi_y withWidth: (unsigned int*)pi_width andHeight: (unsigned int*)pi_height { - id videoView = [o_mainwindow videoView]; + id videoView = [o_mainwindow setupVideoView]; NSRect videoRect = [videoView frame]; int i_x = (int)videoRect.origin.x; int i_y = (int)videoRect.origin.y; unsigned int i_width = (int)videoRect.size.width; unsigned int i_height = (int)videoRect.size.height; - pi_x = (int *)i_x; - pi_y = (int *)i_y; - pi_width = (unsigned int*)i_width; - pi_height = (unsigned int*)i_height; + pi_x = &i_x; + pi_y = &i_y; + pi_width = &i_width; + pi_height = &i_height; msg_Dbg( VLCIntf, "returning videoview with x=%i, y=%i, width=%i, height=%i", i_x, i_y, i_width, i_height ); return videoView; } @@ -1492,14 +1746,17 @@ unsigned int CocoaKeyToVLC( unichar i_key ) - (id)appleRemoteController { - return o_remote; + return o_remote; } - (void)setActiveVideoPlayback:(BOOL)b_value { b_active_videoplayback = b_value; - [o_mainwindow setVideoplayEnabled]; - [o_mainwindow togglePlaylist:nil]; + if( o_mainwindow ) + { + [o_mainwindow performSelectorOnMainThread:@selector(setVideoplayEnabled) withObject:nil waitUntilDone:YES]; + [o_mainwindow performSelectorOnMainThread:@selector(togglePlaylist:) withObject:nil waitUntilDone:NO]; + } } - (BOOL)activeVideoPlayback @@ -1649,42 +1906,55 @@ unsigned int CocoaKeyToVLC( unichar i_key ) - (void)_removeOldPreferences { static NSString * kVLCPreferencesVersion = @"VLCPreferencesVersion"; - static const int kCurrentPreferencesVersion = 1; + static const int kCurrentPreferencesVersion = 2; int version = [[NSUserDefaults standardUserDefaults] integerForKey:kVLCPreferencesVersion]; if( version >= kCurrentPreferencesVersion ) return; - NSArray *libraries = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, - NSUserDomainMask, YES); - if( !libraries || [libraries count] == 0) return; - NSString * preferences = [[libraries objectAtIndex:0] stringByAppendingPathComponent:@"Preferences"]; - - /* File not found, don't attempt anything */ - if(![[NSFileManager defaultManager] fileExistsAtPath:[preferences stringByAppendingPathComponent:@"VLC"]] && - ![[NSFileManager defaultManager] fileExistsAtPath:[preferences stringByAppendingPathComponent:@"org.videolan.vlc.plist"]] ) + if( version == 1 ) { [[NSUserDefaults standardUserDefaults] setInteger:kCurrentPreferencesVersion forKey:kVLCPreferencesVersion]; - return; - } + [[NSUserDefaults standardUserDefaults] synchronize]; - int res = NSRunInformationalAlertPanel(_NS("Remove old preferences?"), - _NS("We just found an older version of VLC's preferences files."), - _NS("Move To Trash and Relaunch VLC"), _NS("Ignore"), nil, nil); - if( res != NSOKButton ) - { - [[NSUserDefaults standardUserDefaults] setInteger:kCurrentPreferencesVersion forKey:kVLCPreferencesVersion]; - return; + if (![[VLCCoreInteraction sharedInstance] fixPreferences]) + return; + else + config_SaveConfigFile( VLCIntf ); // we need to do manually, since we won't quit libvlc cleanly } + else + { + NSArray *libraries = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, + NSUserDomainMask, YES); + if( !libraries || [libraries count] == 0) return; + NSString * preferences = [[libraries objectAtIndex:0] stringByAppendingPathComponent:@"Preferences"]; + + /* File not found, don't attempt anything */ + if(![[NSFileManager defaultManager] fileExistsAtPath:[preferences stringByAppendingPathComponent:@"org.videolan.vlc"]] && + ![[NSFileManager defaultManager] fileExistsAtPath:[preferences stringByAppendingPathComponent:@"org.videolan.vlc.plist"]] ) + { + [[NSUserDefaults standardUserDefaults] setInteger:kCurrentPreferencesVersion forKey:kVLCPreferencesVersion]; + return; + } + + int res = NSRunInformationalAlertPanel(_NS("Remove old preferences?"), + _NS("We just found an older version of VLC's preferences files."), + _NS("Move To Trash and Relaunch VLC"), _NS("Ignore"), nil, nil); + if( res != NSOKButton ) + { + [[NSUserDefaults standardUserDefaults] setInteger:kCurrentPreferencesVersion forKey:kVLCPreferencesVersion]; + return; + } - NSArray * ourPreferences = [NSArray arrayWithObjects:@"org.videolan.vlc.plist", @"VLC", nil]; + NSArray * ourPreferences = [NSArray arrayWithObjects:@"org.videolan.vlc.plist", @"VLC", @"org.videolan.vlc", nil]; - /* Move the file to trash so that user can find them later */ - [[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation source:preferences destination:nil files:ourPreferences tag:0]; + /* Move the file to trash so that user can find them later */ + [[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation source:preferences destination:nil files:ourPreferences tag:0]; - /* really reset the defaults from now on */ - [NSUserDefaults resetStandardUserDefaults]; + /* really reset the defaults from now on */ + [NSUserDefaults resetStandardUserDefaults]; - [[NSUserDefaults standardUserDefaults] setInteger:kCurrentPreferencesVersion forKey:kVLCPreferencesVersion]; - [[NSUserDefaults standardUserDefaults] synchronize]; + [[NSUserDefaults standardUserDefaults] setInteger:kCurrentPreferencesVersion forKey:kVLCPreferencesVersion]; + [[NSUserDefaults standardUserDefaults] synchronize]; + } /* Relaunch now */ const char * path = [[[NSBundle mainBundle] executablePath] UTF8String]; @@ -1700,6 +1970,11 @@ unsigned int CocoaKeyToVLC( unichar i_key ) #pragma mark - #pragma mark Errors, warnings and messages +- (IBAction)updateMessagesPanel:(id)sender +{ + [self windowDidBecomeKey:nil]; +} + - (IBAction)showMessagesPanel:(id)sender { [o_msgs_panel makeKeyAndOrderFront: sender]; @@ -1707,68 +1982,67 @@ unsigned int CocoaKeyToVLC( unichar i_key ) - (void)windowDidBecomeKey:(NSNotification *)o_notification { - if( [o_notification object] == o_msgs_panel ) - [self updateMessageDisplay]; + [o_msgs_table reloadData]; + [o_msgs_table scrollRowToVisible: [o_msg_arr count] - 1]; } -- (void)updateMessageDisplay +- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView { - if( [o_msgs_panel isVisible] && b_msg_arr_changed ) - { - id o_msg; - NSEnumerator * o_enum; - - [o_messages setString: @""]; - - [o_msg_lock lock]; - - o_enum = [o_msg_arr objectEnumerator]; - - while( ( o_msg = [o_enum nextObject] ) != nil ) - { - [o_messages insertText: o_msg]; - } - - b_msg_arr_changed = NO; - [o_msg_lock unlock]; - } + if (aTableView == o_msgs_table) + return [o_msg_arr count]; + return 0; } -- (void)processReceivedlibvlcMessage:(const msg_item_t *)item +- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex { - NSColor *o_white = [NSColor whiteColor]; - NSColor *o_red = [NSColor redColor]; - NSColor *o_yellow = [NSColor yellowColor]; - NSColor *o_gray = [NSColor grayColor]; + NSMutableAttributedString *result = NULL; - NSColor * pp_color[4] = { o_white, o_red, o_yellow, o_gray }; - static const char * ppsz_type[4] = { ": ", " error: ", " warning: ", " debug: " }; + [o_msg_lock lock]; + if( rowIndex < [o_msg_arr count] ) + result = [o_msg_arr objectAtIndex: rowIndex]; + [o_msg_lock unlock]; - NSDictionary *o_attr; - NSAttributedString *o_msg_color; + if( result != NULL ) + return result; + else + return @""; +} - int i_type = item->i_type; +- (void)processReceivedlibvlcMessage:(const msg_item_t *) item ofType: (int)i_type withStr: (char *)str +{ + if (o_msg_arr) + { + NSColor *o_white = [NSColor whiteColor]; + NSColor *o_red = [NSColor redColor]; + NSColor *o_yellow = [NSColor yellowColor]; + NSColor *o_gray = [NSColor grayColor]; + NSString * firstString, * secondString; - [o_msg_lock lock]; + NSColor * pp_color[4] = { o_white, o_red, o_yellow, o_gray }; + static const char * ppsz_type[4] = { ": ", " error: ", " warning: ", " debug: " }; - if( [o_msg_arr count] + 2 > 600 ) - { - [o_msg_arr removeObjectAtIndex: 0]; - [o_msg_arr removeObjectAtIndex: 1]; - } + NSDictionary *o_attr; + NSMutableAttributedString *o_msg_color; - o_attr = [NSDictionary dictionaryWithObject: o_gray forKey: NSForegroundColorAttributeName]; - o_msg_color = [[NSAttributedString alloc] initWithString: [NSString stringWithFormat: @"%s%s", item->psz_module, ppsz_type[i_type]] attributes: o_attr]; - [o_msg_arr addObject: [o_msg_color autorelease]]; + [o_msg_lock lock]; - o_attr = [NSDictionary dictionaryWithObject: pp_color[i_type] forKey: NSForegroundColorAttributeName]; - o_msg_color = [[NSAttributedString alloc] initWithString: [NSString stringWithFormat: @"%s\n", item->psz_msg] attributes: o_attr]; - [o_msg_arr addObject: [o_msg_color autorelease]]; + if( [o_msg_arr count] + 2 > 600 ) + { + [o_msg_arr removeObjectAtIndex: 0]; + [o_msg_arr removeObjectAtIndex: 1]; + } + firstString = [NSString stringWithFormat:@"%s%s", item->psz_module, ppsz_type[i_type]]; + secondString = [NSString stringWithFormat:@"%@%s\n", firstString, str]; - b_msg_arr_changed = YES; - [o_msg_lock unlock]; + o_attr = [NSDictionary dictionaryWithObject: pp_color[i_type] forKey: NSForegroundColorAttributeName]; + o_msg_color = [[NSMutableAttributedString alloc] initWithString: secondString attributes: o_attr]; + o_attr = [NSDictionary dictionaryWithObject: pp_color[3] forKey: NSForegroundColorAttributeName]; + [o_msg_color setAttributes: o_attr range: NSMakeRange( 0, [firstString length] )]; + [o_msg_arr addObject: [o_msg_color autorelease]]; - [self updateMessageDisplay]; + b_msg_arr_changed = YES; + [o_msg_lock unlock]; + } } - (IBAction)saveDebugLog:(id)sender @@ -1786,7 +2060,15 @@ unsigned int CocoaKeyToVLC( unichar i_key ) BOOL b_returned; if( returnCode == NSOKButton ) { - b_returned = [o_messages writeRTFDToFile: [[sheet URL] path] atomically: YES]; + NSUInteger count = [o_msg_arr count]; + NSMutableAttributedString * string = [[NSMutableAttributedString alloc] init]; + for (NSUInteger i = 0; i < count; i++) + { + [string appendAttributedString: [o_msg_arr objectAtIndex: i]]; + } + b_returned = [[string RTFDFileWrapperFromRange:NSMakeRange( 0, [string length] ) documentAttributes:[NSDictionary dictionaryWithObject: NSRTFDTextDocumentType forKey: NSDocumentTypeDocumentAttribute]] writeToFile:[[sheet URL] path] atomically:YES updateFilenames:NO]; + [string release]; + if(! b_returned ) msg_Warn( p_intf, "Error while saving the debug log" ); } @@ -1832,30 +2114,14 @@ unsigned int CocoaKeyToVLC( unichar i_key ) - (void)coreChangedMediaKeySupportSetting: (NSNotification *)o_notification { b_mediaKeySupport = config_GetInt( VLCIntf, "macosx-mediakeys" ); - if (b_mediaKeySupport) { + if (b_mediaKeySupport) + { if (!o_mediaKeyController) o_mediaKeyController = [[SPMediaKeyTap alloc] initWithDelegate:self]; [o_mediaKeyController startWatchingMediaKeys]; } else if (!b_mediaKeySupport && o_mediaKeyController) - { - int returnedValue = NSRunInformationalAlertPanel(_NS("Relaunch required"), - _NS("To make sure that VLC no longer listens to your media key events, it needs to be restarted."), - _NS("Relaunch VLC"), _NS("Ignore"), nil, nil); - if( returnedValue == NSOKButton ) - { - /* Relaunch now */ - const char * path = [[[NSBundle mainBundle] executablePath] UTF8String]; - - /* For some reason we need to fork(), not just execl(), which reports a ENOTSUP then. */ - if(fork() != 0) - { - exit(0); - return; - } - execl(path, path, NULL); - } - } + [o_mediaKeyController stopWatchingMediaKeys]; } @end @@ -1868,7 +2134,7 @@ unsigned int CocoaKeyToVLC( unichar i_key ) // when user selects the quit menu from dock it sends a terminate: // but we need to send a stop: to properly exits libvlc. // However, we are not able to change the action-method sent by this standard menu item. -// thus we override terminat: to send a stop: +// thus we override terminate: to send a stop: // see [af97f24d528acab89969d6541d83f17ce1ecd580] that introduced the removal of setjmp() and longjmp() - (void)terminate:(id)sender {