//
//  ShnFile.mm
//  Cog
//
//  Created by Vincent Spader on 6/6/05.
//  Copyright 2005 Vincent Spader All rights reserved.
//

#import "ShortenDecoder.h"

@implementation ShortenDecoder

- (BOOL)open:(id<CogSource>)source {
	NSURL *url = [source url];

	if(![[url scheme] isEqualToString:@"file"])
		return NO;

	decoder = new shn_reader;

	if(!decoder) {
		return NO;
	}

	decoder->open([[url path] UTF8String], true);

	bufferSize = decoder->shn_get_buffer_block_size(NUM_DEFAULT_BUFFER_BLOCKS);

	bool seekTable;
	decoder->file_info(NULL, &channels, &frequency, NULL, &bitsPerSample, &seekTable);

	seekable = seekTable == true ? YES : NO;

	totalFrames = (decoder->shn_get_song_length() * frequency) / 1000.0;

	decoder->go();

	[self willChangeValueForKey:@"properties"];
	[self didChangeValueForKey:@"properties"];

	return YES;
}

- (int)readAudio:(void *)buf frames:(UInt32)frames {
	long bytesPerFrame = channels * (bitsPerSample / 8);
	long amountRead;

	// For some reason a busy loop is causing pops when output is set to 48000. Probably CPU starvation, since the SHN decoder seems to use a multithreaded nonblocking approach.
	do {
		amountRead = decoder->read(buf, frames * bytesPerFrame);
	} while(amountRead == -1);

	return (int)(amountRead / bytesPerFrame);
}

- (long)seek:(long)sample {
	unsigned int sec = sample / frequency;

	decoder->seek(sec);

	return sample;
}

- (void)close {
	if(decoder) {
		decoder->exit();
		delete decoder;
		decoder = NULL;
	}

	/*if (shn_cleanup_decoder(handle))
	    shn_unload(handle);*/
}

- (void)dealloc {
	[self close];
}

- (NSDictionary *)properties {
	return @{@"channels": [NSNumber numberWithInt:channels],
			 @"bitsPerSample": [NSNumber numberWithInt:bitsPerSample],
			 @"sampleRate": [NSNumber numberWithFloat:frequency],
			 @"totalFrames": [NSNumber numberWithDouble:totalFrames],
			 @"seekable": [NSNumber numberWithBool:seekable],
			 @"codec": @"Shorten",
			 @"endian": @"little",
			 @"encoding": @"lossless"};
}

- (NSDictionary *)metadata {
	return @{};
}

+ (NSArray *)fileTypes {
	return @[@"shn"];
}

+ (NSArray *)mimeTypes {
	return @[@"application/x-shorten"]; // This is basically useless, since we cant stream shorten yet
}

+ (float)priority {
	return 1.0;
}

+ (NSArray *)fileTypeAssociations {
	return @[
		@[@"Shorten File", @"shn.icns", @"shn"]
	];
}

@end