
/* Generated by Interface Builder */

#import "MyObject.h"
#import <musickit/musickit.h>
#import <musickit/synthpatches/Pluck.h>
#import <appkit/appkit.h>

@implementation MyObject

static id aPart;
static id aPartPerformer;
static id orch;

- init
{
    id aSynthIns; 
    [super init];
    numQuarterNotes = 20;
    numEighthNotes = 20;
    numSixteenthNotes = 20;
    numPitchesEnabled = 5;
    tempo = 60;
    pitchMode[0] = 1; pitchMode[2] = 1; pitchMode[4] = 1; pitchMode[7] = 1;
    pitchMode[9] = 1;
    aPart = [[Part alloc] init];
    orch = [Orchestra new];
    aSynthIns = [[SynthInstrument alloc] init];
    MKSetDeltaT(.5);     /* Let Conductor run .5 seconds ahead. */
    aPartPerformer = [[PartPerformer alloc] init];
    [aSynthIns setSynthPatchClass:[Pluck class]];
    [[aPartPerformer noteSender] connect:[aSynthIns noteReceiver]];
    [Conductor setFinishWhenEmpty:YES];
    return self;
}

- setNumQuarterNotes:sender
{
    numQuarterNotes = [sender intValue];
    return self;
}

- setNumEighthNotes:sender
{
    numEighthNotes = [sender intValue];
    return self;
}

- setNumSixteenthNotes:sender
{
    numSixteenthNotes = [sender intValue];
    return self;
}

- setTempoFrom:sender
{
    tempo = [sender doubleValue];
    if ([Conductor inPerformance])
      [[Conductor defaultConductor] setTempo:tempo];
    return self;
}

- setMode:sender
{
    int whichCell = [sender selectedRow];
    int isEnabled = [[sender selectedCell] intValue];
    pitchMode[whichCell] = isEnabled;
    if (isEnabled)
    	numPitchesEnabled++;
    else numPitchesEnabled--;
    return self;
}

static double ranNum()
    /* Returns a random number between 0 and 1. */
{
#   define   RANDOMMAX (double)((long)MAXINT)
    return ((double)random()) / RANDOMMAX;
 }

- compute:sender
{
#   define BASE_KEY_NUM 40
    id aNote;
    int i,j,k,l,keyNum;
    double x,time,rhythm;
     
    if ([Conductor inPerformance]) {
      NXRunAlertPanel("example4",
		      "First stop the performance before computing new notes.",
		      "OK",NULL,NULL);
      return self;
    }
    if (numPitchesEnabled == 0)
        return self;
    i=0;
    j=0;
    k=0;
    time = 0;
    [aPart freeNotes];       /* Just empty old part. */
    while(i<numEighthNotes || j<numSixteenthNotes || k<numQuarterNotes) {
	x = ranNum();
	if (x > .666) {
		if (i++>=numEighthNotes)
			continue;
		rhythm = 0.5;

	} else if (x > .333) {
		if (j++>=numSixteenthNotes)
			continue;
		rhythm = 0.25;
	} else { 
		if (k++>=numQuarterNotes)
			continue;
		rhythm = 1.0;
	}
	keyNum = -1;
	do {
		l = (int)(ranNum() * 11.999);
		if (pitchMode[l]) 
			keyNum = l + BASE_KEY_NUM;
	} while (keyNum == -1);
	aNote = [[Note alloc] init];
	[aNote setDur:rhythm];
	[aNote setTimeTag:time];
	time += rhythm;
	[aNote setPar:MK_keyNum toInt:keyNum];
	[aPart addNote:aNote];
    }
    return self;
}

- endOfTime
/* Invoked by the Conductor when performance finishes. */
{
   [orch close];
   [startStopButton setState:0];
   return self; }

- play:sender
  /* Toggle play/stop */ {
    if ([Conductor inPerformance]) {
      [Conductor finishPerformance];
      return self;
    }
    if (![orch open]) {
      NXRunAlertPanel("example4","Can't open DSP.","OK",NULL,NULL);
      return nil;
    }
    [aPartPerformer setPart:aPart];
    [aPartPerformer activate];
    [[Conductor defaultConductor] setTempo:tempo];
    [Conductor afterPerformanceSel:@selector(endOfTime) to:self
	argCount:0];
    [orch run];
    [Conductor startPerformance];
    return self;
}


@end
