[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.41

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