Overhauled Spotlight metadata importing to make it more easily expandable and reuse NSValueTransformer code.

CQTexperiment
matthewleon 2008-02-18 12:59:20 +00:00
parent 567711e85e
commit b68a2c3a69
5 changed files with 75 additions and 78 deletions

View File

@ -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

View File

@ -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

View File

@ -16,4 +16,8 @@
+ (void)setSearchController:(SpotlightWindowController *)aSearchController;
@property(copy) NSArray *oldResults;
@end
@interface AuthorToArtistTransformer: NSValueTransformer {}
@end

View File

@ -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

View File

@ -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