/*
 * GLIB - a Generic LIBrarian and editor for synths
 *
 * K1 Patch Librarian
 *
 * Code started 19 JAN 89 --  Michael R. Kesti mrk@gvgspd.GVG.TEK.COM
 * Adapted for K1 from D10 version by Greg Lee, lee@uhccux.uhcc.hawaii.edu
 */

#include "glib.h"
#include "machdep.h"
#include "k1vis.h"

#define K1MULTISIZE 75
#define K1SINGLESIZE 87
#define RESERVESIZE 0

char sngnames[64][11];

/* This array contains arbitrary screen labels */
struct labelinfo Lk1mlt[] = {

#MENU for multi
			volume %




   A.........   B................  C.............  D.....................
   single       zn lo zn hi vel sw poly mode rcvch trnsps tune level output
 |-------------|-----|-----|------|----|----|-----|------|----|-----|------|

1  %	          %     %     %     %    %     %     %     %     %     %
2  %	          %     %     %     %    %     %     %     %     %     %
3  %	          %     %     %     %    %     %     %     %     %     %
4  %	          %     %     %     %    %     %     %     %     %     %
5  %	          %     %     %     %    %     %     %     %     %     %
6  %	          %     %     %     %    %     %     %     %     %     %
7  %	          %     %     %     %    %     %     %     %     %     %
8  %	          %     %     %     %    %     %     %     %     %     %





 Press SPACE BAR to sound note %   at volume %   for duration %  on channel % .
#END

-1,-1,NULL
};

char *vismltnum();

struct paraminfo Pk1mlt[] = {

/*NAME		TYPE		POS	MAX	OFFSET	MASK	SHIFT	ADHOC*/

#O volume	pnum		%%	99	10

#O single1	mltnum		%%	63	11
#O zonelo1	cpitch		%%	127	19
#O zonehi1	cpitch		%%	127	27
#O velosw1	velosw		%%	2	43	0x30	4
#O poly1	poly		%%	9	35	0x0F
#O modem1	mode		%%	2	35	0x40	6	*1
/* 2nd bit below goes above */
#O moden1	num		--	1	43	0x40	6	*2
#O rcvch1	pnum		%%	15	43	0x0F
#O trnsps1	keyshift	%%	48	51
#O tune1	finetune	%%	100	59
#O level1	num		%%	100	67
#O output1	pan		%%	2	35	0x30	4

#O single2	mltnum		%%	63	12
#O zonelo2	cpitch		%%	127	20
#O zonehi2	cpitch		%%	127	28
#O velosw2	velosw		%%	2	44	0x30	4
#O poly2	poly		%%	9	36	0x0F
#O modem2	mode		%%	2	36	0x40	6	*1
#O moden2	num		--	1	44	0x40	6	*2
#O rcvch2	pnum		%%	15	44	0x0F
#O trnsps2	keyshift	%%	48	52
#O tune2	finetune	%%	100	60
#O level2	num		%%	100	68
#O output2	pan		%%	2	36	0x30	4

#O single3	mltnum		%%	63	13
#O zonelo3	cpitch		%%	127	21
#O zonehi3	cpitch		%%	127	29
#O velosw3	velosw		%%	2	45	0x30	4
#O poly3	poly		%%	9	37	0x0F
#O modem3	mode		%%	2	37	0x40	6	*1
#O moden3	num		--	1	45	0x40	6	*2
#O rcvch3	pnum		%%	15	45	0x0F
#O trnsps3	keyshift	%%	48	53
#O tune3	finetune	%%	100	61
#O level3	num		%%	100	69
#O output3	pan		%%	2	37	0x30	4

#O single4	mltnum		%%	63	14
#O zonelo4	cpitch		%%	127	22
#O zonehi4	cpitch		%%	127	30
#O velosw4	velosw		%%	2	46	0x30	4
#O poly4	poly		%%	9	38	0x0F
#O modem4	mode		%%	2	38	0x40	6	*1
#O moden4	num		--	1	46	0x40	6	*2
#O rcvch4	pnum		%%	15	46	0x0F
#O trnsps4	keyshift	%%	48	54
#O tune4	finetune	%%	100	62
#O level4	num		%%	100	70
#O output4	pan		%%	2	38	0x30	4

#O single5	mltnum		%%	63	15
#O zonelo5	cpitch		%%	127	23
#O zonehi5	cpitch		%%	127	31
#O velosw5	velosw		%%	2	47	0x30	4
#O poly5	poly		%%	9	39	0x0F
#O modem5	mode		%%	2	39	0x40	6	*1
#O moden5	num		--	1	47	0x40	6	*2
#O rcvch5	pnum		%%	15	47	0x0F
#O trnsps5	keyshift	%%	48	55
#O tune5	finetune	%%	100	63
#O level5	num		%%	100	71
#O output5	pan		%%	2	39	0x30	4

#O single6	mltnum		%%	63	16
#O zonelo6	cpitch		%%	127	24
#O zonehi6	cpitch		%%	127	32
#O velosw6	velosw		%%	2	48	0x30	4
#O poly6	poly		%%	9	40	0x0F
#O modem6	mode		%%	2	40	0x40	6	*1
#O moden6	num		--	1	48	0x40	6	*2
#O rcvch6	pnum		%%	15	48	0x0F
#O trnsps6	keyshift	%%	48	56
#O tune6	finetune	%%	100	64
#O level6	num		%%	100	72
#O output6	pan		%%	2	40	0x30	4

#O single7	mltnum		%%	63	17
#O zonelo7	cpitch		%%	127	25
#O zonehi7	cpitch		%%	127	33
#O velosw7	velosw		%%	2	49	0x30	4
#O poly7	poly		%%	9	41	0x0F
#O modem7	mode		%%	2	41	0x40	6	*1
#O moden7	num		--	1	49	0x40	6	*2
#O rcvch7	pnum		%%	15	49	0x0F
#O trnsps7	keyshift	%%	48	57
#O tune7	finetune	%%	100	65
#O level7	num		%%	100	73
#O output7	pan		%%	2	41	0x30	4

#O single8	mltnum		%%	63	18
#O zonelo8	cpitch		%%	127	26
#O zonehi8	cpitch		%%	127	34
#O velosw8	velosw		%%	2	50	0x30	4
#O poly8	poly		%%	9	42	0x0F
#O modem8	mode		%%	2	42	0x40	6	*1
#O moden8	num		--	1	50	0x40	6	*2
#O rcvch8	pnum		%%	15	50	0x0F
#O trnsps8	keyshift	%%	48	58
#O tune8	finetune	%%	100	66
#O level8	num		%%	100	74
#O output8	pan		%%	2	42	0x30	4

"autopitch",	NULL,	-1,-1, %%, visnum, 		0, 127, 60, 0,
"autovol",	NULL,	-1,-1, %%, visnum, 		0, 127, 63, 0,
"autodur",	NULL,	-1,-1, %%, visnum, 		1,  20,  5, 0,
"autochan",	NULL,	-1,-1, %%, visnum, 		1,  16,  1, 0,

NULL,		NULL,	-1,-1, -1, -1, visnum, 		0,   0, 0, 0
};

/*
 * k1mltnum
 *
 * Convert a voice number (0 to 127) to the string displayed in the
 * librarian (ie. A1 to D8 for multi, to d8 for singles).
 */

char *
k1mltnum(n)
{
	static char v[4];

	if ( n < 0 || n > 63 )
		return("???");

	v[0] = 'A' + (n >> 3);
	if (v[0] > 'D') v[0] += ' ' - 4;

	sprintf(v+1, "%d", (n % 8) + 1);

	return(v);
}

char *
vismltnum(n)
{	static char numnam[15];

	strcpy(numnam, k1mltnum(n));
	if (sngnames[n][0] > ' ') {
		strcat(numnam, " ");
		strcat(numnam, sngnames[n]);
	}
	return(numnam);
}

/*
 * k1nummlt
 *
 * Convert a display-style voice number (A1 to d8) to internal
 * format (0 to 127).
 */

k1nummlt(s)
char *s;
{

	int ld, rd;

	rd = s[0] - 'A';
	if (rd > 3) rd -= ' ' - 4;
	if (rd < 0 || rd > 7) return(-1);

	sscanf(s+1, "%d", &ld);
	if (ld < 1 || ld > 8) return(-1);

	return((rd << 3) + ld - 1);

}

/*
 * k1mltdin
 *
 * Take library bank 'data' and stuff values in the P array, by using
 * the setval function.
 */

k1mltdin(data)
char *data;
{
	/* The first RESERVESIZE bytes are reserved (arbitrarily) for the voice name */
#SETVAL
}

/*
 * k1mltdout
 *
 * Take (possibly changed) parameters values out of the P array and
 * put them back into the library bank 'data'.
 */

k1mltdout(data)
char *data;
{
#GETVAL
}

k1send1(function, voice)
{
	if (Nvoices == 32) voice += 64;

	sendmidi(0xf0);
	sendmidi(0x40);		/* Kawai id */
	sendmidi(Channel - 1);	/* channel = 1 to 16 */
	sendmidi(function);	/* function */
	sendmidi(0x00);		/* group */
	sendmidi(0x03);		/* machine id number of K1 */
	sendmidi(0x00);		/* subcommand 1 = internal */
	sendmidi(voice);	/* subcommand 2 = voice 1 */
}

/*
 * k1mltsedit
 *
 * Send a single voice to the edit buffer of the K1.  This will be whatever
 * voice is currently selected.
 * (So far as I know, one can't do this;  this is here pro forma. -- gl)
 */

k1mltsedit(data)
char *data;
{
	unsigned cksum;
	int n, dumpsize;

	k1send1(0x20, 0);
	cksum = 0xa5;

	if (Nvoices == 32) dumpsize = K1MULTISIZE;
	else dumpsize = K1SINGLESIZE;

	for(n = 0; n < dumpsize; n++) {
		sendmidi(data[n] & 0x7f);
		cksum += data[n] & 0x7f;
	}
	sendmidi(cksum & 0x7f);	/* checksum */
	sendmidi(EOX);
}

/*
 * k1mltnof
 *
 * Return a pointer to the voice name buried in library bank data.
 */
char *
k1mltnof(data)
char *data;
{
	static char currbuff[11];
	char *p;
	int m;

	p = currbuff;
	for ( m = 0 ; m < 10 ; m++ )
		*p++ = data[m];
	*p = '\0';
	return(currbuff);
}

/*
 * k1mltsnof
 *
 * Set the voice name buried in data to name.
 */
k1mltsnof(data,name)
char *data;
char *name;
{
	char *p;
	int m;

	for ( p = name, m = 0 ; *p != '\0' && m < 10 ; p++, m++ )
		data[m] = *p;
	for ( ; m < 10 ; m++ )
		data[m] = ' ';
}

/* k1mltsone - send a single voice to the K1 */
k1mltsone(iv, data)
int iv;
char *data;
{
	unsigned cksum;
	int n, dumpsize;

	k1send1(0x20, iv);
	cksum = 0xa5;

	if (Nvoices == 32) dumpsize = K1MULTISIZE;
	else dumpsize = K1SINGLESIZE;

	for(n = 0; n < dumpsize; n++) {
		sendmidi(data[n] & 0x7f);
		cksum += data[n] & 0x7f;
	}
	sendmidi(cksum & 0x7f);	/* checksum */
	sendmidi(EOX);

	return(0);
}

/* k1mltgbulk - Request and read a bulk dump from the K1 */
k1mltgbulk(data)
char *data;
{
	static	char Buff[BUFSIZ];
	int c, n, v, b2, ret = 1;
	long begin, toolong, wait;
	int dumpsize;
	int cksum;
	
	sprintf(Buff,"\nA: ");
	windstr(Buff);

	if (Nvoices == 32) dumpsize = K1MULTISIZE;
	else dumpsize = K1SINGLESIZE;

	for(v = 0; v < Nvoices; v++) {

		flushmidi();

		if(v == 64) {
			sprintf(Buff,"\nB: ");
			windstr(Buff);
		}
		if((((v > 63) ? (v - 64) : v) % 10) != 0) {
			sprintf(Buff, ".");
		} else {
			sprintf(Buff,"%d", (((v > 63) ? (v - 64) : v) / 10));
		}
		windstr(Buff);

	/* request the dump */
		k1send1(0, v);
		sendmidi(EOX);
	
	/* set up timeout */
		begin = milliclock();
		toolong = begin + (1000 * TIMEOUT);
	
	/* read header */
		for(n = 0; n < 8; ) {
			if ( STATMIDI ) {
				b2 = (getmidi() & 0xff);
				/* burn active sensing and timing clock */
				if((b2 != 0xfe) && (b2 != 0xf8))
					n++;
			} else {
				if ( milliclock() > toolong ) {
					Reason = "Timeout waiting for header";
					goto getout;
				}
			}
		}

	/* read data */
		for(n = 0; n < dumpsize; ) {
			if ( STATMIDI ) {
				b2 = (getmidi() & 0xff);
				/* burn active sensing and timing clock */
				if((b2 != 0xfe) && (b2 != 0xf8)) {
					VOICEBYTE(data,v,n) = b2;
					n++;
				}
			} else {
				if ( milliclock() > toolong ) {
					Reason = "Timeout reading data";
					goto timeout;
				}
			}
		}

	timeout:
		if ( n != dumpsize ) {
			Reason = "Timeout reading data!";
			goto getout;
		}

	/* read checksum */
		for(n = 0; n < 1; ) {
			if ( STATMIDI ) {
				b2 = (getmidi() & 0xff);
				/* burn active sensing and timing clock */
				if((b2 != 0xfe) && (b2 != 0xf8))
					n++;
			} else {
				if ( milliclock() > toolong ) {
					Reason = "Timeout reading checksum";
					goto getout;
				}
			}
		}

	/* read EOX */
		for(n = 0; n < 1; ) {
			if ( STATMIDI ) {
				b2 = (getmidi() & 0xff);
				/* burn active sensing and timing clock */
				if((b2 != 0xfe) && (b2 != 0xf8))
					if ( b2 != EOX ) {
						sprintf(Buff,"EOX not received (%X)\n", b2);
						Reason = Buff;
						goto getout;
					}
					n++;
			} else {
				if ( milliclock() > toolong ) {
					Reason = "Timeout reading EOX";
					goto getout;
				}
			}
		}

	} /* go back for another voice */

	Reason = "";
	ret = 0;	/* all's well */

getout:
	return(ret);
}

/* k1mltsbulk - send a bulk dump to the K1 */
k1mltsbulk(data)
char *data;
{
	static char Buff[BUFSIZ];
	int v, n, databyte, curoff, dumpsize;
	unsigned cksum;

	sprintf(Buff,"\nA: ");
	windstr(Buff);

	if (Nvoices == 32) dumpsize = K1MULTISIZE;
	else dumpsize = K1SINGLESIZE;

	curoff = 0;
	for(v = 0; v <Nvoices ; v++) {
		if(v == 64) {
			sprintf(Buff,"\nB: ");
			windstr(Buff);
		}
		if((((v > 63) ? (v - 64) : v) % 10) != 0) {
			sprintf(Buff, ".");
		} else {
			sprintf(Buff,"%d", (((v > 63) ? (v - 64) : v) / 10));
		}

		windstr(Buff);
		k1send1(0x20, v);
		cksum = 0xa5;

		for(n = 0; n < dumpsize; n++) {
			databyte = data[n + curoff] & 0x7f;
			sendmidi(databyte);
			cksum += databyte;
		}
		sendmidi(cksum & 0x7f);	/* checksum */
		sendmidi(EOX);
		curoff += Voicesize;
	}
	return(0);
}

/* end */
