cog/Audio/CogDecoderMulti.m

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