diff --git a/sndiod/defs.h b/sndiod/defs.h index b63335d..7fc782b 100644 --- a/sndiod/defs.h +++ b/sndiod/defs.h @@ -31,7 +31,7 @@ extern unsigned int log_level; /* * MIDI buffer size */ -#define MIDI_BUFSZ 125 /* 1 second at 31.25kbit/s */ +#define MIDI_BUFSZ 15 /* 1 second at 31.25kbit/s */ /* * units used for MTC clock. diff --git a/sndiod/dev.c b/sndiod/dev.c index dcd7d3b..a62a60d 100644 --- a/sndiod/dev.c +++ b/sndiod/dev.c @@ -50,6 +50,7 @@ void zomb_exit(void *); 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 *); struct midiops dev_midiops = { @@ -465,6 +466,18 @@ dev_midi_omsg(void *arg, unsigned char *msg, int len) } } +void +dev_midi_fill(void *arg, int count) +{ + struct dev *d = arg; + +#ifdef DEBUG + dev_log(d); + log_puts(": can't receive fill input\n"); + panic(); +#endif +} + void dev_midi_exit(void *arg) { @@ -663,7 +676,7 @@ dev_mix_cycle(struct dev *d) *ps = s->next; continue; } - if (s->mix.buf.used < s->round * s->mix.bpf && + if (s->mix.buf.used < s->round * s->mix.bpf && !(s->pstate == SLOT_STOP)) { if (s->xrun == XRUN_IGNORE) { if (s->mode & MODE_RECMASK) @@ -976,6 +989,13 @@ dev_new(char *path, struct aparams *par, } d = xmalloc(sizeof(struct dev), "dev"); d->num = dev_sndnum++; + /* + * XXX + * we don't use the 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->path = path; diff --git a/sndiod/dsp.c b/sndiod/dsp.c index fd4f143..963dab1 100644 --- a/sndiod/dsp.c +++ b/sndiod/dsp.c @@ -697,7 +697,7 @@ sqrtone(int ctx, adata_t *out, int period, int vol, int todo) ctx = period / 2; } ctx--; - *(out++) = vol; + *(out++) += vol; } return ctx; } diff --git a/sndiod/midi.c b/sndiod/midi.c index e4f3d75..084d564 100644 --- a/sndiod/midi.c +++ b/sndiod/midi.c @@ -44,11 +44,13 @@ int port_open(struct port *); void port_imsg(void *, unsigned char *, int); void port_omsg(void *, unsigned char *, int); +void port_fill(void *, int); void port_exit(void *); struct midiops port_midiops = { port_imsg, port_omsg, + port_fill, port_exit }; @@ -83,11 +85,6 @@ midi_ontimo(void *arg) struct midi *ep; for (i = MIDI_NEP, ep = midi_ep; i > 0; i--, ep++) { - ep->tickets = MIDI_XFER; - if (ep->ibuf.used > 0) { - while (midi_in(ep)) - ; /* nothing */ - } } timo_add(&midi_timo, MIDI_TIMO); } @@ -125,7 +122,6 @@ midi_new(struct midiops *ops, void *arg, int mode) ep->st = 0; ep->txmask = 0; ep->rxmask = 1 << i; - ep->tickets = MIDI_XFER; ep->mode = mode; /* * client output is our input (ibuf) and our output (obuf) goes @@ -236,30 +232,55 @@ midi_send(struct midi *iep, unsigned char *msg, int size) } } + +void +midi_fill(struct midi *oep) +{ + int i, count; + struct midi *iep; + + for (i = 0; i < MIDI_NEP ; i++) { + if ((oep->rxmask & (1 << i)) == 0) + continue; + iep = midi_ep + i; + count = midi_in(iep); + if (count) + iep->ops->fill(iep->arg, count); + } +} + int -midi_in(struct midi *ep) +midi_in(struct midi *iep) { unsigned char c, *idata; - int i, icount; + int i, icount, maxavail, avail; + struct midi *oep; - if (ep->ibuf.used == 0) - return 0; - if (ep->tickets == 0) { -#ifdef DEBUG - if (log_level >= 4) { - midi_log(ep); - log_puts(": out of tickets, blocking\n"); - } -#endif - return 0; + /* + * 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; } - idata = abuf_rgetblk(&ep->ibuf, &icount); - //if (icount > ep->tickets) - // icount = ep->tickets; - //ep->tickets -= icount; + + /* + * in the works case output message is twice the + * input message (2-byte messages with running status) + */ + maxavail /= 2; + + idata = abuf_rgetblk(&iep->ibuf, &icount); + if (icount > maxavail) + icount = maxavail; #ifdef DEBUG if (log_level >= 4) { - midi_log(ep); + midi_log(iep); log_puts(": in:"); for (i = 0; i < icount; i++) { log_puts(" "); @@ -272,42 +293,42 @@ midi_in(struct midi *ep) c = *idata++; if (c >= 0xf8) { if (c != MIDI_ACK) - ep->ops->imsg(ep->arg, &c, 1); + iep->ops->imsg(iep->arg, &c, 1); } else if (c == SYSEX_END) { - if (ep->st == SYSEX_START) { - ep->msg[ep->idx++] = c; - ep->ops->imsg(ep->arg, ep->msg, ep->idx); + if (iep->st == SYSEX_START) { + iep->msg[iep->idx++] = c; + iep->ops->imsg(iep->arg, iep->msg, iep->idx); } - ep->st = 0; - ep->idx = 0; + iep->st = 0; + iep->idx = 0; } else if (c >= 0xf0) { - ep->msg[0] = c; - ep->len = common_len[c & 7]; - ep->st = c; - ep->idx = 1; + iep->msg[0] = c; + iep->len = common_len[c & 7]; + iep->st = c; + iep->idx = 1; } else if (c >= 0x80) { - ep->msg[0] = c; - ep->len = voice_len[(c >> 4) & 7]; - ep->st = c; - ep->idx = 1; - } else if (ep->st) { - if (ep->idx == 0 && ep->st != SYSEX_START) - ep->msg[ep->idx++] = ep->st; - ep->msg[ep->idx++] = c; - if (ep->idx == ep->len) { - ep->ops->imsg(ep->arg, ep->msg, ep->idx); - if (ep->st >= 0xf0) - ep->st = 0; - ep->idx = 0; - } else if (ep->idx == MIDI_MSGMAX) { + iep->msg[0] = c; + iep->len = voice_len[(c >> 4) & 7]; + iep->st = c; + iep->idx = 1; + } else if (iep->st) { + if (iep->idx == 0 && iep->st != SYSEX_START) + iep->msg[iep->idx++] = iep->st; + iep->msg[iep->idx++] = c; + if (iep->idx == iep->len) { + iep->ops->imsg(iep->arg, iep->msg, iep->idx); + if (iep->st >= 0xf0) + iep->st = 0; + iep->idx = 0; + } else if (iep->idx == MIDI_MSGMAX) { /* sysex continued */ - ep->ops->imsg(ep->arg, ep->msg, ep->idx); - ep->idx = 0; + iep->ops->imsg(iep->arg, iep->msg, iep->idx); + iep->idx = 0; } } } - abuf_rdiscard(&ep->ibuf, icount); - return 1; + abuf_rdiscard(&iep->ibuf, icount); + return icount; } void @@ -319,7 +340,7 @@ midi_out(struct midi *oep, unsigned char *idata, int icount) while (icount > 0) { if (oep->obuf.used == oep->obuf.len) { #ifdef DEBUG - if (log_level >= 3) { + if (log_level >= 2) { midi_log(oep); log_puts(": overrun, discarding "); log_putu(oep->obuf.used); @@ -385,6 +406,12 @@ port_omsg(void *arg, unsigned char *msg, int size) midi_out(p->midi, msg, size); } +void +port_fill(void *arg, int count) +{ + /* no flow control */ +} + void port_exit(void *arg) { @@ -423,6 +450,7 @@ port_del(struct port *c) if (c->state != PORT_CFG) port_close(c); + midi_del(c->midi); for (p = &port_list; *p != c; p = &(*p)->next) { #ifdef DEBUG if (*p == NULL) { @@ -435,9 +463,18 @@ port_del(struct port *c) xfree(c); } -/* - * Open a MIDI device and connect it to the thru box - */ +struct port * +port_bynum(int num) +{ + struct port *p; + + for (p = port_list; p != NULL; p = p->next) { + if (num-- == 0) + return p; + } + return NULL; +} + int port_open(struct port *c) { @@ -480,5 +517,6 @@ void port_done(struct port *c) { /* XXX: drain */ - port_close(c); + if (c->state != PORT_CFG) + port_close(c); } diff --git a/sndiod/midi.h b/sndiod/midi.h index 9287898..da8e7d7 100644 --- a/sndiod/midi.h +++ b/sndiod/midi.h @@ -56,6 +56,7 @@ struct midiops { void (*imsg)(void *, unsigned char *, int); void (*omsg)(void *, unsigned char *, int); + void (*fill)(void *, int); void (*exit)(void *); }; @@ -70,7 +71,6 @@ struct midi { unsigned int used; /* bytes used in ``msg'' */ unsigned int idx; /* current ``msg'' size */ unsigned int len; /* expected ``msg'' length */ - unsigned int tickets; /* input throttling */ unsigned int txmask; /* list of ep we send to */ unsigned int rxmask; /* single ep we accept data for */ struct abuf ibuf; /* input buffer */ @@ -105,10 +105,12 @@ void midi_log(struct midi *); int midi_in(struct midi *); 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); struct port *port_new(char *, unsigned int); +struct port *port_bynum(int); void port_del(struct port *); int port_init(struct port *); void port_done(struct port *); diff --git a/sndiod/miofile.c b/sndiod/miofile.c index 26adf52..a469dfd 100644 --- a/sndiod/miofile.c +++ b/sndiod/miofile.c @@ -124,6 +124,7 @@ port_mio_out(void *arg) abuf_rdiscard(&ep->obuf, n); if (n < count) break; + midi_fill(ep); } } diff --git a/sndiod/sock.c b/sndiod/sock.c index a038b9d..c3d2110 100644 --- a/sndiod/sock.c +++ b/sndiod/sock.c @@ -65,6 +65,7 @@ void sock_slot_mmcstop(void *); void sock_slot_mmcloc(void *, unsigned int); void sock_midi_imsg(void *, unsigned char *, int); void sock_midi_omsg(void *, unsigned char *, int); +void sock_midi_fill(void *, int); void sock_exit(void *); struct fileops sock_fileops = { @@ -91,6 +92,7 @@ struct slotops sock_slotops = { struct midiops sock_midiops = { sock_midi_imsg, sock_midi_omsg, + sock_midi_fill, sock_exit }; @@ -272,6 +274,16 @@ sock_midi_omsg(void *arg, unsigned char *msg, int size) ; } +void +sock_midi_fill(void *arg, int count) +{ + struct sock *f = arg; + + f->fillpending += count; + while (sock_write(f)) + ; +} + /* * Initialise socket in the SOCK_HELLO state with default * parameters. @@ -540,9 +552,11 @@ sock_rdata(struct sock *f) if (f->slot) slot_write(f->slot); if (f->midi) { + count = f->midi->ibuf.used; while (midi_in(f->midi)) ; /* nothing */ - f->fillpending += f->midi->ibuf.len - f->midi->ibuf.used; + count -= f->midi->ibuf.used; + f->fillpending += count; } return 1; } @@ -597,6 +611,8 @@ sock_wdata(struct sock *f) } if (f->slot) slot_read(f->slot); + if (f->midi) + midi_fill(f->midi); #ifdef DEBUG if (log_level >= 4) { sock_log(f); @@ -814,6 +830,7 @@ sock_hello(struct sock *f) { struct amsg_hello *p = &f->rmsg.u.hello; struct slot *s; + struct port *c; struct dev *d; unsigned int mode; @@ -872,6 +889,14 @@ sock_hello(struct sock *f) midi_tag(f->midi, p->devnum); } else if (p->devnum < 32) { midi_tag(f->midi, p->devnum); + } else if (p->devnum < 48) { + 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; } else return 0; if (mode & MODE_MIDIOUT) @@ -1339,14 +1364,6 @@ sock_buildmsg(struct sock *f) } if (f->fillpending > 0) { -#ifdef DEBUG - if (log_level >= 4) { - sock_log(f); - log_puts(": building FLOWCTL message, count = "); - log_puti(f->fillpending); - log_puts("\n"); - } -#endif AMSG_INIT(&f->wmsg); f->wmsg.cmd = htonl(AMSG_FLOWCTL); f->wmsg.u.ts.delta = htonl(f->fillpending); @@ -1354,6 +1371,16 @@ sock_buildmsg(struct sock *f) if (f->slot) size *= f->slot->mix.bpf; f->rmax += size; +#ifdef DEBUG + if (log_level >= 4) { + sock_log(f); + log_puts(": building FLOWCTL message, count = "); + log_puti(f->fillpending); + log_puts(", rmax -> "); + log_puti(f->rmax); + log_puts("\n"); + } +#endif f->wtodo = sizeof(struct amsg); f->wstate = SOCK_WMSG; f->fillpending = 0;