Move MIDI control endpoint to opt structure

This commit is contained in:
Alexandre Ratchov 2021-01-27 17:57:05 +01:00
parent bb27629080
commit ada702087d
6 changed files with 210 additions and 172 deletions

View File

@ -55,23 +55,26 @@ sndiod: ${OBJS}
abuf.o: abuf.c abuf.h utils.h
dev.o: dev.c ../bsd-compat/bsd-compat.h abuf.h defs.h dev.h \
dsp.h siofile.h file.h midi.h miofile.h sysex.h utils.h
dsp.h siofile.h file.h dev_sioctl.h opt.h midi.h \
miofile.h sysex.h utils.h
dev_sioctl.o: dev_sioctl.c abuf.h defs.h dev.h dsp.h siofile.h file.h \
utils.h
dev_sioctl.h opt.h utils.h ../bsd-compat/bsd-compat.h
dsp.o: dsp.c dsp.h defs.h utils.h
file.o: file.c file.h utils.h
file.o: file.c ../bsd-compat/bsd-compat.h file.h utils.h
listen.o: listen.c listen.h file.h sock.h ../libsndio/amsg.h \
utils.h ../bsd-compat/bsd-compat.h
midi.o: midi.c abuf.h defs.h dev.h dsp.h siofile.h file.h midi.h \
miofile.h sysex.h utils.h ../bsd-compat/bsd-compat.h
midi.o: midi.c abuf.h defs.h dev.h dsp.h siofile.h file.h \
dev_sioctl.h opt.h midi.h miofile.h sysex.h utils.h \
../bsd-compat/bsd-compat.h
miofile.o: miofile.c defs.h file.h midi.h abuf.h miofile.h utils.h
opt.o: opt.c dev.h abuf.h dsp.h defs.h siofile.h file.h opt.h \
utils.h
opt.o: opt.c dev.h abuf.h dsp.h defs.h siofile.h file.h \
dev_sioctl.h opt.h midi.h miofile.h sysex.h utils.h
siofile.o: siofile.c abuf.h defs.h dev.h dsp.h siofile.h file.h \
utils.h
dev_sioctl.h opt.h utils.h
sndiod.o: sndiod.c ../libsndio/amsg.h defs.h dev.h abuf.h dsp.h \
siofile.h file.h listen.h midi.h miofile.h opt.h sock.h \
utils.h ../bsd-compat/bsd-compat.h
sock.o: sock.c abuf.h defs.h dev.h dsp.h siofile.h file.h midi.h \
miofile.h opt.h sock.h ../libsndio/amsg.h utils.h
siofile.h file.h dev_sioctl.h opt.h listen.h midi.h \
miofile.h sock.h utils.h ../bsd-compat/bsd-compat.h
sock.o: sock.c abuf.h defs.h dev.h dsp.h siofile.h file.h \
dev_sioctl.h opt.h midi.h miofile.h sock.h \
../libsndio/amsg.h utils.h ../bsd-compat/bsd-compat.h
utils.o: utils.c utils.h

View File

@ -35,17 +35,12 @@ void zomb_flush(void *);
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 *);
@ -72,9 +67,6 @@ void dev_setalt(struct dev *, unsigned int);
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 *);
@ -91,13 +83,6 @@ int slot_skip(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,
@ -224,6 +209,21 @@ zomb_exit(void *arg)
#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
*/
@ -289,7 +289,7 @@ dev_midi_qfr(struct dev *d, int delta)
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;
}
}
@ -341,7 +341,7 @@ dev_midi_full(struct dev *d)
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));
}
/*
@ -355,7 +355,7 @@ dev_midi_vol(struct dev *d, struct slot *s)
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);
}
/*
@ -395,7 +395,7 @@ dev_midi_master(struct dev *d)
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));
}
/*
@ -416,7 +416,7 @@ dev_midi_slotdesc(struct dev *d, struct slot *s)
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
@ -439,131 +439,7 @@ dev_midi_dump(struct dev *d)
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
@ -1053,15 +929,6 @@ dev_new(char *path, struct aparams *par,
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;
@ -1270,6 +1137,7 @@ dev_abort(struct dev *d)
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)
@ -1290,7 +1158,11 @@ dev_abort(struct 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);
@ -1517,7 +1389,6 @@ dev_del(struct dev *d)
}
#endif
}
midi_del(d->midi);
*p = d->next;
while ((a = d->alt_list) != NULL) {
d->alt_list = a->next;

View File

@ -21,6 +21,7 @@
#include "dsp.h"
#include "siofile.h"
#include "dev_sioctl.h"
#include "opt.h"
/*
* preallocated audio clients
@ -181,7 +182,6 @@ struct ctlslot {
struct dev {
struct dev *next;
struct slot *slot_list; /* audio streams attached */
struct midi *midi;
/*
* name used for various controls
@ -305,11 +305,16 @@ void dev_cycle(struct dev *);
/*
* midi & midi call-backs
*/
void dev_master(struct dev *, unsigned int);
void dev_midi_send(struct dev *, void *, int);
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_mmcstart(struct dev *);
void dev_mmcstop(struct dev *);
void dev_mmcloc(struct dev *, unsigned int);
void dev_master(struct dev *, unsigned int);
void dev_midi_vol(struct dev *, struct slot *);
/*
* sio_open(3) like interface for clients

View File

@ -17,11 +17,154 @@
#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"
*/
@ -66,6 +209,17 @@ opt_new(struct dev *d, char *name,
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;
@ -144,6 +298,7 @@ opt_del(struct opt *o)
}
#endif
}
midi_del(o->midi);
*po = o->next;
xfree(o);
}

View File

@ -24,6 +24,7 @@ struct dev;
struct opt {
struct opt *next;
struct dev *dev;
struct midi *midi;
int num;
#define OPT_NAMEMAX 11
char name[OPT_NAMEMAX + 1];

View File

@ -869,9 +869,12 @@ sock_hello(struct sock *f)
d = dev_bynum(p->devnum);
if (d == NULL)
return 0;
opt = opt_byname(d, p->opt);
if (opt == NULL)
return 0;
if (!dev_ref(d))
return 0;
midi_tag(f->midi, p->devnum);
midi_tag(f->midi, opt->num);
} else if (p->devnum < 32) {
midi_tag(f->midi, p->devnum);
} else if (p->devnum < 48) {