// // CueSheetDecoder.m // CueSheet // // Created by Zaphod Beeblebrox on 10/8/07. // Copyright 2007 __MyCompanyName__. All rights reserved. // #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 numberWithDouble:trackLength] forKey:@"length"]; return [properties autorelease]; } - (BOOL)open:(id)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; bytesPerSecond = (int)(bytesPerFrame * sampleRate); if ([apl endBlock] > [apl startBlock]) trackEnd = ([apl endBlock] / sampleRate) * 1000.0; else trackEnd = [[properties objectForKey:@"length"] doubleValue]; trackStart = ([apl startBlock]/sampleRate) * 1000.0; trackLength = trackEnd - trackStart; [self seekToTime: 0.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; } } - (double)seekToTime:(double)time //milliseconds { if (time > trackLength || time < 0) { //need a better way of returning fail. return -1.0; } time += trackStart; bytePosition = (time/1000.0) * bytesPerSecond; NSLog(@"Before: %li", bytePosition); bytePosition -= bytePosition % bytesPerFrame; NSLog(@"After: %li", bytePosition); return [decoder seekToTime:time]; } - (int)fillBuffer:(void *)buf ofSize:(UInt32)size { long trackByteEnd = (trackEnd/1000.0) * bytesPerSecond; trackByteEnd -= trackByteEnd % (bytesPerFrame); if (bytePosition + size > trackByteEnd) size = trackByteEnd - bytePosition; if (!size) return 0; int n = [decoder fillBuffer:buf ofSize:size]; bytePosition += n; return n; } @end