123 lines
2.6 KiB
Objective-C
123 lines
2.6 KiB
Objective-C
#import "APLDecoder.h"
|
|
#import "APLFile.h"
|
|
|
|
@implementation APLDecoder
|
|
|
|
+ (NSArray *)fileTypes {
|
|
return [NSArray arrayWithObject:@"apl"];
|
|
}
|
|
|
|
+ (NSArray *)mimeTypes {
|
|
return [NSArray arrayWithObjects:@"application/x-apl", nil];
|
|
}
|
|
|
|
- (NSDictionary *)properties {
|
|
NSMutableDictionary *properties = [[decoder properties] mutableCopy];
|
|
|
|
//Need to alter length
|
|
[properties setObject:[NSNumber numberWithLong:trackLength] forKey:@"totalFrames"];
|
|
return [properties autorelease];
|
|
}
|
|
|
|
- (BOOL)open:(id<CogSource>)s
|
|
{
|
|
//NSLog(@"Loading apl...");
|
|
if (![[s url] isFileURL])
|
|
return NO;
|
|
|
|
NSURL *url = [s url];
|
|
[s close];
|
|
|
|
apl = [APLFile createWithFile:[url path]];
|
|
[apl retain];
|
|
|
|
//Kind of a hackish way of accessing outside classes.
|
|
source = [NSClassFromString(@"AudioSource") audioSourceForURL:[apl file]];
|
|
[source retain];
|
|
|
|
if (![source open:[apl file]]) {
|
|
NSLog(@"Could not open source for file '%@' referenced in apl", [apl file]);
|
|
return NO;
|
|
}
|
|
decoder = [NSClassFromString(@"AudioDecoder") audioDecoderForSource:source];
|
|
[decoder retain];
|
|
|
|
if (![decoder open:source]) {
|
|
NSLog(@"Could not open decoder for source for apl");
|
|
return NO;
|
|
}
|
|
|
|
NSDictionary *properties = [decoder properties];
|
|
int bitsPerSample = [[properties objectForKey:@"bitsPerSample"] intValue];
|
|
int channels = [[properties objectForKey:@"channels"] intValue];
|
|
// float sampleRate = [[properties objectForKey:@"sampleRate"] floatValue];
|
|
|
|
|
|
bytesPerFrame = (bitsPerSample/8) * channels;
|
|
|
|
if ([apl endBlock] > [apl startBlock])
|
|
trackEnd = [apl endBlock]; //([apl endBlock] / sampleRate) * 1000.0;
|
|
else
|
|
trackEnd = [[properties objectForKey:@"totalFrames"] doubleValue]; //!!? double?
|
|
|
|
trackStart = [apl startBlock];
|
|
trackLength = trackEnd - trackStart;
|
|
|
|
[self seek: 0];
|
|
|
|
//Note: Should register for observations of the decoder, but laziness consumes all.
|
|
[self willChangeValueForKey:@"properties"];
|
|
[self didChangeValueForKey:@"properties"];
|
|
return YES;
|
|
}
|
|
|
|
- (void)close {
|
|
if (decoder) {
|
|
[decoder close];
|
|
[decoder release];
|
|
decoder = nil;
|
|
}
|
|
|
|
if (source) {
|
|
[source release];
|
|
source = nil;
|
|
}
|
|
if (apl) {
|
|
[apl release];
|
|
apl = nil;
|
|
}
|
|
}
|
|
|
|
|
|
- (long)seek:(long)frame
|
|
{
|
|
if (frame > trackEnd - trackStart) {
|
|
//need a better way of returning fail.
|
|
return -1;
|
|
}
|
|
|
|
frame += trackStart;
|
|
|
|
framePosition = [decoder seek:frame];
|
|
|
|
return framePosition;
|
|
}
|
|
|
|
- (int)readAudio:(void *)buf frames:(UInt32)frames
|
|
{
|
|
if (framePosition + frames > trackEnd)
|
|
frames = trackEnd - framePosition;
|
|
|
|
if (!frames) {
|
|
NSLog(@"APL readAudio Returning 0");
|
|
return 0;
|
|
}
|
|
|
|
int n = [decoder readAudio:buf frames:frames];
|
|
framePosition += n;
|
|
return n;
|
|
}
|
|
|
|
|
|
@end
|