/* FADE -- Control panel for IOTA Midi-Fader, psl 10/87 */ #include #include #include #define DEVMPU "/dev/mpu0" u_char Abreq[] = { /* SysExcl request to dump active buffer */ ID_MISC, ID1_IOTA, ID2_IOTA, /* identify Iota */ ID_IMF, /* identify Midi-Fader */ 0x00, /* Unit number */ IMF_SXC_REQ_ABUF, /* command; dump active buffer */ }; u_char Isetup[] = { /* Initial setup data */ ID_MISC, ID1_IOTA, ID2_IOTA, /* identify Iota */ ID_IMF, /* identify Midi-Fader */ 0x00, /* Unit number */ IMF_SXC_DAT_SETUP, /* command; setup data dump */ 0x01, 0x01, /* do get/send levels */ 0x00, 0x00, /* don't get/send prog commands */ 0x07, /* prog change MIDI channel */ 0x00, /* don't send levels every second */ 0x02, /* fader change rate = 4 ms */ 0x0a, /* dial sensitivity = 10 */ 0x07, 0x00, 0x20, 0x30, /* fader1, lev=32, mute=48 */ 0x07, 0x00, 0x21, 0x31, /* fader2, lev=33, mute=49 */ 0x07, 0x00, 0x22, 0x32, /* fader3, lev=34, mute=50 */ 0x07, 0x00, 0x23, 0x33, /* fader4, lev=35, mute=51 */ 0x07, 0x00, 0x24, 0x34, /* fader5, lev=36, mute=52 */ 0x07, 0x00, 0x25, 0x35, /* fader6, lev=37, mute=53 */ 0x07, 0x00, 0x26, 0x36, /* fader7, lev=38, mute=54 */ 0x07, 0x00, 0x27, 0x37, /* fader8, lev=39, mute=55 */ }; u_char Osetup[] = { /* Other setup data */ ID_MISC, ID1_IOTA, ID2_IOTA, /* identify Iota */ ID_IMF, /* identify Midi-Fader */ 0x00, /* Unit number */ IMF_SXC_DAT_SETUP, /* command; setup data dump */ 0x01, 0x01, /* do get/send levels */ 0x00, 0x00, /* don't get/send prog commands */ 0x07, /* prog change MIDI channel */ 0x01, /* send levels every second */ 0x02, /* fader change rate = 4 ms */ 0x0a, /* dial sensitivity = 10 */ 0x07, 0x00, 0x20, 0x30, /* fader1, lev=32, mute=48 */ 0x07, 0x00, 0x21, 0x31, /* fader2, lev=33, mute=49 */ 0x07, 0x00, 0x22, 0x32, /* fader3, lev=34, mute=50 */ 0x07, 0x00, 0x23, 0x33, /* fader4, lev=35, mute=51 */ 0x07, 0x00, 0x24, 0x34, /* fader5, lev=36, mute=52 */ 0x07, 0x00, 0x25, 0x35, /* fader6, lev=37, mute=53 */ 0x07, 0x00, 0x26, 0x36, /* fader7, lev=38, mute=54 */ 0x07, 0x00, 0x27, 0x37, /* fader8, lev=39, mute=55 */ }; int Ifh = -1; /* where Iota data comes from */ int Ofh = -1; /* where Iota commands go to */ int Chan; /* Iota's MIDI channel */ int Iflg = 0; /* initialization flag */ int Fade[8]; /* 8 fader settings 0-127 */ int Solo[8]; /* 8 solo buttons */ int Mute[8]; /* 8 mute buttons */ int Um[8]; /* Iota fader mutes, 0=>muted */ int Fcntl[8] = { /* controller numbers for the faders */ 32, 33, 34, 35, 36, 37, 38, 39, }; int Mcntl[8] = { /* controller numbers for the mutes */ 48, 49, 50, 51, 52, 53, 54, 55, }; int nlen[] = { /* length of "normal" status commands */ 3, 3, 3, 3, 2, 2, 3, 0, }; int slen[] = { /* length of system status commands */ 0, 1, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }; main(argc, argv) char *argv[]; { char *cp; int i, mask, amask; extern char *getenv(); if (!(cp = getenv("IOTA")) || (Chan = atoi(cp) - 1) < 0) Chan = 0; while (--argc > 0) { if (argv[argc][0] == '-') { switch (argv[argc][1]) { case 'i': /* initialize Iota */ Iflg++; break; case 'f': /* use stdin/stdout */ Ifh = fileno(stdin); Ofh = fileno(stdout); break; default: goto syntax; } } else { syntax: fprintf(stderr, "Usage: %s [-i] [-f >file]\n", argv[0]); fprintf(stderr, "-i initializes Midi-Fader\n"); fprintf(stderr, "-f uses stdin/stdout (no buffering)\n"); exit(2); } } if (Ifh == -1 && Ofh == -1) { if ((Ifh = Ofh = open(DEVMPU, 2)) < 0) { perror(DEVMPU); exit(1); } } else { if (Ifh == -1 && (Ifh = open(DEVMPU, 0)) < 0) { perror(DEVMPU); exit(1); } if (Ofh == -1 && (Ofh = open(DEVMPU, 1)) < 0) { perror(DEVMPU); exit(1); } } if (Iflg) sendinit(); amask = (1 << Ifh) | (1 << 0); rstart(); for (;;) { for (i = 0; i < 8; i++) printf("%d%c", Fade[i], i==7? '\n' : ':'); mask = amask; if (select(Ifh + 1, &mask, 0, 0, 0) < 1) continue; if (mask & (1 << Ifh)) { fadein(); } else { keyin(); } } } sendinit() { /****/printf("sendinit()\n"); sysex(Isetup, sizeof Isetup, 0, 0); } getidata() { register int i, offset; u_char buf[32]; /****/printf("getidata()\n"); sysex(Abreq, sizeof Abreq, buf, sizeof buf); for (offset = 0; offset < 5 && buf[offset] != SX_CMD; offset++); /****/if (offset >= 5) { printf("getidata() screwed up...\n"); return; } offset += 7; for (i = 8; --i >= 0; Fade[i] = buf[offset + i]); for (i = 0; i < 4; i++) { /**** setmute(i, (buf[offset + 8] & (1 << i))? 0 : 1); setmute(i + 4, (buf[offset + 9] & (1 << i))? 0 : 1); /****/; } for (i = 8; --i >= 0; ) { /**** Um[i] = Mute[i]? 0 : 1; setsolo(i, 0); /****/; } } fadein() { int i, ourstatus, skiplen, cmdlen, c, v; u_char buf[512], *bip = buf, *bop = buf; static int status; ourstatus = CH_CTL | Chan; bip = buf + read(Ifh, bop = buf, sizeof buf); while (bop < bip) { i = (*bop++ & 0xFF); /* timing byte */ if (i == RT_TCIP || i == RT_TCIS) continue; skiplen = 0; if (*bop & M_CMD) { i = (*bop & M_CMD_MASK); if (i < SX_CMD) { /* normal status commands */ status = *bop++; cmdlen = nlen[(status >> 4) & 07]; } else { /* weird ones */ if (*bop == SX_CMD) { while (*bop != SX_EOB) /* scan to end of sysex */ if (++bop >= bip) /* (could get stuck) */ bip = buf + read(Ifh, bop = buf, sizeof buf); skiplen = 1; } else skiplen = slen[*bop & 0x0F]; } } if (skiplen == 0 && status != ourstatus) skiplen = cmdlen - 1; /* we're past the status */ if (skiplen) { /* skip over rest of command */ while (skiplen > (bip - bop)) { skiplen -= (bip - bop); /* (could get stuck) */ bip = buf + read(Ifh, bop = buf, sizeof buf); } bop += skiplen; } else { /* this is a fader setting */ while (bop >= bip) bip = buf + read(Ifh, bop = buf, sizeof buf); c = *bop++; while (bop >= bip) bip = buf + read(Ifh, bop = buf, sizeof buf); v = *bop++; if (0x20 <= c && c <= 0x27) Fade[c - 0x20] = v; if (0x30 <= c && c <= 0x37) Mute[c - 0x30] = (v < 64); } } } keyin() { int i, j; static char buf[512]; /****/printf("keyin()\n"); i = read(0, buf, sizeof buf); if (i < 1) return; if (buf[0] == '*') { getidata(); rstart(); } else if (buf[0] == 'X') { sysex(Isetup, sizeof Isetup, 0, 0); rstart(); } else if (buf[0] == 'Z') { sysex(Osetup, sizeof Osetup, 0, 0); rstart(); } else if (i > 3 && buf[1] == '=') { i = atoi(buf); j = atoi(&buf[2]); setfader(i, j); } else printf("Urecognized: %s", buf); } setfader(n, new) { register int old, oldy, newy; mput(CH_CTL | Chan, Fcntl[n], new); } newfader(n, new) { Fade[n] = new; } mput(a, b, c) { u_char buf[8]; buf[0] = MPU_WANT_TO_SEND_DATA + 0; /* 0 = track */ buf[1] = a; buf[2] = b; buf[3] = c; /****/printf("mput(%x,%x,%x); Ofh=%d\n", a, b, c, Ofh); write(Ofh, buf, 4); } sysex(data, len, rbuf, rlen) /* send sys excl., maybe read response */ u_char *data, *rbuf; { u_char buf[4096], *bp, *rbp, *bufend; int i; 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; if (!rbuf || !rlen) { /* no reply */ *bp++ = MPU_RESET; *bp++ = MPU_MIDI_THRU_OFF; *bp++ = MPU_SEND_MEASURE_END_OFF; *bp++ = MPU_START_RECORD; write(Ofh, buf, bp - buf); return(0); } *bp++ = MPU_EXCLUSIVE_TO_HOST_ON; /* get reply */ *bp++ = MPU_SEND_MEASURE_END_OFF; write(Ofh, buf, bp - buf); rbp = rbuf; do { if ((i = read(Ifh, rbp, rlen)) <= 0) { fprintf(stderr, "read(midi) returned %d\n", i); break; } /****/printf("sysex() read %d byte(s)\n", i); bufend = rbp + i; for (bp = rbp; bp < bufend && *bp != SX_EOB; bp++); rlen -= i; rbp += i; } while (rlen > 0 && bp >= bufend); /****/printf("sysex() returns %d\n", rbp - rbuf); return(rbp - rbuf); } rstart() { char *bp, buf[64]; bp = buf; *bp++ = MPU_RESET; *bp++ = MPU_MIDI_THRU_OFF; *bp++ = MPU_SEND_MEASURE_END_OFF; *bp++ = MPU_BENDER_ON; *bp++ = MPU_START_RECORD; write(Ofh, buf, bp - buf); }