On Sat, Oct 27, 2012 at 03:14:07PM +0200, Alexandre Ratchov wrote:
> 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?
>
sorry; the previous diff is wrong, please consider the one
below (thanks jsg@)
-- 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 28 Oct 2012 12:28:51 -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 28 Oct 2012 12:28:51 -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 28 Oct 2012 12:28:51 -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 28 Oct 2012 12:28:51 -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 28 Oct 2012 12:28:52 -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 28 Oct 2012 12:28:52 -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 = 0;
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 28 Oct 2012 12:28:52 -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 */