
/* Generated by Interface Builder */

#import "Delay.h"
#define DMASIZE 4096

static port_t read_port,write_port,reply_port;
short *read_data;
int read_count,ok,currentTag = 0;

static void recorded_data(void *arg, int tag, void *p, int nbytes)
{
	read_data = (short *)p;
	read_count = nbytes/2;
	if(tag != currentTag)
	vm_deallocate(task_self(),(pointer_t)read_data,read_count*2);
	else ok = 1; 
}

static snddriver_handlers_t handlers = { 0, 0, 0, 0, 0, 0, 0, 0, recorded_data};


@implementation Delay

+ new
{
    self = [super new];
    blank = (short*) calloc(600000,sizeof(short));
    return self;
}

- open
{
kern_return_t k_err=0;
int protocol;

    [displayView makeKeyAndOrderFront:self];
    SNDAcquire(SND_ACCESS_OUT|SND_ACCESS_DSP,0,0,0,
    	NULL_NEGOTIATION_FUN,0,&dev_port,&owner_port);
    
    snddriver_set_sndout_bufsize(dev_port,owner_port,512);
    snddriver_get_dsp_cmd_port(dev_port,owner_port,&cmd_port);
    k_err = SNDReadDSPfile([self findPath:"/DSP_Code/Delay.lod"], &Effect, NULL);
    k_err += port_allocate(task_self(),&reply_port);
    reply_msg = (msg_header_t *)malloc(MSG_SIZE_MAX);
    reply_msg->msg_size = MSG_SIZE_MAX;
    reply_msg->msg_local_port = reply_port;
    protocol = SNDDRIVER_DSP_PROTO_RAW;
    k_err += snddriver_stream_setup(dev_port, owner_port,
    				 SNDDRIVER_STREAM_FROM_DSP,
				 DMASIZE, 2, 
				 48*1024, 64*1024,
				 &protocol, &read_port);
    k_err += snddriver_stream_setup(dev_port, owner_port,
    				 SNDDRIVER_STREAM_TO_SNDOUT_44,
				 DMASIZE, 2, 
				 48*1024, 64*1024,
				 &protocol, &write_port);
    k_err += snddriver_dsp_protocol(dev_port, owner_port, protocol);
    k_err += SNDBootDSP(dev_port, owner_port, Effect);
    [button getFrame:&buttonRect];
    [button setIntValue:1];
    [self buttonPush:self];
    return self;
}

- close
{
    SNDRelease(SND_ACCESS_OUT|SND_ACCESS_DSP,dev_port,owner_port);
    [displayView close];
    return self;
}


- buttonPush:sender
{
int k_err;
int length, delay;
int finito = 0;
NXEvent stopEvent;
read_count = 0;

    currentTag = (currentTag + 1) % 10 ;
    length = 20000;
    delay = 16000 + [sliders floatValue] * 425000;
    k_err = snddriver_stream_start_reading(read_port,0,length,currentTag,
					 	0,0,0,0,0,1, reply_port);
    snddriver_stream_start_writing(write_port,blank,delay,-1,
					0,0,0,0,0,0,0,0, reply_port);
    while(!finito)
    {
    ok = 0;
    k_err = snddriver_stream_start_reading(read_port,0,length,currentTag,
					 	0,0,0,0,0,1, reply_port);
    do
    {
    while(msg_receive(reply_msg, RCV_TIMEOUT, 200)!=0)
    if ([NXApp peekNextEvent:(NX_LMOUSEDOWNMASK )
    into:&stopEvent waitFor:0. threshold:NX_MODALRESPTHRESHOLD] != NULL)
    {
	if([button mouse:&stopEvent.location inRect:&buttonRect])
	{
	[NXApp getNextEvent:(NX_LMOUSEDOWNMASK) waitFor:0. 
	threshold:NX_MODALRESPTHRESHOLD];
	}
	finito = 1; break ;
    }
    if(finito) break ;
    k_err += snddriver_reply_handler(reply_msg,&handlers);
    }
    while(ok == 0);
    k_err += snddriver_stream_start_writing(write_port,read_data,
		    read_count,-1,0,0,0,0,0,0,0,0, reply_port);
    vm_deallocate(task_self(),(pointer_t)read_data,read_count*2);
    }
    [button setIntValue:0];
    return self;
}

- sliderChange:sender
{
    return self;
}
@end
