OpenMPT: Update exception handling

Make exception handling more robust and thorough. Never
know what may happen, make sure to handle most cases.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
Christopher Snowhill 2025-01-30 01:02:32 -08:00
parent cd95cd68f8
commit ffa46ae2d0
3 changed files with 109 additions and 84 deletions

View file

@ -37,20 +37,20 @@
id<CogSource> source = [audioSourceClass audioSourceForURL:url]; id<CogSource> source = [audioSourceClass audioSourceForURL:url];
if(![source open:url]) if(![source open:url])
return 0; return @[];
if(![source seekable]) if(![source seekable])
return 0; return @[];
[source seek:0 whence:SEEK_END]; [source seek:0 whence:SEEK_END];
long size = [source tell]; long size = [source tell];
[source seek:0 whence:SEEK_SET]; [source seek:0 whence:SEEK_SET];
std::vector<char> data(static_cast<std::size_t>(size));
[source read:data.data() amount:size];
try { try {
std::vector<char> data(static_cast<std::size_t>(size));
[source read:data.data() amount:size];
std::map<std::string, std::string> ctls; std::map<std::string, std::string> ctls;
openmpt::module *mod = new openmpt::module(data, std::clog, ctls); openmpt::module *mod = new openmpt::module(data, std::clog, ctls);
@ -66,8 +66,9 @@
} }
return tracks; return tracks;
} catch(std::exception & /*e*/) { } catch(std::exception &e) {
return 0; ALog(@"Exception caught while processing with OpenMPT: %s", e.what());
return @[];
} }
} }

View file

@ -13,12 +13,16 @@
#import "PlaylistController.h" #import "PlaylistController.h"
static void g_push_archive_extensions(std::vector<std::string> &list) { static void g_push_archive_extensions(std::vector<std::string> &list) {
static std::string archive_extensions[] = { try {
"mdz", "mdr", "s3z", "xmz", "itz", "mptmz" static std::string archive_extensions[] = {
}; "mdz", "mdr", "s3z", "xmz", "itz", "mptmz"
for(unsigned i = 0, j = 6; i < j; ++i) { };
if(list.empty() || std::find(list.begin(), list.end(), archive_extensions[i]) == list.end()) for(unsigned i = 0, j = 6; i < j; ++i) {
list.push_back(archive_extensions[i]); if(list.empty() || std::find(list.begin(), list.end(), archive_extensions[i]) == list.end())
list.push_back(archive_extensions[i]);
}
} catch (std::exception &e) {
ALog(@"Exception caught pushing archive extensions for OpenMPT: %s", e.what());
} }
} }
@ -46,32 +50,31 @@ static void g_push_archive_extensions(std::vector<std::string> &list) {
sampleRate = 192000.0; sampleRate = 192000.0;
} }
std::vector<char> data(static_cast<std::size_t>(size));
[source read:data.data() amount:size];
int track_num;
if([[source.url fragment] length] == 0)
track_num = 0;
else
track_num = [[source.url fragment] intValue];
int interp = 8;
NSString *resampling = [[NSUserDefaults standardUserDefaults] stringForKey:@"resampling"];
if([resampling isEqualToString:@"zoh"])
interp = 1;
else if([resampling isEqualToString:@"blep"])
interp = 1;
else if([resampling isEqualToString:@"linear"])
interp = 2;
else if([resampling isEqualToString:@"blam"])
interp = 2;
else if([resampling isEqualToString:@"cubic"])
interp = 4;
else if([resampling isEqualToString:@"sinc"])
interp = 8;
try { try {
std::vector<char> data(static_cast<std::size_t>(size));
[source read:data.data() amount:size];
int track_num;
if([[source.url fragment] length] == 0)
track_num = 0;
else
track_num = [[source.url fragment] intValue];
int interp = 8;
NSString *resampling = [[NSUserDefaults standardUserDefaults] stringForKey:@"resampling"];
if([resampling isEqualToString:@"zoh"])
interp = 1;
else if([resampling isEqualToString:@"blep"])
interp = 1;
else if([resampling isEqualToString:@"linear"])
interp = 2;
else if([resampling isEqualToString:@"blam"])
interp = 2;
else if([resampling isEqualToString:@"cubic"])
interp = 4;
else if([resampling isEqualToString:@"sinc"])
interp = 8;
std::map<std::string, std::string> ctls; std::map<std::string, std::string> ctls;
ctls["seek.sync_samples"] = "1"; ctls["seek.sync_samples"] = "1";
mod = new openmpt::module(data, std::clog, ctls); mod = new openmpt::module(data, std::clog, ctls);
@ -86,7 +89,8 @@ static void g_push_archive_extensions(std::vector<std::string> &list) {
mod->set_render_param(openmpt::module::RENDER_INTERPOLATIONFILTER_LENGTH, interp); mod->set_render_param(openmpt::module::RENDER_INTERPOLATIONFILTER_LENGTH, interp);
mod->set_render_param(openmpt::module::RENDER_VOLUMERAMPING_STRENGTH, -1); mod->set_render_param(openmpt::module::RENDER_VOLUMERAMPING_STRENGTH, -1);
mod->ctl_set_boolean("render.resampler.emulate_amiga", true); mod->ctl_set_boolean("render.resampler.emulate_amiga", true);
} catch(std::exception & /*e*/) { } catch(std::exception &e) {
ALog(@"Exception caught opening module with OpenMPT: %s", e.what());
return NO; return NO;
} }
@ -113,43 +117,57 @@ static void g_push_archive_extensions(std::vector<std::string> &list) {
} }
- (AudioChunk *)readAudio { - (AudioChunk *)readAudio {
mod->set_repeat_count(IsRepeatOneSet() ? -1 : 0); try {
mod->set_repeat_count(IsRepeatOneSet() ? -1 : 0);
int frames = 1024; int frames = 1024;
float buffer[frames * 2]; float buffer[frames * 2];
void *buf = (void *)buffer; void *buf = (void *)buffer;
int total = 0; int total = 0;
while(total < frames) { while(total < frames) {
int framesToRender = 1024; int framesToRender = 1024;
if(framesToRender > frames) if(framesToRender > frames)
framesToRender = frames; framesToRender = frames;
std::size_t count = mod->read_interleaved_stereo(sampleRate, framesToRender, ((float *)buf) + total * 2); std::size_t count = mod->read_interleaved_stereo(sampleRate, framesToRender, ((float *)buf) + total * 2);
if(count == 0) if(count == 0)
break; break;
total += count; total += count;
if(count < framesToRender) if(count < framesToRender)
break; break;
}
id audioChunkClass = NSClassFromString(@"AudioChunk");
AudioChunk *chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
[chunk assignSamples:buffer frameCount:total];
return chunk;
} catch (std::exception &e) {
ALog(@"Exception caught while playing with OpenMPT: %s", e.what());
return nil;
} }
id audioChunkClass = NSClassFromString(@"AudioChunk");
AudioChunk *chunk = [[audioChunkClass alloc] initWithProperties:[self properties]];
[chunk assignSamples:buffer frameCount:total];
return chunk;
} }
- (long)seek:(long)frame { - (long)seek:(long)frame {
mod->set_position_seconds(frame / sampleRate); try {
mod->set_position_seconds(frame / sampleRate);
} catch (std::exception &e) {
ALog(@"Exception caught while seeking with OpenMPT: %s", e.what());
return -1;
}
return frame; return frame;
} }
- (void)cleanUp { - (void)cleanUp {
delete mod; try {
delete mod;
} catch (std::exception &e) {
ALog(@"Exception caught while deleting instance of OpenMPT: %s", e.what());
}
mod = NULL; mod = NULL;
} }
@ -170,15 +188,20 @@ static void g_push_archive_extensions(std::vector<std::string> &list) {
} }
+ (NSArray *)fileTypes { + (NSArray *)fileTypes {
std::vector<std::string> extensions = openmpt::get_supported_extensions(); try {
g_push_archive_extensions(extensions); std::vector<std::string> extensions = openmpt::get_supported_extensions();
NSMutableArray *array = [NSMutableArray array]; g_push_archive_extensions(extensions);
NSMutableArray *array = [NSMutableArray array];
for(std::vector<std::string>::iterator ext = extensions.begin(); ext != extensions.end(); ++ext) { for(std::vector<std::string>::iterator ext = extensions.begin(); ext != extensions.end(); ++ext) {
[array addObject:[NSString stringWithUTF8String:ext->c_str()]]; [array addObject:[NSString stringWithUTF8String:ext->c_str()]];
}
return [NSArray arrayWithArray:array];
} catch (std::exception &e) {
ALog(@"Exception caught while enumerating OpenMPT file extensions: %s", e.what());
return @[];
} }
return [NSArray arrayWithArray:array];
} }
+ (NSArray *)mimeTypes { + (NSArray *)mimeTypes {

View file

@ -41,26 +41,26 @@ static void setDictionary(NSMutableDictionary *dict, NSString *tag, NSString *va
id<CogSource> source = [audioSourceClass audioSourceForURL:url]; id<CogSource> source = [audioSourceClass audioSourceForURL:url];
if(![source open:url]) if(![source open:url])
return 0; return @{};
if(![source seekable]) if(![source seekable])
return 0; return @{};
[source seek:0 whence:SEEK_END]; [source seek:0 whence:SEEK_END];
long size = [source tell]; long size = [source tell];
[source seek:0 whence:SEEK_SET]; [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 { try {
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];
std::map<std::string, std::string> ctls; std::map<std::string, std::string> ctls;
openmpt::module *mod = new openmpt::module(data, std::clog, ctls); openmpt::module *mod = new openmpt::module(data, std::clog, ctls);
@ -85,8 +85,9 @@ static void setDictionary(NSMutableDictionary *dict, NSString *tag, NSString *va
delete mod; delete mod;
return dict; return dict;
} catch(std::exception & /*e*/) { } catch(std::exception &e) {
return 0; ALog(@"Exception caught while reading metadata with OpenMPT: %s", e.what());
return @{};
} }
} }