#include #include #include #include #define MAXCMDLEN 65600 /* needs to be big for SysExcl */ u_char pds[MAXCMDLEN]; static int pdi; static int pdl = MAXCMDLEN; static int lvl, cnt, dim; static int status, cmd, cont; #define d define #d START 0 #d GET 1 #d CH_LVL 0 #d SC_LVL 1 #d RT_LVL 2 #d SX_LVL 3 #d RS_LVL 4 #d Int register int #d Uchar register u_char #d lvl_err(x) MidiError("level error= %s\n",x) midi_cmd_in_arg_cnt() { return dim; } /* return #of args to last midi command */ midi_cmd_in_cont(){ return cont; } /* true if command was a continuation */ midi_cmd_in_cmd_type(){ return cmd; } static midi_cmd_in_push(c) u_char c;{ if (pdi>= pdl) MidiError("midi_cmd_in_push: overflow\n"), exit(1); pds[pdi++] = c; } static u_char smc[20]; /* ** Read and parse midi command from 'f', ** and return a pointer to a static, '0'-terminated array of commands. ** Handles full MIDI 1.0 specification, including the ability of ** midi commands at different levels to interrupt each other. ** Also handles unterminated system exclusive commands, ** e.g., as produced by Yamaha dx7. */ u_char * midi_cmd_in(f) FILE *f; { Int x; Uchar *rtn; cont = 0; while ((x=getc(f)) != EOF) { Uchar c = x & 0xFF; if (status==START && (c&M_CMD)==0 && smc[fileno(f)]) { ungetc(c, f); c = smc[fileno(f)]; cont++; /* mark as continuation cmd */ } again: switch (status) { case START: cmd = c; if ((c&M_CMD_MASK) != SX_CMD) c &= M_CMD_MASK; switch (c){ /* three-byte midi channel commands */ case CH_KEY_OFF: case CH_KEY_ON: case CH_POLY_KPRS: case CH_CTL: case CH_P_BEND: if (lvl > CH_LVL) lvl_err("CH"); status = GET; midi_cmd_in_push(cnt); midi_cmd_in_push(lvl); dim = cnt = 2; lvl = CH_LVL; smc[fileno(f)] = c = cmd; goto again; /* two-byte midi channel command */ case CH_PRESSURE: case CH_PRG: if (lvl > CH_LVL) lvl_err("CH"); status = GET; midi_cmd_in_push(cnt); midi_cmd_in_push(lvl); dim = cnt = 1; lvl = CH_LVL; smc[fileno(f)] = c = cmd; goto again; /* three-byte system common commands */ case SC_MSEL: if (lvl > SC_LVL) lvl_err("SC"); status = GET; midi_cmd_in_push(cnt); midi_cmd_in_push(lvl); dim = cnt = 2; lvl = SC_LVL; smc[fileno(f)] = c = cmd; goto again; /* two-byte system common commands */ case SC_SSEL: if (lvl > SC_LVL) lvl_err("SC"); status = GET; midi_cmd_in_push(cnt); midi_cmd_in_push(lvl); dim = cnt = 1; lvl = SC_LVL; smc[fileno(f)] = c = cmd; goto again; /* one-byte system common commands */ case SC_TSEL: if (lvl > SC_LVL) lvl_err("SC"); status = GET; midi_cmd_in_push(cnt); midi_cmd_in_push(lvl); dim = cnt = 0; lvl = SC_LVL; smc[fileno(f)] = c = cmd; goto again; /* one-byte real-time commands */ case RT_TCIP: case RT_TCWME: case RT_SA1M: case RT_CONT: case RT_TCIS: if (lvl > RT_LVL) lvl_err("RT"); case RT_RESET: /* highest priority */ status = GET; midi_cmd_in_push(cnt); midi_cmd_in_push(lvl); dim = cnt = 0; lvl = RT_LVL; c = cmd; goto again; case SX_CMD: status = GET; midi_cmd_in_push(cnt); midi_cmd_in_push(lvl); dim = cnt = 2; lvl = SX_LVL; goto again; case SX_EOB: status = GET; midi_cmd_in_push(cnt); midi_cmd_in_push(lvl); dim = cnt = 0; lvl = SX_LVL; c = cmd; goto again; default: printf("%s%x %s\n", "midi_cmd_in: no such midi command=0x", cmd, ", skipping 1 byte"); status = START; dim = cnt = 0; lvl = 0; continue; } case GET: if (cnt-- > 0) { midi_cmd_in_push(c); rtn = NULL; } else if (cmd == SX_CMD) { if (!(c & M_CMD)) { ++dim; midi_cmd_in_push(c); rtn = NULL; } else { ungetc(c, f); cmd = -cmd; goto again; } } else { midi_cmd_in_push(c); rtn = &pds[pdi - (dim+1)]; lvl = pds[pdi - (dim+2)]; cnt = pds[pdi - (dim+3)]; pdi -= dim+3; status = START; if (cmd < 0) { dim -= 2; cmd = -cmd; } break; } } if (rtn) return rtn; } return NULL; } /* * * struct dx7 * dq; * * main(argc, argv) * char **argv; * { * u_char * c; * extern char *calloc(); * * if ((dq = (struct dx7 *) calloc((unsigned) 1, sizeof(struct dx7))) * ==NULL) { * perror("malloc"); * exit(1); * } * * while ((c = midi_cmd_in(stdin)) != NULL) { * da_cmd(c, dx7_rcv_ctl, dx7_rcv_ctl_len, 127, 32, 16384); * /1* vdx7(dq, c); *1/ * } * /1* da_vdx7(dq); *1/ * exit(0); * } */