/*
**	GETMCMD -- get a midi command from mpu format
**	MCMD *getmcmdb(ifp, time, buf, len, statp) -- uses supplied buffers
**	MCMD *getmcmd(ifp, time) -- uses own static buffer
**	Return struct pointer or 0 for error.
**	Common usage:
**		now = 0L;
**		while (mp = getmcmd(stdin, now)) {
**			now = mp->when;
**			...
**		}
**	RT_TCIP commands are not returned, but when an RT_TCIP ends a file,
**	an extra MPU_NO_OP will be returned (to carry the ending time).
**	psl 2/87
*/
#include	<stdio.h>
#include	<midi.h>

static	int	Status;		/* handles running status */
static	long	Last;		/* last time returned */
static	MCMD	M;
static	u_char	B[4096];

MCMD	*
getmcmdb(ifp, inow, b, len, statp)
FILE		*ifp;
long		inow;
unsigned char	*b;
int		*statp;
{
	register unsigned char *bp;
	register int c, n;
	long last;

	last = inow;
	for (;;) {			/* look for MPU time tag byte */
	    if ((c = getc(ifp)) == EOF) {
		if (inow >= last)
		    return((MCMD *) 0);
		M.when = inow;
		M.len = 1;
		M.cmd = b;
		M.cmd[0] = MPU_NO_OP;
		return(&M);
	    }
	    if (c == MPU_ALL_END)	/* throw this away */
		continue;
	    if (c == RT_TCIP)
		inow += MPU_CLOCK_PERIOD;
	    else
		break;
	}
/****/if (c > 0xEF) fprintf(stderr, "getmcmd: time tag is %d (0x%02x)?\n", c);
	M.when = inow + c;		/* c is timing */
	M.cmd = bp = b;
	if ((c = getc(ifp)) == EOF)	/* c can be status */
	    return((MCMD *) 0);
	n = statproc(statp, c);	/* get length & do running status */
	if (n == 0)
	    return((MCMD *) 0);		/* bad status */
	if ((c & M_CMD) == 0)		/* running status */
	    *bp++ = *statp;		/* re-insert status */
	if (n == -1) {			/* system exclusive */
	    *bp++ = c;			/* status (couldn't be running) */
	    while (--len > 0) {
		if ((c = getc(ifp)) == EOF)
		    return((MCMD *) 0);	/* premature EOF */
		*bp = c;
		if (*bp++ == SX_EOB)
		    break;
	    }
	    if (len < 0)
		return((MCMD *) 0);	/* buffer overflow */
	} else {
	    for (*bp++ = c; --n > 0 && (c = getc(ifp)) != EOF; *bp++ = c);
	    if (n)
		return((MCMD *) 0);	/* premature EOF */
	}
	M.len = bp - M.cmd;
	return(&M);
}

MCMD	*
getmcmd(ifp, inow)
FILE	*ifp;
long	inow;
{
	return(getmcmdb(ifp, inow, B, sizeof B, &Status));
}
