Add sio_flush(3) function to stop playback immediately
authorratchov <ratchov@openbsd.org>
Fri, 29 Apr 2022 08:30:48 +0000 (08:30 +0000)
committerratchov <ratchov@openbsd.org>
Fri, 29 Apr 2022 08:30:48 +0000 (08:30 +0000)
The new sio_flush(3) functions works the same way as sio_stop(3),
except that it doesn't wait for play buffer to be drained. Instead,
it discards its contents and returns immediately.

include/sndio.h
lib/libsndio/Symbols.map
lib/libsndio/amsg.h
lib/libsndio/shlib_version
lib/libsndio/sio.c
lib/libsndio/sio_aucat.c
lib/libsndio/sio_open.3
lib/libsndio/sio_priv.h
lib/libsndio/sio_sun.c
usr.bin/sndiod/siofile.c
usr.bin/sndiod/sock.c

index 03550a0..04c7336 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sndio.h,v 1.13 2020/06/28 05:21:38 ratchov Exp $      */
+/*     $OpenBSD: sndio.h,v 1.14 2022/04/29 08:30:48 ratchov Exp $      */
 /*
  * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
  *
@@ -164,6 +164,7 @@ size_t sio_write(struct sio_hdl *, const void *, size_t);
 size_t sio_read(struct sio_hdl *, void *, size_t);
 int sio_start(struct sio_hdl *);
 int sio_stop(struct sio_hdl *);
+int sio_flush(struct sio_hdl *);
 int sio_nfds(struct sio_hdl *);
 int sio_pollfd(struct sio_hdl *, struct pollfd *, int);
 int sio_revents(struct sio_hdl *, struct pollfd *);
index a83e63d..cf89206 100644 (file)
@@ -11,6 +11,7 @@
                sio_read;
                sio_start;
                sio_stop;
+               sio_flush;
                sio_nfds;
                sio_pollfd;
                sio_revents;
index 6dfb695..6d1a185 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: amsg.h,v 1.14 2021/11/01 14:43:24 ratchov Exp $       */
+/*     $OpenBSD: amsg.h,v 1.15 2022/04/29 08:30:48 ratchov Exp $       */
 /*
  * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
  *
@@ -96,6 +96,9 @@ struct amsg {
 #define AMSG_DATAMAX   0x1000
                        uint32_t size;
                } data;
+               struct amsg_stop {
+                       uint8_t drain;
+               } stop;
                struct amsg_ts {
                        int32_t delta;
                } ts;
index b39addf..a0ace4f 100644 (file)
@@ -1,2 +1,2 @@
 major=7
-minor=1
+minor=2
index 430f884..57fb757 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sio.c,v 1.26 2021/11/01 14:43:24 ratchov Exp $        */
+/*     $OpenBSD: sio.c,v 1.27 2022/04/29 08:30:48 ratchov Exp $        */
 /*
  * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
  *
@@ -129,6 +129,8 @@ sio_start(struct sio_hdl *hdl)
 int
 sio_stop(struct sio_hdl *hdl)
 {
+       if (hdl->ops->stop == NULL)
+               return sio_flush(hdl);
        if (hdl->eof) {
                DPRINTF("sio_stop: eof\n");
                return 0;
@@ -148,6 +150,28 @@ sio_stop(struct sio_hdl *hdl)
        return 1;
 }
 
+int
+sio_flush(struct sio_hdl *hdl)
+{
+       if (hdl->eof) {
+               DPRINTF("sio_flush: eof\n");
+               return 0;
+       }
+       if (!hdl->started) {
+               DPRINTF("sio_flush: not started\n");
+               hdl->eof = 1;
+               return 0;
+       }
+       if (!hdl->ops->flush(hdl))
+               return 0;
+#ifdef DEBUG
+       DPRINTFN(2, "libsndio: polls: %llu, samples = %llu\n",
+           hdl->pollcnt, hdl->cpos);
+#endif
+       hdl->started = 0;
+       return 1;
+}
+
 int
 sio_setpar(struct sio_hdl *hdl, struct sio_par *par)
 {
index 74a1ecd..24c4cd6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sio_aucat.c,v 1.20 2016/01/09 08:27:24 ratchov Exp $  */
+/*     $OpenBSD: sio_aucat.c,v 1.21 2022/04/29 08:30:48 ratchov Exp $  */
 /*
  * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
  *
@@ -49,6 +49,7 @@ struct sio_aucat_hdl {
 static void sio_aucat_close(struct sio_hdl *);
 static int sio_aucat_start(struct sio_hdl *);
 static int sio_aucat_stop(struct sio_hdl *);
+static int sio_aucat_flush(struct sio_hdl *);
 static int sio_aucat_setpar(struct sio_hdl *, struct sio_par *);
 static int sio_aucat_getpar(struct sio_hdl *, struct sio_par *);
 static int sio_aucat_getcap(struct sio_hdl *, struct sio_cap *);
@@ -69,6 +70,7 @@ static struct sio_ops sio_aucat_ops = {
        sio_aucat_read,
        sio_aucat_start,
        sio_aucat_stop,
+       sio_aucat_flush,
        sio_aucat_nfds,
        sio_aucat_pollfd,
        sio_aucat_revents,
@@ -207,7 +209,7 @@ sio_aucat_start(struct sio_hdl *sh)
 }
 
 static int
-sio_aucat_stop(struct sio_hdl *sh)
+sio_aucat_drain(struct sio_hdl *sh, int drain)
 {
 #define ZERO_MAX 0x400
        static unsigned char zero[ZERO_MAX];
@@ -240,6 +242,7 @@ sio_aucat_stop(struct sio_hdl *sh)
         */
        AMSG_INIT(&hdl->aucat.wmsg);
        hdl->aucat.wmsg.cmd = htonl(AMSG_STOP);
+       hdl->aucat.wmsg.u.stop.drain = drain;
        hdl->aucat.wtodo = sizeof(struct amsg);
        if (!_aucat_wmsg(&hdl->aucat, &hdl->sio.eof))
                return 0;
@@ -262,6 +265,18 @@ sio_aucat_stop(struct sio_hdl *sh)
        return 1;
 }
 
+static int
+sio_aucat_stop(struct sio_hdl *sh)
+{
+       return sio_aucat_drain(sh, 1);
+}
+
+static int
+sio_aucat_flush(struct sio_hdl *sh)
+{
+       return sio_aucat_drain(sh, 0);
+}
+
 static int
 sio_aucat_setpar(struct sio_hdl *sh, struct sio_par *par)
 {
index 3bbe489..836bb66 100644 (file)
@@ -1,4 +1,4 @@
-.\" $OpenBSD: sio_open.3,v 1.53 2022/03/31 17:27:18 naddy Exp $
+.\" $OpenBSD: sio_open.3,v 1.54 2022/04/29 08:30:48 ratchov Exp $
 .\"
 .\" Copyright (c) 2007 Alexandre Ratchov <alex@caoua.org>
 .\"
@@ -14,7 +14,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: March 31 2022 $
+.Dd $Mdocdate: April 29 2022 $
 .Dt SIO_OPEN 3
 .Os
 .Sh NAME
@@ -25,6 +25,7 @@
 .Nm sio_getcap ,
 .Nm sio_start ,
 .Nm sio_stop ,
+.Nm sio_flush ,
 .Nm sio_read ,
 .Nm sio_write ,
 .Nm sio_onmove ,
@@ -53,6 +54,8 @@
 .Fn sio_start "struct sio_hdl *hdl"
 .Ft "int"
 .Fn sio_stop "struct sio_hdl *hdl"
+.Ft "int"
+.Fn sio_flush "struct sio_hdl *hdl"
 .Ft "size_t"
 .Fn sio_read "struct sio_hdl *hdl" "void *addr" "size_t nbytes"
 .Ft "size_t"
@@ -257,6 +260,8 @@ Parameters cannot be changed after
 .Fn sio_start
 has been called,
 .Fn sio_stop
+or
+.Fn sio_flush
 must be called before parameters can be changed.
 .Pp
 If the device is exposed by the
@@ -410,6 +415,14 @@ If samples to play are queued but playback hasn't started yet
 then playback is forced immediately; playback will actually stop
 once the buffer is drained.
 In no case are samples in the play buffer discarded.
+.Pp
+The
+.Fn sio_flush
+function stops playback and recording immediately,
+possibly discarding play buffer contents, and puts the audio subsystem
+in the same state as before
+.Fn sio_start
+is called.
 .Ss Playing and recording
 When record mode is selected, the
 .Fn sio_read
@@ -748,6 +761,7 @@ The
 .Fn sio_getcap ,
 .Fn sio_start ,
 .Fn sio_stop ,
+.Fn sio_flush ,
 and
 .Fn sio_setvol
 functions return 1 on success and 0 on failure.
@@ -828,7 +842,8 @@ The
 .Fn sio_getpar ,
 .Fn sio_getcap ,
 .Fn sio_start ,
+.Fn sio_stop ,
 and
-.Fn sio_stop
+.Fn sio_flush
 functions may block for a very short period of time, thus they should
 be avoided in code sections where blocking is not desirable.
index fd31014..9f14332 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sio_priv.h,v 1.9 2015/01/16 16:48:52 deraadt Exp $    */
+/*     $OpenBSD: sio_priv.h,v 1.10 2022/04/29 08:30:48 ratchov Exp $   */
 /*
  * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
  *
@@ -58,6 +58,7 @@ struct sio_ops {
        size_t (*read)(struct sio_hdl *, void *, size_t);
        int (*start)(struct sio_hdl *);
        int (*stop)(struct sio_hdl *);
+       int (*flush)(struct sio_hdl *);
        int (*nfds)(struct sio_hdl *);
        int (*pollfd)(struct sio_hdl *, struct pollfd *, int);
        int (*revents)(struct sio_hdl *, struct pollfd *);
index 5ff939b..2863648 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sio_sun.c,v 1.28 2019/06/28 13:32:42 deraadt Exp $    */
+/*     $OpenBSD: sio_sun.c,v 1.29 2022/04/29 08:30:48 ratchov Exp $    */
 /*
  * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
  *
@@ -48,7 +48,7 @@ struct sio_sun_hdl {
 
 static void sio_sun_close(struct sio_hdl *);
 static int sio_sun_start(struct sio_hdl *);
-static int sio_sun_stop(struct sio_hdl *);
+static int sio_sun_flush(struct sio_hdl *);
 static int sio_sun_setpar(struct sio_hdl *, struct sio_par *);
 static int sio_sun_getpar(struct sio_hdl *, struct sio_par *);
 static int sio_sun_getcap(struct sio_hdl *, struct sio_cap *);
@@ -66,7 +66,8 @@ static struct sio_ops sio_sun_ops = {
        sio_sun_write,
        sio_sun_read,
        sio_sun_start,
-       sio_sun_stop,
+       NULL,
+       sio_sun_flush,
        sio_sun_nfds,
        sio_sun_pollfd,
        sio_sun_revents,
@@ -395,7 +396,7 @@ sio_sun_start(struct sio_hdl *sh)
 }
 
 static int
-sio_sun_stop(struct sio_hdl *sh)
+sio_sun_flush(struct sio_hdl *sh)
 {
        struct sio_sun_hdl *hdl = (struct sio_sun_hdl *)sh;
 
index 48bf862..e437c2a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: siofile.c,v 1.25 2021/11/01 14:43:25 ratchov Exp $    */
+/*     $OpenBSD: siofile.c,v 1.26 2022/04/29 08:30:48 ratchov Exp $    */
 /*
  * Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
  *
@@ -317,7 +317,7 @@ dev_sio_start(struct dev *d)
 void
 dev_sio_stop(struct dev *d)
 {
-       if (!sio_eof(d->sio.hdl) && !sio_stop(d->sio.hdl)) {
+       if (!sio_eof(d->sio.hdl) && !sio_flush(d->sio.hdl)) {
                if (log_level >= 1) {
                        dev_log(d);
                        log_puts(": failed to stop device\n");
index fcf97cf..382fa6a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sock.c,v 1.45 2021/11/01 14:43:25 ratchov Exp $       */
+/*     $OpenBSD: sock.c,v 1.46 2022/04/29 08:30:48 ratchov Exp $       */
 /*
  * Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
  *
@@ -1186,7 +1186,7 @@ sock_execmsg(struct sock *f)
                                f->ralign = s->round * s->mix.bpf;
                        }
                }
-               slot_stop(s, 1);
+               slot_stop(s, AMSG_ISSET(m->u.stop.drain) ? m->u.stop.drain : 1);
                break;
        case AMSG_SETPAR:
 #ifdef DEBUG