Overhauled Spotlight metadata importing to make it more easily expandable and reuse NSValueTransformer code.
parent
567711e85e
commit
b68a2c3a69
|
@ -11,12 +11,12 @@
|
||||||
|
|
||||||
|
|
||||||
@interface SpotlightPlaylistEntry : PlaylistEntry {
|
@interface SpotlightPlaylistEntry : PlaylistEntry {
|
||||||
|
|
||||||
NSNumber *length;
|
NSNumber *length;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (SpotlightPlaylistEntry *)playlistEntryWithMetadataItem:(NSMetadataItem *)metadataItem;
|
+ (SpotlightPlaylistEntry *)playlistEntryWithMetadataItem:(NSMetadataItem *)metadataItem;
|
||||||
+ (NSArray *)allmdKeys;
|
|
||||||
|
|
||||||
@property(copy) NSNumber *length;
|
// New length getters/setters
|
||||||
|
|
||||||
|
@property(retain) NSNumber *length;
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -8,90 +8,74 @@
|
||||||
|
|
||||||
#import "SpotlightPlaylistEntry.h"
|
#import "SpotlightPlaylistEntry.h"
|
||||||
|
|
||||||
// Class array for metadata keys we want
|
// dictionary that lets us translate from and mdKey to an entryKey
|
||||||
static NSArray * mdKeys;
|
// if we need the help of a transformer, we use an nsarray
|
||||||
|
// with format (entryKey, transformerName)
|
||||||
// Corresponding array for playlist entry keys
|
static NSDictionary *importKeys;
|
||||||
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;
|
|
||||||
|
|
||||||
@implementation SpotlightPlaylistEntry
|
@implementation SpotlightPlaylistEntry
|
||||||
|
|
||||||
+ (void)initialize
|
+ (void)initialize
|
||||||
{
|
{
|
||||||
mdKeys = [[NSArray arrayWithObjects:
|
// We need to translate the path string to a full URL
|
||||||
@"kMDItemTitle",
|
NSArray *URLTransform =
|
||||||
@"kMDItemAlbum",
|
[NSArray arrayWithObjects:@"URL", @"StringToURLTransformer", nil];
|
||||||
@"kMDItemAudioTrackNumber",
|
|
||||||
@"kMDItemRecordingYear",
|
// Extract the artist name from the authors array
|
||||||
@"kMDItemMusicalGenre",
|
NSArray *artistTransform =
|
||||||
@"kMDItemDurationSeconds",
|
[NSArray arrayWithObjects:@"artist", @"AuthorToArtistTransformer", nil];
|
||||||
nil] retain];
|
|
||||||
entryKeys = [[NSArray arrayWithObjects:
|
importKeys = [[NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
@"title",
|
@"title", @"kMDItemTitle",
|
||||||
@"album",
|
@"album", @"kMDItemAlbum",
|
||||||
@"track",
|
@"track", @"kMDItemAudioTrackNumber",
|
||||||
@"year",
|
@"year", @"kMDItemRecordingYear",
|
||||||
@"genre",
|
@"genre", @"kMDItemMusicalGenre",
|
||||||
@"length",
|
@"length", @"kMDItemDurationSeconds",
|
||||||
nil]retain];
|
URLTransform, @"kMDItemPath",
|
||||||
extramdKeys = [[NSArray arrayWithObjects:
|
artistTransform, @"kMDItemAuthors",
|
||||||
@"kMDItemPath",
|
nil]retain];
|
||||||
@"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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (SpotlightPlaylistEntry *)playlistEntryWithMetadataItem:(NSMetadataItem *)metadataItem
|
+ (SpotlightPlaylistEntry *)playlistEntryWithMetadataItem:(NSMetadataItem *)metadataItem
|
||||||
{
|
{
|
||||||
// use the matching tag sets to generate a playlist entry
|
|
||||||
SpotlightPlaylistEntry *entry = [[[SpotlightPlaylistEntry alloc] init] autorelease];
|
SpotlightPlaylistEntry *entry = [[[SpotlightPlaylistEntry alloc] init] autorelease];
|
||||||
|
|
||||||
NSDictionary *songAttributes = [metadataItem valuesForAttributes:allmdKeys];
|
// Dictionary of the metadata values
|
||||||
for (NSString * mdKey in tags) {
|
NSDictionary *songAttributes =
|
||||||
[entry setValue: [songAttributes objectForKey:mdKey]
|
[metadataItem valuesForAttributes:[importKeys allKeys]];
|
||||||
forKey:[tags objectForKey:mdKey]];
|
|
||||||
|
|
||||||
|
// 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;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)init
|
|
||||||
{
|
|
||||||
if (self = [super init])
|
|
||||||
{
|
|
||||||
length = nil;
|
|
||||||
}
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)dealloc
|
|
||||||
{
|
|
||||||
[length release];
|
|
||||||
[super dealloc];
|
|
||||||
}
|
|
||||||
|
|
||||||
@synthesize length;
|
@synthesize length;
|
||||||
|
|
||||||
@end
|
@end
|
|
@ -16,4 +16,8 @@
|
||||||
+ (void)setSearchController:(SpotlightWindowController *)aSearchController;
|
+ (void)setSearchController:(SpotlightWindowController *)aSearchController;
|
||||||
|
|
||||||
@property(copy) NSArray *oldResults;
|
@property(copy) NSArray *oldResults;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface AuthorToArtistTransformer: NSValueTransformer {}
|
||||||
|
|
||||||
@end
|
@end
|
|
@ -21,7 +21,6 @@ static SpotlightWindowController * searchController;
|
||||||
searchController = aSearchController;
|
searchController = aSearchController;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert from string to NSURL
|
|
||||||
- (id)transformedValue:(id)value {
|
- (id)transformedValue:(id)value {
|
||||||
// Rather unintuitively, this piece of code eliminates the "flicker"
|
// Rather unintuitively, this piece of code eliminates the "flicker"
|
||||||
// when searching for new results, which resulted from a pause when the
|
// when searching for new results, which resulted from a pause when the
|
||||||
|
@ -41,4 +40,13 @@ static SpotlightWindowController * searchController;
|
||||||
|
|
||||||
@synthesize oldResults;
|
@synthesize oldResults;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation AuthorToArtistTransformer
|
||||||
|
+ (Class)transformedValueClass { return [NSString class]; }
|
||||||
|
+ (BOOL)allowsReverseTransformation { return NO; }
|
||||||
|
- (id)transformedValue:(id)value {
|
||||||
|
return [value objectAtIndex:0];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
|
@ -27,22 +27,23 @@ static NSPredicate * musicOnlyPredicate = nil;
|
||||||
{
|
{
|
||||||
musicOnlyPredicate = [[NSPredicate predicateWithFormat:
|
musicOnlyPredicate = [[NSPredicate predicateWithFormat:
|
||||||
@"kMDItemContentTypeTree==\'public.audio\'"] retain];
|
@"kMDItemContentTypeTree==\'public.audio\'"] retain];
|
||||||
|
|
||||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
|
||||||
|
|
||||||
// Set the home directory as the default search directory
|
// Set the home directory as the default search directory
|
||||||
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||||
NSString * homeDir = @"~";
|
NSString * homeDir = @"~";
|
||||||
homeDir = [homeDir stringByExpandingTildeInPath];
|
homeDir = [homeDir stringByExpandingTildeInPath];
|
||||||
homeDir = [[NSURL fileURLWithPath:homeDir isDirectory:YES] absoluteString];
|
homeDir = [[NSURL fileURLWithPath:homeDir isDirectory:YES] absoluteString];
|
||||||
NSDictionary *searchDefault =
|
NSDictionary *searchDefault =
|
||||||
[NSDictionary dictionaryWithObject:homeDir
|
[NSDictionary dictionaryWithObject:homeDir
|
||||||
forKey:@"spotlightSearchPath"];
|
forKey:@"spotlightSearchPath"];
|
||||||
|
[defaults registerDefaults:searchDefault];
|
||||||
|
|
||||||
|
|
||||||
// Register value transformers
|
// Register value transformers
|
||||||
NSValueTransformer *pausingQueryTransformer = [[[PausingQueryTransformer alloc] init] autorelease];
|
NSValueTransformer *pausingQueryTransformer = [[[PausingQueryTransformer alloc]init]autorelease];
|
||||||
[NSValueTransformer setValueTransformer:pausingQueryTransformer forName:@"PausingQueryTransformer"];
|
[NSValueTransformer setValueTransformer:pausingQueryTransformer forName:@"PausingQueryTransformer"];
|
||||||
|
NSValueTransformer *authorToArtistTransformer = [[[AuthorToArtistTransformer alloc]init]autorelease];
|
||||||
[defaults registerDefaults:searchDefault];
|
[NSValueTransformer setValueTransformer:authorToArtistTransformer forName:@"AuthorToArtistTransformer"];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)init
|
- (id)init
|
||||||
|
|
Loading…
Reference in New Issue