SID: Add exception handling
Exception handling was quite missing from this code as well. Let's fix that too. Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
parent
8eddb7bf40
commit
034b0d20b8
3 changed files with 177 additions and 117 deletions
|
@ -35,31 +35,44 @@
|
|||
id<CogSource> source = [audioSourceClass audioSourceForURL:url];
|
||||
|
||||
if(![source open:url])
|
||||
return 0;
|
||||
return @[];
|
||||
|
||||
if(![source seekable])
|
||||
return 0;
|
||||
return @[];
|
||||
|
||||
[source seek:0 whence:SEEK_END];
|
||||
long size = [source tell];
|
||||
[source seek:0 whence:SEEK_SET];
|
||||
|
||||
if(!size)
|
||||
return @[];
|
||||
|
||||
void *data = malloc(size);
|
||||
if(!data)
|
||||
return @[];
|
||||
|
||||
[source read:data amount:size];
|
||||
|
||||
SidTune *tune = new SidTune((const uint_least8_t *)data, (uint_least32_t)size);
|
||||
unsigned int subsongs = 0;
|
||||
|
||||
try {
|
||||
SidTune *tune = new SidTune((const uint_least8_t *)data, (uint_least32_t)size);
|
||||
|
||||
if(!tune->getStatus()) {
|
||||
delete tune;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const SidTuneInfo *info = tune->getInfo();
|
||||
|
||||
subsongs = info->songs();
|
||||
|
||||
if(!tune->getStatus()) {
|
||||
delete tune;
|
||||
return 0;
|
||||
} catch (std::exception &e) {
|
||||
ALog(@"Exception caught processing SID file for song count: %s", e.what());
|
||||
return @[];
|
||||
}
|
||||
|
||||
const SidTuneInfo *info = tune->getInfo();
|
||||
|
||||
unsigned int subsongs = info->songs();
|
||||
|
||||
delete tune;
|
||||
|
||||
NSMutableArray *tracks = [NSMutableArray array];
|
||||
|
||||
for(unsigned int i = 1; i <= subsongs; ++i) {
|
||||
|
|
|
@ -85,6 +85,8 @@ static const char *extListStr[] = { ".str", NULL };
|
|||
|
||||
[source seek:0 whence:SEEK_END];
|
||||
size_t fileSize = [source tell];
|
||||
if(!fileSize)
|
||||
return;
|
||||
|
||||
void *dataBytes = malloc(fileSize);
|
||||
if(!dataBytes)
|
||||
|
@ -162,17 +164,21 @@ static void sidTuneLoader(const char *fileName, std::vector<uint8_t> &bufferRef)
|
|||
|
||||
// Need this static initializer to create the static global tables that sidplayfp doesn't really lock access to
|
||||
+ (void)initialize {
|
||||
ReSIDfpBuilder *builder = new ReSIDfpBuilder("ReSIDfp");
|
||||
try {
|
||||
ReSIDfpBuilder *builder = new ReSIDfpBuilder("ReSIDfp");
|
||||
|
||||
if(builder) {
|
||||
builder->create(1);
|
||||
if(builder->getStatus()) {
|
||||
builder->filter(true);
|
||||
builder->filter6581Curve(0.5);
|
||||
builder->filter8580Curve(0.5);
|
||||
if(builder) {
|
||||
builder->create(1);
|
||||
if(builder->getStatus()) {
|
||||
builder->filter(true);
|
||||
builder->filter6581Curve(0.5);
|
||||
builder->filter8580Curve(0.5);
|
||||
}
|
||||
|
||||
delete builder;
|
||||
}
|
||||
|
||||
delete builder;
|
||||
} catch (std::exception &e) {
|
||||
ALog(@"Exception caught while doing one-time initialization of SID player: %s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,61 +210,66 @@ static void sidTuneLoader(const char *fileName, std::vector<uint8_t> &bufferRef)
|
|||
|
||||
const char **extList = [extension isEqualToString:@"mus"] ? extListStr : extListEmpty;
|
||||
|
||||
tune = new SidTune(sidTuneLoader, [currentUrl UTF8String], extList, true);
|
||||
try {
|
||||
tune = new SidTune(sidTuneLoader, [currentUrl UTF8String], extList, true);
|
||||
|
||||
if(!tune->getStatus())
|
||||
return NO;
|
||||
|
||||
NSURL *url = [s url];
|
||||
int track_num;
|
||||
if([[url fragment] length] == 0)
|
||||
track_num = 1;
|
||||
else
|
||||
track_num = [[url fragment] intValue];
|
||||
|
||||
n_channels = 1;
|
||||
|
||||
double defaultLength = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthDefaultSeconds"] doubleValue];
|
||||
|
||||
length = (int)ceil(sampleRate * defaultLength);
|
||||
|
||||
tune->selectSong(track_num);
|
||||
|
||||
engine = new sidplayfp;
|
||||
|
||||
engine->setRoms(kernel, basic, chargen);
|
||||
|
||||
if(!engine->load(tune))
|
||||
return NO;
|
||||
|
||||
ReSIDfpBuilder *_builder = new ReSIDfpBuilder("ReSIDfp");
|
||||
builder = _builder;
|
||||
|
||||
if(_builder) {
|
||||
_builder->create((engine->info()).maxsids());
|
||||
if(_builder->getStatus()) {
|
||||
_builder->filter(true);
|
||||
_builder->filter6581Curve(0.5);
|
||||
_builder->filter8580Curve(0.5);
|
||||
}
|
||||
if(!_builder->getStatus())
|
||||
if(!tune->getStatus())
|
||||
return NO;
|
||||
} else
|
||||
|
||||
NSURL *url = [s url];
|
||||
int track_num;
|
||||
if([[url fragment] length] == 0)
|
||||
track_num = 1;
|
||||
else
|
||||
track_num = [[url fragment] intValue];
|
||||
|
||||
n_channels = 1;
|
||||
|
||||
double defaultLength = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthDefaultSeconds"] doubleValue];
|
||||
|
||||
length = (int)ceil(sampleRate * defaultLength);
|
||||
|
||||
tune->selectSong(track_num);
|
||||
|
||||
engine = new sidplayfp;
|
||||
|
||||
engine->setRoms(kernel, basic, chargen);
|
||||
|
||||
if(!engine->load(tune))
|
||||
return NO;
|
||||
|
||||
ReSIDfpBuilder *_builder = new ReSIDfpBuilder("ReSIDfp");
|
||||
builder = _builder;
|
||||
|
||||
if(_builder) {
|
||||
_builder->create((engine->info()).maxsids());
|
||||
if(_builder->getStatus()) {
|
||||
_builder->filter(true);
|
||||
_builder->filter6581Curve(0.5);
|
||||
_builder->filter8580Curve(0.5);
|
||||
}
|
||||
if(!_builder->getStatus())
|
||||
return NO;
|
||||
} else
|
||||
return NO;
|
||||
|
||||
const SidTuneInfo *tuneInfo = tune->getInfo();
|
||||
|
||||
SidConfig conf = engine->config();
|
||||
conf.frequency = (int)ceil(sampleRate);
|
||||
conf.sidEmulation = builder;
|
||||
conf.playback = SidConfig::MONO;
|
||||
if(tuneInfo && (tuneInfo->sidChips() > 1))
|
||||
conf.playback = SidConfig::STEREO;
|
||||
if(!engine->config(conf))
|
||||
return NO;
|
||||
|
||||
if(conf.playback == SidConfig::STEREO) {
|
||||
n_channels = 2;
|
||||
}
|
||||
} catch (std::exception &e) {
|
||||
ALog(@"Exception caught loading SID file: %s", e.what());
|
||||
return NO;
|
||||
|
||||
const SidTuneInfo *tuneInfo = tune->getInfo();
|
||||
|
||||
SidConfig conf = engine->config();
|
||||
conf.frequency = (int)ceil(sampleRate);
|
||||
conf.sidEmulation = builder;
|
||||
conf.playback = SidConfig::MONO;
|
||||
if(tuneInfo && (tuneInfo->sidChips() > 1))
|
||||
conf.playback = SidConfig::STEREO;
|
||||
if(!engine->config(conf))
|
||||
return NO;
|
||||
|
||||
if(conf.playback == SidConfig::STEREO) {
|
||||
n_channels = 2;
|
||||
}
|
||||
|
||||
double defaultFade = [[[[NSUserDefaultsController sharedUserDefaultsController] defaults] valueForKey:@"synthDefaultFadeSeconds"] doubleValue];
|
||||
|
@ -299,7 +310,13 @@ static void sidTuneLoader(const char *fileName, std::vector<uint8_t> &bufferRef)
|
|||
int16_t buffer[1024 * n_channels];
|
||||
|
||||
int framesToRender = 1024;
|
||||
int rendered = engine->play(buffer, framesToRender * n_channels) / n_channels;
|
||||
int rendered = 0;
|
||||
try {
|
||||
rendered = engine->play(buffer, framesToRender * n_channels) / n_channels;
|
||||
} catch (std::exception &e) {
|
||||
ALog(@"Exception caught while playing SID file: %s", e.what());
|
||||
return nil;
|
||||
}
|
||||
|
||||
if(rendered <= 0)
|
||||
return nil;
|
||||
|
@ -343,8 +360,13 @@ static void sidTuneLoader(const char *fileName, std::vector<uint8_t> &bufferRef)
|
|||
|
||||
- (long)seek:(long)frame {
|
||||
if(frame < renderedTotal) {
|
||||
engine->load(tune);
|
||||
renderedTotal = 0;
|
||||
try {
|
||||
engine->load(tune);
|
||||
} catch (std::exception &e) {
|
||||
ALog(@"Exception caught reloading SID tune for seeking: %s", e.what());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int16_t sampleBuffer[1024 * 2];
|
||||
|
@ -352,48 +374,58 @@ static void sidTuneLoader(const char *fileName, std::vector<uint8_t> &bufferRef)
|
|||
long remain = (frame - renderedTotal) % 32;
|
||||
frame /= 32;
|
||||
renderedTotal /= 32;
|
||||
engine->fastForward(100 * 32);
|
||||
|
||||
while(renderedTotal < frame) {
|
||||
long todo = frame - renderedTotal;
|
||||
if(todo > 1024)
|
||||
todo = 1024;
|
||||
int done = engine->play(sampleBuffer, (uint_least32_t)(todo * n_channels)) / n_channels;
|
||||
try {
|
||||
engine->fastForward(100 * 32);
|
||||
|
||||
if(done < todo) {
|
||||
if(engine->error())
|
||||
return -1;
|
||||
while(renderedTotal < frame) {
|
||||
long todo = frame - renderedTotal;
|
||||
if(todo > 1024)
|
||||
todo = 1024;
|
||||
int done = engine->play(sampleBuffer, (uint_least32_t)(todo * n_channels)) / n_channels;
|
||||
|
||||
renderedTotal = length;
|
||||
break;
|
||||
if(done < todo) {
|
||||
if(engine->error())
|
||||
return -1;
|
||||
|
||||
renderedTotal = length;
|
||||
break;
|
||||
}
|
||||
|
||||
renderedTotal += todo;
|
||||
}
|
||||
|
||||
renderedTotal += todo;
|
||||
renderedTotal *= 32;
|
||||
engine->fastForward(100);
|
||||
|
||||
if(remain)
|
||||
renderedTotal += engine->play(sampleBuffer, (uint_least32_t)(remain * n_channels)) / n_channels;
|
||||
} catch (std::exception &e) {
|
||||
ALog(@"Exception caught while brute force seeking SID file: %s", e.what());
|
||||
return -1;
|
||||
}
|
||||
|
||||
renderedTotal *= 32;
|
||||
engine->fastForward(100);
|
||||
|
||||
if(remain)
|
||||
renderedTotal += engine->play(sampleBuffer, (uint_least32_t)(remain * n_channels)) / n_channels;
|
||||
|
||||
return renderedTotal;
|
||||
}
|
||||
|
||||
- (void)cleanUp {
|
||||
if(builder) {
|
||||
delete builder;
|
||||
builder = NULL;
|
||||
}
|
||||
try {
|
||||
if(builder) {
|
||||
delete builder;
|
||||
builder = NULL;
|
||||
}
|
||||
|
||||
if(engine) {
|
||||
delete engine;
|
||||
engine = NULL;
|
||||
}
|
||||
if(engine) {
|
||||
delete engine;
|
||||
engine = NULL;
|
||||
}
|
||||
|
||||
if(tune) {
|
||||
delete tune;
|
||||
tune = NULL;
|
||||
if(tune) {
|
||||
delete tune;
|
||||
tune = NULL;
|
||||
}
|
||||
} catch (std::exception &e) {
|
||||
ALog(@"Exception caught while deleting SID player instances: %s", e.what());
|
||||
}
|
||||
|
||||
source = nil;
|
||||
|
|
|
@ -30,34 +30,49 @@
|
|||
id<CogSource> source = [audioSourceClass audioSourceForURL:url];
|
||||
|
||||
if(![source open:url])
|
||||
return 0;
|
||||
return @{};
|
||||
|
||||
if(![source seekable])
|
||||
return 0;
|
||||
return @{};
|
||||
|
||||
[source seek:0 whence:SEEK_END];
|
||||
long size = [source tell];
|
||||
[source seek:0 whence:SEEK_SET];
|
||||
|
||||
if(!size)
|
||||
return @{};
|
||||
|
||||
void *data = malloc(size);
|
||||
if(!data)
|
||||
return @{};
|
||||
|
||||
[source read:data amount:size];
|
||||
|
||||
SidTune *tune = new SidTune((const uint_least8_t *)data, (uint_least32_t)size);
|
||||
NSString *title = @"";
|
||||
NSString *titletag = @"title";
|
||||
NSString *artist = @"";
|
||||
|
||||
try {
|
||||
SidTune *tune = new SidTune((const uint_least8_t *)data, (uint_least32_t)size);
|
||||
|
||||
if(!tune->getStatus()) {
|
||||
delete tune;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const SidTuneInfo *info = tune->getInfo();
|
||||
|
||||
unsigned int count = info->numberOfInfoStrings();
|
||||
title = count >= 1 ? [guess_encoding_of_string(info->infoString(0)) stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] : @"";
|
||||
titletag = info->songs() > 1 ? @"album" : @"title";
|
||||
artist = count >= 2 ? [guess_encoding_of_string(info->infoString(1)) stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] : @"";
|
||||
|
||||
if(!tune->getStatus()) {
|
||||
delete tune;
|
||||
return 0;
|
||||
} catch (std::exception &e) {
|
||||
ALog(@"Exception caught while reading SID tags: %s", e.what());
|
||||
return @{};
|
||||
}
|
||||
|
||||
const SidTuneInfo *info = tune->getInfo();
|
||||
|
||||
unsigned int count = info->numberOfInfoStrings();
|
||||
NSString *title = count >= 1 ? [guess_encoding_of_string(info->infoString(0)) stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] : @"";
|
||||
NSString *titletag = info->songs() > 1 ? @"album" : @"title";
|
||||
NSString *artist = count >= 2 ? [guess_encoding_of_string(info->infoString(1)) stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] : @"";
|
||||
|
||||
delete tune;
|
||||
|
||||
return @{titletag: title, @"artist": artist};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue