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 */

Reply via email to