diff --git a/Application/MediaKeysApplication.h b/Application/MediaKeysApplication.h index c19a43221..61e0e28cf 100644 --- a/Application/MediaKeysApplication.h +++ b/Application/MediaKeysApplication.h @@ -7,14 +7,8 @@ // #import -#import - -@class SPMediaKeyTap; @interface MediaKeysApplication : NSApplication -{ - SPMediaKeyTap *keyTap; -} @end diff --git a/Application/MediaKeysApplication.m b/Application/MediaKeysApplication.m index ef7f58b72..bc3f425a2 100644 --- a/Application/MediaKeysApplication.m +++ b/Application/MediaKeysApplication.m @@ -8,7 +8,6 @@ #import "MediaKeysApplication.h" #import "AppController.h" -#import "SPMediaKeyTap.h" #import "Logging.h" #import @@ -21,11 +20,6 @@ - (void)finishLaunching { [super finishLaunching]; - - [[NSUserDefaults standardUserDefaults] addObserver:self - forKeyPath:@"allowLastfmMediaKeys" - options:NSKeyValueObservingOptionNew - context:nil]; MPRemoteCommandCenter *remoteCommandCenter = [MPRemoteCommandCenter sharedCommandCenter]; diff --git a/Cog.xcodeproj/project.pbxproj b/Cog.xcodeproj/project.pbxproj index bb6ae6ad5..0f91c4964 100644 --- a/Cog.xcodeproj/project.pbxproj +++ b/Cog.xcodeproj/project.pbxproj @@ -131,8 +131,6 @@ 836D28A818086386005B7299 /* MiniModeMenuTitleTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 836D28A718086386005B7299 /* MiniModeMenuTitleTransformer.m */; }; 836F5BF91A357A01002730CC /* sidplay.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8314D6411A354DFF00EEE8E6 /* sidplay.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 836FB5A718206F2500B3AD2D /* Hively.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 836FB5471820538800B3AD2D /* Hively.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; - 83790D501809F4980073CF51 /* NSObject+SPInvocationGrabbing.m in Sources */ = {isa = PBXBuildFile; fileRef = 83790D4D1809F4980073CF51 /* NSObject+SPInvocationGrabbing.m */; }; - 83790D511809F4980073CF51 /* SPMediaKeyTap.m in Sources */ = {isa = PBXBuildFile; fileRef = 83790D4F1809F4980073CF51 /* SPMediaKeyTap.m */; }; 838491211807F38A00E7332D /* NowPlayingBarView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8384911D1807F38A00E7332D /* NowPlayingBarView.m */; }; 838491221807F38A00E7332D /* NowPlayingBarController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8384911E1807F38A00E7332D /* NowPlayingBarController.xib */; }; 838491231807F38A00E7332D /* NowPlayingBarController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8384911F1807F38A00E7332D /* NowPlayingBarController.m */; }; @@ -888,10 +886,6 @@ 836F6B2518BDB80D0095E648 /* vgmstream.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = vgmstream.xcodeproj; path = Plugins/vgmstream/vgmstream.xcodeproj; sourceTree = ""; }; 836FB5421820538700B3AD2D /* Hively.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Hively.xcodeproj; path = Plugins/Hively/Hively.xcodeproj; sourceTree = ""; }; 8375B05117FFEA400092A79F /* OpusPlugin.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = OpusPlugin.xcodeproj; path = Plugins/Opus/OpusPlugin.xcodeproj; sourceTree = ""; }; - 83790D4C1809F4980073CF51 /* NSObject+SPInvocationGrabbing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+SPInvocationGrabbing.h"; sourceTree = ""; }; - 83790D4D1809F4980073CF51 /* NSObject+SPInvocationGrabbing.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+SPInvocationGrabbing.m"; sourceTree = ""; }; - 83790D4E1809F4980073CF51 /* SPMediaKeyTap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPMediaKeyTap.h; sourceTree = ""; }; - 83790D4F1809F4980073CF51 /* SPMediaKeyTap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPMediaKeyTap.m; sourceTree = ""; }; 8384911D1807F38A00E7332D /* NowPlayingBarView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NowPlayingBarView.m; path = Window/NowPlayingBarView.m; sourceTree = ""; }; 8384911E1807F38A00E7332D /* NowPlayingBarController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = NowPlayingBarController.xib; path = Window/NowPlayingBarController.xib; sourceTree = ""; }; 8384911F1807F38A00E7332D /* NowPlayingBarController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NowPlayingBarController.m; path = Window/NowPlayingBarController.m; sourceTree = ""; }; @@ -1097,7 +1091,6 @@ 177EBF770B8BC2A70000BC8C /* ThirdParty */ = { isa = PBXGroup; children = ( - 83790D4A1809F4980073CF51 /* SPMediaKeyTap */, 177EBF850B8BC2A70000BC8C /* ImageTextCell */, 179790DD0C087AB7001D6996 /* OpenURLPanel */, ); @@ -1596,25 +1589,6 @@ name = Products; sourceTree = ""; }; - 83790D4A1809F4980073CF51 /* SPMediaKeyTap */ = { - isa = PBXGroup; - children = ( - 83790D4B1809F4980073CF51 /* SPInvocationGrabbing */, - 83790D4E1809F4980073CF51 /* SPMediaKeyTap.h */, - 83790D4F1809F4980073CF51 /* SPMediaKeyTap.m */, - ); - path = SPMediaKeyTap; - sourceTree = ""; - }; - 83790D4B1809F4980073CF51 /* SPInvocationGrabbing */ = { - isa = PBXGroup; - children = ( - 83790D4C1809F4980073CF51 /* NSObject+SPInvocationGrabbing.h */, - 83790D4D1809F4980073CF51 /* NSObject+SPInvocationGrabbing.m */, - ); - path = SPInvocationGrabbing; - sourceTree = ""; - }; 83B0669D180D5668008E3612 /* Products */ = { isa = PBXGroup; children = ( @@ -1837,7 +1811,7 @@ LastUpgradeCheck = 1100; TargetAttributes = { 8D1107260486CEB800E47090 = { - DevelopmentTeam = ""; + DevelopmentTeam = RXH4D9SUXM; LastSwiftMigration = 1220; ProvisioningStyle = Automatic; }; @@ -2324,7 +2298,6 @@ 8E75757209F31D5A0080F1EE /* PlaylistController.m in Sources */, 8E75757309F31D5A0080F1EE /* PlaylistEntry.m in Sources */, 8E75757409F31D5A0080F1EE /* PlaylistView.m in Sources */, - 83790D511809F4980073CF51 /* SPMediaKeyTap.m in Sources */, 8E75757509F31D5A0080F1EE /* Shuffle.m in Sources */, 8E1296DB0A2BA9CE00443124 /* PlaylistHeaderView.m in Sources */, 8E07AB790AAC930B00A4B32F /* PreferencesController.m in Sources */, @@ -2340,7 +2313,6 @@ 8E9A30160BA792DC0091081B /* NSFileHandle+CreateFile.m in Sources */, 179790E10C087AB7001D6996 /* OpenURLPanel.m in Sources */, EDAAA41F25A665C000731773 /* PositionSliderToolbarItem.swift in Sources */, - 83790D501809F4980073CF51 /* NSObject+SPInvocationGrabbing.m in Sources */, 1791FF900CB43A2C0070BC5C /* MediaKeysApplication.m in Sources */, 838491211807F38A00E7332D /* NowPlayingBarView.m in Sources */, 5604D45B0D60349B004F5C5D /* SpotlightWindowController.m in Sources */, diff --git a/ThirdParty/SPMediaKeyTap/SPInvocationGrabbing/NSObject+SPInvocationGrabbing.h b/ThirdParty/SPMediaKeyTap/SPInvocationGrabbing/NSObject+SPInvocationGrabbing.h deleted file mode 100644 index d30233daf..000000000 --- a/ThirdParty/SPMediaKeyTap/SPInvocationGrabbing/NSObject+SPInvocationGrabbing.h +++ /dev/null @@ -1,30 +0,0 @@ -#import - -@interface SPInvocationGrabber : NSObject { - id _object; - NSInvocation *_invocation; - int frameCount; - char **frameStrings; - BOOL backgroundAfterForward; - BOOL onMainAfterForward; - BOOL waitUntilDone; -} --(id)initWithObject:(id)obj; --(id)initWithObject:(id)obj stacktraceSaving:(BOOL)saveStack; -@property (readonly, retain, nonatomic) id object; -@property (readonly, retain, nonatomic) NSInvocation *invocation; -@property BOOL backgroundAfterForward; -@property BOOL onMainAfterForward; -@property BOOL waitUntilDone; --(void)invoke; // will release object and invocation --(void)printBacktrace; --(void)saveBacktrace; -@end - -@interface NSObject (SPInvocationGrabbing) --(id)grab; --(id)invokeAfter:(NSTimeInterval)delta; --(id)nextRunloop; --(id)inBackground; --(id)onMainAsync:(BOOL)async; -@end diff --git a/ThirdParty/SPMediaKeyTap/SPInvocationGrabbing/NSObject+SPInvocationGrabbing.m b/ThirdParty/SPMediaKeyTap/SPInvocationGrabbing/NSObject+SPInvocationGrabbing.m deleted file mode 100644 index 3ca7eb2d2..000000000 --- a/ThirdParty/SPMediaKeyTap/SPInvocationGrabbing/NSObject+SPInvocationGrabbing.m +++ /dev/null @@ -1,120 +0,0 @@ -#import "NSObject+SPInvocationGrabbing.h" -#import - -#pragma mark Invocation grabbing -@interface SPInvocationGrabber () -@property (readwrite, retain, nonatomic) id object; -@property (readwrite, retain, nonatomic) NSInvocation *invocation; - -@end - -@implementation SPInvocationGrabber -- (id)initWithObject:(id)obj; -{ - return [self initWithObject:obj stacktraceSaving:YES]; -} - --(id)initWithObject:(id)obj stacktraceSaving:(BOOL)saveStack; -{ - self.object = obj; - - if(saveStack) - [self saveBacktrace]; - - return self; -} --(void)dealloc; -{ - free(frameStrings); - self.object = nil; - self.invocation = nil; -} -@synthesize invocation = _invocation, object = _object; - -@synthesize backgroundAfterForward, onMainAfterForward, waitUntilDone; -- (void)runInBackground; -{ - [self invoke]; -} - - -- (void)forwardInvocation:(NSInvocation *)anInvocation { - [anInvocation retainArguments]; - anInvocation.target = _object; - self.invocation = anInvocation; - - if(backgroundAfterForward) - [NSThread detachNewThreadSelector:@selector(runInBackground) toTarget:self withObject:nil]; - else if(onMainAfterForward) - [self performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:waitUntilDone]; -} -- (NSMethodSignature *)methodSignatureForSelector:(SEL)inSelector { - NSMethodSignature *signature = [super methodSignatureForSelector:inSelector]; - if (signature == NULL) - signature = [_object methodSignatureForSelector:inSelector]; - - return signature; -} - -- (void)invoke; -{ - - @try { - [_invocation invoke]; - } - @catch (NSException * e) { - NSLog(@"SPInvocationGrabber's target raised %@:\n\t%@\nInvocation was originally scheduled at:", e.name, e); - [self printBacktrace]; - printf("\n"); - [e raise]; - } - - self.invocation = nil; - self.object = nil; -} - --(void)saveBacktrace; -{ - void *backtraceFrames[128]; - frameCount = backtrace(&backtraceFrames[0], 128); - frameStrings = backtrace_symbols(&backtraceFrames[0], frameCount); -} --(void)printBacktrace; -{ - for(int x = 3; x < frameCount; x++) { - if(frameStrings[x] == NULL) { break; } - printf("%s\n", frameStrings[x]); - } -} -@end - -@implementation NSObject (SPInvocationGrabbing) --(id)grab; -{ - return [[SPInvocationGrabber alloc] initWithObject:self]; -} --(id)invokeAfter:(NSTimeInterval)delta; -{ - id grabber = [self grab]; - [NSTimer scheduledTimerWithTimeInterval:delta target:grabber selector:@selector(invoke) userInfo:nil repeats:NO]; - return grabber; -} -- (id)nextRunloop; -{ - return [self invokeAfter:0]; -} --(id)inBackground; -{ - SPInvocationGrabber *grabber = [self grab]; - grabber.backgroundAfterForward = YES; - return grabber; -} --(id)onMainAsync:(BOOL)async; -{ - SPInvocationGrabber *grabber = [self grab]; - grabber.onMainAfterForward = YES; - grabber.waitUntilDone = !async; - return grabber; -} - -@end diff --git a/ThirdParty/SPMediaKeyTap/SPMediaKeyTap.h b/ThirdParty/SPMediaKeyTap/SPMediaKeyTap.h deleted file mode 100644 index f3c864fdc..000000000 --- a/ThirdParty/SPMediaKeyTap/SPMediaKeyTap.h +++ /dev/null @@ -1,48 +0,0 @@ -#include -#import -#import - -// http://overooped.com/post/2593597587/mediakeys - -#define SPSystemDefinedEventMediaKeys 8 -#define SPPassthroughEventData2Value -10 - -@interface SPMediaKeyTap : NSObject { - EventHandlerRef _app_switching_ref; - EventHandlerRef _app_terminating_ref; - CFMachPortRef _eventPort; - CFRunLoopSourceRef _eventPortSource; - CFRunLoopRef _tapThreadRL; - BOOL _shouldInterceptMediaKeyEvents; - id _delegate; - // The app that is frontmost in this list owns media keys - NSMutableArray *_mediaKeyAppList; -} -+ (NSArray*)defaultMediaKeyUserBundleIdentifiers; - --(id)initWithDelegate:(id)delegate; - -+(BOOL)usesGlobalMediaKeyTap; --(BOOL)startWatchingMediaKeys; --(void)stopWatchingMediaKeys; --(void)handleAndReleaseMediaKeyEvent:(NSEvent *)event; - -@property NSArray *blackListBundleIdentifiers; - -@end - -@interface NSObject (SPMediaKeyTapDelegate) --(void)mediaKeyTap:(SPMediaKeyTap*)keyTap receivedMediaKeyEvent:(NSEvent*)event; -@end - -#ifdef __cplusplus -extern "C" { -#endif - -extern NSString *kMediaKeyUsingBundleIdentifiersDefaultsKey; -extern NSString *kMediaKeyUsingBlackListBundleIdentifiersDefaultsKey; -extern NSString *kIgnoreMediaKeysDefaultsKey; - -#ifdef __cplusplus -} -#endif diff --git a/ThirdParty/SPMediaKeyTap/SPMediaKeyTap.m b/ThirdParty/SPMediaKeyTap/SPMediaKeyTap.m deleted file mode 100644 index 0325b5617..000000000 --- a/ThirdParty/SPMediaKeyTap/SPMediaKeyTap.m +++ /dev/null @@ -1,390 +0,0 @@ -// Copyright (c) 2010 Spotify AB -#import "SPMediaKeyTap.h" -#import "NSObject+SPInvocationGrabbing.h" // https://gist.github.com/511181, in submodule - -@interface SPMediaKeyTap () --(BOOL)shouldInterceptMediaKeyEvents; --(void)setShouldInterceptMediaKeyEvents:(BOOL)newSetting; --(void)startWatchingAppSwitching; --(void)stopWatchingAppSwitching; --(void)eventTapThread; -@end -static SPMediaKeyTap *singleton = nil; - -static pascal OSStatus appSwitched (EventHandlerCallRef nextHandler, EventRef evt, void* userData); -static pascal OSStatus appTerminated (EventHandlerCallRef nextHandler, EventRef evt, void* userData); -static CGEventRef tapEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon); - - -// Inspired by http://gist.github.com/546311 - -@implementation SPMediaKeyTap - -#pragma mark - -#pragma mark Setup and teardown --(id)initWithDelegate:(id)delegate; -{ - _delegate = delegate; - [self startWatchingAppSwitching]; - singleton = self; - _mediaKeyAppList = [NSMutableArray new]; - _blackListBundleIdentifiers = [[NSUserDefaults standardUserDefaults] - arrayForKey:kMediaKeyUsingBlackListBundleIdentifiersDefaultsKey]; - _tapThreadRL=nil; - _eventPort=nil; - _eventPortSource=nil; - return self; -} --(void)dealloc; -{ - [self stopWatchingMediaKeys]; - [self stopWatchingAppSwitching]; -} - --(void)startWatchingAppSwitching; -{ - // Listen to "app switched" event, so that we don't intercept media keys if we - // weren't the last "media key listening" app to be active - EventTypeSpec eventType = { kEventClassApplication, kEventAppFrontSwitched }; - OSStatus err = InstallApplicationEventHandler(NewEventHandlerUPP(appSwitched), 1, &eventType, (__bridge void*)self, &_app_switching_ref); - assert(err == noErr); - - eventType.eventKind = kEventAppTerminated; - err = InstallApplicationEventHandler(NewEventHandlerUPP(appTerminated), 1, &eventType, (__bridge void*)self, &_app_terminating_ref); - assert(err == noErr); -} --(void)stopWatchingAppSwitching; -{ - if(!_app_switching_ref) return; - RemoveEventHandler(_app_switching_ref); - _app_switching_ref = NULL; -} - --(BOOL)startWatchingMediaKeys;{ - // Prevent having multiple mediaKeys threads - [self stopWatchingMediaKeys]; - - [self setShouldInterceptMediaKeyEvents:YES]; - - @synchronized(self){ - // Add an event tap to intercept the system defined media key events - _eventPort = CGEventTapCreate(kCGSessionEventTap, - kCGHeadInsertEventTap, - kCGEventTapOptionDefault, - CGEventMaskBit(NX_SYSDEFINED), - tapEventCallback, - (__bridge void*)self); - - if (_eventPort != NULL){ - _eventPortSource = CFMachPortCreateRunLoopSource(kCFAllocatorSystemDefault, _eventPort, 0); - - if (_eventPortSource != NULL){ - - // Let's do this in a separate thread so that a slow app doesn't lag the event tap - [NSThread detachNewThreadSelector:@selector(eventTapThread) toTarget:self withObject:nil]; - - return YES; - } - } - - [self setShouldInterceptMediaKeyEvents:NO]; - - return NO; - } -} --(void)stopWatchingMediaKeys; -{ - // TODO: Shut down thread, remove event tap port and source - - @synchronized(self) { - if (_tapThreadRL) { - CFRunLoopStop(_tapThreadRL); - _tapThreadRL = nil; - } - - if (_eventPort) { - CFMachPortInvalidate(_eventPort); - CFRelease(_eventPort); - _eventPort = nil; - } - - if (_eventPortSource) { - CFRelease(_eventPortSource); - _eventPortSource = nil; - } - } -} - -#pragma mark - -#pragma mark Accessors - -+(BOOL)usesGlobalMediaKeyTap -{ -#ifdef _DEBUG - // breaking in gdb with a key tap inserted sometimes locks up all mouse and keyboard input forever, forcing reboot - return NO; -#else - // XXX(nevyn): MediaKey event tap doesn't work on 10.4, feel free to figure out why if you have the energy. - return - ![[NSUserDefaults standardUserDefaults] boolForKey:kIgnoreMediaKeysDefaultsKey] - && floor(NSAppKitVersionNumber) >= 949/*NSAppKitVersionNumber10_5*/; -#endif -} - -+ (NSArray*)defaultMediaKeyUserBundleIdentifiers; -{ - return [NSArray arrayWithObjects: - [[NSBundle mainBundle] bundleIdentifier], - @"com.spotify.client", - @"com.apple.iTunes", - @"com.apple.QuickTimePlayerX", - @"com.apple.quicktimeplayer", - @"com.apple.iWork.Keynote", - @"com.apple.iPhoto", - @"org.videolan.vlc", - @"com.apple.Aperture", - @"com.plexsquared.Plex", - @"com.soundcloud.desktop", - @"org.niltsh.MPlayerX", - @"com.ilabs.PandorasHelper", - @"com.mahasoftware.pandabar", - @"com.bitcartel.pandorajam", - @"org.clementine-player.clementine", - @"fm.last.Last.fm", - @"fm.last.Scrobbler", - @"com.beatport.BeatportPro", - @"com.Timenut.SongKey", - @"com.macromedia.fireworks", // the tap messes up their mouse input - @"at.justp.Theremin", - @"ru.ya.themblsha.YandexMusic", - @"com.jriver.MediaCenter18", - @"com.jriver.MediaCenter19", - @"com.jriver.MediaCenter20", - @"co.rackit.mate", - @"com.ttitt.b-music", - @"com.beardedspice.BeardedSpice", //BeardedSpice - @"com.plug.Plug", - @"com.plug.Plug2", - @"com.netease.163music", - @"com.coppertino.Vox", - @"com.tidal.desktop", - @"com.amazon.music", - @"com.apple.systempreferences", // the tap messes up security dialogs - nil - ]; -} - --(BOOL)shouldInterceptMediaKeyEvents; -{ - BOOL shouldIntercept = NO; - @synchronized(self) { - shouldIntercept = _shouldInterceptMediaKeyEvents; - } - return shouldIntercept; -} - --(void)pauseTapOnTapThread:(BOOL)yeahno; -{ - @synchronized(self){ - if (self->_eventPort) { - CGEventTapEnable(self->_eventPort, yeahno); - } - } -} --(void)setShouldInterceptMediaKeyEvents:(BOOL)newSetting; -{ - BOOL oldSetting; - @synchronized(self) { - oldSetting = _shouldInterceptMediaKeyEvents; - _shouldInterceptMediaKeyEvents = newSetting; - } - if(_tapThreadRL && oldSetting != newSetting) { - id grab = [self grab]; - [grab pauseTapOnTapThread:newSetting]; - NSTimer *timer = [NSTimer timerWithTimeInterval:0 invocation:[grab invocation] repeats:NO]; - CFRunLoopAddTimer(_tapThreadRL, (__bridge CFRunLoopTimerRef)timer, kCFRunLoopCommonModes); - } -} - -#pragma mark -#pragma mark - -#pragma mark Event tap callbacks - -// Note: method called on background thread - -static CGEventRef tapEventCallback2(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) -{ - SPMediaKeyTap *self = (__bridge id)refcon; - - if(type == kCGEventTapDisabledByTimeout) { - NSLog(@"Media key event tap was disabled by timeout"); - @synchronized(self){ - if (self->_eventPort) { - CGEventTapEnable(self->_eventPort, TRUE); - } - } - return event; - } else if(type == kCGEventTapDisabledByUserInput) { - // Was disabled manually by -[pauseTapOnTapThread] - return event; - } - NSEvent *nsEvent = nil; - @try { - nsEvent = [NSEvent eventWithCGEvent:event]; - } - @catch (NSException * e) { - NSLog(@"Strange CGEventType: %d: %@", type, e); - assert(0); - return event; - } - - // Passthrough marker found - if (nsEvent.data2 == SPPassthroughEventData2Value) { - return event; - } - - if (type != NX_SYSDEFINED || [nsEvent subtype] != SPSystemDefinedEventMediaKeys) - return event; - - int keyCode = (([nsEvent data1] & 0xFFFF0000) >> 16); - - if (keyCode != NX_KEYTYPE_PLAY - && keyCode != NX_KEYTYPE_FAST - && keyCode != NX_KEYTYPE_REWIND - && keyCode != NX_KEYTYPE_PREVIOUS - && keyCode != NX_KEYTYPE_NEXT - ) - return event; - - if (![self shouldInterceptMediaKeyEvents]) - return event; - - [self performSelectorOnMainThread:@selector(handleAndReleaseMediaKeyEvent:) withObject:nsEvent waitUntilDone:NO]; - - return NULL; -} - -static CGEventRef tapEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) -{ - return tapEventCallback2(proxy, type, event, refcon); -} - - -// event will have been retained in the other thread --(void)handleAndReleaseMediaKeyEvent:(NSEvent *)event { - [_delegate mediaKeyTap:self receivedMediaKeyEvent:event]; -} - -- (void)eventTapThread; -{ - @synchronized(self) { - if (_eventPortSource) { - _tapThreadRL = CFRunLoopGetCurrent(); - - if (_tapThreadRL) { - CFRunLoopAddSource(_tapThreadRL, _eventPortSource, - kCFRunLoopCommonModes); - } - } - } - CFRunLoopRun(); -} - -#pragma mark Task switching callbacks - -NSString *kMediaKeyUsingBundleIdentifiersDefaultsKey = @"SPApplicationsNeedingMediaKeys"; -NSString *kMediaKeyUsingBlackListBundleIdentifiersDefaultsKey = @"SPApplicationsNotNeedingMediaKeys"; -NSString *kIgnoreMediaKeysDefaultsKey = @"SPIgnoreMediaKeys"; - - - --(void)mediaKeyAppListChanged; -{ - if([_mediaKeyAppList count] == 0) return; - - /*NSLog(@"--"); - int i = 0; - for (NSValue *psnv in _mediaKeyAppList) { - ProcessSerialNumber psn; [psnv getValue:&psn]; - NSDictionary *processInfo = [(id)ProcessInformationCopyDictionary( - &psn, - kProcessDictionaryIncludeAllInformationMask - ) autorelease]; - NSString *bundleIdentifier = [processInfo objectForKey:(id)kCFBundleIdentifierKey]; - NSLog(@"%d: %@", i++, bundleIdentifier); - }*/ - - ProcessSerialNumber mySerial, topSerial; - GetCurrentProcess(&mySerial); - [[_mediaKeyAppList objectAtIndex:0] getValue:&topSerial]; - - Boolean same; - OSErr err = SameProcess(&mySerial, &topSerial, &same); - [self setShouldInterceptMediaKeyEvents:(err == noErr && same)]; - -} -- (void)appIsNowFrontmost:(ProcessSerialNumber)psn; -{ - NSValue *psnv = - [NSValue valueWithBytes:&psn objCType:@encode(ProcessSerialNumber)]; - - NSDictionary *processInfo = CFBridgingRelease(ProcessInformationCopyDictionary( - &psn, kProcessDictionaryIncludeAllInformationMask)); - NSString *bundleIdentifier = - [processInfo objectForKey:(id)kCFBundleIdentifierKey]; - - if ([self.blackListBundleIdentifiers containsObject:bundleIdentifier]) { - NSLog(@"Media key event tap was activated by blacklist"); - [self setShouldInterceptMediaKeyEvents:YES]; - return; - } - NSArray *whitelistIdentifiers = [[NSUserDefaults standardUserDefaults] - arrayForKey:kMediaKeyUsingBundleIdentifiersDefaultsKey]; - if (![whitelistIdentifiers containsObject:bundleIdentifier]) - return; - - [_mediaKeyAppList removeObject:psnv]; - [_mediaKeyAppList insertObject:psnv atIndex:0]; - [self mediaKeyAppListChanged]; -} --(void)appTerminated:(ProcessSerialNumber)psn; -{ - NSValue *psnv = [NSValue valueWithBytes:&psn objCType:@encode(ProcessSerialNumber)]; - [_mediaKeyAppList removeObject:psnv]; - [self mediaKeyAppListChanged]; -} - -static pascal OSStatus appSwitched (EventHandlerCallRef nextHandler, EventRef evt, void* userData) -{ - SPMediaKeyTap *self = (__bridge id)userData; - - ProcessSerialNumber newSerial; - GetFrontProcess(&newSerial); - - [self appIsNowFrontmost:newSerial]; - - return CallNextEventHandler(nextHandler, evt); -} - -static pascal OSStatus appTerminated (EventHandlerCallRef nextHandler, EventRef evt, void* userData) -{ - SPMediaKeyTap *self = (__bridge id)userData; - - ProcessSerialNumber deadPSN; - - GetEventParameter( - evt, - kEventParamProcessID, - typeProcessSerialNumber, - NULL, - sizeof(deadPSN), - NULL, - &deadPSN - ); - - - [self appTerminated:deadPSN]; - return CallNextEventHandler(nextHandler, evt); -} - -@end