198 lines
4.1 KiB
Text
198 lines
4.1 KiB
Text
//
|
|
// AdPlugDecoder.m
|
|
// AdPlug
|
|
//
|
|
// Created by Christopher Snowhill on 1/27/18.
|
|
// Copyright 2018 __LoSnoCo__. All rights reserved.
|
|
//
|
|
|
|
#import "AdPlugDecoder.h"
|
|
|
|
#import <libAdPlug/nemuopl.h>
|
|
|
|
#import "fileprovider.h"
|
|
|
|
#import "Logging.h"
|
|
|
|
#import "PlaylistController.h"
|
|
|
|
@implementation AdPlugDecoder
|
|
|
|
static CAdPlugDatabase *g_database = NULL;
|
|
|
|
+ (void)initialize {
|
|
if(!g_database) {
|
|
NSURL *dbUrl = [[NSBundle bundleWithIdentifier:@"net.kode54.AdPlug"] URLForResource:@"adplug" withExtension:@"db"];
|
|
|
|
NSString *dbPath = [dbUrl path];
|
|
|
|
if(dbPath) {
|
|
g_database = new CAdPlugDatabase;
|
|
g_database->load([dbPath UTF8String]);
|
|
|
|
CAdPlug::set_database(g_database);
|
|
}
|
|
}
|
|
}
|
|
|
|
- (id)init {
|
|
self = [super init];
|
|
if(self) {
|
|
m_player = NULL;
|
|
m_emu = NULL;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (BOOL)open:(id<CogSource>)s {
|
|
[self setSource:s];
|
|
|
|
m_emu = new CNemuopl(44100);
|
|
|
|
NSString *path = [[s url] absoluteString];
|
|
NSRange fragmentRange = [path rangeOfString:@"#" options:NSBackwardsSearch];
|
|
if(fragmentRange.location != NSNotFound) {
|
|
path = [path substringToIndex:fragmentRange.location];
|
|
}
|
|
|
|
std::string _path = [[path stringByRemovingPercentEncoding] UTF8String];
|
|
m_player = CAdPlug::factory(_path, m_emu, CAdPlug::players, CProvider_cog(_path, source));
|
|
|
|
if(!m_player)
|
|
return 0;
|
|
|
|
if([[source.url fragment] length] == 0)
|
|
subsong = 0;
|
|
else
|
|
subsong = [[source.url fragment] intValue];
|
|
|
|
samples_todo = 0;
|
|
|
|
length = m_player->songlength(subsong) * 441 / 10;
|
|
current_pos = 0;
|
|
|
|
m_player->rewind(subsong);
|
|
|
|
[self willChangeValueForKey:@"properties"];
|
|
[self didChangeValueForKey:@"properties"];
|
|
|
|
return YES;
|
|
}
|
|
|
|
- (NSDictionary *)properties {
|
|
return @{@"bitrate": [NSNumber numberWithInt:0],
|
|
@"sampleRate": [NSNumber numberWithFloat:44100],
|
|
@"totalFrames": [NSNumber numberWithDouble:length],
|
|
@"bitsPerSample": [NSNumber numberWithInt:16], // Samples are short
|
|
@"floatingPoint": [NSNumber numberWithBool:NO],
|
|
@"channels": [NSNumber numberWithInt:2], // output from gme_play is in stereo
|
|
@"seekable": [NSNumber numberWithBool:YES],
|
|
@"codec": [NSString stringWithUTF8String:m_player->gettype().c_str()],
|
|
@"encoding": @"synthesized",
|
|
@"endian": @"host"};
|
|
}
|
|
|
|
- (NSDictionary *)metadata {
|
|
return @{};
|
|
}
|
|
|
|
- (int)readAudio:(void *)buf frames:(UInt32)frames {
|
|
int total = 0;
|
|
bool dont_loop = !IsRepeatOneSet();
|
|
if(dont_loop && current_pos + frames > length)
|
|
frames = (UInt32)(length - current_pos);
|
|
while(total < frames) {
|
|
bool running = true;
|
|
if(!samples_todo) {
|
|
running = m_player->update() && running;
|
|
if(!dont_loop || running) {
|
|
samples_todo = 44100 / m_player->getrefresh();
|
|
current_pos += samples_todo;
|
|
}
|
|
}
|
|
if(!samples_todo)
|
|
break;
|
|
int samples_now = samples_todo;
|
|
if(samples_now > (frames - total))
|
|
samples_now = frames - total;
|
|
m_emu->update((short *)buf, samples_now);
|
|
buf = ((short *)buf) + samples_now * 2;
|
|
samples_todo -= samples_now;
|
|
total += samples_now;
|
|
}
|
|
|
|
return total;
|
|
}
|
|
|
|
- (long)seek:(long)frame {
|
|
if(frame < current_pos) {
|
|
current_pos = 0;
|
|
m_player->rewind(subsong);
|
|
}
|
|
|
|
while(current_pos < frame) {
|
|
m_player->update();
|
|
current_pos += 44100 / m_player->getrefresh();
|
|
}
|
|
|
|
samples_todo = (UInt32)(frame - current_pos);
|
|
|
|
return frame;
|
|
}
|
|
|
|
- (void)cleanUp {
|
|
delete m_player;
|
|
m_player = NULL;
|
|
delete m_emu;
|
|
m_emu = NULL;
|
|
}
|
|
|
|
- (void)close {
|
|
[self cleanUp];
|
|
}
|
|
|
|
- (void)dealloc {
|
|
[self close];
|
|
}
|
|
|
|
- (void)setSource:(id<CogSource>)s {
|
|
source = s;
|
|
}
|
|
|
|
- (id<CogSource>)source {
|
|
return source;
|
|
}
|
|
|
|
+ (NSArray *)fileTypes {
|
|
const CPlayers &pl = CAdPlug::players;
|
|
CPlayers::const_iterator i;
|
|
unsigned j;
|
|
NSMutableArray *array = [NSMutableArray array];
|
|
|
|
for(i = pl.begin(); i != pl.end(); ++i) {
|
|
for(j = 0; (*i)->get_extension(j); ++j) {
|
|
[array addObject:[NSString stringWithUTF8String:(*i)->get_extension(j) + 1]];
|
|
}
|
|
}
|
|
|
|
return [NSArray arrayWithArray:array];
|
|
}
|
|
|
|
+ (NSArray *)mimeTypes {
|
|
return nil;
|
|
}
|
|
|
|
+ (float)priority {
|
|
return 0.5;
|
|
}
|
|
|
|
+ (NSArray *)fileTypeAssociations {
|
|
NSMutableArray *ret = [[NSMutableArray alloc] init];
|
|
[ret addObject:@"AdPlug Files"];
|
|
[ret addObject:@"vg.icns"];
|
|
[ret addObjectsFromArray:[self fileTypes]];
|
|
|
|
return @[[NSArray arrayWithArray:ret]];
|
|
}
|
|
|
|
@end
|