Now storing all album art internally as its original format and synthesizing NSImage objects on demand

CQTexperiment
Chris Moeller 2013-10-09 13:53:13 -07:00
parent a63e27f95c
commit 555ccc9e87
6 changed files with 78 additions and 90 deletions

View File

@ -59,7 +59,7 @@
[GrowlApplicationBridge notifyWithTitle:[pe title]
description:[pe artist]
notificationName:@"Stream Changed"
iconData:[[pe albumArt] TIFFRepresentation]
iconData:[pe albumArtInternal]
priority:0
isSticky:NO
clickContext:nil];

View File

@ -31,7 +31,8 @@
NSString *genre;
NSNumber *year;
NSNumber *track;
NSImage *albumArt;
NSData *albumArtInternal;
float replayGainAlbumGain;
float replayGainAlbumPeak;
@ -63,6 +64,7 @@
+ (NSSet *)keyPathsForValuesAffectingStatus;
+ (NSSet *)keyPathsForValuesAffectingStatusMessage;
+ (NSSet *)keyPathsForValuesAffectingSpam;
+ (NSSet *)keyPathsForValuesAffectingAlbumArt;
@property(readonly) NSString *display;
@property(retain, readonly) NSNumber *length;
@ -96,7 +98,9 @@
@property(retain) NSString *genre;
@property(retain) NSNumber *year;
@property(retain) NSNumber *track;
@property(retain) NSImage *albumArt;
@property(retain, readonly) NSImage *albumArt;
@property(retain) NSData *albumArtInternal;
@property long long totalFrames;
@property int bitrate;

View File

@ -32,7 +32,6 @@
@synthesize genre;
@synthesize year;
@synthesize track;
@synthesize albumArt;
@synthesize totalFrames;
@synthesize bitrate;
@ -93,6 +92,11 @@
return [NSSet setWithObjects:@"artist", @"title", @"album", @"track", @"totalFrames", @"currentPosition", @"bitrate", nil];
}
+ (NSSet *)keyPathsForValuesAffectingAlbumArt
{
return [NSSet setWithObject:@"albumArtInternal"];
}
- (NSString *)description
{
return [NSString stringWithFormat:@"PlaylistEntry %i:(%@)", self.index, self.URL];
@ -122,7 +126,7 @@
self.genre = nil;
self.year = nil;
self.track = nil;
self.albumArt = nil;
self.albumArtInternal = nil;
self.endian = nil;
@ -230,6 +234,44 @@
return [elements componentsJoinedByString:@""];
}
@synthesize albumArtInternal;
@dynamic albumArt;
- (NSImage *)albumArt
{
if (!albumArtInternal) return nil;
NSString *imageCacheTag = [NSString stringWithFormat:@"%@-%@-%@-%@", album, artist, genre, year];
NSImage *image = [NSImage imageNamed:imageCacheTag];
if (image == nil)
{
image = [[[NSImage alloc] initWithData:albumArtInternal] autorelease];
[image setName:imageCacheTag];
}
return image;
}
- (void)setAlbumArt:(id)data
{
BOOL isData = NO;
Class class = [data class];
while (class)
{
if (class == [NSData class])
{
isData = YES;
break;
}
class = [class superclass];
}
if (isData)
{
[self setAlbumArtInternal:data];
}
}
@dynamic length;
- (NSNumber *)length
{

View File

@ -201,7 +201,7 @@ NSMutableDictionary * dictionaryWithPropertiesOfObject(id obj, NSArray * filterL
}
[fileHandle truncateFileAtOffset:0];
NSArray * filterList = [NSArray arrayWithObjects:@"display", @"length", @"path", @"filename", @"status", @"statusMessage", @"spam", @"stopAfter", @"shuffleIndex", @"index", @"current", @"queued", @"currentPosition", @"queuePosition", @"error", @"removed", @"URL", nil];
NSArray * filterList = [NSArray arrayWithObjects:@"display", @"length", @"path", @"filename", @"status", @"statusMessage", @"spam", @"stopAfter", @"shuffleIndex", @"index", @"current", @"queued", @"currentPosition", @"queuePosition", @"error", @"removed", @"URL", @"albumArt", nil];
NSMutableArray * topLevel = [[NSMutableArray alloc] init];
@ -212,29 +212,11 @@ NSMutableDictionary * dictionaryWithPropertiesOfObject(id obj, NSArray * filterL
NSString *path = [self relativePathFrom:filename toURL:[pe URL]];
[dict setObject:path forKey:@"URL"];
NSImage * image = [dict objectForKey:@"albumArt"];
if (image)
NSData * albumArt = [dict objectForKey:@"albumArtInternal"];
if (albumArt)
{
NSBitmapImageRep* requiredBitmap = nil;
BOOL setValue =NO;
for(NSBitmapImageRep* imagerep in [image representations])
{
if ([imagerep isKindOfClass:[NSBitmapImageRep class]])
{
if (!setValue) {
requiredBitmap = imagerep;
setValue =YES;
}
if ([requiredBitmap pixelsHigh]<[imagerep pixelsHigh]) {
requiredBitmap = imagerep;
}
}
}
[dict setObject:[requiredBitmap representationUsingType:NSJPEG2000FileType properties:nil] forKey:@"albumArt"];
[dict setObject:albumArt forKey:@"albumArt"];
[dict removeObjectForKey:@"albumArtInternal"];
}
[topLevel addObject:dict];

View File

@ -87,10 +87,6 @@
[preparedEntry setObject:[self urlForPath:[preparedEntry objectForKey:@"URL"] relativeTo:filename] forKey:@"URL"];
NSData * data = [preparedEntry objectForKey:@"albumArt"];
if (data)
[preparedEntry setObject:[[[NSImage alloc] initWithData:data] autorelease] forKey:@"albumArt"];
[entries addObject:[NSDictionary dictionaryWithDictionary:preparedEntry]];
}

View File

@ -69,77 +69,41 @@
}
NSString *imageCacheTag = [NSString stringWithFormat:@"%@-%@-%@-%@", [dict objectForKey:@"album"], [dict objectForKey:@"artist"], [dict objectForKey:@"genre"], [dict objectForKey:@"year"]];
NSImage *image = [NSImage imageNamed:imageCacheTag];
if (nil == image) {
// Try to load the image.
// WARNING: HACK
TagLib::MPEG::File *mf = dynamic_cast<TagLib::MPEG::File *>(f.file());
if (mf) {
TagLib::ID3v2::Tag *tag = mf->ID3v2Tag();
if (tag) {
TagLib::ID3v2::FrameList pictures = mf->ID3v2Tag()->frameListMap()["APIC"];
if (!pictures.isEmpty()) {
TagLib::ID3v2::AttachedPictureFrame *pic = static_cast<TagLib::ID3v2::AttachedPictureFrame *>(pictures.front());
// Try to load the image.
NSData * image = nil;
// WARNING: HACK
TagLib::MPEG::File *mf = dynamic_cast<TagLib::MPEG::File *>(f.file());
if (mf) {
TagLib::ID3v2::Tag *tag = mf->ID3v2Tag();
if (tag) {
TagLib::ID3v2::FrameList pictures = mf->ID3v2Tag()->frameListMap()["APIC"];
if (!pictures.isEmpty()) {
TagLib::ID3v2::AttachedPictureFrame *pic = static_cast<TagLib::ID3v2::AttachedPictureFrame *>(pictures.front());
NSData *data = [[NSData alloc] initWithBytes:pic->picture().data() length:pic->picture().size()];
image = [[[NSImage alloc] initWithData:data] autorelease];
[data release];
}
image = [NSData dataWithBytes:pic->picture().data() length:pic->picture().size()];
}
}
if (nil != image) {
[image setName:imageCacheTag];
}
}
if (nil == image) {
// Try to load image from external file
// If we find an appropriately-named image in this directory, it will
// be tagged with the first image cache tag. Subsequent directory entries
// may have a different tag, but an image search would result in the same
// artwork.
static NSString *lastImagePath = nil;
static NSString *lastCacheTag = nil;
NSString *path = [[url path] stringByDeletingLastPathComponent];
if ([path isEqualToString:lastImagePath]) {
// Use whatever image may have been stored with the initial tag for the path
// (might be nil but no point scanning again)
image = [NSImage imageNamed:lastCacheTag];
} else {
// Book-keeping...
if (nil != lastImagePath)
[lastImagePath release];
lastImagePath = [path retain];
if (nil != lastCacheTag)
[lastCacheTag release];
lastCacheTag = [imageCacheTag retain];
// Gather list of candidate image files
NSArray *fileNames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil];
NSArray *imageFileNames = [fileNames pathsMatchingExtensions:[NSImage imageFileTypes]];
NSArray *fileNames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil];
NSArray *imageFileNames = [fileNames pathsMatchingExtensions:[NSImage imageFileTypes]];
NSEnumerator *imageEnumerator = [imageFileNames objectEnumerator];
NSString *fileName;
NSEnumerator *imageEnumerator = [imageFileNames objectEnumerator];
NSString *fileName;
while (fileName = [imageEnumerator nextObject]) {
if ([TagLibMetadataReader isCoverFile:fileName]) {
image = [[[NSImage alloc] initByReferencingFile:[path stringByAppendingPathComponent:fileName]] autorelease];
[image setName:imageCacheTag];
break;
}
while (fileName = [imageEnumerator nextObject]) {
if ([TagLibMetadataReader isCoverFile:fileName]) {
image = [NSData dataWithContentsOfFile:[path stringByAppendingPathComponent:fileName]];
break;
}
}
}