mirror of https://github.com/ericonr/sndio.git
fix midithru subscriptions
This commit is contained in:
parent
2fd21c86fb
commit
6cb370c626
|
@ -467,13 +467,7 @@ dev_midi_omsg(void *arg, unsigned char *msg, int len)
|
|||
void
|
||||
dev_midi_fill(void *arg, int count)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
struct dev *d = arg;
|
||||
|
||||
dev_log(d);
|
||||
log_puts(": can't receive fill input\n");
|
||||
panic();
|
||||
#endif
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
void
|
||||
|
|
226
sndiod/midi.c
226
sndiod/midi.c
|
@ -61,7 +61,7 @@ struct port *port_list = NULL;
|
|||
unsigned int midi_portnum = 0;
|
||||
|
||||
struct midithru {
|
||||
unsigned txmask;
|
||||
unsigned int txmask, rxmask;
|
||||
#define MIDITHRU_NMAX 32
|
||||
} midithru[MIDITHRU_NMAX];
|
||||
|
||||
|
@ -121,18 +121,16 @@ midi_new(struct midiops *ops, void *arg, int mode)
|
|||
ep->idx = 0;
|
||||
ep->st = 0;
|
||||
ep->txmask = 0;
|
||||
ep->rxmask = 1 << i;
|
||||
ep->self = 1 << i;
|
||||
ep->tickets = 0;
|
||||
ep->mode = mode;
|
||||
|
||||
/*
|
||||
* client output is our input (ibuf) and our output (obuf) goes
|
||||
* to client input
|
||||
* the output buffer is the client intput
|
||||
*/
|
||||
if (ep->mode & MODE_MIDIOUT) {
|
||||
abuf_init(&ep->ibuf, MIDI_BUFSZ);
|
||||
}
|
||||
if (ep->mode & MODE_MIDIIN) {
|
||||
if (ep->mode & MODE_MIDIIN)
|
||||
abuf_init(&ep->obuf, MIDI_BUFSZ);
|
||||
}
|
||||
midi_tickets(ep);
|
||||
return ep;
|
||||
}
|
||||
|
||||
|
@ -140,64 +138,82 @@ void
|
|||
midi_del(struct midi *ep)
|
||||
{
|
||||
int i;
|
||||
struct midi *peer;
|
||||
|
||||
for (i = 0; i < MIDI_NEP; i++)
|
||||
midi_ep[i].txmask &= ~ep->rxmask;
|
||||
for (i = 0; i < MIDITHRU_NMAX; i++)
|
||||
midithru[i].txmask &= ~ep->rxmask;
|
||||
|
||||
/* XXX: drain output */
|
||||
ep->ops = NULL;
|
||||
if (ep->mode & MODE_MIDIOUT) {
|
||||
abuf_done(&ep->ibuf);
|
||||
ep->txmask = 0;
|
||||
for (i = 0; i < MIDI_NEP; i++) {
|
||||
peer = midi_ep + i;
|
||||
if (peer->txmask & ep->self) {
|
||||
peer->txmask &= ~ep->self;
|
||||
midi_tickets(peer);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < MIDITHRU_NMAX; i++) {
|
||||
midithru[i].txmask &= ~ep->self;
|
||||
midithru[i].rxmask &= ~ep->self;
|
||||
}
|
||||
ep->ops = NULL;
|
||||
if (ep->mode & MODE_MIDIIN) {
|
||||
abuf_done(&ep->obuf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* connect two midi endpoints
|
||||
*/
|
||||
void
|
||||
midi_link(struct midi *ep, struct midi *peer)
|
||||
{
|
||||
if (ep->mode & MODE_MIDIOUT) {
|
||||
ep->txmask |= peer->self;
|
||||
midi_tickets(ep);
|
||||
}
|
||||
if (ep->mode & MODE_MIDIIN) {
|
||||
#ifdef DEBUG
|
||||
if (ep->obuf.used > 0) {
|
||||
midi_log(ep);
|
||||
log_puts(": linked with non-empty buffer\n");
|
||||
panic();
|
||||
}
|
||||
#endif
|
||||
/* ep has empry buffer, so no need to call midi_tickets() */
|
||||
peer->txmask |= ep->self;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* add the midi endpoint in the ``tag'' midi thru box
|
||||
*/
|
||||
void
|
||||
midi_tag(struct midi *ep, unsigned int tag)
|
||||
{
|
||||
struct midi *peer;
|
||||
struct midithru *t = midithru + tag;
|
||||
int i;
|
||||
struct midi *m;
|
||||
unsigned members;
|
||||
|
||||
members = midithru[tag].txmask;
|
||||
midithru[tag].txmask |= ep->rxmask;
|
||||
|
||||
for (i = 0, m = midi_ep; i < MIDI_NEP; i++, m++) {
|
||||
if (!(members & (1 << i)))
|
||||
continue;
|
||||
if (ep->mode & MODE_MIDIOUT)
|
||||
ep->txmask |= m->rxmask;
|
||||
if (ep->mode & MODE_MIDIIN)
|
||||
m->txmask |= ep->rxmask;
|
||||
if (ep->mode & MODE_MIDIOUT) {
|
||||
ep->txmask |= t->txmask;
|
||||
midi_tickets(ep);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* remove the midi endpoint from the ``tag'' midi thru box
|
||||
*/
|
||||
void
|
||||
midi_untag(struct midi *ep, unsigned int tag)
|
||||
{
|
||||
int i;
|
||||
struct midi *m;
|
||||
unsigned members;
|
||||
|
||||
members = midithru[tag].txmask;
|
||||
midithru[tag].txmask &= ~ep->rxmask;
|
||||
|
||||
for (i = 0, m = midi_ep;; i++, m++) {
|
||||
if (!(members & (1 << i)))
|
||||
continue;
|
||||
ep->txmask &= ~m->rxmask;
|
||||
m->txmask &= ~ep->rxmask;
|
||||
if (ep->mode & MODE_MIDIIN) {
|
||||
#ifdef DEBUG
|
||||
if (ep->obuf.used > 0) {
|
||||
midi_log(ep);
|
||||
log_puts(": tagged with non-empty buffer\n");
|
||||
panic();
|
||||
}
|
||||
#endif
|
||||
for (i = 0; i < MIDI_NEP; i++) {
|
||||
if (!(t->rxmask & (1 << i)))
|
||||
continue;
|
||||
peer = midi_ep + i;
|
||||
peer->txmask |= ep->self;
|
||||
}
|
||||
}
|
||||
if (ep->mode & MODE_MIDIOUT)
|
||||
t->rxmask |= ep->self;
|
||||
if (ep->mode & MODE_MIDIIN)
|
||||
t->txmask |= ep->self;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -242,27 +258,58 @@ midi_send(struct midi *iep, unsigned char *msg, int size)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* determine if we have gained more input tickets, and if so call the
|
||||
* fill() call-back to notify the i/o layer that it can send more data
|
||||
*/
|
||||
void
|
||||
midi_fill(struct midi *oep)
|
||||
midi_tickets(struct midi *iep)
|
||||
{
|
||||
int i, count;
|
||||
struct midi *iep;
|
||||
int i, tickets, avail, maxavail;
|
||||
struct midi *oep;
|
||||
|
||||
maxavail = MIDI_BUFSZ;
|
||||
for (i = 0; i < MIDI_NEP ; i++) {
|
||||
if ((oep->rxmask & (1 << i)) == 0)
|
||||
if ((iep->txmask & (1 << i)) == 0)
|
||||
continue;
|
||||
iep = midi_ep + i;
|
||||
count = midi_in(iep);
|
||||
if (count)
|
||||
iep->ops->fill(iep->arg, count);
|
||||
oep = midi_ep + i;
|
||||
avail = oep->obuf.len - oep->obuf.used;
|
||||
if (maxavail > avail)
|
||||
maxavail = avail;
|
||||
}
|
||||
|
||||
/*
|
||||
* in the worst case output message is twice the
|
||||
* input message (2-byte messages with running status)
|
||||
*/
|
||||
tickets = maxavail / 2 - iep->tickets;
|
||||
if (tickets > 0) {
|
||||
iep->tickets += tickets;
|
||||
iep->ops->fill(iep->arg, tickets);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* parse the give data chunk, and calling imsg() for each message
|
||||
* recalculate tickets of endpoints sending data to this one
|
||||
*/
|
||||
void
|
||||
midi_parse(struct midi *iep, unsigned char *idata, int icount)
|
||||
midi_fill(struct midi *oep)
|
||||
{
|
||||
int i;
|
||||
struct midi *iep;
|
||||
|
||||
for (i = 0; i < MIDI_NEP; i++) {
|
||||
iep = midi_ep + i;
|
||||
if (iep->txmask & oep->self)
|
||||
midi_tickets(iep);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* parse then give data chunk, and calling imsg() for each message
|
||||
*/
|
||||
void
|
||||
midi_in(struct midi *iep, unsigned char *idata, int icount)
|
||||
{
|
||||
int i;
|
||||
unsigned char c;
|
||||
|
@ -305,60 +352,9 @@ midi_parse(struct midi *iep, unsigned char *idata, int icount)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* process input data stored in ep->ibuf
|
||||
*/
|
||||
int
|
||||
midi_in(struct midi *iep)
|
||||
{
|
||||
unsigned char *idata;
|
||||
int i, icount, maxavail, avail, idone;
|
||||
struct midi *oep;
|
||||
|
||||
/*
|
||||
* calculate the max message size we can process
|
||||
*/
|
||||
maxavail = MIDI_BUFSZ;
|
||||
for (i = 0; i < MIDI_NEP ; i++) {
|
||||
if ((iep->txmask & (1 << i)) == 0)
|
||||
continue;
|
||||
oep = midi_ep + i;
|
||||
avail = oep->obuf.len - oep->obuf.used;
|
||||
if (maxavail > avail)
|
||||
maxavail = avail;
|
||||
}
|
||||
|
||||
/*
|
||||
* in the works case output message is twice the
|
||||
* input message (2-byte messages with running status)
|
||||
*/
|
||||
maxavail /= 2;
|
||||
idone = 0;
|
||||
for (;;) {
|
||||
idata = abuf_rgetblk(&iep->ibuf, &icount);
|
||||
if (icount > maxavail)
|
||||
icount = maxavail;
|
||||
if (icount == 0)
|
||||
break;
|
||||
maxavail -= icount;
|
||||
#ifdef DEBUG
|
||||
if (log_level >= 4) {
|
||||
midi_log(iep);
|
||||
log_puts(": in:");
|
||||
for (i = 0; i < icount; i++) {
|
||||
log_puts(" ");
|
||||
log_putx(idata[i]);
|
||||
}
|
||||
log_puts("\n");
|
||||
}
|
||||
#endif
|
||||
midi_parse(iep, idata, icount);
|
||||
abuf_rdiscard(&iep->ibuf, icount);
|
||||
idone += icount;
|
||||
}
|
||||
return idone;
|
||||
iep->tickets -= icount;
|
||||
if (iep->tickets < 0)
|
||||
iep->tickets = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -378,7 +374,7 @@ midi_out(struct midi *oep, unsigned char *idata, int icount)
|
|||
#ifdef DEBUG
|
||||
if (log_level >= 2) {
|
||||
midi_log(oep);
|
||||
log_puts(": overrun, discarding ");
|
||||
log_puts(": too slow, discarding ");
|
||||
log_putu(oep->obuf.used);
|
||||
log_puts(" bytes\n");
|
||||
}
|
||||
|
|
|
@ -72,8 +72,8 @@ struct midi {
|
|||
unsigned int idx; /* current ``msg'' size */
|
||||
unsigned int len; /* expected ``msg'' length */
|
||||
unsigned int txmask; /* list of ep we send to */
|
||||
unsigned int rxmask; /* single ep we accept data for */
|
||||
struct abuf ibuf; /* input buffer */
|
||||
unsigned int self; /* equal (1 << index) */
|
||||
unsigned int tickets; /* max bytes we can process */
|
||||
struct abuf obuf; /* output buffer */
|
||||
};
|
||||
|
||||
|
@ -102,12 +102,13 @@ void midi_done(void);
|
|||
struct midi *midi_new(struct midiops *, void *, int);
|
||||
void midi_del(struct midi *);
|
||||
void midi_log(struct midi *);
|
||||
int midi_in(struct midi *);
|
||||
void midi_tickets(struct midi *);
|
||||
void midi_in(struct midi *, unsigned char *, int);
|
||||
void midi_out(struct midi *, unsigned char *, int);
|
||||
void midi_send(struct midi *, unsigned char *, int);
|
||||
void midi_fill(struct midi *);
|
||||
void midi_tag(struct midi *, unsigned int);
|
||||
void midi_untag(struct midi *, unsigned int);
|
||||
void midi_link(struct midi *, struct midi *);
|
||||
|
||||
struct port *port_new(char *, unsigned int);
|
||||
struct port *port_bynum(int);
|
||||
|
|
|
@ -68,7 +68,7 @@ port_mio_pollfd(void *addr, struct pollfd *pfd)
|
|||
struct midi *ep = p->midi;
|
||||
int events = 0;
|
||||
|
||||
if ((ep->mode & MODE_MIDIIN) && ep->ibuf.used < ep->ibuf.len)
|
||||
if (ep->mode & MODE_MIDIIN)
|
||||
events |= POLLIN;
|
||||
if ((ep->mode & MODE_MIDIOUT) && ep->obuf.used > 0)
|
||||
events |= POLLOUT;
|
||||
|
@ -86,22 +86,16 @@ port_mio_revents(void *addr, struct pollfd *pfd)
|
|||
void
|
||||
port_mio_in(void *arg)
|
||||
{
|
||||
unsigned char data[MIDI_BUFSZ];
|
||||
struct port *p = arg;
|
||||
struct midi *ep = p->midi;
|
||||
unsigned char *data;
|
||||
int n, count;
|
||||
int n;
|
||||
|
||||
for (;;) {
|
||||
data = abuf_wgetblk(&ep->ibuf, &count);
|
||||
if (count == 0)
|
||||
break;
|
||||
n = mio_read(p->mio.hdl, data, count);
|
||||
n = mio_read(p->mio.hdl, data, MIDI_BUFSZ);
|
||||
if (n == 0)
|
||||
break;
|
||||
abuf_wcommit(&ep->ibuf, n);
|
||||
midi_in(ep);
|
||||
if (n < count)
|
||||
break;
|
||||
midi_in(ep, data, n);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,8 +117,8 @@ port_mio_out(void *arg)
|
|||
abuf_rdiscard(&ep->obuf, n);
|
||||
if (n < count)
|
||||
break;
|
||||
midi_fill(ep);
|
||||
}
|
||||
midi_fill(ep);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -505,7 +505,7 @@ sock_wmsg(struct sock *f)
|
|||
int
|
||||
sock_rdata(struct sock *f)
|
||||
{
|
||||
struct abuf *buf;
|
||||
unsigned char midibuf[MIDI_BUFSZ];
|
||||
unsigned char *data;
|
||||
int n, count;
|
||||
|
||||
|
@ -516,19 +516,23 @@ sock_rdata(struct sock *f)
|
|||
panic();
|
||||
}
|
||||
#endif
|
||||
if (f->slot)
|
||||
buf = &f->slot->mix.buf;
|
||||
else
|
||||
buf = &f->midi->ibuf;
|
||||
while (f->rtodo > 0) {
|
||||
data = abuf_wgetblk(buf, &count);
|
||||
if (f->slot)
|
||||
data = abuf_wgetblk(&f->slot->mix.buf, &count);
|
||||
else {
|
||||
data = midibuf;
|
||||
count = MIDI_BUFSZ;
|
||||
}
|
||||
if (count > f->rtodo)
|
||||
count = f->rtodo;
|
||||
n = sock_fdread(f, data, count);
|
||||
if (n == 0)
|
||||
return 0;
|
||||
f->rtodo -= n;
|
||||
abuf_wcommit(buf, n);
|
||||
if (f->slot)
|
||||
abuf_wcommit(&f->slot->mix.buf, n);
|
||||
else
|
||||
midi_in(f->midi, midibuf, n);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (log_level >= 4) {
|
||||
|
@ -538,8 +542,6 @@ sock_rdata(struct sock *f)
|
|||
#endif
|
||||
if (f->slot)
|
||||
slot_write(f->slot);
|
||||
if (f->midi)
|
||||
f->fillpending += midi_in(f->midi);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -864,14 +866,9 @@ sock_hello(struct sock *f)
|
|||
c = port_bynum(p->devnum - 32);
|
||||
if (c == NULL)
|
||||
return 0;
|
||||
if (mode & MODE_MIDIOUT)
|
||||
f->midi->txmask |= c->midi->rxmask;
|
||||
if (mode & MODE_MIDIIN)
|
||||
c->midi->txmask |= f->midi->rxmask;
|
||||
midi_link(f->midi, c->midi);
|
||||
} else
|
||||
return 0;
|
||||
if (mode & MODE_MIDIOUT)
|
||||
f->fillpending = MIDI_BUFSZ;
|
||||
return 1;
|
||||
}
|
||||
f->opt = opt_byname(p->opt, p->devnum);
|
||||
|
|
Loading…
Reference in New Issue