XML playlists now store album art in an MD5 hash indexed dictionary, but continue to read the older format for backwards compatibility
parent
555ccc9e87
commit
754a22166a
|
@ -144,6 +144,8 @@
|
||||||
56C63D910D647DF300EAE25A /* NSComparisonPredicate+CogPredicate.m in Sources */ = {isa = PBXBuildFile; fileRef = 56C63D900D647DF300EAE25A /* NSComparisonPredicate+CogPredicate.m */; };
|
56C63D910D647DF300EAE25A /* NSComparisonPredicate+CogPredicate.m in Sources */ = {isa = PBXBuildFile; fileRef = 56C63D900D647DF300EAE25A /* NSComparisonPredicate+CogPredicate.m */; };
|
||||||
56DB084C0D6717DC00453B6A /* NSNumber+CogSort.m in Sources */ = {isa = PBXBuildFile; fileRef = 56DB084B0D6717DC00453B6A /* NSNumber+CogSort.m */; };
|
56DB084C0D6717DC00453B6A /* NSNumber+CogSort.m in Sources */ = {isa = PBXBuildFile; fileRef = 56DB084B0D6717DC00453B6A /* NSNumber+CogSort.m */; };
|
||||||
56DB08550D67185300453B6A /* NSArray+CogSort.m in Sources */ = {isa = PBXBuildFile; fileRef = 56DB08540D67185300453B6A /* NSArray+CogSort.m */; };
|
56DB08550D67185300453B6A /* NSArray+CogSort.m in Sources */ = {isa = PBXBuildFile; fileRef = 56DB08540D67185300453B6A /* NSArray+CogSort.m */; };
|
||||||
|
8355D6B6180612F300D05687 /* NSData+MD5.m in Sources */ = {isa = PBXBuildFile; fileRef = 8355D6B5180612F300D05687 /* NSData+MD5.m */; };
|
||||||
|
8355D6B8180613FB00D05687 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8355D6B7180613FB00D05687 /* Security.framework */; };
|
||||||
8359009D17FF06570060F3ED /* ArchiveSource.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8359FF3117FEF35D0060F3ED /* ArchiveSource.bundle */; };
|
8359009D17FF06570060F3ED /* ArchiveSource.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8359FF3117FEF35D0060F3ED /* ArchiveSource.bundle */; };
|
||||||
8360EF6D17F92E56005208A4 /* HighlyComplete.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8360EF0517F92B24005208A4 /* HighlyComplete.bundle */; };
|
8360EF6D17F92E56005208A4 /* HighlyComplete.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8360EF0517F92B24005208A4 /* HighlyComplete.bundle */; };
|
||||||
8375B36517FFEF130092A79F /* Opus.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8375B05717FFEA410092A79F /* Opus.bundle */; };
|
8375B36517FFEF130092A79F /* Opus.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8375B05717FFEA410092A79F /* Opus.bundle */; };
|
||||||
|
@ -746,6 +748,9 @@
|
||||||
56DB084B0D6717DC00453B6A /* NSNumber+CogSort.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSNumber+CogSort.m"; path = "Spotlight/NSNumber+CogSort.m"; sourceTree = "<group>"; };
|
56DB084B0D6717DC00453B6A /* NSNumber+CogSort.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSNumber+CogSort.m"; path = "Spotlight/NSNumber+CogSort.m"; sourceTree = "<group>"; };
|
||||||
56DB08530D67185300453B6A /* NSArray+CogSort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSArray+CogSort.h"; path = "Spotlight/NSArray+CogSort.h"; sourceTree = "<group>"; };
|
56DB08530D67185300453B6A /* NSArray+CogSort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSArray+CogSort.h"; path = "Spotlight/NSArray+CogSort.h"; sourceTree = "<group>"; };
|
||||||
56DB08540D67185300453B6A /* NSArray+CogSort.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSArray+CogSort.m"; path = "Spotlight/NSArray+CogSort.m"; sourceTree = "<group>"; };
|
56DB08540D67185300453B6A /* NSArray+CogSort.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSArray+CogSort.m"; path = "Spotlight/NSArray+CogSort.m"; sourceTree = "<group>"; };
|
||||||
|
8355D6B4180612F300D05687 /* NSData+MD5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+MD5.h"; sourceTree = "<group>"; };
|
||||||
|
8355D6B5180612F300D05687 /* NSData+MD5.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+MD5.m"; sourceTree = "<group>"; };
|
||||||
|
8355D6B7180613FB00D05687 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
|
||||||
8359FF2C17FEF35C0060F3ED /* ArchiveSource.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ArchiveSource.xcodeproj; path = Plugins/ArchiveSource/ArchiveSource.xcodeproj; sourceTree = "<group>"; };
|
8359FF2C17FEF35C0060F3ED /* ArchiveSource.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ArchiveSource.xcodeproj; path = Plugins/ArchiveSource/ArchiveSource.xcodeproj; sourceTree = "<group>"; };
|
||||||
8360EF0017F92B23005208A4 /* HighlyComplete.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = HighlyComplete.xcodeproj; path = Plugins/HighlyComplete/HighlyComplete.xcodeproj; sourceTree = "<group>"; };
|
8360EF0017F92B23005208A4 /* HighlyComplete.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = HighlyComplete.xcodeproj; path = Plugins/HighlyComplete/HighlyComplete.xcodeproj; sourceTree = "<group>"; };
|
||||||
8375B05117FFEA400092A79F /* Opus.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Opus.xcodeproj; path = Plugins/Opus/Opus.xcodeproj; sourceTree = "<group>"; };
|
8375B05117FFEA400092A79F /* Opus.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Opus.xcodeproj; path = Plugins/Opus/Opus.xcodeproj; sourceTree = "<group>"; };
|
||||||
|
@ -789,6 +794,7 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
8355D6B8180613FB00D05687 /* Security.framework in Frameworks */,
|
||||||
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */,
|
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */,
|
||||||
8E6889240AAA403C00AD3950 /* Carbon.framework in Frameworks */,
|
8E6889240AAA403C00AD3950 /* Carbon.framework in Frameworks */,
|
||||||
17BB5CED0B8A86010009ACB1 /* AudioToolbox.framework in Frameworks */,
|
17BB5CED0B8A86010009ACB1 /* AudioToolbox.framework in Frameworks */,
|
||||||
|
@ -956,6 +962,8 @@
|
||||||
07E18DF20D62B38400BB0E11 /* NSArray+ShuffleUtils.m */,
|
07E18DF20D62B38400BB0E11 /* NSArray+ShuffleUtils.m */,
|
||||||
17FAEBAA0F662985007C8707 /* ToolTipTextField.h */,
|
17FAEBAA0F662985007C8707 /* ToolTipTextField.h */,
|
||||||
17FAEBAB0F662985007C8707 /* ToolTipTextField.m */,
|
17FAEBAB0F662985007C8707 /* ToolTipTextField.m */,
|
||||||
|
8355D6B4180612F300D05687 /* NSData+MD5.h */,
|
||||||
|
8355D6B5180612F300D05687 /* NSData+MD5.m */,
|
||||||
);
|
);
|
||||||
path = Utils;
|
path = Utils;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1307,6 +1315,7 @@
|
||||||
29B97323FDCFA39411CA2CEA /* Frameworks */ = {
|
29B97323FDCFA39411CA2CEA /* Frameworks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
8355D6B7180613FB00D05687 /* Security.framework */,
|
||||||
1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */,
|
1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */,
|
||||||
1058C7A2FEA54F0111CA2CBB /* Other Frameworks */,
|
1058C7A2FEA54F0111CA2CBB /* Other Frameworks */,
|
||||||
);
|
);
|
||||||
|
@ -1900,6 +1909,7 @@
|
||||||
1770429C0B8BC53600B86321 /* AppController.m in Sources */,
|
1770429C0B8BC53600B86321 /* AppController.m in Sources */,
|
||||||
1770429E0B8BC53600B86321 /* PlaybackController.m in Sources */,
|
1770429E0B8BC53600B86321 /* PlaybackController.m in Sources */,
|
||||||
1766C6930B911DF1004A7AE4 /* AudioScrobbler.m in Sources */,
|
1766C6930B911DF1004A7AE4 /* AudioScrobbler.m in Sources */,
|
||||||
|
8355D6B6180612F300D05687 /* NSData+MD5.m in Sources */,
|
||||||
1766C6950B911DF1004A7AE4 /* AudioScrobblerClient.m in Sources */,
|
1766C6950B911DF1004A7AE4 /* AudioScrobblerClient.m in Sources */,
|
||||||
1755E1F90BA0D2B600CA3560 /* PlaylistLoader.m in Sources */,
|
1755E1F90BA0D2B600CA3560 /* PlaylistLoader.m in Sources */,
|
||||||
8E9A30160BA792DC0091081B /* NSFileHandle+CreateFile.m in Sources */,
|
8E9A30160BA792DC0091081B /* NSFileHandle+CreateFile.m in Sources */,
|
||||||
|
|
|
@ -255,18 +255,7 @@
|
||||||
|
|
||||||
- (void)setAlbumArt:(id)data
|
- (void)setAlbumArt:(id)data
|
||||||
{
|
{
|
||||||
BOOL isData = NO;
|
if ([data isKindOfClass:[NSData class]])
|
||||||
Class class = [data class];
|
|
||||||
while (class)
|
|
||||||
{
|
|
||||||
if (class == [NSData class])
|
|
||||||
{
|
|
||||||
isData = YES;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
class = [class superclass];
|
|
||||||
}
|
|
||||||
if (isData)
|
|
||||||
{
|
{
|
||||||
[self setAlbumArtInternal:data];
|
[self setAlbumArtInternal:data];
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
|
|
||||||
#import "XMlContainer.h"
|
#import "XMlContainer.h"
|
||||||
|
|
||||||
|
#import "NSData+MD5.h"
|
||||||
|
|
||||||
@implementation PlaylistLoader
|
@implementation PlaylistLoader
|
||||||
|
|
||||||
- (id)init
|
- (id)init
|
||||||
|
@ -203,6 +205,8 @@ NSMutableDictionary * dictionaryWithPropertiesOfObject(id obj, NSArray * filterL
|
||||||
|
|
||||||
NSArray * filterList = [NSArray arrayWithObjects:@"display", @"length", @"path", @"filename", @"status", @"statusMessage", @"spam", @"stopAfter", @"shuffleIndex", @"index", @"current", @"queued", @"currentPosition", @"queuePosition", @"error", @"removed", @"URL", @"albumArt", nil];
|
NSArray * filterList = [NSArray arrayWithObjects:@"display", @"length", @"path", @"filename", @"status", @"statusMessage", @"spam", @"stopAfter", @"shuffleIndex", @"index", @"current", @"queued", @"currentPosition", @"queuePosition", @"error", @"removed", @"URL", @"albumArt", nil];
|
||||||
|
|
||||||
|
NSMutableDictionary * albumArtSet = [[NSMutableDictionary alloc] init];
|
||||||
|
|
||||||
NSMutableArray * topLevel = [[NSMutableArray alloc] init];
|
NSMutableArray * topLevel = [[NSMutableArray alloc] init];
|
||||||
|
|
||||||
for (PlaylistEntry *pe in [playlistController content])
|
for (PlaylistEntry *pe in [playlistController content])
|
||||||
|
@ -215,8 +219,11 @@ NSMutableDictionary * dictionaryWithPropertiesOfObject(id obj, NSArray * filterL
|
||||||
NSData * albumArt = [dict objectForKey:@"albumArtInternal"];
|
NSData * albumArt = [dict objectForKey:@"albumArtInternal"];
|
||||||
if (albumArt)
|
if (albumArt)
|
||||||
{
|
{
|
||||||
[dict setObject:albumArt forKey:@"albumArt"];
|
|
||||||
[dict removeObjectForKey:@"albumArtInternal"];
|
[dict removeObjectForKey:@"albumArtInternal"];
|
||||||
|
NSString * hash = [albumArt MD5];
|
||||||
|
if (![albumArtSet objectForKey:hash])
|
||||||
|
[albumArtSet setObject:albumArt forKey:hash];
|
||||||
|
[dict setObject:hash forKey:@"albumArt"];
|
||||||
}
|
}
|
||||||
|
|
||||||
[topLevel addObject:dict];
|
[topLevel addObject:dict];
|
||||||
|
@ -224,7 +231,13 @@ NSMutableDictionary * dictionaryWithPropertiesOfObject(id obj, NSArray * filterL
|
||||||
[dict release];
|
[dict release];
|
||||||
}
|
}
|
||||||
|
|
||||||
NSData * data = [NSPropertyListSerialization dataWithPropertyList:topLevel format:NSPropertyListXMLFormat_v1_0 options:0 error:0];
|
NSDictionary * dictionary = [NSDictionary dictionaryWithObjectsAndKeys:albumArtSet, @"albumArt", topLevel, @"items", nil];
|
||||||
|
|
||||||
|
NSData * data = [NSPropertyListSerialization dataWithPropertyList:dictionary format:NSPropertyListXMLFormat_v1_0 options:0 error:0];
|
||||||
|
|
||||||
|
[albumArtSet release];
|
||||||
|
|
||||||
|
[topLevel release];
|
||||||
|
|
||||||
[fileHandle writeData:data];
|
[fileHandle writeData:data];
|
||||||
|
|
||||||
|
|
|
@ -70,15 +70,23 @@
|
||||||
NSData* plistData = [contents dataUsingEncoding:NSUTF8StringEncoding];
|
NSData* plistData = [contents dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
|
|
||||||
NSPropertyListFormat format;
|
NSPropertyListFormat format;
|
||||||
NSArray* plist = [NSPropertyListSerialization propertyListFromData:plistData mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&error];
|
id plist = [NSPropertyListSerialization propertyListFromData:plistData mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&error];
|
||||||
if(!plist){
|
if(!plist){
|
||||||
NSLog(@"Error: %@",error);
|
NSLog(@"Error: %@",error);
|
||||||
[error release];
|
[error release];
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL isArray = [plist isKindOfClass:[NSArray class]];
|
||||||
|
BOOL isDict = [plist isKindOfClass:[NSDictionary class]];
|
||||||
|
|
||||||
|
if (!isDict && !isArray) return nil;
|
||||||
|
|
||||||
|
NSArray * items = (isArray) ? (NSArray*)plist : [(NSDictionary *)plist objectForKey:@"items"];
|
||||||
|
|
||||||
NSDictionary *entry;
|
NSDictionary *entry;
|
||||||
NSEnumerator *e = [plist objectEnumerator];
|
NSDictionary *albumArt = (isArray) ? nil : [(NSDictionary *)plist objectForKey:@"albumArt"];
|
||||||
|
NSEnumerator *e = [items objectEnumerator];
|
||||||
NSMutableArray *entries = [NSMutableArray array];
|
NSMutableArray *entries = [NSMutableArray array];
|
||||||
|
|
||||||
while ((entry = [e nextObject]))
|
while ((entry = [e nextObject]))
|
||||||
|
@ -87,6 +95,9 @@
|
||||||
|
|
||||||
[preparedEntry setObject:[self urlForPath:[preparedEntry objectForKey:@"URL"] relativeTo:filename] forKey:@"URL"];
|
[preparedEntry setObject:[self urlForPath:[preparedEntry objectForKey:@"URL"] relativeTo:filename] forKey:@"URL"];
|
||||||
|
|
||||||
|
if (albumArt && [preparedEntry objectForKey:@"albumArt"])
|
||||||
|
[preparedEntry setObject:[albumArt objectForKey:[preparedEntry objectForKey:@"albumArt"]] forKey:@"albumArt"];
|
||||||
|
|
||||||
[entries addObject:[NSDictionary dictionaryWithDictionary:preparedEntry]];
|
[entries addObject:[NSDictionary dictionaryWithDictionary:preparedEntry]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
//
|
||||||
|
// NSData+MD5.h
|
||||||
|
// Cog
|
||||||
|
//
|
||||||
|
// Created by Christopher Snowhill on 10/9/13.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
@interface NSData (MD5)
|
||||||
|
|
||||||
|
- (NSString*)MD5;
|
||||||
|
|
||||||
|
@end
|
|
@ -0,0 +1,35 @@
|
||||||
|
//
|
||||||
|
// NSData+MD5.m
|
||||||
|
// Cog
|
||||||
|
//
|
||||||
|
// Created by Christopher Snowhill on 10/9/13.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <CommonCrypto/CommonDigest.h>
|
||||||
|
|
||||||
|
#import "NSData+MD5.h"
|
||||||
|
|
||||||
|
@implementation NSData (MD5)
|
||||||
|
|
||||||
|
- (NSString*)MD5
|
||||||
|
{
|
||||||
|
// Create pointer to the string as UTF8
|
||||||
|
const void * ptr = [self bytes];
|
||||||
|
NSUInteger len = [self length];
|
||||||
|
|
||||||
|
// Create byte array of unsigned chars
|
||||||
|
unsigned char md5Buffer[CC_MD5_DIGEST_LENGTH];
|
||||||
|
|
||||||
|
// Create 16 byte MD5 hash value, store in buffer
|
||||||
|
CC_MD5(ptr, len, md5Buffer);
|
||||||
|
|
||||||
|
// Convert MD5 value in the buffer to NSString of hex values
|
||||||
|
NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
|
||||||
|
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
|
||||||
|
[output appendFormat:@"%02x",md5Buffer[i]];
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
Loading…
Reference in New Issue