diff options
author | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2012-11-30 20:30:25 +0000 |
---|---|---|
committer | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2012-11-30 20:30:25 +0000 |
commit | 297ca9f8a473c8530bd1b30f84cc7e5e2aef627d (patch) | |
tree | 02bed326b1cef6b69f3e0d4313b156ec8559b089 /usr.bin/sndiod | |
parent | 1004657da7ceda6169e94b363e02d12706b2ba26 (diff) |
Process incoming MIDI data on the fly rather than using an
input fifo; besides being simpler, this way there's no data
to drain when a connection is dropped.
Diffstat (limited to 'usr.bin/sndiod')
-rw-r--r-- | usr.bin/sndiod/midi.c | 218 | ||||
-rw-r--r-- | usr.bin/sndiod/midi.h | 11 | ||||
-rw-r--r-- | usr.bin/sndiod/miofile.c | 20 | ||||
-rw-r--r-- | usr.bin/sndiod/sock.c | 29 |
4 files changed, 133 insertions, 145 deletions
diff --git a/usr.bin/sndiod/midi.c b/usr.bin/sndiod/midi.c index 8e598735f4f..f599d21f94c 100644 --- a/usr.bin/sndiod/midi.c +++ b/usr.bin/sndiod/midi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: midi.c,v 1.1 2012/11/23 07:03:28 ratchov Exp $ */ +/* $OpenBSD: midi.c,v 1.2 2012/11/30 20:30:24 ratchov Exp $ */ /* * Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org> * @@ -60,7 +60,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]; @@ -120,18 +120,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; } @@ -139,64 +137,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); } } /* - * add the midi endpoint in the ``tag'' midi thru box + * connect two midi endpoints */ void -midi_tag(struct midi *ep, unsigned int tag) +midi_link(struct midi *ep, struct midi *peer) { - 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 |= 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; } } /* - * remove the midi endpoint from the ``tag'' midi thru box + * add the midi endpoint in the ``tag'' midi thru box */ void -midi_untag(struct midi *ep, unsigned int tag) +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++, m++) { - if (!(members & (1 << i))) - continue; - ep->txmask &= ~m->rxmask; - m->txmask &= ~ep->rxmask; + if (ep->mode & MODE_MIDIOUT) { + ep->txmask |= t->txmask; + midi_tickets(ep); + } + 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; } /* @@ -241,27 +257,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; + 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); + } +} + +/* + * recalculate tickets of endpoints sending data to this one + */ +void +midi_fill(struct midi *oep) +{ + int i; + struct midi *iep; + + for (i = 0; i < MIDI_NEP; i++) { iep = midi_ep + i; - count = midi_in(iep); - if (count) - iep->ops->fill(iep->arg, count); + if (iep->txmask & oep->self) + midi_tickets(iep); } } /* - * parse the give data chunk, and calling imsg() for each message + * parse then give data chunk, and calling imsg() for each message */ void -midi_parse(struct midi *iep, unsigned char *idata, int icount) +midi_in(struct midi *iep, unsigned char *idata, int icount) { int i; unsigned char c; @@ -304,60 +351,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; } /* @@ -377,7 +373,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"); } diff --git a/usr.bin/sndiod/midi.h b/usr.bin/sndiod/midi.h index 60b37a2866a..34ebfa370e5 100644 --- a/usr.bin/sndiod/midi.h +++ b/usr.bin/sndiod/midi.h @@ -1,4 +1,4 @@ -/* $OpenBSD: midi.h,v 1.1 2012/11/23 07:03:28 ratchov Exp $ */ +/* $OpenBSD: midi.h,v 1.2 2012/11/30 20:30:24 ratchov Exp $ */ /* * Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org> * @@ -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); diff --git a/usr.bin/sndiod/miofile.c b/usr.bin/sndiod/miofile.c index 5fee9f9a1ca..ac56d0d0a0a 100644 --- a/usr.bin/sndiod/miofile.c +++ b/usr.bin/sndiod/miofile.c @@ -1,4 +1,4 @@ -/* $OpenBSD: miofile.c,v 1.1 2012/11/23 07:03:28 ratchov Exp $ */ +/* $OpenBSD: miofile.c,v 1.2 2012/11/30 20:30:24 ratchov Exp $ */ /* * Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org> * @@ -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 diff --git a/usr.bin/sndiod/sock.c b/usr.bin/sndiod/sock.c index 93122aae8a5..e7e9b6678ae 100644 --- a/usr.bin/sndiod/sock.c +++ b/usr.bin/sndiod/sock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sock.c,v 1.1 2012/11/23 07:03:28 ratchov Exp $ */ +/* $OpenBSD: sock.c,v 1.2 2012/11/30 20:30:24 ratchov Exp $ */ /* * Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org> * @@ -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); |