/*
 *	Functions to perform when various midi command arrive
 *
 *	active()			when an FE arrives
 *	keyon(cmd, keyno, vel)		a note has been pressed/released
 *	control(cmd, number, value)
 *	program(cmd,number)
 *	aftertouch(cmd, value)
 *	pitchbend(cmd, LSB, MSB)	7 bits of each
 *	sysexcl(buf, nbytes)		including status byte, but not EOX
 */

#include "midi.h"
#include "dx7.h"

/*
 *	Data structures in which we remember the state of the synth
 */

static Parm key[128];		/* record keyon/keyoff information */
static Parm con[128];		/* values of the control parameters */
static Parm prog;		/* most recent program change */
static Parm aft;		/* after touch value */
static Parm pb;		/* pitch bend value */

/* remember whether we actually know the value of various parameters */
static struct {
	unsigned k_key:1;	/* value in key[] is valid */
	unsigned k_con:1;	/* value in con[] is valid */
} knowns[128];

static struct {
	unsigned k_prog:1;	/* value in prog is valid */
	unsigned k_aft:1;	/* value in aft is valid */
	unsigned k_pb:1;	/* value in pb is valid */
} known;

/*
 *	All the King's functions...
 */

active()
{
	Bconout(CON, '\007');		/* Bling! This could become tedious */
}

keyon(cmd, keyno, vel)
{
	key[keyno] = vel;		/* remember the value */
	knowns[keyno].k_key = 1;	/* now we know about this one */
	disp_key(keyno, vel);		/* and update the display */
}

control(cmd, number, value)
{
	con[number] = value;
	knowns[number].k_con = 1;
	disp_con(number, value);
}

program(cmd, number)
{
	prog = number;
	known.k_prog = 1;
	disp_prog(number);
}

aftertouch(cmd, value)
{
	aft = value;
	known.k_aft = 1;
	disp_aft(value);
}

pitchbend(cmd, value)
{
	pb = value;
	known.k_pb = 1;
	disp_pb(value);
}

sysexcl(buf, nbytes)
Parm *buf;
{
	/* somewhere to stash the broken-out fields of the command */
	int substatus;
	int paramgrp;
	int paramno;
	int data;

	if (buf[1] != 67) {
		disp_mess("Unknown sysex ID %d", buf[1]);
		return;
	}

	/* switch on substatus */
	switch (substatus = (buf[2]>>4) & 07) {		/* 3 bits */
	case 0:
		/* voice dump */
		break;
	case 1:
		/* parameter change */
		if (nbytes != 6) {
			disp_mess("Parameter change block length of %d is wrong", nbytes);
			return;
		}
		paramgrp = buf[3]>>2 & 037;		/* 5 bits */
		paramno  = (buf[3] & 03)<<7 | buf[4];
		data	 = buf[6];

		/* switch on parameter group number */
		switch (paramgrp) {
		case 0:
			/* Common DX Voice parameter */
			break;
		case 2:
			/* DX7 function parameter */
			break;
		default:
			disp_mess("Unknown parameter group %d", paramgrp);
			return;
		}
		break;
	default:
		disp_mess("Unknown sysex substatus %d", substatus);
		return;
	}
}
