cog/Plugins/CueSheet/CueSheetDecoder.m

196 lines
4.1 KiB
Matlab
Raw Normal View History

2007-10-09 02:25:40 +00:00
//
// CueSheetDecoder.m
// CueSheet
//
// Created by Zaphod Beeblebrox on 10/8/07.
// Copyright 2007 __MyCompanyName__. All rights reserved.
//
#import "CueSheetDecoder.h"
#import "CueSheet.h"
#import "CueSheetTrack.h"
#import "CueSheetContainer.h"
2007-10-09 02:25:40 +00:00
#import "Logging.h"
2007-10-09 02:25:40 +00:00
@implementation CueSheetDecoder
+ (NSArray *)fileTypes
{
return [CueSheetContainer fileTypes];
2007-10-09 02:25:40 +00:00
}
2007-10-14 18:39:58 +00:00
+ (NSArray *)mimeTypes
{
2007-10-14 18:56:23 +00:00
return [CueSheetContainer mimeTypes];
2007-10-14 18:39:58 +00:00
}
+ (float)priority
{
return 1.0;
}
2007-10-09 02:25:40 +00:00
- (NSDictionary *)properties
{
NSMutableDictionary *properties = [[decoder properties] mutableCopy];
//Need to alter length
[properties setObject:[NSNumber numberWithLong:(trackEnd - trackStart)] forKey:@"totalFrames"];
return properties;
2007-10-09 02:25:40 +00:00
}
- (BOOL)open:(id<CogSource>)s
2007-10-09 02:25:40 +00:00
{
if (![[s url] isFileURL]) {
return NO;
}
NSURL *url = [s url];
cuesheet = [CueSheet cueSheetWithFile:[url path]];
NSArray *tracks = [cuesheet tracks];
int i;
for (i = 0; i < [tracks count]; i++)
2007-10-09 02:25:40 +00:00
{
if ([[[tracks objectAtIndex:i] track] isEqualToString:[url fragment]]){
track = [tracks objectAtIndex:i];
//Kind of a hackish way of accessing outside classes.
source = [NSClassFromString(@"AudioSource") audioSourceForURL:[track url]];
if (![source open:[track url]]) {
ALog(@"Could not open cuesheet source");
return NO;
}
2007-10-14 18:56:23 +00:00
decoder = [NSClassFromString(@"AudioDecoder") audioDecoderForSource:source];
if (![decoder open:source]) {
ALog(@"Could not open cuesheet decoder");
return NO;
}
CueSheetTrack *nextTrack = nil;
if (i + 1 < [tracks count]) {
nextTrack = [tracks objectAtIndex:i + 1];
}
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;
trackStart = [track time] * sampleRate;
if (nextTrack && [[[nextTrack url] absoluteString] isEqualToString:[[track url] absoluteString]]) {
trackEnd = [nextTrack time] * sampleRate;
}
else {
trackEnd = [[properties objectForKey:@"totalFrames"] doubleValue];
}
[self seek: 0];
//Note: Should register for observations of the decoder
[self willChangeValueForKey:@"properties"];
[self didChangeValueForKey:@"properties"];
return YES;
}
}
return NO;
}
- (void)close {
if (decoder) {
[decoder close];
decoder = nil;
}
source = nil;
cuesheet = nil;
track = nil;
}
- (void)dealloc {
[self close];
}
- (BOOL)setTrack:(NSURL *)url
{
//Same file, just next track...this may be unnecessary since frame-based decoding is done now...
if ([[[track url] path] isEqualToString:[url path]] && [[[track url] host] isEqualToString:[url host]] && [[url fragment] intValue] == [[track track] intValue] + 1) {
NSArray *tracks = [cuesheet tracks];
int i;
for (i = 0; i < [tracks count]; i++) {
if ([[[tracks objectAtIndex:i] track] isEqualToString:[url fragment]]){
track = [tracks objectAtIndex:i];
float sampleRate = [[[decoder properties] objectForKey:@"sampleRate"] floatValue];
trackStart = [track time] * sampleRate;
CueSheetTrack *nextTrack = nil;
if (i + 1 < [tracks count]) {
nextTrack = [tracks objectAtIndex:i + 1];
}
if (nextTrack && [[[nextTrack url] absoluteString] isEqualToString:[[track url] absoluteString]]) {
trackEnd = [nextTrack time] * sampleRate;
}
else {
trackEnd = [[[decoder properties] objectForKey:@"totalFrames"] longValue];
}
DLog(@"CHANGING TRACK!");
return YES;
}
}
}
return NO;
2007-10-09 02:25:40 +00:00
}
- (long)seek:(long)frame
2007-10-09 02:25:40 +00:00
{
if (frame > trackEnd - trackStart) {
2007-10-09 02:25:40 +00:00
//need a better way of returning fail.
return -1;
2007-10-09 02:25:40 +00:00
}
frame += trackStart;
framePosition = [decoder seek:frame];
return framePosition;
2007-10-09 02:25:40 +00:00
}
- (int)readAudio:(void *)buf frames:(UInt32)frames
2007-10-09 02:25:40 +00:00
{
if (framePosition + frames > trackEnd) {
2017-09-18 02:21:48 +00:00
frames = (UInt32)(trackEnd - framePosition);
2007-10-09 02:25:40 +00:00
}
if (!frames)
{
DLog(@"Returning 0");
return 0;
}
int n = [decoder readAudio:buf frames:frames];
2007-10-09 02:25:40 +00:00
framePosition += n;
return n;
2007-10-09 02:25:40 +00:00
}
@end