2022-01-03 09:51:53 +00:00
|
|
|
//
|
|
|
|
// 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>
|
2022-02-07 05:49:27 +00:00
|
|
|
#import <libvgm/player/s98player.hpp>
|
|
|
|
#import <libvgm/player/vgmplayer.hpp>
|
|
|
|
#import <libvgm/utils/MemoryLoader.h>
|
2022-01-03 09:51:53 +00:00
|
|
|
|
|
|
|
@implementation libvgmMetadataReader
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
const int logLevel = DEVLOG_DEBUG;
|
|
|
|
#else
|
|
|
|
const int logLevel = DEVLOG_INFO;
|
|
|
|
#endif
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
static UINT8 FilePlayCallback(PlayerBase* player, void* userParam, UINT8 evtType, void* evtParam) {
|
2022-01-03 09:51:53 +00:00
|
|
|
return 0x00;
|
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
static DATA_LOADER* RequestFileCallback(void* userParam, PlayerBase* player, const char* fileName) {
|
2022-01-03 09:51:53 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
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])))
|
2022-01-03 09:51:53 +00:00
|
|
|
level = 0;
|
|
|
|
return LVL_NAMES[level];
|
|
|
|
}
|
|
|
|
|
|
|
|
static void PlayerLogCallback(void* userParam, PlayerBase* player, UINT8 level, UINT8 srcType,
|
2022-02-07 05:49:27 +00:00
|
|
|
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) {
|
2022-01-08 03:07:46 +00:00
|
|
|
ALog(@"[%s] %s: %s", LogLevel2Str(level), player->GetPlayerName(), message);
|
2022-02-07 05:49:27 +00:00
|
|
|
} else {
|
2022-01-08 03:07:46 +00:00
|
|
|
ALog(@"[%s] %s %s: %s", LogLevel2Str(level), player->GetPlayerName(), srcTag, message);
|
2022-02-07 05:49:27 +00:00
|
|
|
}
|
2022-01-03 09:51:53 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
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;
|
2022-01-03 09:51:53 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
+ (NSArray*)fileTypes {
|
2022-01-03 09:51:53 +00:00
|
|
|
return [libvgmDecoder fileTypes];
|
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
+ (NSArray*)mimeTypes {
|
2022-01-03 09:51:53 +00:00
|
|
|
return [libvgmDecoder mimeTypes];
|
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
+ (float)priority {
|
|
|
|
return [libvgmDecoder priority];
|
2022-01-03 09:51:53 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
+ (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;
|
2022-01-03 09:51:53 +00:00
|
|
|
|
|
|
|
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];
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
UINT8* fileData = (UINT8*)malloc(size);
|
|
|
|
if(!fileData)
|
2022-01-03 09:51:53 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
size_t bytesRead = [source read:fileData amount:size];
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
if(bytesRead != size) {
|
2022-01-03 09:51:53 +00:00
|
|
|
free(fileData);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
DATA_LOADER* dLoad = MemoryLoader_Init(fileData, (unsigned int)size);
|
|
|
|
if(!dLoad) {
|
2022-01-03 09:51:53 +00:00
|
|
|
free(fileData);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
DataLoader_SetPreloadBytes(dLoad, 0x100);
|
|
|
|
if(DataLoader_Load(dLoad)) {
|
2022-01-03 09:51:53 +00:00
|
|
|
DataLoader_Deinit(dLoad);
|
|
|
|
free(fileData);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
if(mainPlr.LoadFile(dLoad)) {
|
2022-01-03 09:51:53 +00:00
|
|
|
DataLoader_Deinit(dLoad);
|
|
|
|
free(fileData);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-02-07 05:49:27 +00:00
|
|
|
NSString* system = @"";
|
|
|
|
NSString* title = @"";
|
|
|
|
NSString* artist = @"";
|
|
|
|
NSString* album = @"";
|
|
|
|
NSNumber* year = [NSNumber numberWithInt:0];
|
2022-01-03 09:51:53 +00:00
|
|
|
|
|
|
|
PlayerBase* player = mainPlr.GetPlayer();
|
|
|
|
|
|
|
|
const char* const* tagList = player->GetTags();
|
2022-02-07 05:49:27 +00:00
|
|
|
for(const char* const* t = tagList; *t; t += 2) {
|
|
|
|
if(!strcmp(t[0], "TITLE"))
|
2022-05-24 08:07:55 +00:00
|
|
|
title = guess_encoding_of_string(t[1]);
|
2022-02-07 05:49:27 +00:00
|
|
|
else if(!strcmp(t[0], "ARTIST"))
|
2022-05-24 08:07:55 +00:00
|
|
|
artist = guess_encoding_of_string(t[1]);
|
2022-02-07 05:49:27 +00:00
|
|
|
else if(!strcmp(t[0], "GAME"))
|
2022-05-24 08:07:55 +00:00
|
|
|
album = guess_encoding_of_string(t[1]);
|
2022-02-07 05:49:27 +00:00
|
|
|
else if(!strcmp(t[0], "DATE")) {
|
|
|
|
char* end;
|
2022-01-03 09:51:53 +00:00
|
|
|
unsigned long theYear = strtoul(t[1], &end, 10);
|
|
|
|
year = [NSNumber numberWithLong:theYear];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PLR_SONG_INFO sInf;
|
|
|
|
player->GetSongInfo(sInf);
|
|
|
|
|
2022-01-05 10:37:39 +00:00
|
|
|
system = [NSString stringWithFormat:@"%s v%X.%02X", FCC2Str(sInf.format).c_str(), sInf.fileVerMaj, sInf.fileVerMin];
|
2022-01-03 09:51:53 +00:00
|
|
|
|
|
|
|
mainPlr.UnloadFile();
|
|
|
|
DataLoader_Deinit(dLoad);
|
|
|
|
free(fileData);
|
2022-02-07 05:49:27 +00:00
|
|
|
|
2022-02-09 03:42:03 +00:00
|
|
|
NSDictionary* dict = @{@"codec": system,
|
|
|
|
@"album": album,
|
|
|
|
@"title": title,
|
|
|
|
@"artist": artist,
|
|
|
|
@"year": [NSNumber numberWithInt:[year intValue]]};
|
2022-02-07 05:49:27 +00:00
|
|
|
|
|
|
|
return dict;
|
2022-01-03 09:51:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@end
|