summaryrefslogtreecommitdiff
path: root/usr.bin/sndiod
diff options
context:
space:
mode:
authorAlexandre Ratchov <ratchov@cvs.openbsd.org>2012-11-30 20:30:25 +0000
committerAlexandre Ratchov <ratchov@cvs.openbsd.org>2012-11-30 20:30:25 +0000
commit297ca9f8a473c8530bd1b30f84cc7e5e2aef627d (patch)
tree02bed326b1cef6b69f3e0d4313b156ec8559b089 /usr.bin/sndiod
parent1004657da7ceda6169e94b363e02d12706b2ba26 (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.c218
-rw-r--r--usr.bin/sndiod/midi.h11
-rw-r--r--usr.bin/sndiod/miofile.c20
-rw-r--r--usr.bin/sndiod/sock.c29
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);