/* MIRSET -- Set Mirage Parameters using Button Command Codes ** psl 10/87 */ #include #include #include #define DEVMPU "/dev/mpu0" int Verbose = 0; main(argc, argv) char *argv[]; { register int i, p, v, fh; char *cp; if (argc < 2) { syntax: fprintf(stderr, "Usage: %s [-v] param=val [...]\n", argv[0]); fprintf(stderr, "param is a decimal integer\n"); fprintf(stderr, "val may be 'on', 'off', dec, hex (0x#), or '?'\n"); exit(2); } if ((fh = open(DEVMPU, 2)) < 0) { perror(DEVMPU); exit(1); } for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'v': Verbose++; break; default: goto syntax; } } } for (i = 1; i < argc; i++) { if (argv[i][0] == '-') continue; for (cp = argv[i]; *cp && *cp != '='; cp++); if (*cp++ != '=') goto syntax; p = atoi(argv[i]); if (p < 0 || p > 99 || Masos_par[p].ptype == MP_UNUSED) { fprintf(stderr, "Unknown MASOS parameter: %d\n", p); goto syntax; } if (Masos_par[p].ptype == MP_ACT) { fprintf(stderr, "[%d] %s is an action, not a settable param.\n", p, Masos_par[p].pname); goto syntax; } if (*cp == 'o') v = (cp[1] == 'n' ? 1 : 0); else if (*cp == '?') v = -1; else { v = myatoi(cp); if (v < Masos_par[p].lolim || v > Masos_par[p].hilim) { fprintf(stderr, "[%d] %s has a range of %d to %d\n", p, Masos_par[p].pname, Masos_par[p].lolim, Masos_par[p].hilim); goto syntax; } } mirset(fh, p, v); } exit(0); } mirset(fh, p, nv) { register int ov; ov = getparam(fh, p); if (nv == -1) { if (Masos_par[p].pfmt == MP_BOOL) { if (Verbose) printf("[%d] %s is %s (%d)", p, Masos_par[p].pname, ov? "on" : "off", ov); else printf("%d=%s\n", p, ov? "on" : "off"); } else if (Masos_par[p].pfmt == MP_DEC) { if (Verbose) printf("[%d] %s is %d (0x%x)", p, Masos_par[p].pname, ov, ov); else printf("%d=%d\n", p, ov); } else if (Masos_par[p].pfmt == MP_HEX) { if (Verbose) printf("[%d] %s is 0x%02x (%d)", p, Masos_par[p].pname, ov, ov); else printf("%d=0x%02x\n", p, ov); } return; } while (ov != nv) { setparam(fh, ov, nv); ov = getparam(fh, p); } } getparam(fh, p) { register u_char *bp; register int i, n, ov, len; u_char obuf[32], ibuf[256]; bp = obuf; *bp++ = ID_ENSONIQ; *bp++ = ID_MIRAGE; *bp++ = MIR_SXF_CC; *bp++ = p / 10; *bp++ = p % 10; *bp++ = MIRBUT_VALUE; *bp++ = MIR_CC_END; if (Verbose > 1) { fprintf(stderr, "About to send:"); for (i = 0; i < bp - obuf; i++) fprintf(stderr, " %x", obuf[i]); fprintf(stderr, "\n"); } len = Masos_par[p].ptype == MIR_SXF_PPAR? MIR_PPAR_LEN : (Masos_par[p].ptype == MIR_SXF_WPAR? MIR_WPAR_LEN : (Masos_par[p].ptype == MIR_SXF_WAVE? MIR_WAVE_LEN : -1)); if (len == -1) { printf("Unknown parameter: [%d]\n", p); return(-1); } sysexout(fh, obuf, bp - obuf); for (ov = 0; ; ov++) { i = sysexin(fh, ibuf, sizeof ibuf); if (i == 0) { printf("Got 0 bytes back, wanted %d; giving up on [%d] %s.\n", len, p, Masos_par[p].pname); return(-1); } if (Verbose > 1) { for (n = 0; n < i; n++) fprintf(stderr, " %x", ibuf[n]); fprintf(stderr, "\n", ibuf[n]); } if (i != len) { if (Verbose > 0) fprintf(stderr, "Got %d byte(s) back, wanted %d\n", i, len); continue; } if (ibuf[0] != ID_ENSONIQ || ibuf[1] != ID_MIRAGE) { fprintf(stderr, "Not Ensonic Mirage?\n"); ov++; } else if (ibuf[2] != Masos_par[p].ptype) { if (Verbose > 0) fprintf(stderr, "Wrong type of parameter? %x\n", ibuf[2]); } else if (Masos_par[p].ptype != MP_WSEL && ibuf[4] != p) { if (Verbose > 0) fprintf(stderr, "Wrong parameter? %d != %d\n", ibuf[4], p); } else break; if (ov > 6) { printf("Too many failures; giving up on [%d] %s.\n", p, Masos_par[p].pname); return(-1); } } if (Masos_par[p].ptype == MP_WSEL) ov = ibuf[3] & 0x07; else ov = ((ibuf[6] << 4) | ibuf[5]) / Masos_par[p].pfact; return(ov + Masos_par[p].pbase); } setparam(fh, ov, nv) { register u_char *bp; register int i, dv, ud, n; u_char obuf[32], ibuf[256]; dv = nv - ov; ud = MIRBUT_UP; if (dv < 0) { dv = -dv; ud = MIRBUT_DOWN; } while (dv > 0) { bp = obuf; *bp++ = ID_ENSONIQ; *bp++ = ID_MIRAGE; *bp++ = MIR_SXF_CC; n = dv > 5? 5 : dv; for (i = 0; i < n; i++) *bp++ = ud; *bp++ = MIR_CC_END; for(;;) { if (Verbose > 1) fprintf(stderr, "Send %d %s push(es)\n", n, ud == MIRBUT_UP? "up" : "down"); sysexout(fh, obuf, bp - obuf); dv -= n; if (dv < n) break; while (!inwait(fh, 0, 200000)) /* wait for .2 sec idle */ read(fh, ibuf, sizeof ibuf); } } while (!inwait(fh, 0, 200000)) /* flush old input */ read(fh, ibuf, sizeof ibuf); } sysexout(ofh, data, len) /* send sys excl. */ u_char *data; { u_char buf[4096], *bp; bp = buf; *bp++ = MPU_RESET; *bp++ = MPU_MIDI_THRU_OFF; *bp++ = MPU_SEND_SYSTEM_MESSAGE; *bp++ = SX_CMD; while (--len >= 0) *bp++ = *data++; *bp++ = SX_EOB; *bp++ = MPU_EXCLUSIVE_TO_HOST_ON; *bp++ = MPU_SEND_MEASURE_END_OFF; write(ofh, buf, bp - buf); } sysexin(ifh, rbuf, rlen) /* read sys excl. */ u_char *rbuf; { u_char *rbp; int i, mode; mode = 0; for (rbp = rbuf; rlen > 0; ) { if (inwait(ifh, 2, 0)) { if (Verbose) fprintf(stderr, "read timed out\n"); break; } if ((i = read(ifh, rbp, 1)) <= 0) { fprintf(stderr, "read(midi) returned %d\n", i); return(0); } if (mode == 0) { if (*rbp == SX_CMD) mode = SX_CMD; continue; } if (MIDI_EOX(*rbp)) { *rbp = '\0'; break; } rbp++; --rlen; } return(rbp - rbuf); } myatoi(cp) char *cp; { register int i, n; if (*cp == '0' && (cp[1] == 'x' || cp[1] == 'X')) for (cp += 2, n = 0; (i = hex(*cp)) >= 0; cp++, n = (16*n) + i); else n = atoi(cp); return(n); } hex(c) char c; { if ('0' <= c && c <= '9') return(c - '0'); if ('A' <= c && c <= 'F') return(10 + c - 'A'); if ('a' <= c && c <= 'f') return(10 + c - 'a'); return(-1); } inwait(fh, sec, usec) { int rfds; struct timeval tout; if (fh < 0) return(1); rfds = 1 << fh; tout.tv_sec = sec; tout.tv_usec = usec; return(select(fh + 1, &rfds, 0, 0, &tout) == 0); }