[BACK]Return to midi.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / aucat

Annotation of src/usr.bin/aucat/midi.c, Revision 1.42

1.42    ! ratchov     1: /*     $OpenBSD: midi.c,v 1.41 2012/03/23 11:59:54 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.42    ! ratchov    71: unsigned int voice_len[] = { 3, 3, 3, 3, 2, 2, 3 };
        !            72: unsigned int common_len[] = { 0, 2, 3, 2, 0, 0, 1, 1 };
1.1       ratchov    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;
1.42    ! ratchov    84:        unsigned int tickets;
1.1       ratchov    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.41      ratchov   128: void
                    129: midi_msg_master(struct aproc *p, char *msg)
                    130: {
                    131:        struct sysex *x = (struct sysex *)msg;
                    132:
                    133:        memset(x, 0, sizeof(struct sysex));
                    134:        x->start = SYSEX_START;
                    135:        x->type = SYSEX_TYPE_RT;
                    136:        x->id0 = SYSEX_CONTROL;
                    137:        x->id1 = SYSEX_MASTER;
                    138:        x->u.master.fine = 0;
                    139:        x->u.master.coarse = p->u.midi.dev->master;
                    140:        x->u.master.end = SYSEX_END;
                    141: }
                    142:
1.7       ratchov   143: /*
1.33      ratchov   144:  * send a message to the given output
                    145:  */
                    146: void
1.42    ! ratchov   147: midi_copy(struct abuf *ibuf, struct abuf *obuf, unsigned char *msg,
        !           148:     unsigned int len)
1.33      ratchov   149: {
1.42    ! ratchov   150:        unsigned int ocount;
1.40      ratchov   151:        unsigned char *odata;
1.33      ratchov   152:
1.40      ratchov   153:        if (msg[0] == SYSEX_START)
                    154:                obuf->w.midi.owner = ibuf;
                    155:        while (len > 0) {
1.33      ratchov   156:                if (!ABUF_WOK(obuf)) {
                    157: #ifdef DEBUG
                    158:                        if (debug_level >= 3) {
                    159:                                abuf_dbg(obuf);
                    160:                                dbg_puts(": overrun, discarding ");
                    161:                                dbg_putu(obuf->used);
                    162:                                dbg_puts(" bytes\n");
                    163:                        }
                    164: #endif
                    165:                        abuf_rdiscard(obuf, obuf->used);
1.40      ratchov   166:                        if (obuf->w.midi.owner == ibuf)
                    167:                                obuf->w.midi.owner = NULL;
                    168:                        return;
1.33      ratchov   169:                }
                    170:                odata = abuf_wgetblk(obuf, &ocount, 0);
1.40      ratchov   171:                if (ocount > len)
                    172:                        ocount = len;
1.33      ratchov   173: #ifdef DEBUG
                    174:                if (debug_level >= 4) {
                    175:                        abuf_dbg(obuf);
                    176:                        dbg_puts(": stored ");
                    177:                        dbg_putu(ocount);
                    178:                        dbg_puts(" bytes\n");
                    179:                }
                    180: #endif
1.40      ratchov   181:                memcpy(odata, msg, ocount);
1.33      ratchov   182:                abuf_wcommit(obuf, ocount);
1.40      ratchov   183:                len -= ocount;
                    184:                msg += ocount;
                    185:        }
                    186: }
                    187:
                    188: /*
                    189:  * flush all buffers. Since most of the MIDI traffic is broadcasted to
                    190:  * all outputs, the flush is delayed to avoid flushing all outputs for
                    191:  * each message.
                    192:  */
                    193: void
                    194: midi_flush(struct aproc *p)
                    195: {
                    196:        struct abuf *i, *inext;
                    197:
                    198:        for (i = LIST_FIRST(&p->outs); i != NULL; i = inext) {
                    199:                inext = LIST_NEXT(i, oent);
                    200:                if (ABUF_ROK(i))
                    201:                        (void)abuf_flush(i);
1.33      ratchov   202:        }
                    203: }
                    204:
                    205: /*
1.7       ratchov   206:  * broadcast a message to all output buffers on the behalf of ibuf.
                    207:  * ie. don't sent back the message to the sender
                    208:  */
1.3       ratchov   209: void
1.42    ! ratchov   210: midi_send(struct aproc *p, struct abuf *ibuf, unsigned char *msg,
        !           211:     unsigned int len)
1.3       ratchov   212: {
                    213:        struct abuf *i, *inext;
                    214:
1.20      ratchov   215:        for (i = LIST_FIRST(&p->outs); i != NULL; i = inext) {
1.3       ratchov   216:                inext = LIST_NEXT(i, oent);
1.19      ratchov   217:                if (i->duplex && i->duplex == ibuf)
1.3       ratchov   218:                        continue;
1.40      ratchov   219:                midi_copy(ibuf, i, msg, len);
1.3       ratchov   220:        }
                    221: }
                    222:
1.7       ratchov   223: /*
1.13      ratchov   224:  * send a quarter frame MTC message
                    225:  */
                    226: void
1.42    ! ratchov   227: midi_send_qfr(struct aproc *p, unsigned int rate, int delta)
1.13      ratchov   228: {
                    229:        unsigned char buf[2];
1.42    ! ratchov   230:        unsigned int data;
1.39      ratchov   231:        int qfrlen;
                    232:
1.40      ratchov   233:        p->u.midi.delta += delta * MTC_SEC;
                    234:        qfrlen = rate * (MTC_SEC / (4 * p->u.midi.fps));
                    235:        while (p->u.midi.delta >= qfrlen) {
                    236:                switch (p->u.midi.qfr) {
1.39      ratchov   237:                case 0:
1.40      ratchov   238:                        data = p->u.midi.fr & 0xf;
1.39      ratchov   239:                        break;
                    240:                case 1:
1.40      ratchov   241:                        data = p->u.midi.fr >> 4;
1.39      ratchov   242:                        break;
                    243:                case 2:
1.40      ratchov   244:                        data = p->u.midi.sec & 0xf;
1.39      ratchov   245:                        break;
                    246:                case 3:
1.40      ratchov   247:                        data = p->u.midi.sec >> 4;
1.39      ratchov   248:                        break;
                    249:                case 4:
1.40      ratchov   250:                        data = p->u.midi.min & 0xf;
1.39      ratchov   251:                        break;
                    252:                case 5:
1.40      ratchov   253:                        data = p->u.midi.min >> 4;
1.39      ratchov   254:                        break;
                    255:                case 6:
1.40      ratchov   256:                        data = p->u.midi.hr & 0xf;
1.39      ratchov   257:                        break;
                    258:                case 7:
1.40      ratchov   259:                        data = (p->u.midi.hr >> 4) | (p->u.midi.fps_id << 1);
1.39      ratchov   260:                        /*
                    261:                         * tick messages are sent 2 frames ahead
                    262:                         */
1.40      ratchov   263:                        p->u.midi.fr += 2;
                    264:                        if (p->u.midi.fr < p->u.midi.fps)
1.39      ratchov   265:                                break;
1.40      ratchov   266:                        p->u.midi.fr -= p->u.midi.fps;
                    267:                        p->u.midi.sec++;
                    268:                        if (p->u.midi.sec < 60)
1.39      ratchov   269:                                break;
1.40      ratchov   270:                        p->u.midi.sec = 0;
                    271:                        p->u.midi.min++;
                    272:                        if (p->u.midi.min < 60)
1.39      ratchov   273:                                break;
1.40      ratchov   274:                        p->u.midi.min = 0;
                    275:                        p->u.midi.hr++;
                    276:                        if (p->u.midi.hr < 24)
1.39      ratchov   277:                                break;
1.40      ratchov   278:                        p->u.midi.hr = 0;
1.13      ratchov   279:                        break;
1.39      ratchov   280:                default:
                    281:                        /* NOTREACHED */
                    282:                        data = 0;
                    283:                }
                    284:                buf[0] = 0xf1;
1.40      ratchov   285:                buf[1] = (p->u.midi.qfr << 4) | data;
                    286:                p->u.midi.qfr++;
                    287:                p->u.midi.qfr &= 7;
                    288:                midi_send(p, NULL, buf, 2);
                    289:                p->u.midi.delta -= qfrlen;
1.13      ratchov   290:        }
                    291: }
                    292:
                    293: /*
                    294:  * send a full frame MTC message
                    295:  */
                    296: void
1.42    ! ratchov   297: midi_send_full(struct aproc *p, unsigned int origin, unsigned int rate,
        !           298:     unsigned int round, unsigned int pos)
1.13      ratchov   299: {
                    300:        unsigned char buf[10];
1.42    ! ratchov   301:        unsigned int fps;
1.13      ratchov   302:
1.40      ratchov   303:        p->u.midi.delta = MTC_SEC * pos;
1.39      ratchov   304:        if (rate % (30 * 4 * round) == 0) {
1.40      ratchov   305:                p->u.midi.fps_id = MTC_FPS_30;
                    306:                p->u.midi.fps = 30;
1.39      ratchov   307:        } else if (rate % (25 * 4 * round) == 0) {
1.40      ratchov   308:                p->u.midi.fps_id = MTC_FPS_25;
                    309:                p->u.midi.fps = 25;
1.39      ratchov   310:        } else {
1.40      ratchov   311:                p->u.midi.fps_id = MTC_FPS_24;
                    312:                p->u.midi.fps = 24;
1.39      ratchov   313:        }
                    314: #ifdef DEBUG
                    315:        if (debug_level >= 3) {
                    316:                aproc_dbg(p);
                    317:                dbg_puts(": mtc full frame at ");
1.40      ratchov   318:                dbg_puti(p->u.midi.delta);
1.39      ratchov   319:                dbg_puts(", ");
1.40      ratchov   320:                dbg_puti(p->u.midi.fps);
1.39      ratchov   321:                dbg_puts(" fps\n");
                    322:        }
                    323: #endif
1.40      ratchov   324:        fps = p->u.midi.fps;
                    325:        p->u.midi.hr =  (origin / (3600 * MTC_SEC)) % 24;
                    326:        p->u.midi.min = (origin / (60 * MTC_SEC))   % 60;
                    327:        p->u.midi.sec = (origin / MTC_SEC)          % 60;
                    328:        p->u.midi.fr =  (origin / (MTC_SEC / fps))  % fps;
1.13      ratchov   329:
                    330:        buf[0] = 0xf0;
                    331:        buf[1] = 0x7f;
                    332:        buf[2] = 0x7f;
                    333:        buf[3] = 0x01;
                    334:        buf[4] = 0x01;
1.40      ratchov   335:        buf[5] = p->u.midi.hr | (p->u.midi.fps_id << 5);
                    336:        buf[6] = p->u.midi.min;
                    337:        buf[7] = p->u.midi.sec;
                    338:        buf[8] = p->u.midi.fr;
1.13      ratchov   339:        buf[9] = 0xf7;
1.40      ratchov   340:        p->u.midi.qfr = 0;
                    341:        midi_send(p, NULL, buf, 10);
1.13      ratchov   342: }
                    343:
1.33      ratchov   344: void
1.40      ratchov   345: midi_copy_dump(struct aproc *p, struct abuf *obuf)
1.35      ratchov   346: {
1.42    ! ratchov   347:        unsigned int i;
1.35      ratchov   348:        unsigned char msg[sizeof(struct sysex)];
                    349:        struct ctl_slot *s;
                    350:
1.41      ratchov   351:        midi_msg_master(p, msg);
                    352:        midi_copy(NULL, obuf, msg, SYSEX_SIZE(master));
1.40      ratchov   353:        for (i = 0, s = p->u.midi.dev->slot; i < CTL_NSLOT; i++, s++) {
                    354:                midi_msg_info(p, i, msg);
                    355:                midi_copy(NULL, obuf, msg, SYSEX_SIZE(mixinfo));
                    356:                midi_msg_vol(p, i, msg);
                    357:                midi_copy(NULL, obuf, msg, 3);
1.35      ratchov   358:        }
                    359:        msg[0] = SYSEX_START;
                    360:        msg[1] = SYSEX_TYPE_EDU;
                    361:        msg[2] = 0;
                    362:        msg[3] = SYSEX_AUCAT;
                    363:        msg[4] = SYSEX_AUCAT_DUMPEND;
                    364:        msg[5] = SYSEX_END;
1.40      ratchov   365:        midi_copy(NULL, obuf, msg, 6);
1.35      ratchov   366: }
                    367:
1.13      ratchov   368: /*
1.7       ratchov   369:  * notifty the mixer that volume changed, called by whom allocad the slot using
                    370:  * ctl_slotnew(). Note: it doesn't make sens to call this from within the
                    371:  * call-back.
                    372:  */
1.3       ratchov   373: void
1.42    ! ratchov   374: midi_send_vol(struct aproc *p, int slot, unsigned int vol)
1.3       ratchov   375: {
                    376:        unsigned char msg[3];
                    377:
1.40      ratchov   378:        midi_msg_vol(p, slot, msg);
                    379:        midi_send(p, NULL, msg, 3);
1.3       ratchov   380: }
                    381:
1.13      ratchov   382: void
1.41      ratchov   383: midi_send_master(struct aproc *p)
                    384: {
                    385:        unsigned char msg[sizeof(struct sysex)];
                    386:
                    387:        midi_msg_master(p, msg);
                    388:        midi_send(p, NULL, msg, SYSEX_SIZE(master));
                    389: }
                    390:
                    391: void
1.40      ratchov   392: midi_send_slot(struct aproc *p, int slot)
1.13      ratchov   393: {
1.39      ratchov   394:        unsigned char msg[sizeof(struct sysex)];
1.13      ratchov   395:
1.40      ratchov   396:        midi_msg_info(p, slot, msg);
                    397:        midi_send(p, NULL, msg, SYSEX_SIZE(mixinfo));
1.19      ratchov   398: }
                    399:
                    400: /*
1.40      ratchov   401:  * handle a MIDI voice event received from ibuf
1.7       ratchov   402:  */
1.3       ratchov   403: void
1.40      ratchov   404: midi_onvoice(struct aproc *p, struct abuf *ibuf)
1.3       ratchov   405: {
1.40      ratchov   406:        struct ctl_slot *slot;
1.42    ! ratchov   407:        unsigned int chan;
1.14      ratchov   408: #ifdef DEBUG
1.42    ! ratchov   409:        unsigned int i;
1.14      ratchov   410:
                    411:        if (debug_level >= 3) {
                    412:                abuf_dbg(ibuf);
1.40      ratchov   413:                dbg_puts(": got voice event:");
1.14      ratchov   414:                for (i = 0; i < ibuf->r.midi.idx; i++) {
                    415:                        dbg_puts(" ");
                    416:                        dbg_putx(ibuf->r.midi.msg[i]);
                    417:                }
                    418:                dbg_puts("\n");
                    419:        }
                    420: #endif
1.10      ratchov   421:        if ((ibuf->r.midi.msg[0] & MIDI_CMDMASK) == MIDI_CTL &&
1.33      ratchov   422:            (ibuf->r.midi.msg[1] == MIDI_CTLVOL)) {
1.10      ratchov   423:                chan = ibuf->r.midi.msg[0] & MIDI_CHANMASK;
1.3       ratchov   424:                if (chan >= CTL_NSLOT)
                    425:                        return;
1.40      ratchov   426:                slot = p->u.midi.dev->slot + chan;
1.22      ratchov   427:                slot->vol = ibuf->r.midi.msg[2];
1.12      ratchov   428:                if (slot->ops == NULL)
1.3       ratchov   429:                        return;
1.12      ratchov   430:                slot->ops->vol(slot->arg, slot->vol);
1.3       ratchov   431:        }
1.40      ratchov   432: }
                    433:
                    434: /*
                    435:  * handle a MIDI sysex received from ibuf
                    436:  */
                    437: void
                    438: midi_onsysex(struct aproc *p, struct abuf *ibuf)
                    439: {
                    440:        struct sysex *x;
1.42    ! ratchov   441:        unsigned int fps, len;
1.40      ratchov   442: #ifdef DEBUG
1.42    ! ratchov   443:        unsigned int i;
1.40      ratchov   444:
                    445:        if (debug_level >= 3) {
                    446:                abuf_dbg(ibuf);
                    447:                dbg_puts(": got sysex:");
                    448:                for (i = 0; i < ibuf->r.midi.idx; i++) {
                    449:                        dbg_puts(" ");
                    450:                        dbg_putx(ibuf->r.midi.msg[i]);
                    451:                }
                    452:                dbg_puts("\n");
                    453:        }
                    454: #endif
1.33      ratchov   455:        x = (struct sysex *)ibuf->r.midi.msg;
                    456:        len = ibuf->r.midi.idx;
                    457:        if (x->start != SYSEX_START)
                    458:                return;
                    459:        if (len < SYSEX_SIZE(empty))
                    460:                return;
                    461:        switch (x->type) {
                    462:        case SYSEX_TYPE_RT:
1.41      ratchov   463:                if (x->id0 == SYSEX_CONTROL && x->id1 == SYSEX_MASTER) {
                    464:                        if (len == SYSEX_SIZE(master))
                    465:                                dev_master(p->u.midi.dev, x->u.master.coarse);
                    466:                        return;
                    467:                }
1.33      ratchov   468:                if (x->id0 != SYSEX_MMC)
                    469:                        return;
                    470:                switch (x->id1) {
                    471:                case SYSEX_MMC_STOP:
                    472:                        if (len != SYSEX_SIZE(stop))
                    473:                                return;
1.14      ratchov   474: #ifdef DEBUG
1.19      ratchov   475:                        if (debug_level >= 3) {
1.14      ratchov   476:                                abuf_dbg(ibuf);
                    477:                                dbg_puts(": mmc stop\n");
                    478:                        }
                    479: #endif
1.40      ratchov   480:                        dev_mmcstop(p->u.midi.dev);
1.13      ratchov   481:                        break;
1.33      ratchov   482:                case SYSEX_MMC_START:
                    483:                        if (len != SYSEX_SIZE(start))
                    484:                                return;
1.14      ratchov   485: #ifdef DEBUG
1.19      ratchov   486:                        if (debug_level >= 3) {
1.14      ratchov   487:                                abuf_dbg(ibuf);
                    488:                                dbg_puts(": mmc start\n");
                    489:                        }
                    490: #endif
1.40      ratchov   491:                        dev_mmcstart(p->u.midi.dev);
1.13      ratchov   492:                        break;
1.33      ratchov   493:                case SYSEX_MMC_LOC:
                    494:                        if (len != SYSEX_SIZE(loc) ||
                    495:                            x->u.loc.len != SYSEX_MMC_LOC_LEN ||
                    496:                            x->u.loc.cmd != SYSEX_MMC_LOC_CMD)
                    497:                                return;
                    498:                        switch (x->u.loc.hr >> 5) {
                    499:                        case MTC_FPS_24:
                    500:                                fps = 24;
                    501:                                break;
                    502:                        case MTC_FPS_25:
                    503:                                fps = 25;
                    504:                                break;
                    505:                        case MTC_FPS_30:
                    506:                                fps = 30;
                    507:                                break;
                    508:                        default:
1.39      ratchov   509:                                /* XXX: should dev_mmcstop() here */
1.33      ratchov   510:                                return;
                    511:                        }
1.40      ratchov   512:                        dev_loc(p->u.midi.dev,
1.33      ratchov   513:                            (x->u.loc.hr & 0x1f) * 3600 * MTC_SEC +
                    514:                             x->u.loc.min * 60 * MTC_SEC +
                    515:                             x->u.loc.sec * MTC_SEC +
                    516:                             x->u.loc.fr * (MTC_SEC / fps) +
                    517:                             x->u.loc.cent * (MTC_SEC / 100 / fps));
1.13      ratchov   518:                        break;
                    519:                }
1.35      ratchov   520:                break;
                    521:        case SYSEX_TYPE_EDU:
                    522:                if (x->id0 != SYSEX_AUCAT || x->id1 != SYSEX_AUCAT_DUMPREQ)
                    523:                        return;
                    524:                if (len != SYSEX_SIZE(dumpreq))
                    525:                        return;
                    526:                if (ibuf->duplex)
1.40      ratchov   527:                        midi_copy_dump(p, ibuf->duplex);
1.33      ratchov   528:                break;
1.13      ratchov   529:        }
1.3       ratchov   530: }
                    531:
                    532: int
1.40      ratchov   533: midi_in(struct aproc *p, struct abuf *ibuf)
1.3       ratchov   534: {
1.40      ratchov   535:        unsigned char c, *idata;
1.42    ! ratchov   536:        unsigned int i, icount;
1.3       ratchov   537:
                    538:        if (!ABUF_ROK(ibuf))
                    539:                return 0;
1.40      ratchov   540:        if (ibuf->tickets == 0) {
                    541: #ifdef DEBUG
                    542:                if (debug_level >= 4) {
                    543:                        abuf_dbg(ibuf);
                    544:                        dbg_puts(": out of tickets, blocking\n");
                    545:                }
                    546: #endif
                    547:                return 0;
                    548:        }
1.3       ratchov   549:        idata = abuf_rgetblk(ibuf, &icount, 0);
1.40      ratchov   550:        if (icount > ibuf->tickets)
                    551:                icount = ibuf->tickets;
                    552:        ibuf->tickets -= icount;
1.3       ratchov   553:        for (i = 0; i < icount; i++) {
                    554:                c = *idata++;
1.8       ratchov   555:                if (c >= 0xf8) {
1.40      ratchov   556:                        if (!p->u.midi.dev && c != MIDI_ACK)
                    557:                                midi_send(p, ibuf, &c, 1);
                    558:                } else if (c == SYSEX_END) {
                    559:                        if (ibuf->r.midi.st == SYSEX_START) {
1.10      ratchov   560:                                ibuf->r.midi.msg[ibuf->r.midi.idx++] = c;
1.40      ratchov   561:                                if (!p->u.midi.dev) {
                    562:                                        midi_send(p, ibuf,
                    563:                                            ibuf->r.midi.msg, ibuf->r.midi.idx);
                    564:                                } else
                    565:                                        midi_onsysex(p, ibuf);
1.8       ratchov   566:                        }
1.40      ratchov   567:                        ibuf->r.midi.st = 0;
                    568:                        ibuf->r.midi.idx = 0;
                    569:                } else if (c >= 0xf0) {
1.10      ratchov   570:                        ibuf->r.midi.msg[0] = c;
                    571:                        ibuf->r.midi.len = common_len[c & 7];
                    572:                        ibuf->r.midi.st = c;
                    573:                        ibuf->r.midi.idx = 1;
1.3       ratchov   574:                } else if (c >= 0x80) {
1.10      ratchov   575:                        ibuf->r.midi.msg[0] = c;
                    576:                        ibuf->r.midi.len = voice_len[(c >> 4) & 7];
                    577:                        ibuf->r.midi.st = c;
                    578:                        ibuf->r.midi.idx = 1;
                    579:                } else if (ibuf->r.midi.st) {
1.40      ratchov   580:                        if (ibuf->r.midi.idx == 0 &&
                    581:                            ibuf->r.midi.st != SYSEX_START) {
                    582:                                ibuf->r.midi.msg[ibuf->r.midi.idx++] =
                    583:                                    ibuf->r.midi.st;
                    584:                        }
1.10      ratchov   585:                        ibuf->r.midi.msg[ibuf->r.midi.idx++] = c;
                    586:                        if (ibuf->r.midi.idx == ibuf->r.midi.len) {
1.40      ratchov   587:                                if (!p->u.midi.dev) {
                    588:                                        midi_send(p, ibuf,
                    589:                                            ibuf->r.midi.msg, ibuf->r.midi.idx);
                    590:                                } else
                    591:                                        midi_onvoice(p, ibuf);
                    592:                                if (ibuf->r.midi.st >= 0xf0)
                    593:                                        ibuf->r.midi.st = 0;
                    594:                                ibuf->r.midi.idx = 0;
                    595:                        } else if (ibuf->r.midi.idx == MIDI_MSGMAX) {
                    596:                                if (!p->u.midi.dev) {
                    597:                                        midi_send(p, ibuf,
                    598:                                            ibuf->r.midi.msg, ibuf->r.midi.idx);
                    599:                                }
1.10      ratchov   600:                                ibuf->r.midi.idx = 0;
1.3       ratchov   601:                        }
                    602:                }
                    603:        }
1.40      ratchov   604:        /*
                    605:         * XXX: if the sysex is received byte by byte, partial messages
                    606:         * won't be sent until the end byte is received. On the other
                    607:         * hand we can't flush it here, since we would loose messages
                    608:         * we parse
                    609:         */
1.3       ratchov   610:        abuf_rdiscard(ibuf, icount);
1.40      ratchov   611:        midi_flush(p);
1.3       ratchov   612:        return 1;
                    613: }
                    614:
                    615: int
1.40      ratchov   616: midi_out(struct aproc *p, struct abuf *obuf)
1.3       ratchov   617: {
                    618:        return 0;
                    619: }
                    620:
                    621: void
1.40      ratchov   622: midi_eof(struct aproc *p, struct abuf *ibuf)
1.3       ratchov   623: {
1.39      ratchov   624:        if ((p->flags & APROC_QUIT) && LIST_EMPTY(&p->ins))
1.13      ratchov   625:                aproc_del(p);
1.3       ratchov   626: }
                    627:
                    628: void
1.40      ratchov   629: midi_hup(struct aproc *p, struct abuf *obuf)
1.3       ratchov   630: {
1.39      ratchov   631:        if ((p->flags & APROC_QUIT) && LIST_EMPTY(&p->ins))
1.13      ratchov   632:                aproc_del(p);
1.3       ratchov   633: }
                    634:
                    635: void
1.40      ratchov   636: midi_newin(struct aproc *p, struct abuf *ibuf)
1.3       ratchov   637: {
1.10      ratchov   638:        ibuf->r.midi.used = 0;
                    639:        ibuf->r.midi.len = 0;
                    640:        ibuf->r.midi.idx = 0;
                    641:        ibuf->r.midi.st = 0;
1.40      ratchov   642:        ibuf->tickets = MIDITHRU_XFER;
                    643: }
                    644:
                    645: void
                    646: midi_done(struct aproc *p)
                    647: {
                    648:        timo_del(&p->u.midi.timo);
1.3       ratchov   649: }
                    650:
1.40      ratchov   651: struct aproc_ops midi_ops = {
                    652:        "midi",
                    653:        midi_in,
                    654:        midi_out,
                    655:        midi_eof,
                    656:        midi_hup,
                    657:        midi_newin,
1.3       ratchov   658:        NULL, /* newout */
                    659:        NULL, /* ipos */
                    660:        NULL, /* opos */
1.40      ratchov   661:        midi_done,
1.3       ratchov   662: };
                    663:
                    664: struct aproc *
1.40      ratchov   665: midi_new(char *name, struct dev *dev)
1.3       ratchov   666: {
                    667:        struct aproc *p;
                    668:
1.40      ratchov   669:        p = aproc_new(&midi_ops, name);
                    670:        timo_set(&p->u.midi.timo, midi_cb, p);
                    671:        timo_add(&p->u.midi.timo, MIDITHRU_TIMO);
                    672:        p->u.midi.dev = dev;
1.1       ratchov   673:        return p;
                    674: }