cog/Audio/Chain/InputNode.m

232 lines
5.1 KiB
Matlab
Raw Normal View History

2006-01-20 15:34:02 +00:00
//
// InputNode.m
2006-01-20 15:34:02 +00:00
// Cog
//
// 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"
#import "BufferChain.h"
#import "Plugin.h"
#import "CoreAudioUtils.h"
#import "AudioPlayer.h"
#import "OutputNode.h"
2006-01-20 15:34:02 +00:00
#import "Logging.h"
2006-01-20 15:34:02 +00:00
@implementation InputNode
@synthesize exitAtTheEndOfTheStream;
2006-01-20 15:34:02 +00:00
- (id)initWithController:(id)c previous:(id)p {
self = [super initWithController:c previous:p];
if (self) {
exitAtTheEndOfTheStream = [[Semaphore alloc] init];
}
return self;
}
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];
if (decoder == nil)
2006-04-13 02:51:22 +00:00
return NO;
[self registerObservers];
if (![decoder open:source])
{
ALog(@"Couldn't open decoder...");
return NO;
}
NSDictionary *properties = [decoder properties];
int bitsPerSample = [[properties objectForKey:@"bitsPerSample"] intValue];
int channels = [[properties objectForKey:@"channels"] intValue];
bytesPerFrame = (bitsPerSample / 8) * channels;
shouldContinue = YES;
2006-04-02 20:03:12 +00:00
shouldSeek = NO;
2006-04-13 02:51:22 +00:00
return YES;
2006-01-20 15:34:02 +00:00
}
- (BOOL)openWithDecoder:(id<CogDecoder>) d
{
DLog(@"Opening with old decoder: %@", d);
decoder = d;
2008-05-01 23:34:23 +00:00
NSDictionary *properties = [decoder properties];
int bitsPerSample = [[properties objectForKey:@"bitsPerSample"] intValue];
int channels = [[properties objectForKey:@"channels"] intValue];
bytesPerFrame = (bitsPerSample / 8) * channels;
2008-05-01 23:34:23 +00:00
[self registerObservers];
shouldContinue = YES;
shouldSeek = NO;
DLog(@"DONES: %@", decoder);
return YES;
}
- (void)registerObservers
{
DLog(@"REGISTERING OBSERVERS");
[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
{
DLog(@"SOMETHING CHANGED!");
if ([keyPath isEqual:@"properties"]) {
//Setup converter!
//Inform something of properties change
2013-10-12 21:01:21 +00:00
//Disable support until it is properly implemented.
//[controller inputFormatDidChange: propertiesToASBD([decoder properties])];
}
else if ([keyPath isEqual:@"metadata"]) {
//Inform something of metadata change
}
}
2006-01-20 15:34:02 +00:00
- (void)process
{
int amountInBuffer = 0;
2007-03-03 21:13:25 +00:00
void *inputBuffer = malloc(CHUNK_SIZE);
2006-01-20 15:34:02 +00:00
BOOL shouldClose = YES;
BOOL seekError = NO;
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)
{
OutputNode *output = [[controller controller] output];
BOOL isPaused = [output isPaused];
if ( !isPaused ) [output pause];
DLog(@"SEEKING!");
seekError = [decoder seek:seekFrame] < 0;
if ( !isPaused ) [output resume];
2006-04-02 20:03:12 +00:00
shouldSeek = NO;
DLog(@"Seeked! Resetting Buffer");
2007-05-26 22:13:11 +00:00
[self resetBuffer];
DLog(@"Reset buffer!");
2007-05-26 22:13:11 +00:00
initialBufferFilled = NO;
2006-04-02 20:03:12 +00:00
}
if (amountInBuffer < CHUNK_SIZE) {
int framesToRead = (CHUNK_SIZE - amountInBuffer)/bytesPerFrame;
int framesRead = [decoder readAudio:((char *)inputBuffer) + amountInBuffer frames:framesToRead];
if (framesRead > 0 && !seekError)
{
amountInBuffer += (framesRead * bytesPerFrame);
[self writeData:inputBuffer amount:amountInBuffer];
amountInBuffer = 0;
}
else
{
if (initialBufferFilled == NO) {
[controller initialBufferFilled:self];
}
DLog(@"End of stream? %@", [self properties]);
endOfStream = YES;
shouldClose = [controller endOfInputReached]; //Lets us know if we should keep going or not (occassionally, for track changes within a file)
DLog(@"closing? is %i", shouldClose);
// wait before exiting, as we might still get seeking request
DLog("InputNode: Before wait")
[exitAtTheEndOfTheStream waitIndefinitely];
DLog("InputNode: After wait, should seek = %d", shouldSeek)
if (shouldSeek)
{
endOfStream = NO;
shouldClose = NO;
continue;
}
else
{
break;
}
2007-05-16 23:07:00 +00:00
}
}
2006-01-20 15:34:02 +00:00
}
if (shouldClose)
[decoder close];
2006-05-07 13:19:23 +00:00
free(inputBuffer);
[exitAtTheEndOfTheStream signal];
DLog("Input node thread stopping");
2006-01-20 15:34:02 +00:00
}
- (void)seek:(long)frame
2006-04-02 20:03:12 +00:00
{
seekFrame = frame;
2006-04-02 20:03:12 +00:00
shouldSeek = YES;
DLog(@"Should seek!");
2007-05-26 22:13:11 +00:00
[semaphore signal];
if (endOfStream)
{
[exitAtTheEndOfTheStream signal];
}
2006-04-02 20:03:12 +00:00
}
- (BOOL)setTrack:(NSURL *)track
{
if ([decoder respondsToSelector:@selector(setTrack:)] && [decoder setTrack:track]) {
DLog(@"SET TRACK!");
return YES;
}
return NO;
}
- (void)dealloc
{
DLog(@"Input Node dealloc");
[decoder removeObserver:self forKeyPath:@"properties"];
[decoder removeObserver:self forKeyPath:@"metadata"];
}
- (NSDictionary *) properties
2006-01-20 15:34:02 +00:00
{
return [decoder properties];
2006-01-20 15:34:02 +00:00
}
- (id<CogDecoder>) decoder
{
return decoder;
}
2006-01-20 15:34:02 +00:00
@end