Add sio_flush(3) function to stop playback immediately

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.
This commit is contained in:
ratchov 2022-04-29 08:30:48 +00:00
parent 1f8040da28
commit ec8a3410fb
11 changed files with 79 additions and 18 deletions

View 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 *);

View File

@ -11,6 +11,7 @@
sio_read;
sio_start;
sio_stop;
sio_flush;
sio_nfds;
sio_pollfd;
sio_revents;

View 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;

View File

@ -1,2 +1,2 @@
major=7
minor=1
minor=2

View 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)
{

View 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)
{

View 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.

View 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 *);

View 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;

View 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");

View 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