diff --git a/Application/PlaybackController.h b/Application/PlaybackController.h index c6c81db43..bebab0f12 100644 --- a/Application/PlaybackController.h +++ b/Application/PlaybackController.h @@ -2,8 +2,6 @@ #import -#import - #import "CogAudio/AudioPlayer.h" #import "TrackingSlider.h" #import "AudioScrobbler.h" @@ -11,10 +9,16 @@ #define DEFAULT_VOLUME_DOWN 5 #define DEFAULT_VOLUME_UP DEFAULT_VOLUME_DOWN +extern NSString *CogPlaybackDidBeginNotficiation; +extern NSString *CogPlaybackDidPauseNotficiation; +extern NSString *CogPlaybackDidResumeNotficiation; +extern NSString *CogPlaybackDidStopNotficiation; + + @class PlaylistController; @class PlaylistView; -@interface PlaybackController : NSObject +@interface PlaybackController : NSObject { IBOutlet PlaylistController *playlistController; IBOutlet PlaylistView *playlistView; @@ -31,9 +35,6 @@ double position; BOOL seekable; BOOL fading; - - AudioScrobbler *scrobbler; - } @property int playbackStatus; diff --git a/Application/PlaybackController.m b/Application/PlaybackController.m index 188f50b31..3704651d5 100644 --- a/Application/PlaybackController.m +++ b/Application/PlaybackController.m @@ -11,6 +11,11 @@ #define DEFAULT_SEEK 5 +NSString *CogPlaybackDidBeginNotficiation = @"CogPlaybackDidBeginNotficiation"; +NSString *CogPlaybackDidPauseNotficiation = @"CogPlaybackDidPauseNotficiation"; +NSString *CogPlaybackDidResumeNotficiation = @"CogPlaybackDidResumeNotficiation"; +NSString *CogPlaybackDidStopNotficiation = @"CogPlaybackDidStopNotficiation"; + @synthesize playbackStatus; + (NSSet *)keyPathsForValuesAffectingSeekable @@ -31,9 +36,6 @@ audioPlayer = [[AudioPlayer alloc] init]; [audioPlayer setDelegate:self]; [self setPlaybackStatus: kCogStatusStopped]; - - scrobbler = [[AudioScrobbler alloc] init]; - [GrowlApplicationBridge setGrowlDelegate:self]; } return self; @@ -42,24 +44,12 @@ - (void)initDefaults { NSDictionary *defaultsDictionary = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithBool:YES], @"enableAudioScrobbler", - [NSNumber numberWithBool:NO], @"automaticallyLaunchLastFM", [NSNumber numberWithDouble:100.0], @"volume", nil]; [[NSUserDefaults standardUserDefaults] registerDefaults:defaultsDictionary]; } -- (NSDictionary *) registrationDictionaryForGrowl -{ - NSArray *notifications = [NSArray arrayWithObjects:@"Stream Changed", nil]; - - return [NSDictionary dictionaryWithObjectsAndKeys: - @"Cog", GROWL_APP_NAME, - notifications, GROWL_NOTIFICATIONS_ALL, - notifications, GROWL_NOTIFICATIONS_DEFAULT, - nil]; -} - (void)awakeFromNib @@ -96,30 +86,17 @@ { [audioPlayer pause]; [self setPlaybackStatus: kCogStatusPaused]; - - if([[NSUserDefaults standardUserDefaults] boolForKey:@"enableAudioScrobbler"]) { - [scrobbler pause]; - } } - (IBAction)resume:(id)sender { [audioPlayer resume]; - - if([[NSUserDefaults standardUserDefaults] boolForKey:@"enableAudioScrobbler"]) { - [scrobbler resume]; - } } - (IBAction)stop:(id)sender { [audioPlayer stop]; - - if([[NSUserDefaults standardUserDefaults] boolForKey:@"enableAudioScrobbler"]) { - [scrobbler stop]; - } - } //called by double-clicking on table @@ -154,18 +131,6 @@ return; [audioPlayer play:[pe URL] withUserInfo:pe]; - - if([[NSUserDefaults standardUserDefaults] boolForKey:@"enableAudioScrobbler"]) { - [scrobbler start:pe]; - } - - [GrowlApplicationBridge notifyWithTitle:[pe title] - description:[pe artist] - notificationName:@"Stream Changed" - iconData:nil - priority:0 - isSticky:NO - clickContext:nil]; } - (IBAction)next:(id)sender @@ -455,7 +420,7 @@ [[NSUserDefaults standardUserDefaults] setDouble:[audioPlayer volume] forKey:@"volume"]; } -- (void)audioPlayer:(AudioPlayer *)player requestNextStream:(id)userInfo +- (void)audioPlayer:(AudioPlayer *)player willEndStream:(id)userInfo { PlaylistEntry *curEntry = (PlaylistEntry *)userInfo; PlaylistEntry *pe; @@ -468,28 +433,18 @@ [player setNextStream:[pe URL] withUserInfo:pe]; } -- (void)audioPlayer:(AudioPlayer *)player streamChanged:(id)userInfo +- (void)audioPlayer:(AudioPlayer *)player didBeginStream:(id)userInfo { PlaylistEntry *pe = (PlaylistEntry *)userInfo; [playlistController setCurrentEntry:pe]; [self setPosition:0]; - - if([[NSUserDefaults standardUserDefaults] boolForKey:@"enableAudioScrobbler"]) { - [scrobbler start:pe]; - } - - [GrowlApplicationBridge notifyWithTitle:[pe title] - description:[pe artist] - notificationName:@"Stream Changed" - iconData:nil - priority:0 - isSticky:NO - clickContext:nil]; + + [[NSNotificationCenter defaultCenter] postNotificationName:CogPlaybackDidBeginNotficiation object:pe]; } -- (void)audioPlayer:(AudioPlayer *)player statusChanged:(id)s +- (void)audioPlayer:(AudioPlayer *)player didChangeStatus:(NSNumber *)s userInfo:(id)userInfo { int status = [s intValue]; if (status == kCogStatusStopped || status == kCogStatusPaused) @@ -504,6 +459,12 @@ { [self setPosition:0]; [self setSeekable:NO]; // the player stopped, disable the slider + + [[NSNotificationCenter defaultCenter] postNotificationName:CogPlaybackDidStopNotficiation object:nil]; + } + else // paused + { + [[NSNotificationCenter defaultCenter] postNotificationName:CogPlaybackDidPauseNotficiation object:nil]; } } else if (status == kCogStatusPlaying) @@ -512,6 +473,8 @@ positionTimer = [NSTimer timerWithTimeInterval:1.00 target:self selector:@selector(updatePosition:) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:positionTimer forMode:NSRunLoopCommonModes]; } + + [[NSNotificationCenter defaultCenter] postNotificationName:CogPlaybackDidResumeNotficiation object:nil]; } if (status == kCogStatusStopped) { diff --git a/Audio/AudioPlayer.h b/Audio/AudioPlayer.h index 770c6c2b3..25bb69777 100644 --- a/Audio/AudioPlayer.h +++ b/Audio/AudioPlayer.h @@ -80,11 +80,12 @@ - (void)launchOutputThread; - (void)endOfInputPlayed; - (void)sendDelegateMethod:(SEL)selector withObject:(id)obj waitUntilDone:(BOOL)wait; +- (void)sendDelegateMethod:(SEL)selector withObject:(id)obj withObject:(id)obj2 waitUntilDone:(BOOL)wait; @end @protocol AudioPlayerDelegate -- (void)audioPlayer:(AudioPlayer *)player requestNextStream:(id)userInfo; //You must use setNextStream in this method -- (void)audioPlayer:(AudioPlayer *)player streamChanged:(id)userInfo; -- (void)audioPlayer:(AudioPlayer *)player changedStatus:(id)status; +- (void)audioPlayer:(AudioPlayer *)player willEndStream:(id)userInfo; //You must use setNextStream in this method +- (void)audioPlayer:(AudioPlayer *)player didBeginStream:(id)userInfo; +- (void)audioPlayer:(AudioPlayer *)player didChangeStatus:(id)status; @end diff --git a/Audio/AudioPlayer.m b/Audio/AudioPlayer.m index f36aa180b..14942c176 100644 --- a/Audio/AudioPlayer.m +++ b/Audio/AudioPlayer.m @@ -75,7 +75,8 @@ } bufferChain = [[BufferChain alloc] initWithController:self]; - + [self notifyStreamChanged:userInfo]; + while (![bufferChain open:url withOutputFormat:[output format]]) { [bufferChain release]; @@ -206,12 +207,12 @@ - (void)requestNextStream:(id)userInfo { - [self sendDelegateMethod:@selector(audioPlayer:requestNextStream:) withObject:userInfo waitUntilDone:YES]; + [self sendDelegateMethod:@selector(audioPlayer:willEndStream:) withObject:userInfo waitUntilDone:YES]; } - (void)notifyStreamChanged:(id)userInfo { - [self sendDelegateMethod:@selector(audioPlayer:streamChanged:) withObject:userInfo waitUntilDone:NO]; + [self sendDelegateMethod:@selector(audioPlayer:didBeginStream:) withObject:userInfo waitUntilDone:NO]; } - (void)addChainToQueue:(BufferChain *)newChain @@ -318,7 +319,18 @@ [invocation setSelector:selector]; [invocation setArgument:&self atIndex:2]; //Indexes start at 2, the first being self, the second being command. [invocation setArgument:&obj atIndex:3]; + + [self performSelectorOnMainThread:@selector(sendDelegateMethodMainThread:) withObject:invocation waitUntilDone:wait]; +} +- (void)sendDelegateMethod:(SEL)selector withObject:(id)obj withObject:(id)obj2 waitUntilDone:(BOOL)wait +{ + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[delegate methodSignatureForSelector:selector]]; + [invocation setSelector:selector]; + [invocation setArgument:&self atIndex:2]; //Indexes start at 2, the first being self, the second being command. + [invocation setArgument:&obj atIndex:3]; + [invocation setArgument:&obj2 atIndex:4]; + [self performSelectorOnMainThread:@selector(sendDelegateMethodMainThread:) withObject:invocation waitUntilDone:wait]; } @@ -330,7 +342,7 @@ - (void)setPlaybackStatus:(int)status waitUntilDone:(BOOL)wait { - [self sendDelegateMethod:@selector(audioPlayer:statusChanged:) withObject:[NSNumber numberWithInt:status] waitUntilDone:wait]; + [self sendDelegateMethod:@selector(audioPlayer:didChangeStatus:userInfo:) withObject:[NSNumber numberWithInt:status] withObject:[bufferChain userInfo] waitUntilDone:wait]; } - (void)setPlaybackStatus:(int)status diff --git a/Cog.xcodeproj/project.pbxproj b/Cog.xcodeproj/project.pbxproj index d3cfa9c65..331c5a349 100644 --- a/Cog.xcodeproj/project.pbxproj +++ b/Cog.xcodeproj/project.pbxproj @@ -130,6 +130,7 @@ 17F3BB890CBC565900864489 /* CueSheet.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 17F3BB880CBC565100864489 /* CueSheet.bundle */; }; 17F561400C3BD4F30019975C /* CogAudio.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 17F561330C3BD4DC0019975C /* CogAudio.framework */; }; 17F562390C3BD91B0019975C /* General.preferencePane in Resources */ = {isa = PBXBuildFile; fileRef = 17F5622E0C3BD8FB0019975C /* General.preferencePane */; }; + 17F6C8070F603701000D9DA9 /* PlaybackEventController.m in Sources */ = {isa = PBXBuildFile; fileRef = 17F6C8060F603701000D9DA9 /* PlaybackEventController.m */; }; 5604D4580D603459004F5C5D /* SpotlightPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5604D4570D603459004F5C5D /* SpotlightPanel.xib */; }; 5604D45B0D60349B004F5C5D /* SpotlightWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5604D4590D60349B004F5C5D /* SpotlightWindowController.m */; }; 5604D4F60D60726E004F5C5D /* SpotlightPlaylistEntry.m in Sources */ = {isa = PBXBuildFile; fileRef = 5604D4F50D60726E004F5C5D /* SpotlightPlaylistEntry.m */; }; @@ -695,6 +696,8 @@ 17F3BB830CBC565100864489 /* CueSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CueSheet.xcodeproj; path = Plugins/CueSheet/CueSheet.xcodeproj; sourceTree = ""; }; 17F5612A0C3BD4DC0019975C /* CogAudio.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CogAudio.xcodeproj; path = Audio/CogAudio.xcodeproj; sourceTree = ""; }; 17F562260C3BD8FB0019975C /* General.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = General.xcodeproj; path = Preferences/General/General.xcodeproj; sourceTree = ""; }; + 17F6C8050F603701000D9DA9 /* PlaybackEventController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlaybackEventController.h; sourceTree = ""; }; + 17F6C8060F603701000D9DA9 /* PlaybackEventController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PlaybackEventController.m; sourceTree = ""; }; 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; @@ -859,6 +862,8 @@ 1791FF8E0CB43A2C0070BC5C /* MediaKeysApplication.m */, 171EFE8A0F59FEAE000ADC42 /* DockIconController.h */, 171EFE8B0F59FEAE000ADC42 /* DockIconController.m */, + 17F6C8050F603701000D9DA9 /* PlaybackEventController.h */, + 17F6C8060F603701000D9DA9 /* PlaybackEventController.m */, ); path = Application; sourceTree = ""; @@ -1894,6 +1899,7 @@ 172A12A90F59AF8A0078EF0C /* NSString+CogSort.m in Sources */, 1752C36C0F59E00100F85F28 /* PlaybackButtons.m in Sources */, 171EFE8C0F59FEAE000ADC42 /* DockIconController.m in Sources */, + 17F6C8070F603701000D9DA9 /* PlaybackEventController.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/English.lproj/MainMenu.xib b/English.lproj/MainMenu.xib index 2c9cb2560..fcda5036e 100644 --- a/English.lproj/MainMenu.xib +++ b/English.lproj/MainMenu.xib @@ -2845,6 +2845,9 @@ OQA DockIconController + + PlaybackEventController + AppController @@ -6871,6 +6874,14 @@ OQA 2404 + + + playbackController + + + + 2406 + @@ -9188,6 +9199,11 @@ OQA + + 2405 + + + @@ -9650,6 +9666,7 @@ OQA 24.ImportedFromIB2 24.editorWindowContentRectSynchronizationRect 2403.IBPluginDependency + 2405.IBPluginDependency 268.IBEditorWindowLastContentRect 268.IBWindowTemplateEditedContentRect 268.ImportedFromIB2 @@ -10272,6 +10289,7 @@ OQA {{442, 733}, {197, 103}} com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin {{314, 416}, {480, 376}} {{314, 416}, {480, 376}} @@ -10457,7 +10475,7 @@ OQA - 2404 + 2406 @@ -10868,6 +10886,18 @@ OQA + + PlaybackEventController + NSObject + + playbackController + PlaybackController + + + IBProjectSource + Application/PlaybackEventController.h + + PlaylistController DNDArrayController