FFmpeg input: Support reading metadata
Where TagLib is not being employed, use FFmpeg to read tags where possible. This allows reading tags from files like IFF. It reads it through properties, otherwise allowing tag readers to function like usual. Signed-off-by: Christopher Snowhill <kode54@gmail.com>CQTexperiment
parent
5ff1f95481
commit
39dcb88728
|
@ -66,6 +66,8 @@
|
|||
8384912718080FF100E7332D /* Logging.h in Headers */ = {isa = PBXBuildFile; fileRef = 8384912618080FF100E7332D /* Logging.h */; };
|
||||
839366671815923C006DD712 /* CogPluginMulti.h in Headers */ = {isa = PBXBuildFile; fileRef = 839366651815923C006DD712 /* CogPluginMulti.h */; };
|
||||
839366681815923C006DD712 /* CogPluginMulti.m in Sources */ = {isa = PBXBuildFile; fileRef = 839366661815923C006DD712 /* CogPluginMulti.m */; };
|
||||
8399CF2C27B5D1D5008751F1 /* NSDictionary+Merge.h in Headers */ = {isa = PBXBuildFile; fileRef = 8399CF2A27B5D1D4008751F1 /* NSDictionary+Merge.h */; };
|
||||
8399CF2D27B5D1D5008751F1 /* NSDictionary+Merge.m in Sources */ = {isa = PBXBuildFile; fileRef = 8399CF2B27B5D1D4008751F1 /* NSDictionary+Merge.m */; };
|
||||
8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
|
||||
8E8D3D2F0CBAEE6E00135C1B /* AudioContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8D3D2D0CBAEE6E00135C1B /* AudioContainer.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
8E8D3D300CBAEE6E00135C1B /* AudioContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E8D3D2E0CBAEE6E00135C1B /* AudioContainer.m */; };
|
||||
|
@ -160,6 +162,8 @@
|
|||
8384912618080FF100E7332D /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Logging.h; path = ../../Utils/Logging.h; sourceTree = "<group>"; };
|
||||
839366651815923C006DD712 /* CogPluginMulti.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CogPluginMulti.h; sourceTree = "<group>"; };
|
||||
839366661815923C006DD712 /* CogPluginMulti.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CogPluginMulti.m; sourceTree = "<group>"; };
|
||||
8399CF2A27B5D1D4008751F1 /* NSDictionary+Merge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSDictionary+Merge.h"; path = "../../Utils/NSDictionary+Merge.h"; sourceTree = "<group>"; };
|
||||
8399CF2B27B5D1D4008751F1 /* NSDictionary+Merge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSDictionary+Merge.m"; path = "../../Utils/NSDictionary+Merge.m"; sourceTree = "<group>"; };
|
||||
8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
|
||||
8DC2EF5B0486A6940098B216 /* CogAudio.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CogAudio.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
8E8D3D2D0CBAEE6E00135C1B /* AudioContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AudioContainer.h; sourceTree = "<group>"; };
|
||||
|
@ -333,6 +337,8 @@
|
|||
17D21CDC0B8BE5B400D1EBDE /* Utils */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8399CF2A27B5D1D4008751F1 /* NSDictionary+Merge.h */,
|
||||
8399CF2B27B5D1D4008751F1 /* NSDictionary+Merge.m */,
|
||||
8347C73F2796C58800FA8A7D /* NSFileHandle+CreateFile.h */,
|
||||
8347C7402796C58800FA8A7D /* NSFileHandle+CreateFile.m */,
|
||||
8384912618080FF100E7332D /* Logging.h */,
|
||||
|
@ -430,6 +436,7 @@
|
|||
17D21CA10B8BE4BA00D1EBDE /* BufferChain.h in Headers */,
|
||||
17D21CA50B8BE4BA00D1EBDE /* InputNode.h in Headers */,
|
||||
17D21CA70B8BE4BA00D1EBDE /* Node.h in Headers */,
|
||||
8399CF2C27B5D1D5008751F1 /* NSDictionary+Merge.h in Headers */,
|
||||
17D21CA90B8BE4BA00D1EBDE /* OutputNode.h in Headers */,
|
||||
17D21CC50B8BE4BA00D1EBDE /* OutputCoreAudio.h in Headers */,
|
||||
834FD4F427AFA2150063BC83 /* Downmix.h in Headers */,
|
||||
|
@ -536,6 +543,7 @@
|
|||
835EDD7B279FE23A001EDCCE /* HeadphoneFilter.m in Sources */,
|
||||
17D21CA20B8BE4BA00D1EBDE /* BufferChain.m in Sources */,
|
||||
17D21CA60B8BE4BA00D1EBDE /* InputNode.m in Sources */,
|
||||
8399CF2D27B5D1D5008751F1 /* NSDictionary+Merge.m in Sources */,
|
||||
17D21CA80B8BE4BA00D1EBDE /* Node.m in Sources */,
|
||||
17D21CAA0B8BE4BA00D1EBDE /* OutputNode.m in Sources */,
|
||||
834FD4F527AFA2150063BC83 /* Downmix.m in Sources */,
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#import "NSFileHandle+CreateFile.h"
|
||||
|
||||
#import "NSDictionary+Merge.h"
|
||||
|
||||
@implementation PluginController
|
||||
|
||||
@synthesize sources;
|
||||
|
@ -535,10 +537,11 @@ static PluginController *sharedPluginController = nil;
|
|||
}
|
||||
|
||||
NSDictionary *properties = [decoder properties];
|
||||
NSDictionary *metadata = [decoder metadata];
|
||||
|
||||
[decoder close];
|
||||
|
||||
return properties;
|
||||
return [NSDictionary dictionaryByMerging:properties with:metadata];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -371,7 +371,7 @@
|
|||
|
||||
@dynamic albumArt;
|
||||
- (NSImage *)albumArt {
|
||||
if(!albumArtInternal) return nil;
|
||||
if(!albumArtInternal || ![albumArtInternal length]) return nil;
|
||||
|
||||
NSString *imageCacheTag = [NSString stringWithFormat:@"%@-%@-%@-%@", album, artist, genre, year];
|
||||
NSImage *image = [NSImage imageNamed:imageCacheTag];
|
||||
|
|
|
@ -47,10 +47,22 @@
|
|||
BOOL endOfAudio;
|
||||
|
||||
int metadataIndex;
|
||||
NSString *genre;
|
||||
NSString *artist;
|
||||
NSString *title;
|
||||
NSString *albumartist;
|
||||
NSString *album;
|
||||
NSString *title;
|
||||
NSString *genre;
|
||||
NSNumber *year;
|
||||
NSNumber *track;
|
||||
NSNumber *disc;
|
||||
float replayGainAlbumGain;
|
||||
float replayGainAlbumPeak;
|
||||
float replayGainTrackGain;
|
||||
float replayGainTrackPeak;
|
||||
|
||||
int attachedPicIndex;
|
||||
NSData *albumArt;
|
||||
|
||||
NSDictionary *id3Metadata;
|
||||
}
|
||||
|
||||
|
|
|
@ -157,6 +157,7 @@ static uint8_t reverse_bits[0x100];
|
|||
|
||||
streamIndex = -1;
|
||||
metadataIndex = -1;
|
||||
attachedPicIndex = -1;
|
||||
AVCodecParameters *codecPar;
|
||||
|
||||
for(i = 0; i < formatCtx->nb_streams; i++) {
|
||||
|
@ -167,6 +168,8 @@ static uint8_t reverse_bits[0x100];
|
|||
streamIndex = i;
|
||||
} else if(codecPar->codec_id == AV_CODEC_ID_TIMED_ID3) {
|
||||
metadataIndex = i;
|
||||
} else if(stream->disposition & AV_DISPOSITION_ATTACHED_PIC) {
|
||||
attachedPicIndex = i;
|
||||
} else {
|
||||
stream->discard = AVDISCARD_ALL;
|
||||
}
|
||||
|
@ -445,10 +448,19 @@ static uint8_t reverse_bits[0x100];
|
|||
|
||||
seekable = [s seekable];
|
||||
|
||||
genre = @"";
|
||||
album = @"";
|
||||
artist = @"";
|
||||
albumartist = @"";
|
||||
album = @"";
|
||||
title = @"";
|
||||
genre = @"";
|
||||
year = @(0);
|
||||
track = @(0);
|
||||
disc = @(0);
|
||||
replayGainAlbumGain = 0.0;
|
||||
replayGainAlbumPeak = 0.0;
|
||||
replayGainTrackGain = 0.0;
|
||||
replayGainTrackPeak = 0.0;
|
||||
albumArt = [NSData data];
|
||||
id3Metadata = @{};
|
||||
[self updateMetadata];
|
||||
|
||||
|
@ -495,13 +507,19 @@ static uint8_t reverse_bits[0x100];
|
|||
}
|
||||
|
||||
- (void)updateMetadata {
|
||||
if([source seekable]) return;
|
||||
|
||||
const AVDictionaryEntry *tag = NULL;
|
||||
NSString *_genre = genre;
|
||||
NSString *_album = album;
|
||||
NSString *_artist = artist;
|
||||
NSString *_albumartist = albumartist;
|
||||
NSString *_album = album;
|
||||
NSString *_title = title;
|
||||
NSString *_genre = genre;
|
||||
NSNumber *_year = year;
|
||||
NSNumber *_track = track;
|
||||
NSNumber *_disc = disc;
|
||||
float _replayGainAlbumGain = replayGainAlbumGain;
|
||||
float _replayGainAlbumPeak = replayGainAlbumPeak;
|
||||
float _replayGainTrackGain = replayGainTrackGain;
|
||||
float _replayGainTrackPeak = replayGainTrackPeak;
|
||||
if(formatCtx->metadata) {
|
||||
while((tag = av_dict_get(formatCtx->metadata, "", tag, AV_DICT_IGNORE_SUFFIX))) {
|
||||
if(!strcasecmp(tag->key, "streamtitle")) {
|
||||
|
@ -517,10 +535,35 @@ static uint8_t reverse_bits[0x100];
|
|||
_album = [NSString stringWithUTF8String:tag->value];
|
||||
} else if(!strcasecmp(tag->key, "icy-genre")) {
|
||||
_genre = [NSString stringWithUTF8String:tag->value];
|
||||
} else if(!strcasecmp(tag->key, "album")) {
|
||||
_album = [NSString stringWithUTF8String:tag->value];
|
||||
} else if(!strcasecmp(tag->key, "album_artist")) {
|
||||
_albumartist = [NSString stringWithUTF8String:tag->value];
|
||||
} else if(!strcasecmp(tag->key, "artist")) {
|
||||
_artist = [NSString stringWithUTF8String:tag->value];
|
||||
} else if(!strcasecmp(tag->key, "title")) {
|
||||
_title = [NSString stringWithUTF8String:tag->value];
|
||||
} else if(!strcasecmp(tag->key, "date")) {
|
||||
NSString *dateString = [NSString stringWithUTF8String:tag->value];
|
||||
_year = @([dateString intValue]);
|
||||
} else if(!strcasecmp(tag->key, "track")) {
|
||||
NSString *trackString = [NSString stringWithUTF8String:tag->value];
|
||||
_track = @([trackString intValue]);
|
||||
} else if(!strcasecmp(tag->key, "disc")) {
|
||||
NSString *discString = [NSString stringWithUTF8String:tag->value];
|
||||
_disc = @([discString intValue]);
|
||||
} else if(!strcasecmp(tag->key, "replaygain_album_gain")) {
|
||||
NSString *rgValue = [NSString stringWithUTF8String:tag->value];
|
||||
_replayGainAlbumGain = [rgValue floatValue];
|
||||
} else if(!strcasecmp(tag->key, "replaygain_album_peak")) {
|
||||
NSString *rgValue = [NSString stringWithUTF8String:tag->value];
|
||||
_replayGainAlbumPeak = [rgValue floatValue];
|
||||
} else if(!strcasecmp(tag->key, "replaygain_track_gain")) {
|
||||
NSString *rgValue = [NSString stringWithUTF8String:tag->value];
|
||||
_replayGainTrackGain = [rgValue floatValue];
|
||||
} else if(!strcasecmp(tag->key, "replaygain_track_peak")) {
|
||||
NSString *rgValue = [NSString stringWithUTF8String:tag->value];
|
||||
_replayGainTrackPeak = [rgValue floatValue];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -537,16 +580,34 @@ static uint8_t reverse_bits[0x100];
|
|||
}
|
||||
}
|
||||
|
||||
if(![_genre isEqual:genre] ||
|
||||
if(![_artist isEqual:artist] ||
|
||||
![_albumartist isEqual:albumartist] ||
|
||||
![_album isEqual:album] ||
|
||||
![_artist isEqual:artist] ||
|
||||
![_title isEqual:title]) {
|
||||
genre = _genre;
|
||||
album = _album;
|
||||
![_title isEqual:title] ||
|
||||
![_genre isEqual:genre] ||
|
||||
![_year isEqual:year] ||
|
||||
![_track isEqual:track] ||
|
||||
![_disc isEqual:disc] ||
|
||||
_replayGainAlbumGain != replayGainAlbumGain ||
|
||||
_replayGainAlbumPeak != replayGainAlbumPeak ||
|
||||
_replayGainTrackGain != replayGainTrackGain ||
|
||||
_replayGainTrackPeak != replayGainTrackPeak) {
|
||||
artist = _artist;
|
||||
albumartist = _albumartist;
|
||||
album = _album;
|
||||
title = _title;
|
||||
[self willChangeValueForKey:@"metadata"];
|
||||
[self didChangeValueForKey:@"metadata"];
|
||||
genre = _genre;
|
||||
year = _year;
|
||||
track = _track;
|
||||
disc = _disc;
|
||||
replayGainAlbumGain = _replayGainAlbumGain;
|
||||
replayGainAlbumPeak = _replayGainAlbumPeak;
|
||||
replayGainTrackGain = _replayGainTrackGain;
|
||||
replayGainTrackPeak = _replayGainTrackPeak;
|
||||
if(![source seekable]) {
|
||||
[self willChangeValueForKey:@"metadata"];
|
||||
[self didChangeValueForKey:@"metadata"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -563,6 +624,17 @@ static uint8_t reverse_bits[0x100];
|
|||
}
|
||||
}
|
||||
|
||||
- (void)updateArtwork {
|
||||
NSData *_albumArt = [NSData dataWithBytes:lastReadPacket->data length:lastReadPacket->size];
|
||||
if(![_albumArt isEqual:albumArt]) {
|
||||
albumArt = _albumArt;
|
||||
if(![source seekable]) {
|
||||
[self willChangeValueForKey:@"metadata"];
|
||||
[self didChangeValueForKey:@"metadata"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (int)readAudio:(void *)buf frames:(UInt32)frames {
|
||||
if(totalFrames && framesRead >= totalFrames)
|
||||
return 0;
|
||||
|
@ -611,6 +683,9 @@ static uint8_t reverse_bits[0x100];
|
|||
if(lastReadPacket->stream_index == metadataIndex) {
|
||||
[self updateID3Metadata];
|
||||
continue;
|
||||
} else if(lastReadPacket->stream_index == attachedPicIndex) {
|
||||
[self updateArtwork];
|
||||
continue;
|
||||
}
|
||||
|
||||
if(lastReadPacket->stream_index != streamIndex)
|
||||
|
@ -832,7 +907,7 @@ static uint8_t reverse_bits[0x100];
|
|||
}
|
||||
|
||||
- (NSDictionary *)metadata {
|
||||
return [NSDictionary dictionaryByMerging:@{ @"genre": genre, @"album": album, @"artist": artist, @"title": title } with:id3Metadata];
|
||||
return [NSDictionary dictionaryByMerging:@{ @"artist": artist, @"albumartist": albumartist, @"album": album, @"title": title, @"genre": genre, @"year": year, @"track": track, @"disc": disc, @"replayGainAlbumGain": @(replayGainAlbumGain), @"replayGainAlbumPeak": @(replayGainAlbumPeak), @"replayGainTrackGain": @(replayGainTrackGain), @"replayGainTrackPeak": @(replayGainTrackPeak), @"albumArt": albumArt } with:id3Metadata];
|
||||
}
|
||||
|
||||
+ (NSArray *)fileTypes {
|
||||
|
|
Loading…
Reference in New Issue