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

Annotation of src/usr.bin/sndiod/opt.c, Revision 1.8

1.8     ! ratchov     1: /*     $OpenBSD: opt.c,v 1.7 2021/03/03 10:13:06 ratchov Exp $ */
1.1       ratchov     2: /*
                      3:  * Copyright (c) 2008-2011 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: #include <string.h>
                     18:
                     19: #include "dev.h"
1.7       ratchov    20: #include "midi.h"
1.1       ratchov    21: #include "opt.h"
1.7       ratchov    22: #include "sysex.h"
1.1       ratchov    23: #include "utils.h"
                     24:
1.5       ratchov    25: struct opt *opt_list;
                     26:
1.7       ratchov    27: void opt_midi_imsg(void *, unsigned char *, int);
                     28: void opt_midi_omsg(void *, unsigned char *, int);
                     29: void opt_midi_fill(void *, int);
                     30: void opt_midi_exit(void *);
                     31:
                     32: struct midiops opt_midiops = {
                     33:        opt_midi_imsg,
                     34:        opt_midi_omsg,
                     35:        opt_midi_fill,
                     36:        opt_midi_exit
                     37: };
                     38:
                     39: void
                     40: opt_midi_imsg(void *arg, unsigned char *msg, int len)
                     41: {
                     42: #ifdef DEBUG
                     43:        struct opt *o = arg;
                     44:
                     45:        log_puts(o->name);
                     46:        log_puts(": can't receive midi messages\n");
                     47:        panic();
                     48: #endif
                     49: }
                     50:
                     51: void
                     52: opt_midi_omsg(void *arg, unsigned char *msg, int len)
                     53: {
                     54:        struct opt *o = arg;
                     55:        struct sysex *x;
                     56:        unsigned int fps, chan;
                     57:
                     58:        if ((msg[0] & MIDI_CMDMASK) == MIDI_CTL && msg[1] == MIDI_CTL_VOL) {
                     59:                chan = msg[0] & MIDI_CHANMASK;
                     60:                if (chan >= DEV_NSLOT)
                     61:                        return;
                     62:                if (slot_array[chan].opt == NULL ||
                     63:                    slot_array[chan].opt->dev != o->dev)
                     64:                        return;
                     65:                slot_setvol(slot_array + chan, msg[2]);
                     66:                ctl_onval(CTL_SLOT_LEVEL, slot_array + chan, NULL, msg[2]);
                     67:                return;
                     68:        }
                     69:        x = (struct sysex *)msg;
                     70:        if (x->start != SYSEX_START)
                     71:                return;
                     72:        if (len < SYSEX_SIZE(empty))
                     73:                return;
                     74:        switch (x->type) {
                     75:        case SYSEX_TYPE_RT:
                     76:                if (x->id0 == SYSEX_CONTROL && x->id1 == SYSEX_MASTER) {
                     77:                        if (len == SYSEX_SIZE(master)) {
                     78:                                dev_master(o->dev, x->u.master.coarse);
                     79:                                if (o->dev->master_enabled) {
                     80:                                        ctl_onval(CTL_DEV_MASTER, o->dev, NULL,
                     81:                                           x->u.master.coarse);
                     82:                                }
                     83:                        }
                     84:                        return;
                     85:                }
                     86:                if (x->id0 != SYSEX_MMC)
                     87:                        return;
                     88:                switch (x->id1) {
                     89:                case SYSEX_MMC_STOP:
                     90:                        if (len != SYSEX_SIZE(stop))
                     91:                                return;
1.8     ! ratchov    92:                        if (o->mtc == NULL)
1.7       ratchov    93:                                return;
                     94:                        if (log_level >= 2) {
                     95:                                log_puts(o->name);
                     96:                                log_puts(": mmc stop\n");
                     97:                        }
1.8     ! ratchov    98:                        mtc_stop(o->mtc);
1.7       ratchov    99:                        break;
                    100:                case SYSEX_MMC_START:
                    101:                        if (len != SYSEX_SIZE(start))
                    102:                                return;
1.8     ! ratchov   103:                        if (o->mtc == NULL)
1.7       ratchov   104:                                return;
                    105:                        if (log_level >= 2) {
                    106:                                log_puts(o->name);
                    107:                                log_puts(": mmc start\n");
                    108:                        }
1.8     ! ratchov   109:                        mtc_start(o->mtc);
1.7       ratchov   110:                        break;
                    111:                case SYSEX_MMC_LOC:
                    112:                        if (len != SYSEX_SIZE(loc) ||
                    113:                            x->u.loc.len != SYSEX_MMC_LOC_LEN ||
                    114:                            x->u.loc.cmd != SYSEX_MMC_LOC_CMD)
                    115:                                return;
1.8     ! ratchov   116:                        if (o->mtc == NULL)
1.7       ratchov   117:                                return;
                    118:                        switch (x->u.loc.hr >> 5) {
                    119:                        case MTC_FPS_24:
                    120:                                fps = 24;
                    121:                                break;
                    122:                        case MTC_FPS_25:
                    123:                                fps = 25;
                    124:                                break;
                    125:                        case MTC_FPS_30:
                    126:                                fps = 30;
                    127:                                break;
                    128:                        default:
1.8     ! ratchov   129:                                mtc_stop(o->mtc);
1.7       ratchov   130:                                return;
                    131:                        }
1.8     ! ratchov   132:                        mtc_loc(o->mtc,
1.7       ratchov   133:                            (x->u.loc.hr & 0x1f) * 3600 * MTC_SEC +
                    134:                             x->u.loc.min * 60 * MTC_SEC +
                    135:                             x->u.loc.sec * MTC_SEC +
                    136:                             x->u.loc.fr * (MTC_SEC / fps));
                    137:                        break;
                    138:                }
                    139:                break;
                    140:        case SYSEX_TYPE_EDU:
                    141:                if (x->id0 != SYSEX_AUCAT || x->id1 != SYSEX_AUCAT_DUMPREQ)
                    142:                        return;
                    143:                if (len != SYSEX_SIZE(dumpreq))
                    144:                        return;
                    145:                dev_midi_dump(o->dev);
                    146:                break;
                    147:        }
                    148: }
                    149:
                    150: void
                    151: opt_midi_fill(void *arg, int count)
                    152: {
                    153:        /* nothing to do */
                    154: }
                    155:
                    156: void
                    157: opt_midi_exit(void *arg)
                    158: {
                    159:        struct opt *o = arg;
                    160:
                    161:        if (log_level >= 1) {
                    162:                log_puts(o->name);
                    163:                log_puts(": midi end point died\n");
                    164:                panic();
                    165:        }
                    166: }
                    167:
1.1       ratchov   168: /*
                    169:  * create a new audio sub-device "configuration"
                    170:  */
                    171: struct opt *
1.4       ratchov   172: opt_new(struct dev *d, char *name,
1.1       ratchov   173:     int pmin, int pmax, int rmin, int rmax,
                    174:     int maxweight, int mmc, int dup, unsigned int mode)
                    175: {
1.6       ratchov   176:        struct opt *o, **po;
                    177:        unsigned int len, num;
1.1       ratchov   178:        char c;
                    179:
                    180:        for (len = 0; name[len] != '\0'; len++) {
                    181:                if (len == OPT_NAMEMAX) {
1.3       ratchov   182:                        log_puts(name);
                    183:                        log_puts(": too long\n");
                    184:                        return NULL;
1.1       ratchov   185:                }
                    186:                c = name[len];
                    187:                if ((c < 'a' || c > 'z') &&
                    188:                    (c < 'A' || c > 'Z')) {
1.3       ratchov   189:                        log_puts(name);
                    190:                        log_puts(": only alphabetic chars allowed\n");
                    191:                        return NULL;
1.1       ratchov   192:                }
                    193:        }
1.6       ratchov   194:        num = 0;
                    195:        for (po = &opt_list; *po != NULL; po = &(*po)->next)
                    196:                num++;
                    197:        if (num >= OPT_NMAX) {
                    198:                log_puts(name);
                    199:                log_puts(": too many opts\n");
                    200:                return NULL;
                    201:        }
                    202:        if (opt_byname(d, name)) {
                    203:                dev_log(d);
                    204:                log_puts(".");
                    205:                log_puts(name);
                    206:                log_puts(": already defined\n");
                    207:                return NULL;
                    208:        }
1.8     ! ratchov   209:
        !           210:        if (mmc) {
        !           211:                if (mtc_array[0].dev != NULL && mtc_array[0].dev != d) {
        !           212:                        log_puts(name);
        !           213:                        log_puts(": MTC already setup for another device\n");
        !           214:                        return NULL;
        !           215:                }
        !           216:                mtc_array[0].dev = d;
        !           217:                if (log_level >= 2) {
        !           218:                        dev_log(d);
        !           219:                        log_puts(": initial MTC source, controlled by MMC\n");
        !           220:                }
        !           221:        }
        !           222:
1.1       ratchov   223:        o = xmalloc(sizeof(struct opt));
1.6       ratchov   224:        o->num = num;
1.5       ratchov   225:        o->dev = d;
1.7       ratchov   226:
                    227:        /*
                    228:         * XXX: below, we allocate a midi input buffer, since we don't
                    229:         *      receive raw midi data, so no need to allocate a input
                    230:         *      ibuf.  Possibly set imsg & fill callbacks to NULL and
                    231:         *      use this to in midi_new() to check if buffers need to be
                    232:         *      allocated
                    233:         */
                    234:        o->midi = midi_new(&opt_midiops, o, MODE_MIDIIN | MODE_MIDIOUT);
                    235:        midi_tag(o->midi, o->num);
                    236:
1.1       ratchov   237:        if (mode & MODE_PLAY) {
                    238:                o->pmin = pmin;
                    239:                o->pmax = pmax;
                    240:        }
                    241:        if (mode & MODE_RECMASK) {
                    242:                o->rmin = rmin;
                    243:                o->rmax = rmax;
                    244:        }
                    245:        o->maxweight = maxweight;
1.8     ! ratchov   246:        o->mtc = mmc ? &mtc_array[0] : NULL;
1.1       ratchov   247:        o->dup = dup;
                    248:        o->mode = mode;
                    249:        memcpy(o->name, name, len + 1);
1.6       ratchov   250:        o->next = *po;
                    251:        *po = o;
1.1       ratchov   252:        if (log_level >= 2) {
1.4       ratchov   253:                dev_log(d);
1.1       ratchov   254:                log_puts(".");
                    255:                log_puts(o->name);
                    256:                log_puts(":");
                    257:                if (o->mode & MODE_REC) {
                    258:                        log_puts(" rec=");
                    259:                        log_putu(o->rmin);
                    260:                        log_puts(":");
                    261:                        log_putu(o->rmax);
                    262:                }
                    263:                if (o->mode & MODE_PLAY) {
                    264:                        log_puts(" play=");
                    265:                        log_putu(o->pmin);
                    266:                        log_puts(":");
                    267:                        log_putu(o->pmax);
                    268:                        log_puts(" vol=");
                    269:                        log_putu(o->maxweight);
                    270:                }
                    271:                if (o->mode & MODE_MON) {
                    272:                        log_puts(" mon=");
                    273:                        log_putu(o->rmin);
                    274:                        log_puts(":");
                    275:                        log_putu(o->rmax);
                    276:                }
                    277:                if (o->mode & (MODE_RECMASK | MODE_PLAY)) {
1.8     ! ratchov   278:                        if (o->mtc)
        !           279:                                log_puts(" mtc");
1.1       ratchov   280:                        if (o->dup)
                    281:                                log_puts(" dup");
                    282:                }
                    283:                log_puts("\n");
                    284:        }
                    285:        return o;
                    286: }
                    287:
                    288: struct opt *
1.4       ratchov   289: opt_byname(struct dev *d, char *name)
1.1       ratchov   290: {
                    291:        struct opt *o;
                    292:
1.5       ratchov   293:        for (o = opt_list; o != NULL; o = o->next) {
                    294:                if (d != NULL && o->dev != d)
                    295:                        continue;
1.1       ratchov   296:                if (strcmp(name, o->name) == 0)
                    297:                        return o;
                    298:        }
                    299:        return NULL;
                    300: }
                    301:
                    302: void
1.5       ratchov   303: opt_del(struct opt *o)
1.1       ratchov   304: {
                    305:        struct opt **po;
                    306:
1.5       ratchov   307:        for (po = &opt_list; *po != o; po = &(*po)->next) {
1.1       ratchov   308: #ifdef DEBUG
                    309:                if (*po == NULL) {
                    310:                        log_puts("opt_del: not on list\n");
                    311:                        panic();
                    312:                }
                    313: #endif
                    314:        }
1.7       ratchov   315:        midi_del(o->midi);
1.1       ratchov   316:        *po = o->next;
                    317:        xfree(o);
                    318: }