Now storing all album art internally as its original format and synthesizing NSImage objects on demand
parent
a63e27f95c
commit
555ccc9e87
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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]];
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue