diff --git a/Application/PlaybackEventController.m b/Application/PlaybackEventController.m index fc6c7cbc8..35904f0be 100644 --- a/Application/PlaybackEventController.m +++ b/Application/PlaybackEventController.m @@ -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]; diff --git a/Playlist/PlaylistEntry.h b/Playlist/PlaylistEntry.h index 6d7df89af..52a370183 100644 --- a/Playlist/PlaylistEntry.h +++ b/Playlist/PlaylistEntry.h @@ -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; diff --git a/Playlist/PlaylistEntry.m b/Playlist/PlaylistEntry.m index 448d21116..eb92e7580 100644 --- a/Playlist/PlaylistEntry.m +++ b/Playlist/PlaylistEntry.m @@ -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 { diff --git a/Playlist/PlaylistLoader.m b/Playlist/PlaylistLoader.m index d71310a2f..a3892e3ee 100755 --- a/Playlist/PlaylistLoader.m +++ b/Playlist/PlaylistLoader.m @@ -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]; diff --git a/Playlist/XmlContainer.m b/Playlist/XmlContainer.m index a9afe8343..91a2ec619 100644 --- a/Playlist/XmlContainer.m +++ b/Playlist/XmlContainer.m @@ -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]]; } diff --git a/Plugins/TagLib/TagLibMetadataReader.m b/Plugins/TagLib/TagLibMetadataReader.m index 5a4ba7d2f..479b35e3d 100644 --- a/Plugins/TagLib/TagLibMetadataReader.m +++ b/Plugins/TagLib/TagLibMetadataReader.m @@ -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(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(pictures.front()); + + // Try to load the image. + NSData * image = nil; + + // WARNING: HACK + TagLib::MPEG::File *mf = dynamic_cast(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(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; } } }