diff options
author | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2014-03-05 20:40:50 +0000 |
---|---|---|
committer | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2014-03-05 20:40:50 +0000 |
commit | b44d0b8f3ec7db2b4ec2a73b639b3b990bdd7c94 (patch) | |
tree | 8755deebb0979f62f2f4bffa835577a478cd0413 /lib/libsndio/sio_sun.c | |
parent | a18588b445edf7039f38a835c60b47c33d0d623c (diff) |
- use relative read/write positions to keep track of buffer
usage as seen by the caller
- refresh current position before reading/writing data, to keep the
current position always consistent with read & write pointers
- fix confusion between processed samples by the hardware (as reported
by GET{I,O}OFFS) and samples played as reported by GETINFO(). Fixes
incorrect delta propagated after xruns in play-only and rec-only
modes
- don't wait for POLLIN or POLLOUT to be set to refresh ring pointers,
as they may not be set in certain cases. Fixes sndiod crash after
few days of continuous playback.
- save current parameters instead of calling getpar() too often
Diffstat (limited to 'lib/libsndio/sio_sun.c')
-rw-r--r-- | lib/libsndio/sio_sun.c | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/lib/libsndio/sio_sun.c b/lib/libsndio/sio_sun.c index 023ff4b1b5a..948302eaa96 100644 --- a/lib/libsndio/sio_sun.c +++ b/lib/libsndio/sio_sun.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sio_sun.c,v 1.10 2013/12/20 08:51:28 ratchov Exp $ */ +/* $OpenBSD: sio_sun.c,v 1.11 2014/03/05 20:40:49 ratchov Exp $ */ /* * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> * @@ -436,14 +436,11 @@ sio_sun_close(struct sio_hdl *sh) static int sio_sun_start(struct sio_hdl *sh) { - struct sio_par par; struct sio_sun_hdl *hdl = (struct sio_sun_hdl *)sh; struct audio_info aui; - if (!sio_getpar(&hdl->sio, &par)) - return 0; - hdl->obpf = par.pchan * par.bps; - hdl->ibpf = par.rchan * par.bps; + hdl->obpf = hdl->sio.par.pchan * hdl->sio.par.bps; + hdl->ibpf = hdl->sio.par.rchan * hdl->sio.par.bps; hdl->ibytes = 0; hdl->obytes = 0; hdl->ierr = 0; @@ -828,7 +825,7 @@ sio_sun_revents(struct sio_hdl *sh, struct pollfd *pfd) if (!hdl->sio.started) return pfd->revents; - if ((revents & POLLOUT) && (hdl->sio.mode & SIO_PLAY)) { + if (hdl->sio.mode & SIO_PLAY) { if (ioctl(hdl->fd, AUDIO_GETOOFFS, &ao) < 0) { DPERROR("sio_sun_revents: GETOOFFS"); hdl->sio.eof = 1; @@ -840,7 +837,7 @@ sio_sun_revents(struct sio_hdl *sh, struct pollfd *pfd) if (!(hdl->sio.mode & SIO_REC)) hdl->idelta += delta; } - if ((revents & POLLIN) && (hdl->sio.mode & SIO_REC)) { + if (hdl->sio.mode & SIO_REC) { if (ioctl(hdl->fd, AUDIO_GETIOFFS, &ao) < 0) { DPERROR("sio_sun_revents: GETIOFFS"); hdl->sio.eof = 1; @@ -878,16 +875,22 @@ sio_sun_revents(struct sio_hdl *sh, struct pollfd *pfd) if (dierr > 0) DPRINTFN(2, "rec xrun %d\n", dierr); } + + /* + * GET{I,O}OFFS report positions including xruns, + * so we have to substract to get the real position + */ + hdl->idelta -= dierr; + hdl->odelta -= doerr; + offset = doerr - dierr; if (offset > 0) { hdl->sio.rdrop += offset * hdl->ibpf; - hdl->idelta -= doerr; - hdl->odelta -= doerr; + hdl->idelta -= offset; DPRINTFN(2, "will drop %d and pause %d\n", offset, doerr); } else if (offset < 0) { hdl->sio.wsil += -offset * hdl->obpf; - hdl->idelta -= dierr; - hdl->odelta -= dierr; + hdl->odelta -= offset; DPRINTFN(2, "will insert %d and pause %d\n", -offset, dierr); } |