139 lines
3.8 KiB
Objective-C
139 lines
3.8 KiB
Objective-C
//
|
|
// 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;
|
|
cachedObservers = [[NSMutableArray alloc] init];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)dealloc
|
|
{
|
|
[cachedObservers release];
|
|
[super dealloc];
|
|
}
|
|
|
|
- (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];
|
|
for (NSDictionary *obsItem in cachedObservers) {
|
|
[theDecoder removeObserver:[obsItem objectForKey:@"observer"] forKeyPath:[obsItem objectForKey:@"keyPath"]];
|
|
}
|
|
[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]];
|
|
}
|
|
|
|
/* And this is currently called after the decoder is closed */
|
|
- (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];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
@end
|