/*
**	GETMCMD -- get a midi command from mpu format
**	Common usage:
**		now = 0L;
**		while (mp = getmcmd(stdin, now)) {
**			now = mp->when;
**			...
**		}
**	RT_TCIP commands are not returned.
**	psl 2/87
*/
#include	<stdio.h>
#include	<midi.h>

static	int	bcnts[]	= { 3, 3, 3, 3, 2, 2, 3, -1, };
static	int	smbcnts[]	= {
	-1, 1, 3, 2, 1, 1, 1, 1,
	 1, 1, 1, 1, 1, 1, 1, 1,
};

MCMD	*
getmcmd(ifp, inow)
FILE	*ifp;
long	inow;
{
	register int i, c, b1, b2, b3, type;
	static unsigned char b[4096];
	static int bcnt, status;
	static MCMD m;

	for (;;) {
	    if ((b1 = getc(ifp)) == EOF)
		return((MCMD *) 0);
	    if (b1 != RT_TCIP)
		break;
	    inow += MPU_CLOCK_PERIOD;
	}
	m.when = inow + b1;		/* b1 is timing */
	m.cmd = b;
	if ((b2 = getc(ifp)) == EOF)	/* b2 can be status */
	    return((MCMD *) 0);
	if ((b2 & M_CMD) == 0)		/* not a status byte */
	    b3 = b2;
	else {				/* a status byte */
	    type = (b2 >> 4) & 0x7;
	    i = bcnts[type];
	    if (i == -1)		/* Eeek!  A system message! */
		i = smbcnts[b2 & 0xF];
	    if (i == 1) {		/* these don't alter running status */
		b[0] = b2;
		m.len = 1;
		return(&m);
	    }
	    status = b2;
	    bcnt = i;
	    if ((b3 = getc(ifp)) == EOF)
		return((MCMD *) 0);
	}
	b[0] = status;
	b[1] = b3;
	if (bcnt == -1) {	/* system exclusive */
	    for (i = 2; i < sizeof b; i++) {
		if ((c = getc(ifp)) == EOF)
		    return((MCMD *) 0);
		b[i] = c;
		if (b[i] == 0xF7)
		    break;
	    }
	} else
	    for (i = 2; i < bcnt; b[i++] = c)
		if ((c = getc(ifp)) == EOF)
		    return((MCMD *) 0);
	m.len = i;
	return(&m);
}
