Added file storage dictionary, so that psflib can recycle CogSource objects passed into the decoder. Also fixes issues of various file objects being leaked
This commit is contained in:
parent
4d51c93c39
commit
5d141f1d70
2 changed files with 124 additions and 41 deletions
|
@ -10,7 +10,8 @@
|
||||||
#import "Plugin.h"
|
#import "Plugin.h"
|
||||||
|
|
||||||
@interface HCDecoder : NSObject<CogDecoder,CogMetadataReader> {
|
@interface HCDecoder : NSObject<CogDecoder,CogMetadataReader> {
|
||||||
id<CogSource> currentSource;
|
id<CogSource> currentSource;
|
||||||
|
NSString *currentUrl;
|
||||||
uint8_t *emulatorCore;
|
uint8_t *emulatorCore;
|
||||||
void *emulatorExtra;
|
void *emulatorExtra;
|
||||||
|
|
||||||
|
|
|
@ -24,40 +24,90 @@
|
||||||
|
|
||||||
#import <HighlyAdvanced/GBA.h>
|
#import <HighlyAdvanced/GBA.h>
|
||||||
|
|
||||||
|
@interface psf_file_container : NSObject {
|
||||||
@implementation HCDecoder
|
NSLock * lock;
|
||||||
|
NSMutableDictionary * list;
|
||||||
+ (void)initialize
|
|
||||||
{
|
|
||||||
bios_set_image(hebios, HEBIOS_SIZE);
|
|
||||||
psx_init();
|
|
||||||
sega_init();
|
|
||||||
qsound_init();
|
|
||||||
}
|
}
|
||||||
|
+ (psf_file_container *)instance;
|
||||||
|
- (void)add_hint:(NSString *)path source:(id)source;
|
||||||
|
- (void)remove_hint:(NSString *)path;
|
||||||
|
- (BOOL)try_hint:(NSString *)path source:(id*)source;
|
||||||
|
@end
|
||||||
|
|
||||||
- (NSDictionary *)metadata
|
@implementation psf_file_container
|
||||||
{
|
+ (psf_file_container *)instance {
|
||||||
return metadataList;
|
static psf_file_container * instance;
|
||||||
}
|
|
||||||
|
|
||||||
- (long)retrieveTotalFrames
|
@synchronized(self) {
|
||||||
{
|
if (!instance) {
|
||||||
return (tagLengthMs + tagFadeMs) * (sampleRate / 100) / 10;
|
instance = [[self alloc] init];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
|
- (psf_file_container *)init
|
||||||
|
{
|
||||||
|
if ((self = [super init]))
|
||||||
|
{
|
||||||
|
lock = [[NSLock alloc] init];
|
||||||
|
list = [[NSMutableDictionary alloc] initWithCapacity:0];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
[list release];
|
||||||
|
[lock release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
- (void)add_hint:(NSString *)path source:(id)source
|
||||||
|
{
|
||||||
|
[lock lock];
|
||||||
|
[list setObject:source forKey:path];
|
||||||
|
[lock unlock];
|
||||||
|
}
|
||||||
|
- (void)remove_hint:(NSString *)path
|
||||||
|
{
|
||||||
|
[lock lock];
|
||||||
|
[list removeObjectForKey:path];
|
||||||
|
[lock unlock];
|
||||||
|
}
|
||||||
|
- (BOOL)try_hint:(NSString *)path source:(id *)source
|
||||||
|
{
|
||||||
|
[lock lock];
|
||||||
|
*source = [list objectForKey:path];
|
||||||
|
[lock unlock];
|
||||||
|
if ( *source )
|
||||||
|
{
|
||||||
|
[ *source seek:0 whence:0 ];
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
void * source_fopen(const char * path)
|
void * source_fopen(const char * path)
|
||||||
{
|
{
|
||||||
NSString * urlString = [NSString stringWithUTF8String:path];
|
id<CogSource> source;
|
||||||
NSURL * url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
|
if ( ![[psf_file_container instance] try_hint:[NSString stringWithUTF8String:path] source:&source] )
|
||||||
|
{
|
||||||
|
NSString * urlString = [NSString stringWithUTF8String:path];
|
||||||
|
NSURL * url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
|
||||||
|
|
||||||
id audioSourceClass = NSClassFromString(@"AudioSource");
|
id audioSourceClass = NSClassFromString(@"AudioSource");
|
||||||
id<CogSource> source = [audioSourceClass audioSourceForURL:url];
|
source = [audioSourceClass audioSourceForURL:url];
|
||||||
|
|
||||||
if (![source open:url])
|
if (![source open:url])
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (![source seekable])
|
if (![source seekable])
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return [source retain];
|
return [source retain];
|
||||||
}
|
}
|
||||||
|
@ -102,6 +152,27 @@ static psf_file_callbacks source_callbacks =
|
||||||
source_ftell
|
source_ftell
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@implementation HCDecoder
|
||||||
|
|
||||||
|
+ (void)initialize
|
||||||
|
{
|
||||||
|
bios_set_image(hebios, HEBIOS_SIZE);
|
||||||
|
psx_init();
|
||||||
|
sega_init();
|
||||||
|
qsound_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSDictionary *)metadata
|
||||||
|
{
|
||||||
|
return metadataList;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (long)retrieveTotalFrames
|
||||||
|
{
|
||||||
|
return (tagLengthMs + tagFadeMs) * (sampleRate / 100) / 10;
|
||||||
|
}
|
||||||
|
|
||||||
struct psf_info_meta_state
|
struct psf_info_meta_state
|
||||||
{
|
{
|
||||||
NSMutableDictionary * info;
|
NSMutableDictionary * info;
|
||||||
|
@ -152,6 +223,9 @@ static int psf_info_meta(void * context, const char * name, const char * value)
|
||||||
NSString * taglc = [tag lowercaseString];
|
NSString * taglc = [tag lowercaseString];
|
||||||
NSString * svalue = [NSString stringWithUTF8String:value];
|
NSString * svalue = [NSString stringWithUTF8String:value];
|
||||||
|
|
||||||
|
if ( svalue == nil )
|
||||||
|
return 0;
|
||||||
|
|
||||||
if ([taglc isEqualToString:@"game"])
|
if ([taglc isEqualToString:@"game"])
|
||||||
{
|
{
|
||||||
taglc = @"album";
|
taglc = @"album";
|
||||||
|
@ -551,8 +625,6 @@ struct gsf_sound_out : public GBASoundOut
|
||||||
|
|
||||||
- (BOOL)initializeDecoder
|
- (BOOL)initializeDecoder
|
||||||
{
|
{
|
||||||
NSString * decodedUrl = [[[currentSource url] absoluteString] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
|
||||||
|
|
||||||
if ( type == 1 )
|
if ( type == 1 )
|
||||||
{
|
{
|
||||||
emulatorCore = ( uint8_t * ) malloc( psx_get_state_size( 1 ) );
|
emulatorCore = ( uint8_t * ) malloc( psx_get_state_size( 1 ) );
|
||||||
|
@ -565,7 +637,7 @@ struct gsf_sound_out : public GBASoundOut
|
||||||
state.first = true;
|
state.first = true;
|
||||||
state.refresh = 0;
|
state.refresh = 0;
|
||||||
|
|
||||||
if ( psf_load( [decodedUrl UTF8String], &source_callbacks, 1, psf1_loader, &state, psf1_info, &state ) <= 0 )
|
if ( psf_load( [currentUrl UTF8String], &source_callbacks, 1, psf1_loader, &state, psf1_info, &state ) <= 0 )
|
||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
if ( state.refresh )
|
if ( state.refresh )
|
||||||
|
@ -579,7 +651,7 @@ struct gsf_sound_out : public GBASoundOut
|
||||||
|
|
||||||
state.refresh = 0;
|
state.refresh = 0;
|
||||||
|
|
||||||
if ( psf_load( [decodedUrl UTF8String], &source_callbacks, 2, psf2fs_load_callback, emulatorExtra, psf1_info, &state ) <= 0 )
|
if ( psf_load( [currentUrl UTF8String], &source_callbacks, 2, psf2fs_load_callback, emulatorExtra, psf1_info, &state ) <= 0 )
|
||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
emulatorCore = ( uint8_t * ) malloc( psx_get_state_size( 2 ) );
|
emulatorCore = ( uint8_t * ) malloc( psx_get_state_size( 2 ) );
|
||||||
|
@ -596,7 +668,7 @@ struct gsf_sound_out : public GBASoundOut
|
||||||
struct sdsf_loader_state state;
|
struct sdsf_loader_state state;
|
||||||
memset( &state, 0, sizeof(state) );
|
memset( &state, 0, sizeof(state) );
|
||||||
|
|
||||||
if ( psf_load( [decodedUrl UTF8String], &source_callbacks, type, sdsf_loader, &state, 0, 0) <= 0 )
|
if ( psf_load( [currentUrl UTF8String], &source_callbacks, type, sdsf_loader, &state, 0, 0) <= 0 )
|
||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
emulatorCore = ( uint8_t * ) malloc( sega_get_state_size( type - 0x10 ) );
|
emulatorCore = ( uint8_t * ) malloc( sega_get_state_size( type - 0x10 ) );
|
||||||
|
@ -623,7 +695,7 @@ struct gsf_sound_out : public GBASoundOut
|
||||||
struct gsf_loader_state state;
|
struct gsf_loader_state state;
|
||||||
memset( &state, 0, sizeof(state) );
|
memset( &state, 0, sizeof(state) );
|
||||||
|
|
||||||
if ( psf_load( [decodedUrl UTF8String], &source_callbacks, 0x22, gsf_loader, &state, 0, 0 ) <= 0 )
|
if ( psf_load( [currentUrl UTF8String], &source_callbacks, 0x22, gsf_loader, &state, 0, 0 ) <= 0 )
|
||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
GBASystem * system = new GBASystem;
|
GBASystem * system = new GBASystem;
|
||||||
|
@ -652,7 +724,7 @@ struct gsf_sound_out : public GBASoundOut
|
||||||
|
|
||||||
emulatorExtra = state;
|
emulatorExtra = state;
|
||||||
|
|
||||||
if ( psf_load( [decodedUrl UTF8String], &source_callbacks, 0x41, qsf_loader, state, 0, 0) <= 0 )
|
if ( psf_load( [currentUrl UTF8String], &source_callbacks, 0x41, qsf_loader, state, 0, 0) <= 0 )
|
||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
emulatorCore = ( uint8_t * ) malloc( qsound_get_state_size() );
|
emulatorCore = ( uint8_t * ) malloc( qsound_get_state_size() );
|
||||||
|
@ -683,7 +755,7 @@ struct gsf_sound_out : public GBASoundOut
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentSource = [source retain];
|
currentSource = [source retain];
|
||||||
|
|
||||||
struct psf_info_meta_state info;
|
struct psf_info_meta_state info;
|
||||||
|
|
||||||
|
@ -693,9 +765,11 @@ struct gsf_sound_out : public GBASoundOut
|
||||||
info.tag_fade_ms = 0;
|
info.tag_fade_ms = 0;
|
||||||
info.volume_scale = 0;
|
info.volume_scale = 0;
|
||||||
|
|
||||||
NSString * decodedUrl = [[[source url] absoluteString] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
currentUrl = [[[[source url] absoluteString] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] retain];
|
||||||
|
|
||||||
type = psf_load( [decodedUrl UTF8String], &source_callbacks, 0, 0, 0, psf_info_meta, &info );
|
[[psf_file_container instance] add_hint:currentUrl source:currentSource];
|
||||||
|
|
||||||
|
type = psf_load( [currentUrl UTF8String], &source_callbacks, 0, 0, 0, psf_info_meta, &info );
|
||||||
|
|
||||||
if (type <= 0)
|
if (type <= 0)
|
||||||
return NO;
|
return NO;
|
||||||
|
@ -792,7 +866,7 @@ struct gsf_sound_out : public GBASoundOut
|
||||||
return frames;
|
return frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)close
|
- (void)closeDecoder
|
||||||
{
|
{
|
||||||
if ( emulatorCore ) {
|
if ( emulatorCore ) {
|
||||||
if ( type == 0x22 ) {
|
if ( type == 0x22 ) {
|
||||||
|
@ -822,10 +896,18 @@ struct gsf_sound_out : public GBASoundOut
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)close
|
||||||
|
{
|
||||||
|
[self closeDecoder];
|
||||||
|
[currentSource release];
|
||||||
|
[[psf_file_container instance] remove_hint:currentUrl];
|
||||||
|
[currentUrl release];
|
||||||
|
}
|
||||||
|
|
||||||
- (long)seek:(long)frame
|
- (long)seek:(long)frame
|
||||||
{
|
{
|
||||||
if (frame < framesRead) {
|
if (frame < framesRead) {
|
||||||
[self close];
|
[self closeDecoder];
|
||||||
if (![self initializeDecoder])
|
if (![self initializeDecoder])
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue