cog/Plugins/libvgmPlayer/libvgmMetadataReader.mm

173 lines
4.2 KiB
Plaintext

//
// libvgmMetadataReader.mm
// libvgmPlayer
//
// Created by Christopher Snowhill on 1/03/22.
// Copyright 2022 __LoSnoCo__. All rights reserved.
//
#import "libvgmMetadataReader.h"
#import "libvgmDecoder.h"
#import "Logging.h"
#import <libvgm/player/droplayer.hpp>
#import <libvgm/player/gymplayer.hpp>
#import <libvgm/player/s98player.hpp>
#import <libvgm/player/vgmplayer.hpp>
#import <libvgm/utils/MemoryLoader.h>
@implementation libvgmMetadataReader
#ifdef _DEBUG
const int logLevel = DEVLOG_DEBUG;
#else
const int logLevel = DEVLOG_INFO;
#endif
static UINT8 FilePlayCallback(PlayerBase* player, void* userParam, UINT8 evtType, void* evtParam) {
return 0x00;
}
static DATA_LOADER* RequestFileCallback(void* userParam, PlayerBase* player, const char* fileName) {
return NULL;
}
static const char* LogLevel2Str(UINT8 level) {
static const char* LVL_NAMES[6] = { " ??? ", "Error", "Warn ", "Info ", "Debug", "Trace" };
if(level >= (sizeof(LVL_NAMES) / sizeof(LVL_NAMES[0])))
level = 0;
return LVL_NAMES[level];
}
static void PlayerLogCallback(void* userParam, PlayerBase* player, UINT8 level, UINT8 srcType,
const char* srcTag, const char* message) {
if(level > logLevel)
return; // don't print messages with higher verbosity than current log level
if(srcType == PLRLOGSRC_PLR) {
ALog(@"[%s] %s: %s", LogLevel2Str(level), player->GetPlayerName(), message);
} else {
ALog(@"[%s] %s %s: %s", LogLevel2Str(level), player->GetPlayerName(), srcTag, message);
}
return;
}
static std::string FCC2Str(UINT32 fcc) {
std::string result(4, '\0');
result[0] = (char)((fcc >> 24) & 0xFF);
result[1] = (char)((fcc >> 16) & 0xFF);
result[2] = (char)((fcc >> 8) & 0xFF);
result[3] = (char)((fcc >> 0) & 0xFF);
return result;
}
+ (NSArray*)fileTypes {
return [libvgmDecoder fileTypes];
}
+ (NSArray*)mimeTypes {
return [libvgmDecoder mimeTypes];
}
+ (float)priority {
return [libvgmDecoder priority];
}
+ (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;
PlayerA mainPlr;
mainPlr.RegisterPlayerEngine(new VGMPlayer);
mainPlr.RegisterPlayerEngine(new S98Player);
mainPlr.RegisterPlayerEngine(new DROPlayer);
mainPlr.RegisterPlayerEngine(new GYMPlayer);
mainPlr.SetEventCallback(FilePlayCallback, NULL);
mainPlr.SetFileReqCallback(RequestFileCallback, NULL);
mainPlr.SetLogCallback(PlayerLogCallback, NULL);
mainPlr.SetOutputSettings(44100, 2, 24, 2048);
[source seek:0 whence:SEEK_END];
size_t size = [source tell];
[source seek:0 whence:SEEK_SET];
UINT8* fileData = (UINT8*)malloc(size);
if(!fileData)
return 0;
size_t bytesRead = [source read:fileData amount:size];
if(bytesRead != size) {
free(fileData);
return 0;
}
DATA_LOADER* dLoad = MemoryLoader_Init(fileData, (unsigned int)size);
if(!dLoad) {
free(fileData);
return 0;
}
DataLoader_SetPreloadBytes(dLoad, 0x100);
if(DataLoader_Load(dLoad)) {
DataLoader_Deinit(dLoad);
free(fileData);
return 0;
}
if(mainPlr.LoadFile(dLoad)) {
DataLoader_Deinit(dLoad);
free(fileData);
return 0;
}
NSString* system = @"";
NSString* title = @"";
NSString* artist = @"";
NSString* album = @"";
NSNumber* year = @(0);
PlayerBase* player = mainPlr.GetPlayer();
const char* const* tagList = player->GetTags();
for(const char* const* t = tagList; *t; t += 2) {
if(!strcmp(t[0], "TITLE"))
title = guess_encoding_of_string(t[1]);
else if(!strcmp(t[0], "ARTIST"))
artist = guess_encoding_of_string(t[1]);
else if(!strcmp(t[0], "GAME"))
album = guess_encoding_of_string(t[1]);
else if(!strcmp(t[0], "DATE")) {
char* end;
unsigned long theYear = strtoul(t[1], &end, 10);
year = @(theYear);
}
}
PLR_SONG_INFO sInf;
player->GetSongInfo(sInf);
system = [NSString stringWithFormat:@"%s v%X.%02X", FCC2Str(sInf.format).c_str(), sInf.fileVerMaj, sInf.fileVerMin];
mainPlr.UnloadFile();
DataLoader_Deinit(dLoad);
free(fileData);
NSDictionary* dict = @{ @"codec": system,
@"album": album,
@"title": title,
@"artist": artist,
@"year": year };
return dict;
}
@end