-/* $OpenBSD: dev.c,v 1.92 2021/03/03 10:00:27 ratchov Exp $ */
+/* $OpenBSD: dev.c,v 1.93 2021/03/03 10:13:06 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
void zomb_eof(void *);
void zomb_exit(void *);
-void dev_log(struct dev *);
void dev_midi_qfr(struct dev *, int);
void dev_midi_full(struct dev *);
void dev_midi_vol(struct dev *, struct slot *);
void dev_midi_master(struct dev *);
void dev_midi_slotdesc(struct dev *, struct slot *);
void dev_midi_dump(struct dev *);
-void dev_midi_imsg(void *, unsigned char *, int);
-void dev_midi_omsg(void *, unsigned char *, int);
-void dev_midi_fill(void *, int);
-void dev_midi_exit(void *);
void dev_mix_badd(struct dev *, struct slot *);
void dev_mix_adjvol(struct dev *);
unsigned int dev_roundof(struct dev *, unsigned int);
void dev_wakeup(struct dev *);
void dev_sync_attach(struct dev *);
-void dev_mmcstart(struct dev *);
-void dev_mmcstop(struct dev *);
-void dev_mmcloc(struct dev *, unsigned int);
void slot_ctlname(struct slot *, char *, size_t);
void slot_log(struct slot *);
void ctl_node_log(struct ctl_node *);
void ctl_log(struct ctl *);
-struct midiops dev_midiops = {
- dev_midi_imsg,
- dev_midi_omsg,
- dev_midi_fill,
- dev_midi_exit
-};
-
struct slotops zomb_slotops = {
zomb_onmove,
zomb_onvol,
#endif
}
+/*
+ * Broadcast MIDI data to all opts using this device
+ */
+void
+dev_midi_send(struct dev *d, void *msg, int msglen)
+{
+ struct opt *o;
+
+ for (o = opt_list; o != NULL; o = o->next) {
+ if (o->dev != d)
+ continue;
+ midi_send(o->midi, msg, msglen);
+ }
+}
+
/*
* send a quarter frame MTC message
*/
buf[1] = (d->mtc.qfr << 4) | data;
d->mtc.qfr++;
d->mtc.qfr &= 7;
- midi_send(d->midi, buf, 2);
+ dev_midi_send(d, buf, 2);
d->mtc.delta -= qfrlen;
}
}
x.u.full.fr = d->mtc.fr;
x.u.full.end = SYSEX_END;
d->mtc.qfr = 0;
- midi_send(d->midi, (unsigned char *)&x, SYSEX_SIZE(full));
+ dev_midi_send(d, (unsigned char *)&x, SYSEX_SIZE(full));
}
/*
msg[0] = MIDI_CTL | (s - slot_array);
msg[1] = MIDI_CTL_VOL;
msg[2] = s->vol;
- midi_send(d->midi, msg, 3);
+ dev_midi_send(d, msg, 3);
}
/*
x.u.master.fine = 0;
x.u.master.coarse = master;
x.u.master.end = SYSEX_END;
- midi_send(d->midi, (unsigned char *)&x, SYSEX_SIZE(master));
+ dev_midi_send(d, (unsigned char *)&x, SYSEX_SIZE(master));
}
/*
slot_ctlname(s, (char *)x.u.slotdesc.name, SYSEX_NAMELEN);
x.u.slotdesc.chan = (s - slot_array);
x.u.slotdesc.end = SYSEX_END;
- midi_send(d->midi, (unsigned char *)&x, SYSEX_SIZE(slotdesc));
+ dev_midi_send(d, (unsigned char *)&x, SYSEX_SIZE(slotdesc));
}
void
x.id0 = SYSEX_AUCAT;
x.id1 = SYSEX_AUCAT_DUMPEND;
x.u.dumpend.end = SYSEX_END;
- midi_send(d->midi, (unsigned char *)&x, SYSEX_SIZE(dumpend));
-}
-
-void
-dev_midi_imsg(void *arg, unsigned char *msg, int len)
-{
-#ifdef DEBUG
- struct dev *d = arg;
-
- dev_log(d);
- log_puts(": can't receive midi messages\n");
- panic();
-#endif
-}
-
-void
-dev_midi_omsg(void *arg, unsigned char *msg, int len)
-{
- struct dev *d = arg;
- struct sysex *x;
- unsigned int fps, chan;
-
- if ((msg[0] & MIDI_CMDMASK) == MIDI_CTL && msg[1] == MIDI_CTL_VOL) {
- chan = msg[0] & MIDI_CHANMASK;
- if (chan >= DEV_NSLOT)
- return;
- if (slot_array[chan].opt == NULL ||
- slot_array[chan].opt->dev != d)
- return;
- slot_setvol(slot_array + chan, msg[2]);
- ctl_onval(CTL_SLOT_LEVEL, slot_array + chan, NULL, msg[2]);
- return;
- }
- x = (struct sysex *)msg;
- if (x->start != SYSEX_START)
- return;
- if (len < SYSEX_SIZE(empty))
- return;
- switch (x->type) {
- case SYSEX_TYPE_RT:
- if (x->id0 == SYSEX_CONTROL && x->id1 == SYSEX_MASTER) {
- if (len == SYSEX_SIZE(master)) {
- dev_master(d, x->u.master.coarse);
- if (d->master_enabled) {
- ctl_onval(CTL_DEV_MASTER, d, NULL,
- x->u.master.coarse);
- }
- }
- return;
- }
- if (x->id0 != SYSEX_MMC)
- return;
- switch (x->id1) {
- case SYSEX_MMC_STOP:
- if (len != SYSEX_SIZE(stop))
- return;
- if (log_level >= 2) {
- dev_log(d);
- log_puts(": mmc stop\n");
- }
- dev_mmcstop(d);
- break;
- case SYSEX_MMC_START:
- if (len != SYSEX_SIZE(start))
- return;
- if (log_level >= 2) {
- dev_log(d);
- log_puts(": mmc start\n");
- }
- dev_mmcstart(d);
- break;
- case SYSEX_MMC_LOC:
- if (len != SYSEX_SIZE(loc) ||
- x->u.loc.len != SYSEX_MMC_LOC_LEN ||
- x->u.loc.cmd != SYSEX_MMC_LOC_CMD)
- return;
- switch (x->u.loc.hr >> 5) {
- case MTC_FPS_24:
- fps = 24;
- break;
- case MTC_FPS_25:
- fps = 25;
- break;
- case MTC_FPS_30:
- fps = 30;
- break;
- default:
- dev_mmcstop(d);
- return;
- }
- dev_mmcloc(d,
- (x->u.loc.hr & 0x1f) * 3600 * MTC_SEC +
- x->u.loc.min * 60 * MTC_SEC +
- x->u.loc.sec * MTC_SEC +
- x->u.loc.fr * (MTC_SEC / fps));
- break;
- }
- break;
- case SYSEX_TYPE_EDU:
- if (x->id0 != SYSEX_AUCAT || x->id1 != SYSEX_AUCAT_DUMPREQ)
- return;
- if (len != SYSEX_SIZE(dumpreq))
- return;
- dev_midi_dump(d);
- break;
- }
-}
-
-void
-dev_midi_fill(void *arg, int count)
-{
- /* nothing to do */
-}
-
-void
-dev_midi_exit(void *arg)
-{
- struct dev *d = arg;
-
- if (log_level >= 1) {
- dev_log(d);
- log_puts(": midi end point died\n");
- }
- if (d->pstate != DEV_CFG)
- dev_close(d);
+ dev_midi_send(d, (unsigned char *)&x, SYSEX_SIZE(dumpend));
}
int
d->num = dev_sndnum++;
d->alt_num = -1;
- /*
- * XXX: below, we allocate a midi input buffer, since we don't
- * receive raw midi data, so no need to allocate a input
- * ibuf. Possibly set imsg & fill callbacks to NULL and
- * use this to in midi_new() to check if buffers need to be
- * allocated
- */
- d->midi = midi_new(&dev_midiops, d, MODE_MIDIIN | MODE_MIDIOUT);
- midi_tag(d->midi, d->num);
d->reqpar = *par;
d->reqmode = mode;
d->reqpchan = d->reqrchan = 0;
int i;
struct slot *s;
struct ctlslot *c;
+ struct opt *o;
for (i = 0, s = slot_array; i < DEV_NSLOT; i++, s++) {
if (s->opt == NULL || s->opt->dev != d)
c->ops = NULL;
}
- midi_abort(d->midi);
+ for (o = opt_list; o != NULL; o = o->next) {
+ if (o->dev != d)
+ continue;
+ midi_abort(o->midi);
+ }
if (d->pstate != DEV_CFG)
dev_close(d);
}
#endif
}
- midi_del(d->midi);
*p = d->next;
while ((a = d->alt_list) != NULL) {
d->alt_list = a->next;
-/* $OpenBSD: opt.c,v 1.6 2021/01/29 11:25:05 ratchov Exp $ */
+/* $OpenBSD: opt.c,v 1.7 2021/03/03 10:13:06 ratchov Exp $ */
/*
* Copyright (c) 2008-2011 Alexandre Ratchov <alex@caoua.org>
*
#include <string.h>
#include "dev.h"
+#include "midi.h"
#include "opt.h"
+#include "sysex.h"
#include "utils.h"
struct opt *opt_list;
+void opt_midi_imsg(void *, unsigned char *, int);
+void opt_midi_omsg(void *, unsigned char *, int);
+void opt_midi_fill(void *, int);
+void opt_midi_exit(void *);
+
+struct midiops opt_midiops = {
+ opt_midi_imsg,
+ opt_midi_omsg,
+ opt_midi_fill,
+ opt_midi_exit
+};
+
+void
+opt_midi_imsg(void *arg, unsigned char *msg, int len)
+{
+#ifdef DEBUG
+ struct opt *o = arg;
+
+ log_puts(o->name);
+ log_puts(": can't receive midi messages\n");
+ panic();
+#endif
+}
+
+void
+opt_midi_omsg(void *arg, unsigned char *msg, int len)
+{
+ struct opt *o = arg;
+ struct sysex *x;
+ unsigned int fps, chan;
+
+ if ((msg[0] & MIDI_CMDMASK) == MIDI_CTL && msg[1] == MIDI_CTL_VOL) {
+ chan = msg[0] & MIDI_CHANMASK;
+ if (chan >= DEV_NSLOT)
+ return;
+ if (slot_array[chan].opt == NULL ||
+ slot_array[chan].opt->dev != o->dev)
+ return;
+ slot_setvol(slot_array + chan, msg[2]);
+ ctl_onval(CTL_SLOT_LEVEL, slot_array + chan, NULL, msg[2]);
+ return;
+ }
+ x = (struct sysex *)msg;
+ if (x->start != SYSEX_START)
+ return;
+ if (len < SYSEX_SIZE(empty))
+ return;
+ switch (x->type) {
+ case SYSEX_TYPE_RT:
+ if (x->id0 == SYSEX_CONTROL && x->id1 == SYSEX_MASTER) {
+ if (len == SYSEX_SIZE(master)) {
+ dev_master(o->dev, x->u.master.coarse);
+ if (o->dev->master_enabled) {
+ ctl_onval(CTL_DEV_MASTER, o->dev, NULL,
+ x->u.master.coarse);
+ }
+ }
+ return;
+ }
+ if (x->id0 != SYSEX_MMC)
+ return;
+ switch (x->id1) {
+ case SYSEX_MMC_STOP:
+ if (len != SYSEX_SIZE(stop))
+ return;
+ if (!o->mmc)
+ return;
+ if (log_level >= 2) {
+ log_puts(o->name);
+ log_puts(": mmc stop\n");
+ }
+ dev_mmcstop(o->dev);
+ break;
+ case SYSEX_MMC_START:
+ if (len != SYSEX_SIZE(start))
+ return;
+ if (!o->mmc)
+ return;
+ if (log_level >= 2) {
+ log_puts(o->name);
+ log_puts(": mmc start\n");
+ }
+ dev_mmcstart(o->dev);
+ break;
+ case SYSEX_MMC_LOC:
+ if (len != SYSEX_SIZE(loc) ||
+ x->u.loc.len != SYSEX_MMC_LOC_LEN ||
+ x->u.loc.cmd != SYSEX_MMC_LOC_CMD)
+ return;
+ if (!o->mmc)
+ return;
+ switch (x->u.loc.hr >> 5) {
+ case MTC_FPS_24:
+ fps = 24;
+ break;
+ case MTC_FPS_25:
+ fps = 25;
+ break;
+ case MTC_FPS_30:
+ fps = 30;
+ break;
+ default:
+ dev_mmcstop(o->dev);
+ return;
+ }
+ dev_mmcloc(o->dev,
+ (x->u.loc.hr & 0x1f) * 3600 * MTC_SEC +
+ x->u.loc.min * 60 * MTC_SEC +
+ x->u.loc.sec * MTC_SEC +
+ x->u.loc.fr * (MTC_SEC / fps));
+ break;
+ }
+ break;
+ case SYSEX_TYPE_EDU:
+ if (x->id0 != SYSEX_AUCAT || x->id1 != SYSEX_AUCAT_DUMPREQ)
+ return;
+ if (len != SYSEX_SIZE(dumpreq))
+ return;
+ dev_midi_dump(o->dev);
+ break;
+ }
+}
+
+void
+opt_midi_fill(void *arg, int count)
+{
+ /* nothing to do */
+}
+
+void
+opt_midi_exit(void *arg)
+{
+ struct opt *o = arg;
+
+ if (log_level >= 1) {
+ log_puts(o->name);
+ log_puts(": midi end point died\n");
+ panic();
+ }
+}
+
/*
* create a new audio sub-device "configuration"
*/
o = xmalloc(sizeof(struct opt));
o->num = num;
o->dev = d;
+
+ /*
+ * XXX: below, we allocate a midi input buffer, since we don't
+ * receive raw midi data, so no need to allocate a input
+ * ibuf. Possibly set imsg & fill callbacks to NULL and
+ * use this to in midi_new() to check if buffers need to be
+ * allocated
+ */
+ o->midi = midi_new(&opt_midiops, o, MODE_MIDIIN | MODE_MIDIOUT);
+ midi_tag(o->midi, o->num);
+
if (mode & MODE_PLAY) {
o->pmin = pmin;
o->pmax = pmax;
}
#endif
}
+ midi_del(o->midi);
*po = o->next;
xfree(o);
}