Cog/Plugins/OpenMPT/OpenMPT/OMPTMetadataReader.mm
Christopher Snowhill 8ee4a04f3b Experimental tag support redesign
This redesign completely changes how tags are stored in memory. Now all
arbitrary tag names are supported, where possible. Some extra work will
be needed to support arbitrary tags with TagLib, such as replacing it
with a different library.

Translation pending for a couple of strings.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-07-08 16:35:34 -07:00

91 lines
2 KiB
Text

//
// OMPTMetadataReader.m
// OpenMPT
//
// Created by Christopher Snowhill on 1/4/18.
// Copyright 2018 __LoSnoCo__. All rights reserved.
//
#import "OMPTMetadataReader.h"
#import "OMPTDecoder.h"
#import <libOpenMPT/libopenmpt.hpp>
#import "Logging.H"
@implementation OMPTMetadataReader
+ (NSArray *)fileTypes {
return [OMPTDecoder fileTypes];
}
+ (NSArray *)mimeTypes {
return [OMPTDecoder mimeTypes];
}
+ (float)priority {
return 1.0f;
}
static void setDictionary(NSMutableDictionary *dict, NSString *tag, NSString *value) {
NSMutableArray *array = [dict valueForKey:tag];
if(!array) {
array = [[NSMutableArray alloc] init];
[dict setObject:array forKey:tag];
}
[array addObject:value];
}
+ (NSDictionary *)metadataForURL:(NSURL *)url {
id audioSourceClass = NSClassFromString(@"AudioSource");
id<CogSource> source = [audioSourceClass audioSourceForURL:url];
if(![source open:url])
return 0;
if(![source seekable])
return 0;
[source seek:0 whence:SEEK_END];
long size = [source tell];
[source seek:0 whence:SEEK_SET];
std::vector<char> data(static_cast<std::size_t>(size));
[source read:data.data() amount:size];
int track_num;
if([[url fragment] length] == 0)
track_num = 0;
else
track_num = [[url fragment] intValue];
try {
std::map<std::string, std::string> ctls;
openmpt::module *mod = new openmpt::module(data, std::clog, ctls);
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
std::vector<std::string> keys = mod->get_metadata_keys();
for(std::vector<std::string>::iterator key = keys.begin(); key != keys.end(); ++key) {
NSString *tag = guess_encoding_of_string((*key).c_str());
NSString *value = guess_encoding_of_string(mod->get_metadata(*key).c_str());
if(*key == "type")
continue;
else if(*key == "type_long") {
setDictionary(dict, @"codec", value);
} else {
setDictionary(dict, tag, value);
}
}
delete mod;
return dict;
} catch(std::exception & /*e*/) {
return 0;
}
}
@end