#include <stdio.h>
#include <midi.h>
#include <mpuvar.h>
/*
** SXMPU -- Send the sys. excl. command found in stdin to the MPU
**	and (optionally) capture any response.
**	psl 8/87
*/

char	*Midi_dev	= MPU_DEV_0;	/* default */
int	Dflg	= 0;	/* delay the output (unbuffered) */
int	Mflg	= 0;	/* send/receive multiple sysex commands */
int	Rflg	= 0;	/* record commands coming back */
int	Sflg	= 0;	/* how long to wait to time-out */
int	Tflg	= 0;	/* output received data as ASCII */
int	Vflg	= 0;	/* give message lengths */
int	Wflg	= 1;	/* write out sys excl message */

main(argc, argv)
char	*argv[];
{
	register int fh, i, j;
	unsigned char *bp, *bufend, buf[1024];
	int bcnt;

	for (i = 1; i < argc; i++) {
	    if (argv[i][0] == '-') {
		switch (argv[i][1]) {
		case 'd':	Dflg = atoi(&argv[i][2]);	break;
		case 'm':	Mflg++;	break;
		case 'o':	Midi_dev = &argv[i][2];	break;
		case 'r':	Rflg++;	Sflg = atoi(&argv[i][2]);	break;
		case 't':	Tflg++;	break;
		case 'u':	setbuf(stdout, 0);	break;
		case 'v':	Vflg++;	bcnt = 0;	break;
		case 'w':	Wflg = 0;	break;
		default:	goto syntax;
		}
	    } else {
syntax:
		fprintf(stderr,
		 "Usage: %s [options] ... <sxfile [>sxfile]\n", argv[0]);
		fprintf(stderr, "-d#\tdelay # msec between output bytes\n");
		fprintf(stderr, "-multi\treceive/send mult. sysex commands\n");
		fprintf(stderr, "-oDEV\tuse DEV instead of /dev/mpu0\n");
		fprintf(stderr, "-record\trecord return info\n");
		fprintf(stderr, "-r#\trecord & time out after # seconds.\n");
		fprintf(stderr, "-test\tprint input data in ASCII (for -r)\n");
		fprintf(stderr, "-unbuff\tunbuffered stdout (for -r)\n");
		fprintf(stderr, "-verb\treport counts (sent & received)\n");
		fprintf(stderr, "-write\tskip writing (e.g. record only)\n");
		exit(2);
	    }
	}
	if ((fh = open(Midi_dev, 2)) < 0) {
	    perror(Midi_dev);
	    exit(3);
	}
	MpuSetTrack(fh, MPU_TR_COM);
	bp = buf;
	*bp++ = MPU_RESET;
	*bp++ = MPU_MIDI_THRU_OFF;
	write(fh, buf, bp - buf);
	if (Wflg)
	    while (sysex(fh) && Mflg);
	if (!Rflg)
	    exit(0);
	bp = buf;
	*bp++ = MPU_EXCLUSIVE_TO_HOST_ON;
	*bp++ = MPU_SEND_MEASURE_END_OFF;
	write(fh, buf, bp - buf);
	bcnt = 0;
	do {
	    if (Sflg)
		alarm(Sflg);
	    if ((i = read(fh, buf, sizeof buf)) <= 0)
		fprintf(stderr, "read(midi) returned %d\n", i);
	    if (Sflg)
		alarm(0);
	    if (Tflg) {
		for (j = 0; j < i; j++)
		    printf("%02x%s", buf[j]&0xFF, (j&0xF)==0xF? "\n" : " ");
		printf(" ...\n");
	    } else {
		if (write(fileno(stdout), buf, i) != i)
		    fprintf(stderr, "write(%d, buf, %d) failed\n",
		     fileno(stdout), i);
	    }
	    bcnt += i;
	    bufend = &buf[i];
	    for (bp = buf; bp < bufend && !MIDI_EOX(*bp); bp++);
	    if (Vflg && bp < bufend) {
		fprintf(stderr, "%d bytes of SysExcl received.\n", bcnt);
		bcnt = 0;
	    }
	} while (Mflg || bp >= bufend);
	if (Vflg && bcnt)
	    fprintf(stderr, "%d bytes of unterminated SysExcl received.\n",
	     bcnt);
	exit(0);
}

sysex(ofh)	/* Read sys. excl. from stdin and send it to ofh. */
{		/* Return 0 on EOF, else count of chars sent. */
	register int i, bcnt;
	unsigned char *bp, *datend, buf[1024];

	*buf = 0;
	while ((i = getc(stdin)) != EOF && (i & 0xFF) != SX_CMD);
	if (i == EOF)
	    return(0);
	bp = buf;
	*bp++ = MPU_SEND_SYSTEM_MESSAGE;
	bcnt = -1;
	*bp++ = SX_CMD;
	for (i = 0; !MIDI_EOX(i) && (i = getc(stdin)) != EOF; ) {
	    *bp++ = i;
	    if (Dflg || MIDI_EOX(i) || (bp - buf >= sizeof buf)) {
		write(ofh, buf, bp - buf);
		bcnt += bp - buf;
		bp = buf;
		if (Dflg)
		    snooze(Dflg);
	    }
	}
	if (Vflg)
	    fprintf(stderr, "%d bytes of SysExcl sent.\n", bcnt);
	return(bcnt);
}
