/* ** 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 #include 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)); }