From b68a2c3a69a8754818fe6a5896b8c54aea918375 Mon Sep 17 00:00:00 2001 From: matthewleon Date: Mon, 18 Feb 2008 12:59:20 +0000 Subject: [PATCH] Overhauled Spotlight metadata importing to make it more easily expandable and reuse NSValueTransformer code. --- Spotlight/SpotlightPlaylistEntry.h | 6 +- Spotlight/SpotlightPlaylistEntry.m | 122 +++++++++++--------------- Spotlight/SpotlightTransformers.h | 4 + Spotlight/SpotlightTransformers.m | 10 ++- Spotlight/SpotlightWindowController.m | 11 +-- 5 files changed, 75 insertions(+), 78 deletions(-) diff --git a/Spotlight/SpotlightPlaylistEntry.h b/Spotlight/SpotlightPlaylistEntry.h index 35309eee5..a5433001e 100644 --- a/Spotlight/SpotlightPlaylistEntry.h +++ b/Spotlight/SpotlightPlaylistEntry.h @@ -11,12 +11,12 @@ @interface SpotlightPlaylistEntry : PlaylistEntry { - NSNumber *length; } + (SpotlightPlaylistEntry *)playlistEntryWithMetadataItem:(NSMetadataItem *)metadataItem; -+ (NSArray *)allmdKeys; -@property(copy) NSNumber *length; +// New length getters/setters + +@property(retain) NSNumber *length; @end diff --git a/Spotlight/SpotlightPlaylistEntry.m b/Spotlight/SpotlightPlaylistEntry.m index 088e0d612..fea850988 100644 --- a/Spotlight/SpotlightPlaylistEntry.m +++ b/Spotlight/SpotlightPlaylistEntry.m @@ -8,90 +8,74 @@ #import "SpotlightPlaylistEntry.h" -// Class array for metadata keys we want -static NSArray * mdKeys; - -// Corresponding array for playlist entry keys -static NSArray * entryKeys; - -// extramdKeys represents those keys that require additional processing -static NSArray * extramdKeys; - -// allmdKeys is a combined array of both mdKeys and entryKeys -static NSArray * allmdKeys; - -// tags matches mdKeys and entryKeys for automated extraction -static NSDictionary * tags; +// dictionary that lets us translate from and mdKey to an entryKey +// if we need the help of a transformer, we use an nsarray +// with format (entryKey, transformerName) +static NSDictionary *importKeys; @implementation SpotlightPlaylistEntry + (void)initialize { - mdKeys = [[NSArray arrayWithObjects: - @"kMDItemTitle", - @"kMDItemAlbum", - @"kMDItemAudioTrackNumber", - @"kMDItemRecordingYear", - @"kMDItemMusicalGenre", - @"kMDItemDurationSeconds", - nil] retain]; - entryKeys = [[NSArray arrayWithObjects: - @"title", - @"album", - @"track", - @"year", - @"genre", - @"length", - nil]retain]; - extramdKeys = [[NSArray arrayWithObjects: - @"kMDItemPath", - @"kMDItemAuthors", - nil]retain]; - allmdKeys = [[mdKeys arrayByAddingObjectsFromArray:extramdKeys]retain]; - tags = [[NSDictionary dictionaryWithObjects:entryKeys forKeys:mdKeys]retain]; -} - -// Use this to access the array of all the keys we want. -+ (NSArray *)allmdKeys -{ - return allmdKeys; + // We need to translate the path string to a full URL + NSArray *URLTransform = + [NSArray arrayWithObjects:@"URL", @"StringToURLTransformer", nil]; + + // Extract the artist name from the authors array + NSArray *artistTransform = + [NSArray arrayWithObjects:@"artist", @"AuthorToArtistTransformer", nil]; + + importKeys = [[NSDictionary dictionaryWithObjectsAndKeys: + @"title", @"kMDItemTitle", + @"album", @"kMDItemAlbum", + @"track", @"kMDItemAudioTrackNumber", + @"year", @"kMDItemRecordingYear", + @"genre", @"kMDItemMusicalGenre", + @"length", @"kMDItemDurationSeconds", + URLTransform, @"kMDItemPath", + artistTransform, @"kMDItemAuthors", + nil]retain]; } + (SpotlightPlaylistEntry *)playlistEntryWithMetadataItem:(NSMetadataItem *)metadataItem { - // use the matching tag sets to generate a playlist entry SpotlightPlaylistEntry *entry = [[[SpotlightPlaylistEntry alloc] init] autorelease]; - NSDictionary *songAttributes = [metadataItem valuesForAttributes:allmdKeys]; - for (NSString * mdKey in tags) { - [entry setValue: [songAttributes objectForKey:mdKey] - forKey:[tags objectForKey:mdKey]]; + // Dictionary of the metadata values + NSDictionary *songAttributes = + [metadataItem valuesForAttributes:[importKeys allKeys]]; + // loop through the keys we want to extract + for (NSString *mdKey in importKeys) { + id importTarget = [importKeys objectForKey:mdKey]; + // Just copy the object from metadata + if ([importTarget isKindOfClass:[NSString class]]) + { + [entry setValue: [songAttributes objectForKey:mdKey] + forKey: importTarget]; + } + // Transform the value in metadata before copying it in + else if ([importTarget isKindOfClass:[NSArray class]]) + { + NSString * importKey = [importTarget objectAtIndex:0]; + NSValueTransformer *transformer = + [NSValueTransformer valueTransformerForName:[importTarget objectAtIndex:1]]; + id transformedValue = [transformer transformedValue: + [songAttributes objectForKey:mdKey]]; + [entry setValue: transformedValue + forKey: importKey]; + } + // The importKeys dictionary contains something strange... + else + { + NSString *errString = + [NSString stringWithFormat:@"ERROR: Could not import key %@", mdKey]; + NSAssert(NO, errString); + } } - - // URL needs to be generated from the simple path stored in kMDItemPath - [entry setURL: [NSURL fileURLWithPath: [songAttributes objectForKey:@"kMDItemPath"]]]; - - // Authors is an array, but we only care about the first item in it - - [entry setArtist: [[songAttributes objectForKey:@"kMDItemAuthors"] objectAtIndex:0]]; return entry; } -- (id)init -{ - if (self = [super init]) - { - length = nil; - } - return self; -} - -- (void)dealloc -{ - [length release]; - [super dealloc]; -} - @synthesize length; + @end \ No newline at end of file diff --git a/Spotlight/SpotlightTransformers.h b/Spotlight/SpotlightTransformers.h index 53ba98cc4..145c9d55e 100644 --- a/Spotlight/SpotlightTransformers.h +++ b/Spotlight/SpotlightTransformers.h @@ -16,4 +16,8 @@ + (void)setSearchController:(SpotlightWindowController *)aSearchController; @property(copy) NSArray *oldResults; +@end + +@interface AuthorToArtistTransformer: NSValueTransformer {} + @end \ No newline at end of file diff --git a/Spotlight/SpotlightTransformers.m b/Spotlight/SpotlightTransformers.m index 9140acd4b..c347aed4f 100644 --- a/Spotlight/SpotlightTransformers.m +++ b/Spotlight/SpotlightTransformers.m @@ -21,7 +21,6 @@ static SpotlightWindowController * searchController; searchController = aSearchController; } -// Convert from string to NSURL - (id)transformedValue:(id)value { // Rather unintuitively, this piece of code eliminates the "flicker" // when searching for new results, which resulted from a pause when the @@ -41,4 +40,13 @@ static SpotlightWindowController * searchController; @synthesize oldResults; +@end + +@implementation AuthorToArtistTransformer ++ (Class)transformedValueClass { return [NSString class]; } ++ (BOOL)allowsReverseTransformation { return NO; } +- (id)transformedValue:(id)value { + return [value objectAtIndex:0]; +} + @end \ No newline at end of file diff --git a/Spotlight/SpotlightWindowController.m b/Spotlight/SpotlightWindowController.m index 9a2c04863..3b4d55f6b 100644 --- a/Spotlight/SpotlightWindowController.m +++ b/Spotlight/SpotlightWindowController.m @@ -27,22 +27,23 @@ static NSPredicate * musicOnlyPredicate = nil; { musicOnlyPredicate = [[NSPredicate predicateWithFormat: @"kMDItemContentTypeTree==\'public.audio\'"] retain]; - - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; // Set the home directory as the default search directory + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSString * homeDir = @"~"; homeDir = [homeDir stringByExpandingTildeInPath]; homeDir = [[NSURL fileURLWithPath:homeDir isDirectory:YES] absoluteString]; NSDictionary *searchDefault = [NSDictionary dictionaryWithObject:homeDir forKey:@"spotlightSearchPath"]; + [defaults registerDefaults:searchDefault]; + // Register value transformers - NSValueTransformer *pausingQueryTransformer = [[[PausingQueryTransformer alloc] init] autorelease]; + NSValueTransformer *pausingQueryTransformer = [[[PausingQueryTransformer alloc]init]autorelease]; [NSValueTransformer setValueTransformer:pausingQueryTransformer forName:@"PausingQueryTransformer"]; - - [defaults registerDefaults:searchDefault]; + NSValueTransformer *authorToArtistTransformer = [[[AuthorToArtistTransformer alloc]init]autorelease]; + [NSValueTransformer setValueTransformer:authorToArtistTransformer forName:@"AuthorToArtistTransformer"]; } - (id)init