From d6a0b0670ed12b748c1fc92622ec843fbcc2b22d Mon Sep 17 00:00:00 2001 From: vspader Date: Thu, 5 Mar 2009 20:37:44 -0800 Subject: [PATCH] Playback events for last.fm and growl are now done in the background via an operation queue. Removed hack to load metadata for autoplay. Now metadata is reloaded for each file you play. --- Application/AppController.h | 3 -- Application/AppController.m | 4 -- Application/PlaybackEventController.h | 4 +- Application/PlaybackEventController.m | 63 ++++++++++++++++++++------- English.lproj/MainMenu.xib | 16 +++++-- Playlist/PlaylistController.m | 4 -- Playlist/PlaylistLoader.h | 12 ++--- Playlist/PlaylistLoader.m | 25 ++++------- 8 files changed, 77 insertions(+), 54 deletions(-) diff --git a/Application/AppController.h b/Application/AppController.h index 3c0152e4a..e92e04d36 100644 --- a/Application/AppController.h +++ b/Application/AppController.h @@ -83,7 +83,4 @@ OSStatus handleHotKey(EventHandlerCallRef nextHandler,EventRef theEvent,void *us - (IBAction)decreaseFontSize:(id)sender; - (void)changeFontSize:(float)size; -// return the operation queue -- (NSOperationQueue *)sharedOperationQueue; - @end diff --git a/Application/AppController.m b/Application/AppController.m index c50926c2a..352140f14 100644 --- a/Application/AppController.m +++ b/Application/AppController.m @@ -469,8 +469,4 @@ increase/decrease as long as the user holds the left/right, plus/minus button */ } -- (NSOperationQueue *)sharedOperationQueue -{ - return queue; -} @end diff --git a/Application/PlaybackEventController.h b/Application/PlaybackEventController.h index 2d94ade4a..e39302c45 100644 --- a/Application/PlaybackEventController.h +++ b/Application/PlaybackEventController.h @@ -9,13 +9,13 @@ #import #import -@class PlaybackController; +@class PlaylistLoader; @class AudioScrobbler; @interface PlaybackEventController : NSObject { NSOperationQueue *queue; AudioScrobbler *scrobbler; - IBOutlet PlaybackController *playbackController; + IBOutlet PlaylistLoader *playlistLoader; } @end diff --git a/Application/PlaybackEventController.m b/Application/PlaybackEventController.m index 513c47a0b..5d41e564c 100644 --- a/Application/PlaybackEventController.m +++ b/Application/PlaybackEventController.m @@ -8,9 +8,10 @@ #import "PlaybackEventController.h" -#import "PlaylistEntry.h" #import "AudioScrobbler.h" #import "PlaybackController.h" +#import "PlaylistLoader.h" +#import "PlaylistEntry.h" @implementation PlaybackEventController @@ -32,6 +33,8 @@ [self initDefaults]; queue = [[NSOperationQueue alloc] init]; + [queue setMaxConcurrentOperationCount:1]; + scrobbler = [[AudioScrobbler alloc] init]; [GrowlApplicationBridge setGrowlDelegate:self]; } @@ -46,21 +49,14 @@ [super dealloc]; } -- (void)awakeFromNib +- (void)performPlaybackDidBeginActions:(PlaylistEntry *)pe { - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackDidBegin:) name:CogPlaybackDidBeginNotficiation object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackDidPause:) name:CogPlaybackDidPauseNotficiation object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackDidResume:) name:CogPlaybackDidResumeNotficiation object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackDidStop:) name:CogPlaybackDidStopNotficiation object:nil]; -} - -- (void)playbackDidBegin:(NSNotification *)notification -{ - PlaylistEntry *pe = [notification object]; + [pe performSelectorOnMainThread:@selector(setValuesForKeysWithDictionary:) withObject:[playlistLoader readEntryInfo:pe] waitUntilDone:YES]; + if([[NSUserDefaults standardUserDefaults] boolForKey:@"enableAudioScrobbler"]) { [scrobbler start:pe]; } - + // Note: We don't want to send a growl notification on resume. [GrowlApplicationBridge notifyWithTitle:[pe title] description:[pe artist] @@ -71,27 +67,64 @@ clickContext:nil]; } -- (void)playbackDidPause:(NSNotification *)notification +- (void)performPlaybackDidPauseActions { if([[NSUserDefaults standardUserDefaults] boolForKey:@"enableAudioScrobbler"]) { [scrobbler pause]; } } -- (void)playbackDidResume:(NSNotification *)notification +- (void)performPlaybackDidResumeActions { if([[NSUserDefaults standardUserDefaults] boolForKey:@"enableAudioScrobbler"]) { [scrobbler resume]; } } -- (void)playbackDidStop:(NSNotification *)notification +- (void)performPlaybackDidStopActions { if([[NSUserDefaults standardUserDefaults] boolForKey:@"enableAudioScrobbler"]) { [scrobbler stop]; } } + +- (void)awakeFromNib +{ + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackDidBegin:) name:CogPlaybackDidBeginNotficiation object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackDidPause:) name:CogPlaybackDidPauseNotficiation object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackDidResume:) name:CogPlaybackDidResumeNotficiation object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackDidStop:) name:CogPlaybackDidStopNotficiation object:nil]; +} + +- (void)playbackDidBegin:(NSNotification *)notification +{ + NSOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(performPlaybackDidBeginActions:) object:[notification object]]; + [queue addOperation:op]; + [op release]; +} + +- (void)playbackDidPause:(NSNotification *)notification +{ + NSOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(performPlaybackDidPauseActions) object:nil]; + [queue addOperation:op]; + [op release]; +} + +- (void)playbackDidResume:(NSNotification *)notification +{ + NSOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(performPlaybackDidResumeActions) object:nil]; + [queue addOperation:op]; + [op release]; +} + +- (void)playbackDidStop:(NSNotification *)notification +{ + NSOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(performPlaybackDidStopActions) object:nil]; + [queue addOperation:op]; + [op release]; +} + - (NSDictionary *) registrationDictionaryForGrowl { NSArray *notifications = [NSArray arrayWithObjects:@"Stream Changed", nil]; diff --git a/English.lproj/MainMenu.xib b/English.lproj/MainMenu.xib index fcda5036e..b616ea4c6 100644 --- a/English.lproj/MainMenu.xib +++ b/English.lproj/MainMenu.xib @@ -9,8 +9,8 @@ YES - + YES @@ -6882,6 +6882,14 @@ OQA 2406 + + + playlistLoader + + + + 2407 + @@ -10475,7 +10483,7 @@ OQA - 2406 + 2407 @@ -10890,8 +10898,8 @@ OQA PlaybackEventController NSObject - playbackController - PlaybackController + playlistLoader + PlaylistLoader IBProjectSource diff --git a/Playlist/PlaylistController.m b/Playlist/PlaylistController.m index 2a272f546..7fc9f3162 100644 --- a/Playlist/PlaylistController.m +++ b/Playlist/PlaylistController.m @@ -843,10 +843,6 @@ //Auto start playback if (shouldPlay && [[entriesController entries] count] > 0) { - // HACK ALERT! - [[urls objectAtIndex:0] setValuesForKeysWithDictionary:[playlistLoader readEntryInfo:[urls objectAtIndex:0]]]; - // END HACK - [playbackController playEntry: [urls objectAtIndex:0]]; } } diff --git a/Playlist/PlaylistLoader.h b/Playlist/PlaylistLoader.h index 2dd1fd67d..67c15d277 100755 --- a/Playlist/PlaylistLoader.h +++ b/Playlist/PlaylistLoader.h @@ -20,22 +20,22 @@ typedef enum { @interface PlaylistLoader : NSObject { IBOutlet PlaylistController *playlistController; + + NSOperationQueue *queue; } -- (void)initDefaults; - -//load arrays of urls... +// Load arrays of urls... - (NSArray*)addURLs:(NSArray *)urls sort:(BOOL)sort; - (NSArray*)addURL:(NSURL *)url; - (NSArray*)insertURLs:(NSArray *)urls atIndex:(int)index sort:(BOOL)sort; -//save playlist, auto-determines type based on extension. Uses m3u if it cannot be determined. +// Save playlist, auto-determines type based on extension. Uses m3u if it cannot be determined. - (BOOL)save:(NSString *)filename; - (BOOL)save:(NSString *)filename asType:(PlaylistType)type; - (BOOL)saveM3u:(NSString *)filename; - (BOOL)savePls:(NSString *)filename; -//read info for a playlist entry +// Read info for a playlist entry - (NSDictionary *)readEntryInfo:(PlaylistEntry *)pe; - (void)loadInfoForEntries:(NSArray *)entries; @@ -44,7 +44,7 @@ typedef enum { - (NSArray *)acceptablePlaylistTypes; //Only m3u and pls saving - (NSArray *)acceptableContainerTypes; -// Event inlets (passed to playlist controler): +// Events (passed to playlist controler): - (void)willInsertURLs:(NSArray*)urls origin:(URLOrigin)origin; - (void)didInsertURLs:(NSArray*)entries origin:(URLOrigin)origin; diff --git a/Playlist/PlaylistLoader.m b/Playlist/PlaylistLoader.m index 2e697392a..cdce75a9c 100755 --- a/Playlist/PlaylistLoader.m +++ b/Playlist/PlaylistLoader.m @@ -26,18 +26,20 @@ self = [super init]; if (self) { - [self initDefaults]; + queue = [[NSOperationQueue alloc] init]; + [queue setMaxConcurrentOperationCount:1]; } return self; } -- (void)initDefaults +- (void)dealloc { - + [queue release]; + + [super dealloc]; } - - (BOOL)save:(NSString *)filename { NSString *ext = [filename pathExtension]; @@ -292,10 +294,6 @@ - (void)loadInfoForEntries:(NSArray *)entries { - NSOperationQueue *queue; - queue = [[[NSApplication sharedApplication] delegate] sharedOperationQueue]; - - NSInvocationOperation *oldReadEntryInfoOperation = nil; for (PlaylistEntry *pe in entries) { NSAutoreleasePool *pool =[[NSAutoreleasePool alloc] init]; @@ -305,22 +303,17 @@ initWithTarget:self selector:@selector(readEntryInfo:) object:pe]; - if (oldReadEntryInfoOperation) - { - [readEntryInfoOperation addDependency:oldReadEntryInfoOperation]; - [oldReadEntryInfoOperation release]; - } + [readEntryInfoOperation addObserver:self forKeyPath:@"isFinished" options:NSKeyValueObservingOptionNew context:NULL]; [queue addOperation:readEntryInfoOperation]; - oldReadEntryInfoOperation = [readEntryInfoOperation retain]; + [readEntryInfoOperation release]; [pool release]; } - [oldReadEntryInfoOperation release]; [queue waitUntilAllOperationsAreFinished]; @@ -346,7 +339,7 @@ NSDictionary *entryInfo = [operation result]; PlaylistEntry *pe; // get the playlist entry that the thread was inspecting - [[operation invocation]getArgument:&pe atIndex:2]; + [[operation invocation] getArgument:&pe atIndex:2]; if (entryInfo == nil) { pe.error = YES;