Redid threading for reading file info and metadata. Still a bit buggy.

This commit is contained in:
matthewleon 2008-03-01 18:29:14 +00:00
parent a0cdf1a03e
commit 4168bb43eb
6 changed files with 90 additions and 55 deletions

View file

@ -49,6 +49,8 @@
AppleRemote *remote; AppleRemote *remote;
BOOL remoteButtonHeld; /* true as long as the user holds the left,right,plus or minus on the remote control */ BOOL remoteButtonHeld; /* true as long as the user holds the left,right,plus or minus on the remote control */
NSOperationQueue *queue; // Since we are the app delegate, we take care of the op queue
} }
- (IBAction)openURL:(id)sender; - (IBAction)openURL:(id)sender;
@ -82,5 +84,7 @@ OSStatus handleHotKey(EventHandlerCallRef nextHandler,EventRef theEvent,void *us
- (IBAction)decreaseFontSize:(id)sender; - (IBAction)decreaseFontSize:(id)sender;
- (void)changeFontSize:(float)size; - (void)changeFontSize:(float)size;
// return the operation queue
- (NSOperationQueue *)sharedOperationQueue;
@end @end

View file

@ -35,11 +35,19 @@
remote = [[AppleRemote alloc] init]; remote = [[AppleRemote alloc] init];
[remote setDelegate: self]; [remote setDelegate: self];
queue = [[NSOperationQueue alloc]init];
} }
return self; return self;
} }
- (void)dealloc
{
[queue release];
[super dealloc];
}
// Listen to the remote in exclusive mode, only when Cog is the active application // Listen to the remote in exclusive mode, only when Cog is the active application
- (void)applicationDidBecomeActive:(NSNotification *)notification - (void)applicationDidBecomeActive:(NSNotification *)notification
{ {
@ -462,4 +470,9 @@ increase/decrease as long as the user holds the left/right, plus/minus button */
[self changeFontSize:-1]; [self changeFontSize:-1];
} }
- (NSOperationQueue *)sharedOperationQueue
{
return queue;
}
@end @end

View file

@ -50,10 +50,6 @@
+ (NSSet *)keyPathsForValuesAffectingStatus; + (NSSet *)keyPathsForValuesAffectingStatus;
+ (NSSet *)keyPathsForValuesAffectingStatusMessage; + (NSSet *)keyPathsForValuesAffectingStatusMessage;
- (void)setProperties:(NSDictionary *)properties;
- (void)readPropertiesThread;
- (void)readMetadataThread;
@property(readonly) NSString *display; @property(readonly) NSString *display;
@property(retain, readonly) NSNumber *length; @property(retain, readonly) NSNumber *length;
@property(readonly) NSString *path; @property(readonly) NSString *path;

View file

@ -7,8 +7,6 @@
// //
#import "PlaylistEntry.h" #import "PlaylistEntry.h"
#import "CogAudio/AudioPropertiesReader.h"
#import "CogAudio/AudioMetadataReader.h"
@implementation PlaylistEntry @implementation PlaylistEntry
@ -76,34 +74,6 @@
return [NSSet setWithObjects:@"current", @"queued", @"queuePosition", @"error", @"errorMessage", @"stopAfter", nil]; return [NSSet setWithObjects:@"current", @"queued", @"queuePosition", @"error", @"errorMessage", @"stopAfter", nil];
} }
- (void)setProperties:(NSDictionary *)properties
{
if (properties == nil)
{
self.error = YES;
self.errorMessage = @"Unable to retrieve properties.";
return;
}
[self setValuesForKeysWithDictionary:properties];
}
- (void)readPropertiesThread
{
NSDictionary *properties = [AudioPropertiesReader propertiesForURL:self.URL];
[self performSelectorOnMainThread:@selector(setProperties:) withObject:properties waitUntilDone:YES];
}
- (void)readMetadataThread
{
NSDictionary *metadata = [AudioMetadataReader metadataForURL:self.URL];
[self performSelectorOnMainThread:@selector(setValuesForKeysWithDictionary:) withObject:metadata waitUntilDone:YES];
}
- (NSString *)description - (NSString *)description
{ {
return [NSString stringWithFormat:@"PlaylistEntry %i:(%@)", self.index, self.URL]; return [NSString stringWithFormat:@"PlaylistEntry %i:(%@)", self.index, self.URL];

View file

@ -9,6 +9,7 @@
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
@class PlaylistController; @class PlaylistController;
@class PlaylistEntry;
typedef enum { typedef enum {
kPlaylistM3u, kPlaylistM3u,
@ -30,6 +31,9 @@ typedef enum {
- (BOOL)saveM3u:(NSString *)filename; - (BOOL)saveM3u:(NSString *)filename;
- (BOOL)savePls:(NSString *)filename; - (BOOL)savePls:(NSString *)filename;
//read info for a playlist entry
- (NSDictionary *)readEntryInfo:(PlaylistEntry *)pe;
- (NSArray *)acceptableFileTypes; - (NSArray *)acceptableFileTypes;
- (NSArray *)acceptablePlaylistTypes; //Only m3u and pls saving - (NSArray *)acceptablePlaylistTypes; //Only m3u and pls saving
- (NSArray *)acceptableContainerTypes; - (NSArray *)acceptableContainerTypes;

View file

@ -9,11 +9,14 @@
#import "PlaylistLoader.h" #import "PlaylistLoader.h"
#import "PlaylistController.h" #import "PlaylistController.h"
#import "PlaylistEntry.h" #import "PlaylistEntry.h"
#import "AppController.h"
#import "NSFileHandle+CreateFile.h" #import "NSFileHandle+CreateFile.h"
#import "CogAudio/AudioPlayer.h" #import "CogAudio/AudioPlayer.h"
#import "CogAudio/AudioContainer.h" #import "CogAudio/AudioContainer.h"
#import "CogAudio/AudioPropertiesReader.h"
#import "CogAudio/AudioMetadataReader.h"
@implementation PlaylistLoader @implementation PlaylistLoader
@ -265,32 +268,77 @@
//Select the first entry in the group that was just added //Select the first entry in the group that was just added
[playlistController setSelectionIndex:index]; [playlistController setSelectionIndex:index];
//Other thread for reading things... NSOperationQueue *queue;
[self performSelectorInBackground:@selector(readEntriesInfoThread:) withObject:entries]; queue = [[[NSApplication sharedApplication] delegate] sharedOperationQueue];
NSInvocationOperation *oldReadEntryInfoOperation = Nil;
for (PlaylistEntry *pe in entries)
{
NSInvocationOperation *readEntryInfoOperation;
readEntryInfoOperation = [[[NSInvocationOperation alloc]
initWithTarget:self
selector:@selector(readEntryInfo:)
object:pe] autorelease];
if (oldReadEntryInfoOperation)
{
[readEntryInfoOperation addDependency:oldReadEntryInfoOperation];
[oldReadEntryInfoOperation release];
}
[readEntryInfoOperation addObserver:self
forKeyPath:@"isFinished"
options:NSKeyValueObservingOptionNew
context:NULL];
[queue addOperation:readEntryInfoOperation];
oldReadEntryInfoOperation = [readEntryInfoOperation retain];
}
return; return;
} }
- (void)readEntriesInfoThread:(NSArray *)entries - (NSDictionary *)readEntryInfo:(PlaylistEntry *)pe
{ {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // Just setting this to 30 for now...
NSMutableDictionary *entryInfo = [NSMutableDictionary dictionaryWithCapacity:30];
NSDictionary *entryProperties;
entryProperties = [AudioPropertiesReader propertiesForURL:pe.URL];
if (entryProperties == nil)
return nil;
PlaylistEntry *pe; [entryInfo addEntriesFromDictionary:entryProperties];
for (pe in entries) [entryInfo addEntriesFromDictionary:[AudioMetadataReader metadataForURL:pe.URL]];
return entryInfo;
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
// We finished reading the info for a playlist entry
if ([keyPath isEqualToString:@"isFinished"] && [object isFinished])
{ {
[pe readPropertiesThread]; // get the results
NSDictionary *entryInfo = [object result];
// get the playlist entry that the thread was inspecting
PlaylistEntry *pe;
[[object invocation]getArgument:&pe atIndex:2];
[pe readMetadataThread]; if (entryInfo == nil)
{
pe.error = YES;
pe.errorMessage = @"Unable to retrieve properties.";
}
else
{
[pe setValuesForKeysWithDictionary:entryInfo];
[playlistController updateTotalTime];
}
//Hack so the display gets updated //Hack so the display gets updated
if (pe == [playlistController currentEntry]) if (pe == [playlistController currentEntry])
[playlistController performSelectorOnMainThread:@selector(setCurrentEntry:) withObject:[playlistController currentEntry] waitUntilDone:YES]; [playlistController setCurrentEntry:[playlistController currentEntry]];
// stop observing
[object removeObserver:self forKeyPath:keyPath];
} }
[playlistController performSelectorOnMainThread:@selector(updateTotalTime) withObject:nil waitUntilDone:NO];
[pool release];
} }
- (void)addURLs:(NSArray *)urls sort:(BOOL)sort - (void)addURLs:(NSArray *)urls sort:(BOOL)sort