cog/Audio/Chain/Node.m

212 lines
3.5 KiB
Objective-C

//
// Node.m
// CogNew
//
// Created by Vincent Spader on 1/4/06.
// Copyright 2006 Vincent Spader. All rights reserved.
//
#import "Node.h"
#import "Logging.h"
#import "BufferChain.h"
@implementation Node
@synthesize nodeFormat;
- (id)initWithController:(id)c previous:(id)p
{
self = [super init];
if (self)
{
buffer = [[VirtualRingBuffer alloc] initWithLength:BUFFER_SIZE];
semaphore = [[Semaphore alloc] init];
initialBufferFilled = NO;
controller = c;
endOfStream = NO;
shouldContinue = YES;
[self setPreviousNode:p];
}
return self;
}
- (int)writeData:(void *)ptr amount:(int)amount
{
void *writePtr;
int amountToCopy, availOutput;
int amountLeft = amount;
while (shouldContinue == YES && amountLeft > 0)
{
BOOL wrapped;
availOutput = [buffer lengthAvailableToWriteReturningPointer:&writePtr bufferWrapped:&wrapped];
if (availOutput == 0) {
if (initialBufferFilled == NO) {
initialBufferFilled = YES;
if ([controller respondsToSelector:@selector(initialBufferFilled:)])
[controller performSelector:@selector(initialBufferFilled:) withObject:self];
}
}
if (availOutput == 0 || shouldReset)
{
if (availOutput)
{
// Unlock the buffer
[buffer didWriteLength:0];
}
[semaphore wait];
}
else
{
amountToCopy = availOutput;
if (amountToCopy > amountLeft)
amountToCopy = amountLeft;
memcpy(writePtr, &((char *)ptr)[amount - amountLeft], amountToCopy);
[buffer didWriteLength:amountToCopy];
amountLeft -= amountToCopy;
}
}
return (amount - amountLeft);
}
//Should be overwriten by subclass.
- (void)process
{
}
- (void)threadEntry:(id)arg
{
@autoreleasepool {
[self process];
}
}
- (int)readData:(void *)ptr amount:(int)amount
{
void *readPtr;
int amountToCopy;
int availInput;
if ([[previousNode buffer] isEmpty] && [previousNode endOfStream] == YES)
{
endOfStream = YES;
return 0;
}
availInput = [[previousNode buffer] lengthAvailableToReadReturningPointer:&readPtr];
/* if (availInput <= 0) {
DLog(@"BUFFER RAN DRY!");
}
else if (availInput < amount) {
DLog(@"BUFFER IN DANGER");
}
*/
if ([previousNode shouldReset] == YES) {
[buffer empty];
shouldReset = YES;
[previousNode setShouldReset: NO];
[[previousNode semaphore] signal];
}
amountToCopy = availInput;
if (amountToCopy > amount)
{
amountToCopy = amount;
}
memcpy(ptr, readPtr, amountToCopy);
[[previousNode buffer] didReadLength:amountToCopy];
if (amountToCopy > 0)
{
[[previousNode semaphore] signal];
}
return amountToCopy;
}
- (void)launchThread
{
[NSThread detachNewThreadSelector:@selector(threadEntry:) toTarget:self withObject:nil];
}
- (void)setPreviousNode:(id)p
{
previousNode = p;
}
- (id)previousNode
{
return previousNode;
}
- (BOOL)shouldContinue
{
return shouldContinue;
}
- (void)setShouldContinue:(BOOL)s
{
shouldContinue = s;
}
- (VirtualRingBuffer *)buffer
{
return buffer;
}
- (void)resetBuffer
{
shouldReset = YES; //Will reset on next write.
if (previousNode == nil) {
[buffer empty];
}
}
- (Semaphore *)semaphore
{
return semaphore;
}
- (BOOL)endOfStream
{
return endOfStream;
}
- (void)setEndOfStream:(BOOL)e
{
endOfStream = e;
}
- (void)setShouldReset:(BOOL)s
{
shouldReset = s;
}
- (BOOL)shouldReset
{
return shouldReset;
}
// Buffering nodes should implement this
- (double)secondsBuffered
{
return 0.0;
}
@end