Hi,
This diff is to use dedicated messages for flow control instead of
abusing clock tick messages and to enable flow control for MIDI.
There should be no change in behaviour, but this change is
necessary for future developpement of sndiod.
any regression? ok?
-- Alexandre
Index: lib/libsndio/amsg.h
===================================================================
RCS file: /cvs/src/lib/libsndio/amsg.h,v
retrieving revision 1.4
diff -u -p -r1.4 amsg.h
--- lib/libsndio/amsg.h 15 Nov 2011 08:05:22 -0000 1.4
+++ lib/libsndio/amsg.h 27 Oct 2012 13:04:01 -0000
@@ -42,7 +42,7 @@ struct amsg {
#define AMSG_START 3 /* request the server to start the stream */
#define AMSG_STOP 4 /* request the server to stop the stream */
#define AMSG_DATA 5 /* data block */
-#define AMSG_POS 6 /* initial position */
+#define AMSG_FLOWCTL 6 /* feedback about buffer usage */
#define AMSG_MOVE 7 /* position changed */
#define AMSG_SETVOL 9 /* set volume */
#define AMSG_HELLO 10 /* say hello, check versions and so ... */
@@ -80,7 +80,7 @@ struct amsg {
} vol;
struct amsg_hello {
uint16_t mode; /* bitmap of MODE_XXX */
-#define AMSG_VERSION 5
+#define AMSG_VERSION 6
uint8_t version; /* protocol version */
uint8_t devnum; /* device number */
uint32_t _reserved[1]; /* for future use */
Index: lib/libsndio/aucat.c
===================================================================
RCS file: /cvs/src/lib/libsndio/aucat.c,v
retrieving revision 1.54
diff -u -p -r1.54 aucat.c
--- lib/libsndio/aucat.c 11 Apr 2012 06:05:43 -0000 1.54
+++ lib/libsndio/aucat.c 27 Oct 2012 13:04:01 -0000
@@ -463,6 +463,7 @@ aucat_open(struct aucat *hdl, const char
hdl->rtodo = sizeof(struct amsg);
hdl->wstate = WSTATE_IDLE;
hdl->wtodo = 0xdeadbeef;
+ hdl->maxwrite = 0;
/*
* say hello to server
Index: lib/libsndio/aucat.h
===================================================================
RCS file: /cvs/src/lib/libsndio/aucat.h,v
retrieving revision 1.4
diff -u -p -r1.4 aucat.h
--- lib/libsndio/aucat.h 15 Nov 2011 08:05:22 -0000 1.4
+++ lib/libsndio/aucat.h 27 Oct 2012 13:04:01 -0000
@@ -14,6 +14,7 @@ struct aucat {
#define WSTATE_MSG 3 /* message being transferred */
#define WSTATE_DATA 4 /* data being transferred */
unsigned wstate; /* one of above */
+ unsigned maxwrite; /* bytes we're allowed to write */
};
int aucat_rmsg(struct aucat *, int *);
Index: lib/libsndio/mio_aucat.c
===================================================================
RCS file: /cvs/src/lib/libsndio/mio_aucat.c,v
retrieving revision 1.8
diff -u -p -r1.8 mio_aucat.c
--- lib/libsndio/mio_aucat.c 27 Oct 2012 12:08:25 -0000 1.8
+++ lib/libsndio/mio_aucat.c 27 Oct 2012 13:04:01 -0000
@@ -54,6 +54,35 @@ static struct mio_ops mio_aucat_ops = {
mio_aucat_revents
};
+/*
+ * execute the next message, return 0 if blocked
+ */
+static int
+mio_aucat_runmsg(struct mio_aucat_hdl *hdl)
+{
+ int delta;
+
+ if (!aucat_rmsg(&hdl->aucat, &hdl->mio.eof))
+ return 0;
+ switch (ntohl(hdl->aucat.rmsg.cmd)) {
+ case AMSG_DATA:
+ return 1;
+ case AMSG_FLOWCTL:
+ delta = ntohl(hdl->aucat.rmsg.u.ts.delta);
+ hdl->aucat.maxwrite += delta;
+ DPRINTF("aucat: flowctl = %d, maxwrite = %d\n",
+ delta, hdl->aucat.maxwrite);
+ break;
+ default:
+ DPRINTF("mio_aucat_runmsg: unhandled message %u\n",
hdl->aucat.rmsg.cmd);
+ hdl->mio.eof = 1;
+ return 0;
+ }
+ hdl->aucat.rstate = RSTATE_MSG;
+ hdl->aucat.rtodo = sizeof(struct amsg);
+ return 1;
+}
+
struct mio_hdl *
mio_aucat_open(const char *str, unsigned int mode,
int nbio, unsigned int type)
@@ -91,7 +120,7 @@ mio_aucat_read(struct mio_hdl *sh, void
struct mio_aucat_hdl *hdl = (struct mio_aucat_hdl *)sh;
while (hdl->aucat.rstate == RSTATE_MSG) {
- if (!aucat_rmsg(&hdl->aucat, &hdl->mio.eof))
+ if (!mio_aucat_runmsg(hdl))
return 0;
}
return aucat_rdata(&hdl->aucat, buf, len, &hdl->mio.eof);
@@ -101,8 +130,15 @@ static size_t
mio_aucat_write(struct mio_hdl *sh, const void *buf, size_t len)
{
struct mio_aucat_hdl *hdl = (struct mio_aucat_hdl *)sh;
+ size_t n;
- return aucat_wdata(&hdl->aucat, buf, len, 1, &hdl->mio.eof);
+ if (len <= 0 || hdl->aucat.maxwrite <= 0)
+ return 0;
+ if (len > hdl->aucat.maxwrite)
+ len = hdl->aucat.maxwrite;
+ n = aucat_wdata(&hdl->aucat, buf, len, 1, &hdl->mio.eof);
+ hdl->aucat.maxwrite -= n;
+ return n;
}
static int
@@ -117,6 +153,8 @@ mio_aucat_pollfd(struct mio_hdl *sh, str
struct mio_aucat_hdl *hdl = (struct mio_aucat_hdl *)sh;
hdl->events = events;
+ if (hdl->aucat.maxwrite <= 0)
+ events &= ~POLLOUT;
return aucat_pollfd(&hdl->aucat, pfd, events);
}
@@ -128,11 +166,15 @@ mio_aucat_revents(struct mio_hdl *sh, st
if (revents & POLLIN) {
while (hdl->aucat.rstate == RSTATE_MSG) {
- if (!aucat_rmsg(&hdl->aucat, &hdl->mio.eof))
+ if (!mio_aucat_runmsg(hdl))
break;
}
if (hdl->aucat.rstate != RSTATE_DATA)
revents &= ~POLLIN;
+ }
+ if (revents & POLLOUT) {
+ if (hdl->aucat.maxwrite <= 0)
+ revents &= ~POLLOUT;
}
if (hdl->mio.eof)
return POLLHUP;
Index: lib/libsndio/sio_aucat.c
===================================================================
RCS file: /cvs/src/lib/libsndio/sio_aucat.c,v
retrieving revision 1.12
diff -u -p -r1.12 sio_aucat.c
--- lib/libsndio/sio_aucat.c 27 Oct 2012 11:56:04 -0000 1.12
+++ lib/libsndio/sio_aucat.c 27 Oct 2012 13:04:02 -0000
@@ -35,8 +35,7 @@
struct sio_aucat_hdl {
struct sio_hdl sio;
struct aucat aucat;
- unsigned int rbpf, wbpf; /* read and write
bytes-per-frame */
- int maxwrite; /* latency constraint */
+ unsigned int rbpf, wbpf; /* read and write bytes-per-frame */
int events; /* events the user requested */
unsigned int curvol, reqvol; /* current and requested volume */
int delta; /* some of received deltas */
@@ -97,23 +96,17 @@ sio_aucat_runmsg(struct sio_aucat_hdl *h
return 0;
}
return 1;
- case AMSG_POS:
+ case AMSG_FLOWCTL:
delta = ntohl(hdl->aucat.rmsg.u.ts.delta);
- hdl->maxwrite += delta * (int)hdl->wbpf;
- DPRINTF("aucat: pos = %d, maxwrite = %d\n",
- delta, hdl->maxwrite);
- hdl->delta = delta;
- if (hdl->delta >= 0) {
- sio_onmove_cb(&hdl->sio, hdl->delta);
- hdl->delta = 0;
- }
+ hdl->aucat.maxwrite += delta * (int)hdl->wbpf;
+ DPRINTF("aucat: flowctl = %d, maxwrite = %d\n",
+ delta, hdl->aucat.maxwrite);
break;
case AMSG_MOVE:
delta = ntohl(hdl->aucat.rmsg.u.ts.delta);
- hdl->maxwrite += delta * hdl->wbpf;
hdl->delta += delta;
DPRINTFN(2, "aucat: move = %d, delta = %d, maxwrite = %d\n",
- delta, hdl->delta, hdl->maxwrite);
+ delta, hdl->delta, hdl->aucat.maxwrite);
if (hdl->delta >= 0) {
sio_onmove_cb(&hdl->sio, hdl->delta);
hdl->delta = 0;
@@ -196,10 +189,10 @@ sio_aucat_start(struct sio_hdl *sh)
return 0;
hdl->wbpf = par.bps * par.pchan;
hdl->rbpf = par.bps * par.rchan;
- hdl->maxwrite = hdl->wbpf * par.bufsz;
+ hdl->aucat.maxwrite = hdl->wbpf * par.bufsz;
hdl->round = par.round;
hdl->delta = 0;
- DPRINTF("aucat: start, maxwrite = %d\n", hdl->maxwrite);
+ DPRINTF("aucat: start, maxwrite = %d\n", hdl->aucat.maxwrite);
AMSG_INIT(&hdl->aucat.wmsg);
hdl->aucat.wmsg.cmd = htonl(AMSG_START);
@@ -233,7 +226,7 @@ sio_aucat_stop(struct sio_hdl *sh)
return 0;
}
if (hdl->aucat.wstate == WSTATE_DATA) {
- hdl->maxwrite = hdl->aucat.wtodo;
+ hdl->aucat.maxwrite = hdl->aucat.wtodo;
while (hdl->aucat.wstate != WSTATE_IDLE) {
count = hdl->aucat.wtodo;
if (count > ZERO_MAX)
@@ -427,14 +420,14 @@ sio_aucat_write(struct sio_hdl *sh, cons
if (!sio_aucat_buildmsg(hdl))
break;
}
- if (len <= 0 || hdl->maxwrite <= 0)
+ if (len <= 0 || hdl->aucat.maxwrite <= 0)
return 0;
- if (len > hdl->maxwrite)
- len = hdl->maxwrite;
+ if (len > hdl->aucat.maxwrite)
+ len = hdl->aucat.maxwrite;
if (len > hdl->walign)
len = hdl->walign;
n = aucat_wdata(&hdl->aucat, buf, len, hdl->wbpf, &hdl->sio.eof);
- hdl->maxwrite -= n;
+ hdl->aucat.maxwrite -= n;
hdl->walign -= n;
if (hdl->walign == 0)
hdl->walign = hdl->round * hdl->wbpf;
@@ -453,7 +446,7 @@ sio_aucat_pollfd(struct sio_hdl *sh, str
struct sio_aucat_hdl *hdl = (struct sio_aucat_hdl *)sh;
hdl->events = events;
- if (hdl->maxwrite <= 0)
+ if (hdl->aucat.maxwrite <= 0)
events &= ~POLLOUT;
return aucat_pollfd(&hdl->aucat, pfd, events);
}
@@ -473,7 +466,7 @@ sio_aucat_revents(struct sio_hdl *sh, st
revents &= ~POLLIN;
}
if (revents & POLLOUT) {
- if (hdl->maxwrite <= 0)
+ if (hdl->aucat.maxwrite <= 0)
revents &= ~POLLOUT;
}
if (hdl->sio.eof)
Index: usr.bin/aucat/sock.c
===================================================================
RCS file: /cvs/src/usr.bin/aucat/sock.c,v
retrieving revision 1.65
diff -u -p -r1.65 sock.c
--- usr.bin/aucat/sock.c 27 Oct 2012 11:54:27 -0000 1.65
+++ usr.bin/aucat/sock.c 27 Oct 2012 13:04:02 -0000
@@ -335,8 +335,7 @@ sock_new(struct fileops *ops, int fd)
f->xrun = XRUN_IGNORE;
f->delta = 0;
f->tickpending = 0;
- f->startpos = 0;
- f->startpending = 0;
+ f->fillpending = 0;
f->vol = f->lastvol = MIDI_MAXCTL;
f->slot = -1;
@@ -380,7 +379,7 @@ sock_freebuf(struct sock *f)
if (wbuf)
abuf_hup(wbuf);
f->tickpending = 0;
- f->startpending = 0;
+ f->fillpending = 0;
}
/*
@@ -408,9 +407,8 @@ sock_allocbuf(struct sock *f)
f->wmax = 0;
}
f->delta = 0;
- f->startpos = 0;
f->tickpending = 0;
- f->startpending = 0;
+ f->fillpending = 0;
#ifdef DEBUG
if (debug_level >= 3) {
sock_dbg(f);
@@ -551,14 +549,15 @@ sock_attach(struct sock *f, int force)
* get the current position, the origin is when
* the first sample is played/recorded
*/
- f->startpos = dev_getpos(f->dev) * (int)f->round / (int)f->dev->round;
- f->startpending = 1;
+ f->delta = dev_getpos(f->dev) *
+ (int)f->round / (int)f->dev->round;
+ f->fillpending = f->delta;
f->pstate = SOCK_RUN;
#ifdef DEBUG
if (debug_level >= 3) {
sock_dbg(f);
dbg_puts(": attaching at ");
- dbg_puti(f->startpos);
+ dbg_puti(f->delta);
dbg_puts("\n");
}
#endif
@@ -960,6 +959,7 @@ sock_midiattach(struct sock *f)
aproc_setin(f->pipe.file.wproc, wbuf);
}
f->pstate = SOCK_MIDI;
+ f->fillpending = MIDI_BUFSZ;
dev_midiattach(f->dev, rbuf, wbuf);
}
@@ -1164,6 +1164,8 @@ sock_execmsg(struct sock *f)
#endif
if (f->pstate != SOCK_MIDI)
f->rmax -= f->rtodo;
+ else
+ f->fillpending += f->rtodo;
if (f->rtodo == 0) {
#ifdef DEBUG
if (debug_level >= 1) {
@@ -1425,48 +1427,45 @@ sock_buildmsg(struct sock *f)
unsigned int size, max;
/*
- * Send initial position
+ * If pos changed, build a MOVE message.
*/
- if (f->startpending) {
+ if (f->tickpending && f->delta >= 0) {
#ifdef DEBUG
if (debug_level >= 4) {
sock_dbg(f);
- dbg_puts(": building POS message, pos = ");
- dbg_puti(f->startpos);
+ dbg_puts(": building MOVE message, delta = ");
+ dbg_puti(f->delta);
dbg_puts("\n");
}
#endif
AMSG_INIT(&f->wmsg);
- f->wmsg.cmd = htonl(AMSG_POS);
- f->wmsg.u.ts.delta = htonl(f->startpos);
- f->rmax += f->startpos;
+ f->wmsg.cmd = htonl(AMSG_MOVE);
+ f->wmsg.u.ts.delta = htonl(f->delta);
f->wtodo = sizeof(struct amsg);
f->wstate = SOCK_WMSG;
- f->startpending = 0;
+ f->wmax += f->delta;
+ f->fillpending += f->delta;
+ f->delta = 0;
+ f->tickpending = 0;
return 1;
}
- /*
- * If pos changed, build a MOVE message.
- */
- if (f->tickpending) {
+ if (f->fillpending > 0) {
#ifdef DEBUG
if (debug_level >= 4) {
sock_dbg(f);
- dbg_puts(": building MOVE message, delta = ");
- dbg_puti(f->delta);
+ dbg_puts(": building FLOWCTL message, count = ");
+ dbg_puti(f->fillpending);
dbg_puts("\n");
}
#endif
- f->wmax += f->delta;
- f->rmax += f->delta;
AMSG_INIT(&f->wmsg);
- f->wmsg.cmd = htonl(AMSG_MOVE);
- f->wmsg.u.ts.delta = htonl(f->delta);
+ f->wmsg.cmd = htonl(AMSG_FLOWCTL);
+ f->wmsg.u.ts.delta = htonl(f->fillpending);
f->wtodo = sizeof(struct amsg);
f->wstate = SOCK_WMSG;
- f->delta = 0;
- f->tickpending = 0;
+ f->rmax += f->fillpending;
+ f->fillpending = 0;
return 1;
}
Index: usr.bin/aucat/sock.h
===================================================================
RCS file: /cvs/src/usr.bin/aucat/sock.h,v
retrieving revision 1.20
diff -u -p -r1.20 sock.h
--- usr.bin/aucat/sock.h 11 Apr 2012 06:05:43 -0000 1.20
+++ usr.bin/aucat/sock.h 27 Oct 2012 13:04:02 -0000
@@ -55,9 +55,8 @@ struct sock {
struct aparams rpar; /* read (ie play) parameters */
struct aparams wpar; /* write (ie rec) parameters */
int delta; /* pos. change to send */
- int startpos; /* initial pos. to send */
int tickpending; /* delta waiting to be transmitted */
- int startpending; /* initial delta waiting to be
transmitted */
+ int fillpending; /* pending buffer fill request */
unsigned int walign; /* align data packets to this */
unsigned int bufsz; /* total buffer size */
unsigned int round; /* block size */