Annotation of src/usr.bin/aucat/midi.c, Revision 1.40
1.40 ! ratchov 1: /* $OpenBSD: midi.c,v 1.39 2011/11/20 22:54:51 ratchov Exp $ */
1.1 ratchov 2: /*
3: * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17: /*
18: * TODO
19: *
1.7 ratchov 20: * use shadow variables (to save NRPNs, LSB of controller)
21: * in the midi merger
1.1 ratchov 22: */
23: #include <stdio.h>
24: #include <stdlib.h>
25: #include <string.h>
26:
27: #include "abuf.h"
28: #include "aproc.h"
1.3 ratchov 29: #include "conf.h"
30: #include "dev.h"
1.1 ratchov 31: #include "midi.h"
1.33 ratchov 32: #include "sysex.h"
1.14 ratchov 33: #ifdef DEBUG
34: #include "dbg.h"
35: #endif
1.1 ratchov 36:
37: /*
38: * input data rate is XFER / TIMO (in bytes per microsecond),
39: * it must be slightly larger than the MIDI standard 3125 bytes/s
40: */
41: #define MIDITHRU_XFER 340
42: #define MIDITHRU_TIMO 100000
43:
1.3 ratchov 44: /*
45: * masks to extract command and channel of status byte
46: */
47: #define MIDI_CMDMASK 0xf0
48: #define MIDI_CHANMASK 0x0f
49:
50: /*
51: * MIDI status bytes of voice messages
52: */
53: #define MIDI_NOFF 0x80 /* note off */
54: #define MIDI_NON 0x90 /* note on */
55: #define MIDI_KAT 0xa0 /* key after touch */
56: #define MIDI_CTL 0xb0 /* controller */
57: #define MIDI_PC 0xc0 /* program change */
58: #define MIDI_CAT 0xd0 /* channel after touch */
59: #define MIDI_BEND 0xe0 /* pitch bend */
1.16 ratchov 60: #define MIDI_ACK 0xfe /* active sensing message */
1.3 ratchov 61:
62: /*
63: * MIDI controller numbers
64: */
65: #define MIDI_CTLVOL 7 /* volume */
66: #define MIDI_CTLPAN 11 /* pan */
67:
68: /*
69: * length of voice and common messages (status byte included)
70: */
1.1 ratchov 71: unsigned voice_len[] = { 3, 3, 3, 3, 2, 2, 3 };
72: unsigned common_len[] = { 0, 2, 3, 2, 0, 0, 1, 1 };
73:
1.7 ratchov 74: /*
1.40 ! ratchov 75: * call-back invoked periodically to implement throttling; at each invocation
1.7 ratchov 76: * gain more ``tickets'' for processing. If one of the buffer was blocked by
77: * the throttelling mechanism, then run it
78: */
1.1 ratchov 79: void
1.40 ! ratchov 80: midi_cb(void *addr)
1.1 ratchov 81: {
82: struct aproc *p = (struct aproc *)addr;
83: struct abuf *i, *inext;
84: unsigned tickets;
85:
1.40 ! ratchov 86: timo_add(&p->u.midi.timo, MIDITHRU_TIMO);
1.1 ratchov 87:
1.20 ratchov 88: for (i = LIST_FIRST(&p->ins); i != NULL; i = inext) {
1.1 ratchov 89: inext = LIST_NEXT(i, ient);
1.10 ratchov 90: tickets = i->tickets;
91: i->tickets = MIDITHRU_XFER;
1.1 ratchov 92: if (tickets == 0)
93: abuf_run(i);
94: }
95: }
96:
1.40 ! ratchov 97: void
! 98: midi_msg_info(struct aproc *p, int slot, char *msg)
! 99: {
! 100: struct ctl_slot *s;
! 101: struct sysex *x = (struct sysex *)msg;
! 102:
! 103: s = p->u.midi.dev->slot + slot;
! 104: memset(x, 0, sizeof(struct sysex));
! 105: x->start = SYSEX_START;
! 106: x->type = SYSEX_TYPE_EDU;
! 107: x->id0 = SYSEX_AUCAT;
! 108: x->id1 = SYSEX_AUCAT_MIXINFO;
! 109: if (*s->name != '\0') {
! 110: snprintf(x->u.mixinfo.name,
! 111: SYSEX_NAMELEN, "%s%u", s->name, s->unit);
! 112: }
! 113: x->u.mixinfo.chan = slot;
! 114: x->u.mixinfo.end = SYSEX_END;
! 115: }
! 116:
! 117: void
! 118: midi_msg_vol(struct aproc *p, int slot, char *msg)
1.1 ratchov 119: {
1.40 ! ratchov 120: struct ctl_slot *s;
1.1 ratchov 121:
1.40 ! ratchov 122: s = p->u.midi.dev->slot + slot;
! 123: msg[0] = MIDI_CTL | slot;
! 124: msg[1] = MIDI_CTLVOL;
! 125: msg[2] = s->vol;
1.3 ratchov 126: }
127:
1.7 ratchov 128: /*
1.33 ratchov 129: * send a message to the given output
130: */
131: void
1.40 ! ratchov 132: midi_copy(struct abuf *ibuf, struct abuf *obuf, unsigned char *msg, unsigned len)
1.33 ratchov 133: {
1.40 ! ratchov 134: unsigned ocount;
! 135: unsigned char *odata;
1.33 ratchov 136:
1.40 ! ratchov 137: if (msg[0] == SYSEX_START)
! 138: obuf->w.midi.owner = ibuf;
! 139: while (len > 0) {
1.33 ratchov 140: if (!ABUF_WOK(obuf)) {
141: #ifdef DEBUG
142: if (debug_level >= 3) {
143: abuf_dbg(obuf);
144: dbg_puts(": overrun, discarding ");
145: dbg_putu(obuf->used);
146: dbg_puts(" bytes\n");
147: }
148: #endif
149: abuf_rdiscard(obuf, obuf->used);
1.40 ! ratchov 150: if (obuf->w.midi.owner == ibuf)
! 151: obuf->w.midi.owner = NULL;
! 152: return;
1.33 ratchov 153: }
154: odata = abuf_wgetblk(obuf, &ocount, 0);
1.40 ! ratchov 155: if (ocount > len)
! 156: ocount = len;
1.33 ratchov 157: #ifdef DEBUG
158: if (debug_level >= 4) {
159: abuf_dbg(obuf);
160: dbg_puts(": stored ");
161: dbg_putu(ocount);
162: dbg_puts(" bytes\n");
163: }
164: #endif
1.40 ! ratchov 165: memcpy(odata, msg, ocount);
1.33 ratchov 166: abuf_wcommit(obuf, ocount);
1.40 ! ratchov 167: len -= ocount;
! 168: msg += ocount;
! 169: }
! 170: }
! 171:
! 172: /*
! 173: * flush all buffers. Since most of the MIDI traffic is broadcasted to
! 174: * all outputs, the flush is delayed to avoid flushing all outputs for
! 175: * each message.
! 176: */
! 177: void
! 178: midi_flush(struct aproc *p)
! 179: {
! 180: struct abuf *i, *inext;
! 181:
! 182: for (i = LIST_FIRST(&p->outs); i != NULL; i = inext) {
! 183: inext = LIST_NEXT(i, oent);
! 184: if (ABUF_ROK(i))
! 185: (void)abuf_flush(i);
1.33 ratchov 186: }
187: }
188:
189: /*
1.7 ratchov 190: * broadcast a message to all output buffers on the behalf of ibuf.
191: * ie. don't sent back the message to the sender
192: */
1.3 ratchov 193: void
1.40 ! ratchov 194: midi_send(struct aproc *p, struct abuf *ibuf, unsigned char *msg, unsigned len)
1.3 ratchov 195: {
196: struct abuf *i, *inext;
197:
1.20 ratchov 198: for (i = LIST_FIRST(&p->outs); i != NULL; i = inext) {
1.3 ratchov 199: inext = LIST_NEXT(i, oent);
1.19 ratchov 200: if (i->duplex && i->duplex == ibuf)
1.3 ratchov 201: continue;
1.40 ! ratchov 202: midi_copy(ibuf, i, msg, len);
1.3 ratchov 203: }
204: }
205:
1.7 ratchov 206: /*
1.13 ratchov 207: * send a quarter frame MTC message
208: */
209: void
1.40 ! ratchov 210: midi_send_qfr(struct aproc *p, unsigned rate, int delta)
1.13 ratchov 211: {
212: unsigned char buf[2];
213: unsigned data;
1.39 ratchov 214: int qfrlen;
215:
1.40 ! ratchov 216: p->u.midi.delta += delta * MTC_SEC;
! 217: qfrlen = rate * (MTC_SEC / (4 * p->u.midi.fps));
! 218: while (p->u.midi.delta >= qfrlen) {
! 219: switch (p->u.midi.qfr) {
1.39 ratchov 220: case 0:
1.40 ! ratchov 221: data = p->u.midi.fr & 0xf;
1.39 ratchov 222: break;
223: case 1:
1.40 ! ratchov 224: data = p->u.midi.fr >> 4;
1.39 ratchov 225: break;
226: case 2:
1.40 ! ratchov 227: data = p->u.midi.sec & 0xf;
1.39 ratchov 228: break;
229: case 3:
1.40 ! ratchov 230: data = p->u.midi.sec >> 4;
1.39 ratchov 231: break;
232: case 4:
1.40 ! ratchov 233: data = p->u.midi.min & 0xf;
1.39 ratchov 234: break;
235: case 5:
1.40 ! ratchov 236: data = p->u.midi.min >> 4;
1.39 ratchov 237: break;
238: case 6:
1.40 ! ratchov 239: data = p->u.midi.hr & 0xf;
1.39 ratchov 240: break;
241: case 7:
1.40 ! ratchov 242: data = (p->u.midi.hr >> 4) | (p->u.midi.fps_id << 1);
1.39 ratchov 243: /*
244: * tick messages are sent 2 frames ahead
245: */
1.40 ! ratchov 246: p->u.midi.fr += 2;
! 247: if (p->u.midi.fr < p->u.midi.fps)
1.39 ratchov 248: break;
1.40 ! ratchov 249: p->u.midi.fr -= p->u.midi.fps;
! 250: p->u.midi.sec++;
! 251: if (p->u.midi.sec < 60)
1.39 ratchov 252: break;
1.40 ! ratchov 253: p->u.midi.sec = 0;
! 254: p->u.midi.min++;
! 255: if (p->u.midi.min < 60)
1.39 ratchov 256: break;
1.40 ! ratchov 257: p->u.midi.min = 0;
! 258: p->u.midi.hr++;
! 259: if (p->u.midi.hr < 24)
1.39 ratchov 260: break;
1.40 ! ratchov 261: p->u.midi.hr = 0;
1.13 ratchov 262: break;
1.39 ratchov 263: default:
264: /* NOTREACHED */
265: data = 0;
266: }
267: buf[0] = 0xf1;
1.40 ! ratchov 268: buf[1] = (p->u.midi.qfr << 4) | data;
! 269: p->u.midi.qfr++;
! 270: p->u.midi.qfr &= 7;
! 271: midi_send(p, NULL, buf, 2);
! 272: p->u.midi.delta -= qfrlen;
1.13 ratchov 273: }
274: }
275:
276: /*
277: * send a full frame MTC message
278: */
279: void
1.40 ! ratchov 280: midi_send_full(struct aproc *p, unsigned origin, unsigned rate, unsigned round, unsigned pos)
1.13 ratchov 281: {
282: unsigned char buf[10];
1.39 ratchov 283: unsigned fps;
1.13 ratchov 284:
1.40 ! ratchov 285: p->u.midi.delta = MTC_SEC * pos;
1.39 ratchov 286: if (rate % (30 * 4 * round) == 0) {
1.40 ! ratchov 287: p->u.midi.fps_id = MTC_FPS_30;
! 288: p->u.midi.fps = 30;
1.39 ratchov 289: } else if (rate % (25 * 4 * round) == 0) {
1.40 ! ratchov 290: p->u.midi.fps_id = MTC_FPS_25;
! 291: p->u.midi.fps = 25;
1.39 ratchov 292: } else {
1.40 ! ratchov 293: p->u.midi.fps_id = MTC_FPS_24;
! 294: p->u.midi.fps = 24;
1.39 ratchov 295: }
296: #ifdef DEBUG
297: if (debug_level >= 3) {
298: aproc_dbg(p);
299: dbg_puts(": mtc full frame at ");
1.40 ! ratchov 300: dbg_puti(p->u.midi.delta);
1.39 ratchov 301: dbg_puts(", ");
1.40 ! ratchov 302: dbg_puti(p->u.midi.fps);
1.39 ratchov 303: dbg_puts(" fps\n");
304: }
305: #endif
1.40 ! ratchov 306: fps = p->u.midi.fps;
! 307: p->u.midi.hr = (origin / (3600 * MTC_SEC)) % 24;
! 308: p->u.midi.min = (origin / (60 * MTC_SEC)) % 60;
! 309: p->u.midi.sec = (origin / MTC_SEC) % 60;
! 310: p->u.midi.fr = (origin / (MTC_SEC / fps)) % fps;
1.13 ratchov 311:
312: buf[0] = 0xf0;
313: buf[1] = 0x7f;
314: buf[2] = 0x7f;
315: buf[3] = 0x01;
316: buf[4] = 0x01;
1.40 ! ratchov 317: buf[5] = p->u.midi.hr | (p->u.midi.fps_id << 5);
! 318: buf[6] = p->u.midi.min;
! 319: buf[7] = p->u.midi.sec;
! 320: buf[8] = p->u.midi.fr;
1.13 ratchov 321: buf[9] = 0xf7;
1.40 ! ratchov 322: p->u.midi.qfr = 0;
! 323: midi_send(p, NULL, buf, 10);
1.13 ratchov 324: }
325:
1.33 ratchov 326: void
1.40 ! ratchov 327: midi_copy_dump(struct aproc *p, struct abuf *obuf)
1.35 ratchov 328: {
329: unsigned i;
330: unsigned char msg[sizeof(struct sysex)];
331: struct ctl_slot *s;
332:
1.40 ! ratchov 333: for (i = 0, s = p->u.midi.dev->slot; i < CTL_NSLOT; i++, s++) {
! 334: midi_msg_info(p, i, msg);
! 335: midi_copy(NULL, obuf, msg, SYSEX_SIZE(mixinfo));
! 336: midi_msg_vol(p, i, msg);
! 337: midi_copy(NULL, obuf, msg, 3);
1.35 ratchov 338: }
339: msg[0] = SYSEX_START;
340: msg[1] = SYSEX_TYPE_EDU;
341: msg[2] = 0;
342: msg[3] = SYSEX_AUCAT;
343: msg[4] = SYSEX_AUCAT_DUMPEND;
344: msg[5] = SYSEX_END;
1.40 ! ratchov 345: midi_copy(NULL, obuf, msg, 6);
1.35 ratchov 346: }
347:
1.13 ratchov 348: /*
1.7 ratchov 349: * notifty the mixer that volume changed, called by whom allocad the slot using
350: * ctl_slotnew(). Note: it doesn't make sens to call this from within the
351: * call-back.
352: */
1.3 ratchov 353: void
1.40 ! ratchov 354: midi_send_vol(struct aproc *p, int slot, unsigned vol)
1.3 ratchov 355: {
356: unsigned char msg[3];
357:
1.40 ! ratchov 358: midi_msg_vol(p, slot, msg);
! 359: midi_send(p, NULL, msg, 3);
1.3 ratchov 360: }
361:
1.13 ratchov 362: void
1.40 ! ratchov 363: midi_send_slot(struct aproc *p, int slot)
1.13 ratchov 364: {
1.39 ratchov 365: unsigned char msg[sizeof(struct sysex)];
1.13 ratchov 366:
1.40 ! ratchov 367: midi_msg_info(p, slot, msg);
! 368: midi_send(p, NULL, msg, SYSEX_SIZE(mixinfo));
1.19 ratchov 369: }
370:
371: /*
1.40 ! ratchov 372: * handle a MIDI voice event received from ibuf
1.7 ratchov 373: */
1.3 ratchov 374: void
1.40 ! ratchov 375: midi_onvoice(struct aproc *p, struct abuf *ibuf)
1.3 ratchov 376: {
1.40 ! ratchov 377: struct ctl_slot *slot;
1.3 ratchov 378: unsigned chan;
1.14 ratchov 379: #ifdef DEBUG
380: unsigned i;
381:
382: if (debug_level >= 3) {
383: abuf_dbg(ibuf);
1.40 ! ratchov 384: dbg_puts(": got voice event:");
1.14 ratchov 385: for (i = 0; i < ibuf->r.midi.idx; i++) {
386: dbg_puts(" ");
387: dbg_putx(ibuf->r.midi.msg[i]);
388: }
389: dbg_puts("\n");
390: }
391: #endif
1.10 ratchov 392: if ((ibuf->r.midi.msg[0] & MIDI_CMDMASK) == MIDI_CTL &&
1.33 ratchov 393: (ibuf->r.midi.msg[1] == MIDI_CTLVOL)) {
1.10 ratchov 394: chan = ibuf->r.midi.msg[0] & MIDI_CHANMASK;
1.3 ratchov 395: if (chan >= CTL_NSLOT)
396: return;
1.40 ! ratchov 397: slot = p->u.midi.dev->slot + chan;
1.22 ratchov 398: slot->vol = ibuf->r.midi.msg[2];
1.12 ratchov 399: if (slot->ops == NULL)
1.3 ratchov 400: return;
1.12 ratchov 401: slot->ops->vol(slot->arg, slot->vol);
1.3 ratchov 402: }
1.40 ! ratchov 403: }
! 404:
! 405: /*
! 406: * handle a MIDI sysex received from ibuf
! 407: */
! 408: void
! 409: midi_onsysex(struct aproc *p, struct abuf *ibuf)
! 410: {
! 411: struct sysex *x;
! 412: unsigned fps, len;
! 413: #ifdef DEBUG
! 414: unsigned i;
! 415:
! 416: if (debug_level >= 3) {
! 417: abuf_dbg(ibuf);
! 418: dbg_puts(": got sysex:");
! 419: for (i = 0; i < ibuf->r.midi.idx; i++) {
! 420: dbg_puts(" ");
! 421: dbg_putx(ibuf->r.midi.msg[i]);
! 422: }
! 423: dbg_puts("\n");
! 424: }
! 425: #endif
1.33 ratchov 426: x = (struct sysex *)ibuf->r.midi.msg;
427: len = ibuf->r.midi.idx;
428: if (x->start != SYSEX_START)
429: return;
430: if (len < SYSEX_SIZE(empty))
431: return;
432: switch (x->type) {
433: case SYSEX_TYPE_RT:
434: if (x->id0 != SYSEX_MMC)
435: return;
436: switch (x->id1) {
437: case SYSEX_MMC_STOP:
438: if (len != SYSEX_SIZE(stop))
439: return;
1.14 ratchov 440: #ifdef DEBUG
1.19 ratchov 441: if (debug_level >= 3) {
1.14 ratchov 442: abuf_dbg(ibuf);
443: dbg_puts(": mmc stop\n");
444: }
445: #endif
1.40 ! ratchov 446: dev_mmcstop(p->u.midi.dev);
1.13 ratchov 447: break;
1.33 ratchov 448: case SYSEX_MMC_START:
449: if (len != SYSEX_SIZE(start))
450: return;
1.14 ratchov 451: #ifdef DEBUG
1.19 ratchov 452: if (debug_level >= 3) {
1.14 ratchov 453: abuf_dbg(ibuf);
454: dbg_puts(": mmc start\n");
455: }
456: #endif
1.40 ! ratchov 457: dev_mmcstart(p->u.midi.dev);
1.13 ratchov 458: break;
1.33 ratchov 459: case SYSEX_MMC_LOC:
460: if (len != SYSEX_SIZE(loc) ||
461: x->u.loc.len != SYSEX_MMC_LOC_LEN ||
462: x->u.loc.cmd != SYSEX_MMC_LOC_CMD)
463: return;
464: switch (x->u.loc.hr >> 5) {
465: case MTC_FPS_24:
466: fps = 24;
467: break;
468: case MTC_FPS_25:
469: fps = 25;
470: break;
471: case MTC_FPS_30:
472: fps = 30;
473: break;
474: default:
1.39 ratchov 475: /* XXX: should dev_mmcstop() here */
1.33 ratchov 476: return;
477: }
1.40 ! ratchov 478: dev_loc(p->u.midi.dev,
1.33 ratchov 479: (x->u.loc.hr & 0x1f) * 3600 * MTC_SEC +
480: x->u.loc.min * 60 * MTC_SEC +
481: x->u.loc.sec * MTC_SEC +
482: x->u.loc.fr * (MTC_SEC / fps) +
483: x->u.loc.cent * (MTC_SEC / 100 / fps));
1.13 ratchov 484: break;
485: }
1.35 ratchov 486: break;
487: case SYSEX_TYPE_EDU:
488: if (x->id0 != SYSEX_AUCAT || x->id1 != SYSEX_AUCAT_DUMPREQ)
489: return;
490: if (len != SYSEX_SIZE(dumpreq))
491: return;
492: if (ibuf->duplex)
1.40 ! ratchov 493: midi_copy_dump(p, ibuf->duplex);
1.33 ratchov 494: break;
1.13 ratchov 495: }
1.3 ratchov 496: }
497:
498: int
1.40 ! ratchov 499: midi_in(struct aproc *p, struct abuf *ibuf)
1.3 ratchov 500: {
1.40 ! ratchov 501: unsigned char c, *idata;
! 502: unsigned i, icount;
1.3 ratchov 503:
504: if (!ABUF_ROK(ibuf))
505: return 0;
1.40 ! ratchov 506: if (ibuf->tickets == 0) {
! 507: #ifdef DEBUG
! 508: if (debug_level >= 4) {
! 509: abuf_dbg(ibuf);
! 510: dbg_puts(": out of tickets, blocking\n");
! 511: }
! 512: #endif
! 513: return 0;
! 514: }
1.3 ratchov 515: idata = abuf_rgetblk(ibuf, &icount, 0);
1.40 ! ratchov 516: if (icount > ibuf->tickets)
! 517: icount = ibuf->tickets;
! 518: ibuf->tickets -= icount;
1.3 ratchov 519: for (i = 0; i < icount; i++) {
520: c = *idata++;
1.8 ratchov 521: if (c >= 0xf8) {
1.40 ! ratchov 522: if (!p->u.midi.dev && c != MIDI_ACK)
! 523: midi_send(p, ibuf, &c, 1);
! 524: } else if (c == SYSEX_END) {
! 525: if (ibuf->r.midi.st == SYSEX_START) {
1.10 ratchov 526: ibuf->r.midi.msg[ibuf->r.midi.idx++] = c;
1.40 ! ratchov 527: if (!p->u.midi.dev) {
! 528: midi_send(p, ibuf,
! 529: ibuf->r.midi.msg, ibuf->r.midi.idx);
! 530: } else
! 531: midi_onsysex(p, ibuf);
1.8 ratchov 532: }
1.40 ! ratchov 533: ibuf->r.midi.st = 0;
! 534: ibuf->r.midi.idx = 0;
! 535: } else if (c >= 0xf0) {
1.10 ratchov 536: ibuf->r.midi.msg[0] = c;
537: ibuf->r.midi.len = common_len[c & 7];
538: ibuf->r.midi.st = c;
539: ibuf->r.midi.idx = 1;
1.3 ratchov 540: } else if (c >= 0x80) {
1.10 ratchov 541: ibuf->r.midi.msg[0] = c;
542: ibuf->r.midi.len = voice_len[(c >> 4) & 7];
543: ibuf->r.midi.st = c;
544: ibuf->r.midi.idx = 1;
545: } else if (ibuf->r.midi.st) {
1.40 ! ratchov 546: if (ibuf->r.midi.idx == 0 &&
! 547: ibuf->r.midi.st != SYSEX_START) {
! 548: ibuf->r.midi.msg[ibuf->r.midi.idx++] =
! 549: ibuf->r.midi.st;
! 550: }
1.10 ratchov 551: ibuf->r.midi.msg[ibuf->r.midi.idx++] = c;
552: if (ibuf->r.midi.idx == ibuf->r.midi.len) {
1.40 ! ratchov 553: if (!p->u.midi.dev) {
! 554: midi_send(p, ibuf,
! 555: ibuf->r.midi.msg, ibuf->r.midi.idx);
! 556: } else
! 557: midi_onvoice(p, ibuf);
! 558: if (ibuf->r.midi.st >= 0xf0)
! 559: ibuf->r.midi.st = 0;
! 560: ibuf->r.midi.idx = 0;
! 561: } else if (ibuf->r.midi.idx == MIDI_MSGMAX) {
! 562: if (!p->u.midi.dev) {
! 563: midi_send(p, ibuf,
! 564: ibuf->r.midi.msg, ibuf->r.midi.idx);
! 565: }
1.10 ratchov 566: ibuf->r.midi.idx = 0;
1.3 ratchov 567: }
568: }
569: }
1.40 ! ratchov 570: /*
! 571: * XXX: if the sysex is received byte by byte, partial messages
! 572: * won't be sent until the end byte is received. On the other
! 573: * hand we can't flush it here, since we would loose messages
! 574: * we parse
! 575: */
1.3 ratchov 576: abuf_rdiscard(ibuf, icount);
1.40 ! ratchov 577: midi_flush(p);
1.3 ratchov 578: return 1;
579: }
580:
581: int
1.40 ! ratchov 582: midi_out(struct aproc *p, struct abuf *obuf)
1.3 ratchov 583: {
584: return 0;
585: }
586:
587: void
1.40 ! ratchov 588: midi_eof(struct aproc *p, struct abuf *ibuf)
1.3 ratchov 589: {
1.39 ratchov 590: if ((p->flags & APROC_QUIT) && LIST_EMPTY(&p->ins))
1.13 ratchov 591: aproc_del(p);
1.3 ratchov 592: }
593:
594: void
1.40 ! ratchov 595: midi_hup(struct aproc *p, struct abuf *obuf)
1.3 ratchov 596: {
1.39 ratchov 597: if ((p->flags & APROC_QUIT) && LIST_EMPTY(&p->ins))
1.13 ratchov 598: aproc_del(p);
1.3 ratchov 599: }
600:
601: void
1.40 ! ratchov 602: midi_newin(struct aproc *p, struct abuf *ibuf)
1.3 ratchov 603: {
1.10 ratchov 604: ibuf->r.midi.used = 0;
605: ibuf->r.midi.len = 0;
606: ibuf->r.midi.idx = 0;
607: ibuf->r.midi.st = 0;
1.40 ! ratchov 608: ibuf->tickets = MIDITHRU_XFER;
! 609: }
! 610:
! 611: void
! 612: midi_done(struct aproc *p)
! 613: {
! 614: timo_del(&p->u.midi.timo);
1.3 ratchov 615: }
616:
1.40 ! ratchov 617: struct aproc_ops midi_ops = {
! 618: "midi",
! 619: midi_in,
! 620: midi_out,
! 621: midi_eof,
! 622: midi_hup,
! 623: midi_newin,
1.3 ratchov 624: NULL, /* newout */
625: NULL, /* ipos */
626: NULL, /* opos */
1.40 ! ratchov 627: midi_done,
1.3 ratchov 628: };
629:
630: struct aproc *
1.40 ! ratchov 631: midi_new(char *name, struct dev *dev)
1.3 ratchov 632: {
633: struct aproc *p;
634:
1.40 ! ratchov 635: p = aproc_new(&midi_ops, name);
! 636: timo_set(&p->u.midi.timo, midi_cb, p);
! 637: timo_add(&p->u.midi.timo, MIDITHRU_TIMO);
! 638: p->u.midi.dev = dev;
1.1 ratchov 639: return p;
640: }