2006-01-20 15:34:02 +00:00
|
|
|
//
|
2006-04-02 15:44:08 +00:00
|
|
|
// InputNode.m
|
2006-01-20 15:34:02 +00:00
|
|
|
// Cog
|
|
|
|
//
|
2006-09-04 18:46:18 +00:00
|
|
|
// Created by Vincent Spader on 8/2/05.
|
|
|
|
// Copyright 2005 Vincent Spader. All rights reserved.
|
2006-01-20 15:34:02 +00:00
|
|
|
//
|
|
|
|
|
|
|
|
#import "InputNode.h"
|
2007-02-24 20:36:27 +00:00
|
|
|
#import "BufferChain.h"
|
2007-03-02 01:36:52 +00:00
|
|
|
#import "Plugin.h"
|
2007-03-03 17:19:37 +00:00
|
|
|
#import "CoreAudioUtils.h"
|
2006-01-20 15:34:02 +00:00
|
|
|
|
|
|
|
@implementation InputNode
|
|
|
|
|
2007-10-14 18:12:15 +00:00
|
|
|
- (BOOL)openWithSource:(id<CogSource>)source
|
2006-01-20 15:34:02 +00:00
|
|
|
{
|
2007-10-14 18:12:15 +00:00
|
|
|
decoder = [AudioDecoder audioDecoderForSource:source];
|
2007-02-24 20:36:27 +00:00
|
|
|
[decoder retain];
|
2007-03-03 17:19:37 +00:00
|
|
|
|
2007-02-24 20:36:27 +00:00
|
|
|
if (decoder == nil)
|
2006-04-13 02:51:22 +00:00
|
|
|
return NO;
|
2007-02-24 20:36:27 +00:00
|
|
|
|
2007-10-11 02:08:29 +00:00
|
|
|
[self registerObservers];
|
|
|
|
|
2007-03-02 01:36:52 +00:00
|
|
|
if (![decoder open:source])
|
|
|
|
{
|
|
|
|
NSLog(@"Couldn't open decoder...");
|
2007-02-24 20:36:27 +00:00
|
|
|
return NO;
|
2007-03-02 01:36:52 +00:00
|
|
|
}
|
2007-03-03 17:19:37 +00:00
|
|
|
|
2007-11-24 20:16:27 +00:00
|
|
|
NSDictionary *properties = [decoder properties];
|
|
|
|
int bitsPerSample = [[properties objectForKey:@"bitsPerSample"] intValue];
|
|
|
|
int channels = [[properties objectForKey:@"channels"] intValue];
|
|
|
|
|
|
|
|
bytesPerFrame = (bitsPerSample/8) * channels;
|
|
|
|
|
2006-04-02 15:44:08 +00:00
|
|
|
shouldContinue = YES;
|
2006-04-02 20:03:12 +00:00
|
|
|
shouldSeek = NO;
|
2007-11-24 20:16:27 +00:00
|
|
|
|
2006-04-13 02:51:22 +00:00
|
|
|
return YES;
|
2006-01-20 15:34:02 +00:00
|
|
|
}
|
|
|
|
|
2007-10-11 02:08:29 +00:00
|
|
|
- (BOOL)openWithDecoder:(id<CogDecoder>) d
|
|
|
|
{
|
|
|
|
NSLog(@"Opening with old decoder: %@", d);
|
|
|
|
decoder = d;
|
|
|
|
[decoder retain];
|
|
|
|
|
|
|
|
[self registerObservers];
|
|
|
|
|
|
|
|
shouldContinue = YES;
|
|
|
|
shouldSeek = NO;
|
|
|
|
|
|
|
|
NSLog(@"DONES: %@", decoder);
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-03-03 17:19:37 +00:00
|
|
|
- (void)registerObservers
|
|
|
|
{
|
2007-10-12 02:55:59 +00:00
|
|
|
NSLog(@"REGISTERING OBSERVERS");
|
2007-03-03 17:19:37 +00:00
|
|
|
[decoder addObserver:self
|
|
|
|
forKeyPath:@"properties"
|
|
|
|
options:(NSKeyValueObservingOptionNew)
|
|
|
|
context:NULL];
|
|
|
|
|
|
|
|
[decoder addObserver:self
|
|
|
|
forKeyPath:@"metadata"
|
|
|
|
options:(NSKeyValueObservingOptionNew)
|
|
|
|
context:NULL];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)observeValueForKeyPath:(NSString *)keyPath
|
|
|
|
ofObject:(id)object
|
|
|
|
change:(NSDictionary *)change
|
|
|
|
context:(void *)context
|
|
|
|
{
|
2007-10-12 02:55:59 +00:00
|
|
|
NSLog(@"SOMETHING CHANGED!");
|
2007-03-03 17:19:37 +00:00
|
|
|
if ([keyPath isEqual:@"properties"]) {
|
|
|
|
//Setup converter!
|
|
|
|
//Inform something of properties change
|
2007-11-24 20:16:27 +00:00
|
|
|
//Disable support until it is properly implimented.
|
|
|
|
//[controller inputFormatDidChange: propertiesToASBD([decoder properties])];
|
2007-03-03 17:19:37 +00:00
|
|
|
}
|
|
|
|
else if ([keyPath isEqual:@"metadata"]) {
|
|
|
|
//Inform something of metadata change
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:34:02 +00:00
|
|
|
- (void)process
|
|
|
|
{
|
2007-11-24 20:16:27 +00:00
|
|
|
int amountInBuffer = 0;
|
2007-03-03 21:13:25 +00:00
|
|
|
void *inputBuffer = malloc(CHUNK_SIZE);
|
2006-01-20 15:34:02 +00:00
|
|
|
|
2007-10-11 02:08:29 +00:00
|
|
|
BOOL shouldClose = YES;
|
|
|
|
|
2006-04-02 15:44:08 +00:00
|
|
|
while ([self shouldContinue] == YES && [self endOfStream] == NO)
|
2006-01-20 15:34:02 +00:00
|
|
|
{
|
2006-04-02 20:03:12 +00:00
|
|
|
if (shouldSeek == YES)
|
|
|
|
{
|
2007-10-03 20:23:14 +00:00
|
|
|
NSLog(@"SEEKING!");
|
2007-11-24 20:16:27 +00:00
|
|
|
[decoder seek:seekFrame];
|
2006-04-02 20:03:12 +00:00
|
|
|
shouldSeek = NO;
|
2007-10-03 20:23:14 +00:00
|
|
|
NSLog(@"Seeked! Resetting Buffer");
|
|
|
|
|
2007-05-26 22:13:11 +00:00
|
|
|
[self resetBuffer];
|
2007-10-03 20:23:14 +00:00
|
|
|
|
|
|
|
NSLog(@"Reset buffer!");
|
2007-05-26 22:13:11 +00:00
|
|
|
initialBufferFilled = NO;
|
2006-04-02 20:03:12 +00:00
|
|
|
}
|
2007-05-16 01:06:23 +00:00
|
|
|
|
|
|
|
if (amountInBuffer < CHUNK_SIZE) {
|
2007-11-24 20:16:27 +00:00
|
|
|
int framesToRead = (CHUNK_SIZE - amountInBuffer)/bytesPerFrame;
|
|
|
|
int framesRead = [decoder readAudio:((char *)inputBuffer) + amountInBuffer frames:framesToRead];
|
|
|
|
amountInBuffer += (framesRead * bytesPerFrame);
|
2006-04-02 20:03:12 +00:00
|
|
|
|
2007-11-24 20:16:27 +00:00
|
|
|
if (framesRead <= 0)
|
2007-10-03 20:23:14 +00:00
|
|
|
{
|
|
|
|
if (initialBufferFilled == NO) {
|
2007-10-12 02:55:59 +00:00
|
|
|
[controller initialBufferFilled:self];
|
2007-10-03 20:23:14 +00:00
|
|
|
}
|
|
|
|
|
2007-10-12 02:55:59 +00:00
|
|
|
NSLog(@"End of stream? %@", [self properties]);
|
2007-10-03 20:23:14 +00:00
|
|
|
endOfStream = YES;
|
2007-10-11 02:08:29 +00:00
|
|
|
shouldClose = [controller endOfInputReached]; //Lets us know if we should keep going or not (occassionally, for track changes within a file)
|
|
|
|
NSLog(@"closing? is %i", shouldClose);
|
|
|
|
break;
|
2007-05-16 23:07:00 +00:00
|
|
|
}
|
2007-10-03 20:23:14 +00:00
|
|
|
|
|
|
|
[self writeData:inputBuffer amount:amountInBuffer];
|
|
|
|
amountInBuffer = 0;
|
2006-01-20 15:34:02 +00:00
|
|
|
}
|
|
|
|
}
|
2007-10-11 02:08:29 +00:00
|
|
|
if (shouldClose)
|
|
|
|
[decoder close];
|
2006-05-07 13:19:23 +00:00
|
|
|
|
2007-03-03 21:13:25 +00:00
|
|
|
free(inputBuffer);
|
2006-01-20 15:34:02 +00:00
|
|
|
}
|
|
|
|
|
2007-11-24 20:16:27 +00:00
|
|
|
- (void)seek:(long)frame
|
2006-04-02 20:03:12 +00:00
|
|
|
{
|
2007-11-24 20:16:27 +00:00
|
|
|
seekFrame = frame;
|
2006-04-02 20:03:12 +00:00
|
|
|
shouldSeek = YES;
|
2007-10-03 20:23:14 +00:00
|
|
|
NSLog(@"Should seek!");
|
2007-05-26 22:13:11 +00:00
|
|
|
[semaphore signal];
|
2006-04-02 20:03:12 +00:00
|
|
|
}
|
|
|
|
|
2007-10-11 02:08:29 +00:00
|
|
|
- (BOOL)setTrack:(NSURL *)track
|
|
|
|
{
|
|
|
|
if ([decoder respondsToSelector:@selector(setTrack:)] && [decoder setTrack:track]) {
|
|
|
|
NSLog(@"SET TRACK!");
|
|
|
|
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
2007-02-24 20:36:27 +00:00
|
|
|
- (void)dealloc
|
|
|
|
{
|
2007-10-13 07:09:46 +00:00
|
|
|
NSLog(@"Input Node dealloc");
|
2007-10-11 02:08:29 +00:00
|
|
|
|
2007-03-03 17:19:37 +00:00
|
|
|
[decoder removeObserver:self forKeyPath:@"properties"];
|
|
|
|
[decoder removeObserver:self forKeyPath:@"metadata"];
|
|
|
|
|
2007-02-24 20:36:27 +00:00
|
|
|
[decoder release];
|
|
|
|
|
|
|
|
[super dealloc];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSDictionary *) properties
|
2006-01-20 15:34:02 +00:00
|
|
|
{
|
2007-02-24 20:36:27 +00:00
|
|
|
return [decoder properties];
|
2006-01-20 15:34:02 +00:00
|
|
|
}
|
|
|
|
|
2007-10-11 02:08:29 +00:00
|
|
|
- (id<CogDecoder>) decoder
|
|
|
|
{
|
|
|
|
return decoder;
|
|
|
|
}
|
|
|
|
|
2006-01-20 15:34:02 +00:00
|
|
|
@end
|