Implemented support for multiple decoders per file name extension, with a floating point priority control per interface. In the event that more than one input is registered to a given extension, and we match that extension, it will be passed off to an instance of the multi-decoder wrapper, which will try opening the file with all of the decoders in order of priority, until either one of them accepts it, or all of them have failed. This paves the way for adding a VGMSTREAM input, so I can give it a very low priority, since it has several formats that are verified by file name extension only. All current inputs have been given a priority of 1.0, except for CoreAudio, which was given a priority of 0.5, because it contains an MP3 and AC3 decoders that I'd rather not use if I don't have to.
2013-10-21 17:54:11 +00:00
|
|
|
//
|
|
|
|
// CogDecoderMulti.m
|
|
|
|
// CogAudio
|
|
|
|
//
|
|
|
|
// Created by Christopher Snowhill on 10/21/13.
|
|
|
|
//
|
|
|
|
//
|
|
|
|
|
|
|
|
#import "CogDecoderMulti.h"
|
|
|
|
|
|
|
|
@implementation CogDecoderMulti
|
|
|
|
|
|
|
|
+ (NSArray *)mimeTypes
|
|
|
|
{
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (NSArray *)fileTypes
|
|
|
|
{
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (float)priority
|
|
|
|
{
|
|
|
|
return -1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id)initWithDecoders:(NSArray *)decoders
|
|
|
|
{
|
|
|
|
self = [super init];
|
|
|
|
if ( self )
|
|
|
|
{
|
|
|
|
NSMutableArray *sortedDecoders = [NSMutableArray arrayWithArray:decoders];
|
|
|
|
[sortedDecoders sortUsingComparator:
|
|
|
|
^NSComparisonResult(id obj1, id obj2)
|
|
|
|
{
|
|
|
|
NSString *classString1 = (NSString *)obj1;
|
|
|
|
NSString *classString2 = (NSString *)obj2;
|
|
|
|
|
|
|
|
Class decoder1 = NSClassFromString(classString1);
|
|
|
|
Class decoder2 = NSClassFromString(classString2);
|
|
|
|
|
|
|
|
float priority1 = [decoder1 priority];
|
|
|
|
float priority2 = [decoder2 priority];
|
|
|
|
|
|
|
|
if (priority1 == priority2) return NSOrderedSame;
|
|
|
|
else if (priority1 > priority2) return NSOrderedAscending;
|
|
|
|
else return NSOrderedDescending;
|
|
|
|
}];
|
|
|
|
theDecoders = sortedDecoders;
|
|
|
|
theDecoder = nil;
|
2013-10-21 18:24:48 +00:00
|
|
|
cachedObservers = [[NSMutableArray alloc] init];
|
Implemented support for multiple decoders per file name extension, with a floating point priority control per interface. In the event that more than one input is registered to a given extension, and we match that extension, it will be passed off to an instance of the multi-decoder wrapper, which will try opening the file with all of the decoders in order of priority, until either one of them accepts it, or all of them have failed. This paves the way for adding a VGMSTREAM input, so I can give it a very low priority, since it has several formats that are verified by file name extension only. All current inputs have been given a priority of 1.0, except for CoreAudio, which was given a priority of 0.5, because it contains an MP3 and AC3 decoders that I'd rather not use if I don't have to.
2013-10-21 17:54:11 +00:00
|
|
|
}
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2013-10-21 18:24:48 +00:00
|
|
|
- (void)dealloc
|
|
|
|
{
|
|
|
|
[cachedObservers release];
|
|
|
|
[super dealloc];
|
|
|
|
}
|
|
|
|
|
Implemented support for multiple decoders per file name extension, with a floating point priority control per interface. In the event that more than one input is registered to a given extension, and we match that extension, it will be passed off to an instance of the multi-decoder wrapper, which will try opening the file with all of the decoders in order of priority, until either one of them accepts it, or all of them have failed. This paves the way for adding a VGMSTREAM input, so I can give it a very low priority, since it has several formats that are verified by file name extension only. All current inputs have been given a priority of 1.0, except for CoreAudio, which was given a priority of 0.5, because it contains an MP3 and AC3 decoders that I'd rather not use if I don't have to.
2013-10-21 17:54:11 +00:00
|
|
|
- (NSDictionary *)properties
|
|
|
|
{
|
|
|
|
if ( theDecoder != nil ) return [theDecoder properties];
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (int)readAudio:(void *)buffer frames:(UInt32)frames
|
|
|
|
{
|
|
|
|
if ( theDecoder != nil ) return [theDecoder readAudio:buffer frames:frames];
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)open:(id<CogSource>)source
|
|
|
|
{
|
|
|
|
for (NSString *classString in theDecoders)
|
|
|
|
{
|
|
|
|
Class decoder = NSClassFromString(classString);
|
|
|
|
theDecoder = [[decoder alloc] init];
|
|
|
|
for (NSDictionary *obsItem in cachedObservers) {
|
|
|
|
[theDecoder addObserver:[obsItem objectForKey:@"observer"] forKeyPath:[obsItem objectForKey:@"keyPath"] options:[obsItem objectForKey:@"options"] context:[obsItem objectForKey:@"context"]];
|
|
|
|
}
|
|
|
|
if ([theDecoder open:source])
|
|
|
|
return YES;
|
|
|
|
for (NSDictionary *obsItem in cachedObservers) {
|
|
|
|
[theDecoder removeObserver:[obsItem objectForKey:@"observer"] forKeyPath:[obsItem objectForKey:@"keyPath"]];
|
|
|
|
}
|
|
|
|
[theDecoder release];
|
|
|
|
[source seek:0 whence:SEEK_SET];
|
|
|
|
}
|
|
|
|
theDecoder = nil;
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (long)seek:(long)frame
|
|
|
|
{
|
|
|
|
if ( theDecoder != nil ) return [theDecoder seek:frame];
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)close
|
|
|
|
{
|
|
|
|
if ( theDecoder != nil ) {
|
|
|
|
[theDecoder close];
|
2013-10-21 18:24:48 +00:00
|
|
|
for (NSDictionary *obsItem in cachedObservers) {
|
|
|
|
[theDecoder removeObserver:[obsItem objectForKey:@"observer"] forKeyPath:[obsItem objectForKey:@"keyPath"]];
|
|
|
|
}
|
Implemented support for multiple decoders per file name extension, with a floating point priority control per interface. In the event that more than one input is registered to a given extension, and we match that extension, it will be passed off to an instance of the multi-decoder wrapper, which will try opening the file with all of the decoders in order of priority, until either one of them accepts it, or all of them have failed. This paves the way for adding a VGMSTREAM input, so I can give it a very low priority, since it has several formats that are verified by file name extension only. All current inputs have been given a priority of 1.0, except for CoreAudio, which was given a priority of 0.5, because it contains an MP3 and AC3 decoders that I'd rather not use if I don't have to.
2013-10-21 17:54:11 +00:00
|
|
|
[theDecoder release];
|
|
|
|
theDecoder = nil;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)setTrack:(NSURL *)track
|
|
|
|
{
|
|
|
|
if ( theDecoder != nil && [theDecoder respondsToSelector: @selector(setTrack:)] ) return [theDecoder setTrack:track];
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* By the current design, the core adds its observers to decoders before they are opened */
|
|
|
|
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
|
|
|
|
{
|
|
|
|
[cachedObservers addObject:[NSDictionary dictionaryWithObjectsAndKeys:observer, @"observer", keyPath, @"keyPath", options, @"options", context, @"context", nil]];
|
|
|
|
}
|
|
|
|
|
2013-10-21 18:24:48 +00:00
|
|
|
/* And this is currently called after the decoder is closed */
|
Implemented support for multiple decoders per file name extension, with a floating point priority control per interface. In the event that more than one input is registered to a given extension, and we match that extension, it will be passed off to an instance of the multi-decoder wrapper, which will try opening the file with all of the decoders in order of priority, until either one of them accepts it, or all of them have failed. This paves the way for adding a VGMSTREAM input, so I can give it a very low priority, since it has several formats that are verified by file name extension only. All current inputs have been given a priority of 1.0, except for CoreAudio, which was given a priority of 0.5, because it contains an MP3 and AC3 decoders that I'd rather not use if I don't have to.
2013-10-21 17:54:11 +00:00
|
|
|
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath
|
|
|
|
{
|
|
|
|
for (NSDictionary *obsItem in cachedObservers)
|
|
|
|
{
|
|
|
|
if ([obsItem objectForKey:@"observer"] == observer && [keyPath isEqualToString:[obsItem objectForKey:@"keyPath"]]) {
|
|
|
|
[cachedObservers removeObject:obsItem];
|
2013-10-21 18:24:48 +00:00
|
|
|
break;
|
Implemented support for multiple decoders per file name extension, with a floating point priority control per interface. In the event that more than one input is registered to a given extension, and we match that extension, it will be passed off to an instance of the multi-decoder wrapper, which will try opening the file with all of the decoders in order of priority, until either one of them accepts it, or all of them have failed. This paves the way for adding a VGMSTREAM input, so I can give it a very low priority, since it has several formats that are verified by file name extension only. All current inputs have been given a priority of 1.0, except for CoreAudio, which was given a priority of 0.5, because it contains an MP3 and AC3 decoders that I'd rather not use if I don't have to.
2013-10-21 17:54:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|