
/* Generated by Interface Builder */

#import "MidiControl.h"

@implementation MidiControl

+ new
{
    self = [super new];	// super is the generic Object class, in our case
    pitch = .75;
    velocity = .75;
    return self;	// Don't forget this! Otherwise big mess.
}

- setPitch:sender
{
    pitch = [sender floatValue];
    return self;
}

- setVelocity:sender
{
    velocity = [sender floatValue];
    return self;
}

- setMapping:sender
{
    mapping = [[sender selectedCell] tag];
    return self;
}

- (int) getSizeOfQueue
{
u_int size,max;

    if(running == 0) return(-1);
    midi_output_queue_size(dev_port,&size,&max);
    // This function returns the current number of pending MIDI messages.
    // Along with the maximum size of the midiOutput queue (setup below) 
    // Henon uses it to wait for the Midi output queue to flush before 
    // calculating more points...
    return(size);
}


- start:sender
{
static int firstStart = 0;

    if(firstStart == 0)
    {
	firstStart = 1;
	[self init];		// setup the midiDriver, if not already done
    }
    running = [sender intValue];
    if(running ==0) 
    {
	timer_stop(timer_port,owner_port); 	// Stops the timer!
	midi_clear_queue(xmit_port);		// And clear the queue!
    }
    else 
    {
	time = 0;
    }
    return self;
}

- send:(float)x:(float)y:(float)speed
{
float x_aux,y_aux;

    speed *= 200;
    time += speed;
    switch(mapping)		// Two different mappings...
    {
	case 0 : x_aux = (x+1.5)/3. ; y_aux = (y+.5); break;
	case 1 : x_aux = (y+.5) ; y_aux = (x+1.5)/3.; break;
    }
    if(running == 0) return self;
    
    midi_data[0].quanta = (int) (time);	// Time value at which to play it
    midi_data[0].ndata = 3;		// Number of midi words (3)
    midi_data[0].data[0] = MIDI_NOTEON;
    midi_data[0].data[1] = (char) (128. * pitch * x_aux);
    midi_data[0].data[2] = (char) (128. * velocity * y_aux);
    
    midi_data[1].quanta = (int) (time + 500);
    midi_data[1].ndata = 3;
    midi_data[1].data[0] = MIDI_NOTEOFF;
    midi_data[1].data[1] = (char) (128. * pitch * x_aux);
    midi_data[1].data[2] = (char) 0;
    
    // Start the timer (if not already done) and send the midi data. They are
    // cooked (see /usr/include/midi/midi_types.h).
    timer_start(timer_port,owner_port);	
    k_err = midi_send_cooked_data(xmit_port,midi_data,2,TRUE);
    if (k_err != KERN_SUCCESS) {
	midi_error("Midi didn't send event! ", k_err);
	exit(1);
    }
}


// Init initializes the Midi Driver to setup a midi ouput. The successive calls
// are pretty general in the Mach OS (almost the same for the DSP/Sound driver.

-init
{
// First, get the port corresponding to midi0 (midi0 = serial port A)

    k_err = netname_look_up(name_server_port,"","midi0", &dev_port);
    if (k_err != KERN_SUCCESS) {
	midi_error("netname lookup failure ", k_err);
	exit(1);
    }
    else printf("Look up done ...\n");

// Create a port (owner port) associated with the current task    
    k_err = port_allocate(task_self(), &owner_port);
    if (k_err != KERN_SUCCESS) {
	midi_error("Cannot allocate owner port ", k_err);
	exit(1);
    }
    temp_port = owner_port;
  
// Grab the midi port (dev_port);  
    k_err = midi_set_owner(dev_port,owner_port,&temp_port);
    if (k_err != KERN_SUCCESS) {
	midi_error("Midi Ownership refused! ", k_err);
	exit(1);
    }
    else printf("Midi ownership acquired ...\n");

// Retrieve the transmit port of the midi device.    
    k_err = midi_get_xmit(dev_port,owner_port,&xmit_port);
    if (k_err != KERN_SUCCESS) {
	midi_error("Midi Transmit port refused ", k_err);
	exit(1);
    }
    else printf("Midi transmit port acquired ...\n");
    
// Setup the midi protocol (including the size of the output queue.)
    k_err = midi_set_proto(xmit_port,MIDI_PROTO_COOKED,0,MIDI_PROTO_SYNC_SYS,10,2,1000);
    if (k_err != KERN_SUCCESS) {
	midi_error("Midi proto refused ", k_err);
	exit(1);
    }
    else printf("Midi Protocol set ...\n");
   
// Retriev the out timer port. 
    k_err = midi_get_out_timer_port(dev_port,&timer_port);
    if (k_err != KERN_SUCCESS) {
	midi_error("Midi timer port refused ", k_err);
	exit(1);
    }
    else printf("Midi Timer port acquired ...\n");
    
    return self;	// AND THAT'S IT!!!!!
}

@end
