/* ** TXPUT -- Store voice(s) and/or performance(s) into DX7 or TX816 */ #include #include #include #include #d DEFCHAN 0 #d e MidiError #d MIN 0 #d MAX 31 #d EDIT 77 #d ALL 99 #d MAX1LEN (TX1PLEN + DX7VOXLEN) /* need room for either */ u_char P64[6 + TX64PTOTLEN]; /* for assembling single-perf update */ u_char V32[6 + DX732VTOTLEN]; /* for assembling single-voice update */ int Chan = DEFCHAN; /* Midi channel to be used */ main(argc, argv) char *argv[]; { int i, n; av0 = argv[0]; for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'c': /* set channel */ n = atoi(&argv[i][2]) - 1; if (n < 0 || 15 < n) { e("%s: bad chan number (%d)\n", av0, Chan); use(); } if (n != Chan) { if (*P64) { P64[2] = DX7_SXSS_BD | Chan; pvsend(P64, 6, &P64[6], TX64PTOTLEN); *P64 = 0; } if (*V32) { V32[2] = DX7_SXSS_BD | Chan; pvsend(V32, 6, &V32[6], DX732VTOTLEN); *V32 = 0; } Chan = n; } break; case 'p': /* load performance(s) */ put(argv[i], "performance", TX_SXF_64P, TX64PTOTLEN, TX_SXF_1P, TX1PLEN); break; case 'v': /* load voice(s) */ put(argv[i], "voice", DX7_SXF_32V, DX732VTOTLEN, DX7_SXF_1V, DX7VOXLEN); break; default: use(); } } } if (*P64) { P64[2] = DX7_SXSS_BD | Chan; pvsend(P64, 6, &P64[6], TX64PTOTLEN); } if (*V32) { V32[2] = DX7_SXSS_BD | Chan; pvsend(V32, 6, &V32[6], DX732VTOTLEN); } exit(0); } put(arg, vorp, afmt, alen, efmt, elen) char *arg, *vorp; { register char *cp; int fh; for (cp = arg; *cp && *cp != '='; cp++); if (*cp != '=') { e("%s: missing '=' in %s\n", av0, arg); use(); } *cp++ = '\0'; if (*cp == '-' && cp[1] == '\0') fh = 0; else if ((fh = open(cp, 0)) < 0) { perror(cp); use(); } if (strcmp(&arg[2], "edit") == 0 || (arg[2] == '0' && arg[3] == '\0')) pvput(fh, efmt, elen); else if (strcmp(&arg[2], "all") == 0) pvput(fh, afmt, alen); else if ('0' <= arg[2] && arg[2] <= '9') pvup(fh, vorp, atoi(&arg[2]) - 1, afmt, alen, efmt, elen); else { e("%s: bad %s spec in %s=%s\n", av0, vorp, arg, cp); use(); } } pvup(fh, vorp, n, afmt, alen, efmt, elen) char *vorp; { u_char buf[6 + MAX1LEN]; if (n < 0 || n >= (*vorp == 'p'? 64 : 32)) { e("%s: %s number %d is out of range\n", av0, vorp, n); return; } if (!pvfile(fh, efmt, elen, buf)) return; if (*vorp == 'p') { if (*P64 == 0 && pvget(afmt, alen, P64) == 0) return; if (!tx1p64(&buf[6], n, &P64[6])) e("tx1p64() failed\n"); } else { if (*V32 == 0 && pvget(afmt, alen, V32) == 0) return; if (!tx1v32(&buf[6], n, &V32[6])) e("tx1v32() failed\n"); } } pvget(fmt, dlen, buf) u_char *buf; { u_char cbuf[16], *cp; int lhi, llo, mfh, len, i; if ((mfh = open(MidiDevice, 2)) == -1) { e("%s: ", av0); perror(MidiDevice); return(0); } lhi = dlen / 128; llo = dlen % 128; MpuSetTrack(mfh, MPU_TR_COM); cp = cbuf; *cp++ = MPU_RESET; *cp++ = MPU_MIDI_THRU_OFF; *cp++ = MPU_SEND_SYSTEM_MESSAGE; *cp++ = SX_CMD; *cp++ = ID_YAMAHA; *cp++ = DX7_SXSS_DR | Chan; *cp++ = fmt; *cp++ = SX_EOB; *cp++ = MPU_EXCLUSIVE_TO_HOST_ON; *cp++ = MPU_SEND_MEASURE_END_OFF; if ((i = write(mfh, cbuf, cp - cbuf)) != cp - cbuf) { e("write(mfh, cbuf, %d) returned %d\n", cp - cbuf, i); perror(MidiDevice); return(0); } MpuSetTrack(mfh, 0); for (;;) { while (read(mfh, buf, 1) == 1 && *buf != SX_CMD); if (read(mfh, &buf[1], 5) != 5) { /* get header */ e("%s: EOF in bulk header\n", av0); close(mfh); return(0); } if (buf[1] == ID_YAMAHA && buf[3] == fmt && buf[4] == lhi && buf[5] == llo) break; e("%s: naughty header for bulk dump:", av0); e(" %x %x %x %x %x\n", buf[1], buf[2], buf[3], buf[4], buf[5]); e("Wanted: %x, xx, %x, %x %x\n", ID_YAMAHA, fmt, lhi, llo); e("Scanning past wrong dump\n"); } len = dlen; for (cp = &buf[6]; (i = read(mfh, cp, len)) > 0; cp += i) if ((len -= i) <= 0) break; if (len > 0) { e("%s: expected %d bytes, got %d\n", av0, dlen, dlen - len); close(mfh); return(0); } read(mfh, cbuf, 2); /* get rid of check-sum & SX_EOB */; close(mfh); return(1); } pvput(fh, fmt, dlen) { u_char buf[6 + TX64PTOTLEN]; if (pvfile(fh, fmt, dlen, buf) == 0) return; buf[2] = DX7_SXSS_BD | Chan; pvsend(buf, 6, &buf[6], dlen); } pvsend(cmd, clen, data, dlen) u_char *cmd, *data; { char buf[4]; int mfh; #ifdef TEST if ((mfh = creat("txput.test", 0644)) == -1) { e("%s: ", av0); perror("txput.test"); exit(1); } #else if ((mfh = open(MidiDevice, 2)) == -1) { e("%s: ", av0); perror(MidiDevice); exit(1); } MpuSetTrack(mfh, MPU_TR_COM); buf[0] = MPU_RESET; buf[1] = MPU_MIDI_THRU_OFF; buf[2] = MPU_SEND_SYSTEM_MESSAGE; write(mfh, buf, 3); #endif write(mfh, cmd, clen); write(mfh, data, dlen); buf[0] = CheckSum(data, dlen); buf[1] = SX_EOB; write(mfh, buf, 2); #ifndef TEST MpuSetTrack(mfh, 0); #endif close(mfh); } pvfile(fh, fmt, len, cp) u_char *cp; { u_char buf[2]; int lhi, llo; lhi = len / 128; llo = len % 128; while (read(fh, cp, 1) == 1 && *cp != SX_CMD); if (read(fh, &cp[1], 5) != 5) { e("%s: EOF in file header?\n", av0); return(0); } if (cp[1] != ID_YAMAHA || (cp[2] != Chan && cp[2] != 0) /* TX816 likes 0 */ || cp[3] != fmt || cp[4] != lhi || cp[5] != llo) { e("%s: naughty file header:", av0); e(" %x %x %x %x %x\n", cp[1], cp[2], cp[3], cp[4], cp[5]); return(0); } if (read(fh, &cp[6], len) != len) { e("%s: EOF in file body?\n", av0); return(0); } if (read(fh, buf, 2) != 2) { e("%s: EOF in checksum/SX_EOB?\n", av0); return(0); } if (buf[0] != (llo = CheckSum(&cp[6], len))) e("%s: Bad checksum (%d should be %d)\n", av0, buf[0], llo); if (buf[1] != SX_EOB) e("%s: Missing SX_EOB\n", av0); return(1); } use() { e("Usage: %s [-c#] [-pNUM=FILE ...] [-vNUM=FILE ...]\n", av0); e(" -c# send data on midi channel # default is %d\n", DEFCHAN+1); e("NUM is either a decimal number, 1-32, 'edit', or 'all'\n"); e("FILE is a filename, '-' represents stdin\n"); e("Arguments are processed left to right; for example:\n"); e("% %s -c9 -v1=v.1.9 -v2=v.2.9 -c10 -vall=v..10 -pall=p..10\n", av0); exit(2); }