move wsil/rdrop code in sio.c

This commit is contained in:
Alexandre Ratchov 2013-04-12 16:14:53 +02:00
parent 92bec779c0
commit 8748c853c2
4 changed files with 132 additions and 327 deletions

View File

@ -131,6 +131,7 @@ sio_start(struct sio_hdl *hdl)
clock_gettime(CLOCK_MONOTONIC, &ts);
hdl->start_nsec = 1000000000LL * ts.tv_sec + ts.tv_nsec;
#endif
hdl->rdrop = hdl->wsil = 0;
if (!hdl->ops->start(hdl))
return 0;
hdl->started = 1;
@ -254,6 +255,46 @@ sio_psleep(struct sio_hdl *hdl, int event)
return 1;
}
static int
sio_rdrop(struct sio_hdl *hdl)
{
#define DROP_NMAX 0x1000
static char dummy[DROP_NMAX];
ssize_t n, todo;
while (hdl->rdrop > 0) {
todo = hdl->rdrop;
if (todo > DROP_NMAX)
todo = DROP_NMAX;
n = hdl->ops->read(hdl, dummy, todo);
if (n == 0)
return 0;
hdl->rdrop -= n;
DPRINTF("sio_rdrop: dropped %zu/%zu bytes\n", n, todo);
}
return 1;
}
static int
sio_wsil(struct sio_hdl *hdl)
{
#define ZERO_NMAX 0x1000
static char zero[ZERO_NMAX];
ssize_t n, todo;
while (hdl->wsil > 0) {
todo = hdl->wsil;
if (todo > ZERO_NMAX)
todo = ZERO_NMAX;
n = hdl->ops->write(hdl, zero, todo);
if (n == 0)
return 0;
hdl->wsil -= n;
DPRINTF("sio_wsil: inserted %zu/%zu bytes\n", n, todo);
}
return 1;
}
size_t
sio_read(struct sio_hdl *hdl, void *buf, size_t len)
{
@ -274,6 +315,8 @@ sio_read(struct sio_hdl *hdl, void *buf, size_t len)
DPRINTF("sio_read: zero length read ignored\n");
return 0;
}
if (!sio_rdrop(hdl))
return 0;
while (todo > 0) {
n = hdl->ops->read(hdl, data, todo);
if (n == 0) {
@ -312,6 +355,8 @@ sio_write(struct sio_hdl *hdl, const void *buf, size_t len)
DPRINTF("sio_write: zero length write ignored\n");
return 0;
}
if (!sio_wsil(hdl))
return 0;
while (todo > 0) {
n = hdl->ops->write(hdl, data, todo);
if (n == 0) {
@ -375,6 +420,10 @@ sio_revents(struct sio_hdl *hdl, struct pollfd *pfd)
ts1.tv_nsec - ts0.tv_nsec);
}
#endif
if ((hdl->mode & SIO_PLAY) && !sio_wsil(hdl))
revents &= ~POLLOUT;
if ((hdl->mode & SIO_REC) && !sio_rdrop(hdl))
revents &= ~POLLIN;
return revents;
}
@ -408,9 +457,9 @@ sio_printpos(struct sio_hdl *hdl)
clock_gettime(CLOCK_MONOTONIC, &ts);
rpos = (hdl->mode & SIO_REC) ?
hdl->rcnt / (hdl->par.bps * hdl->par.rchan) : 0;// + hdl->idrop;
hdl->rcnt / (hdl->par.bps * hdl->par.rchan) : 0;
wpos = (hdl->mode & SIO_PLAY) ?
hdl->wcnt / (hdl->par.bps * hdl->par.pchan) : 0;// + hdl->osil;
hdl->wcnt / (hdl->par.bps * hdl->par.pchan) : 0;
cdiff = hdl->cpos % hdl->par.round;
cpos = hdl->cpos / hdl->par.round;
@ -442,7 +491,7 @@ sio_onmove_cb(struct sio_hdl *hdl, int delta)
{
#ifdef DEBUG
hdl->cpos += delta;
if (sndio_debug >= 2)
if (sndio_debug >= 1)
sio_printpos(hdl);
#endif
if (hdl->move_cb)

View File

@ -48,16 +48,11 @@ struct sio_alsa_hdl {
snd_pcm_t *opcm;
snd_pcm_t *ipcm;
unsigned ibpf, obpf; /* bytes per frame */
unsigned int osil; /* frames to insert on next write */
unsigned int idrop; /* frames to discard on next read */
int iused, oused; /* frames used in hardware fifos */
int idelta, odelta; /* position reported to client */
int nfds, infds, onfds;
int running;
int events;
long long wpos; /* frames written */
long long rpos; /* frames read */
long long cpos; /* hardware position (frames) */
};
static void sio_alsa_close(struct sio_hdl *);
@ -275,11 +270,6 @@ sio_alsa_open(const char *str, unsigned mode, int nbio)
* that grows later, after the stream is started
*/
hdl->nfds = SIO_MAXNFDS;
//if (mode & SIO_PLAY)
// hdl->nfds += snd_pcm_poll_descriptors_count(hdl->opcm);
//if (mode & SIO_REC)
// hdl->nfds += snd_pcm_poll_descriptors_count(hdl->ipcm);
DPRINTF("mode = %d, nfds = %d\n", mode, hdl->nfds);
/*
* Default parameters may not be compatible with libsndio (eg. mulaw
@ -322,45 +312,6 @@ sio_alsa_close(struct sio_hdl *sh)
free(hdl);
}
#ifdef DEBUG
void
sio_alsa_printpos(struct sio_alsa_hdl *hdl)
{
long long rpos, rdiff;
long long cpos, cdiff;
long long wpos, wdiff;
rpos = hdl->rpos + hdl->idrop;
wpos = hdl->wpos + hdl->osil;
cdiff = hdl->cpos % hdl->par.round;
cpos = hdl->cpos / hdl->par.round;
if (cdiff > hdl->par.round / 2) {
cpos++;
cdiff = cdiff - hdl->par.round;
}
rdiff = rpos % hdl->par.round;
rpos = rpos / hdl->par.round;
if (rdiff > hdl->par.round / 2) {
rpos++;
rdiff = rdiff - hdl->par.round;
}
wdiff = wpos % hdl->par.round;
wpos = wpos / hdl->par.round;
if (wdiff > hdl->par.round / 2) {
wpos++;
wdiff = wdiff - hdl->par.round;
}
//DPRINTF("iused=%d idelta=%d oused=%d, odelta=%d\n",
// hdl->iused, hdl->idelta, hdl->oused, hdl->odelta);
DPRINTF("clk: %+4lld %+4lld, wr %+4lld %+4lld rd: %+4lld %+4lld\n",
cpos, cdiff, wpos, wdiff, rpos, rdiff);
}
#endif
static int
sio_alsa_start(struct sio_hdl *sh)
{
@ -377,10 +328,7 @@ sio_alsa_start(struct sio_hdl *sh)
hdl->odelta = 0;
hdl->infds = 0;
hdl->onfds = 0;
hdl->osil = 0;
hdl->idrop = 0;
hdl->running = 0;
hdl->cpos = hdl->rpos = hdl->wpos = 0;
if (hdl->sio.mode & SIO_PLAY) {
err = snd_pcm_prepare(hdl->opcm);
@ -458,13 +406,15 @@ sio_alsa_xrun(struct sio_alsa_hdl *hdl)
int wdiff, cdiff, rdiff;
int wsil, rdrop, cmove;
DPRINTF("- - - - - - - - - - - - - - - - - - - - - xrun begin\n");
sio_alsa_printpos(hdl);
DPRINTF("sio_alsa_xrun:\n");
sio_printpos(&hdl->sio);
rpos = (hdl->sio.mode & SIO_REC) ? hdl->rpos : hdl->cpos;
wpos = (hdl->sio.mode & SIO_PLAY) ? hdl->wpos : hdl->cpos;
rpos = (hdl->sio.mode & SIO_REC) ?
hdl->sio.rcnt / hdl->ibpf : hdl->sio.cpos;
wpos = (hdl->sio.mode & SIO_PLAY) ?
hdl->sio.wcnt / hdl->obpf : hdl->sio.cpos;
cdiff = hdl->par.round - (hdl->cpos % hdl->par.round);
cdiff = hdl->par.round - (hdl->sio.cpos % hdl->par.round);
if (cdiff == hdl->par.round)
cdiff = 0;
@ -478,7 +428,7 @@ sio_alsa_xrun(struct sio_alsa_hdl *hdl)
wsil = rdiff + wpos - rpos;
rdrop = rdiff;
cmove = -(rdiff + hdl->cpos - rpos);
cmove = -(rdiff + hdl->sio.cpos - rpos);
DPRINTF("wsil = %d, cmove = %d, rdrop = %d\n", wsil, cmove, rdrop);
@ -486,20 +436,17 @@ sio_alsa_xrun(struct sio_alsa_hdl *hdl)
return 0;
if (!sio_alsa_start(&hdl->sio))
return 0;
if (hdl->sio.mode & SIO_PLAY) {
hdl->osil = wsil;
hdl->odelta -= cmove;
hdl->odelta += cmove;
hdl->sio.wsil += wsil * hdl->obpf;
}
if (hdl->sio.mode & SIO_REC) {
hdl->idrop = rdrop;
hdl->idelta -= rdiff;
hdl->idelta += cmove;
hdl->sio.rdrop += rdrop * hdl->ibpf;
}
DPRINTF("xrun: corrected\n");
DPRINTF("osil = %d, odrop = %d, odelta = %d, idelta = %d\n",
hdl->osil, hdl->idrop, hdl->odelta, hdl->idelta);
sio_alsa_printpos(hdl);
DPRINTF("- - - - - - - - - - - - - - - - - - - - - xrun end\n");
DPRINTF("wsil = %d, rdrop = %d, odelta = %d, idelta = %d\n",
wsil, rdrop, hdl->odelta, hdl->idelta);
return 1;
}
@ -794,59 +741,6 @@ sio_alsa_getpar(struct sio_hdl *sh, struct sio_par *par)
return 1;
}
/*
* drop recorded samples to compensate xruns
*/
static int
sio_alsa_rdrop(struct sio_alsa_hdl *hdl)
{
#define DROP_NMAX 0x1000
static char buf[DROP_NMAX];
ssize_t n, todo, max;
if (hdl->idrop == 0)
return 1;
max = DROP_NMAX / hdl->ibpf;
while (hdl->idrop > 0) {
todo = hdl->idrop;
if (todo > max)
todo = max;
while ((n = snd_pcm_readi(hdl->ipcm, buf, todo)) < 0) {
if (n == -EINTR)
continue;
if (n == -EPIPE || n == -ESTRPIPE) {
sio_alsa_xrun(hdl);
return 0;
}
if (n != -EAGAIN) {
DALSA("couldn't read data to drop", n);
hdl->sio.eof = 1;
}
return 0;
}
if (n == 0) {
DPRINTF("sio_alsa_rdrop: eof\n");
hdl->sio.eof = 1;
return 0;
}
hdl->idrop -= n;
hdl->rpos += n;
/*
* dropping samples is clock-wise neutral, so we
* should not bump hdl->idelta += n; but since
* we dropped samples, kernel buffer usage changed
* and we have to take this into account here, to
* prevent sio_alsa_revents() interpretin iused
* change as clock tick
*/
hdl->iused -= n;
DPRINTF("sio_alsa_rdrop: dropped %zu/%zu frames\n", n, todo);
}
return 0;
}
static size_t
sio_alsa_read(struct sio_hdl *sh, void *buf, size_t len)
{
@ -873,67 +767,17 @@ sio_alsa_read(struct sio_hdl *sh, void *buf, size_t len)
hdl->sio.eof = 1;
return 0;
}
hdl->rpos += n;
hdl->idelta += n;
n *= hdl->ibpf;
return n;
}
/*
* insert silence to play to compensate xruns
*/
static int
sio_alsa_wsil(struct sio_alsa_hdl *hdl)
{
#define ZERO_NMAX 0x10000
static char zero[ZERO_NMAX];
ssize_t n, todo, max;
if (hdl->osil == 0)
return 1;
max = ZERO_NMAX / hdl->obpf;
while (hdl->osil > 0) {
todo = hdl->osil;
if (todo > max)
todo = max;
while ((n = snd_pcm_writei(hdl->opcm, zero, todo)) < 0) {
if (n == -EINTR)
continue;
if (n == -ESTRPIPE || n == -EPIPE) {
sio_alsa_xrun(hdl);
return 0;
}
if (n != -EAGAIN) {
DALSA("couldn't write silence", n);
hdl->sio.eof = 1;
}
return 0;
}
#ifdef DEBUG
hdl->wpos += n;
#endif
/*
* be clock-wise neutral, see end of sio_alsa_wsil()
*/
hdl->oused += n;
hdl->osil -= n;
DPRINTF("sio_alsa_wsil: inserted %zu/%zu frames\n", n, todo);
}
return 0;
}
static size_t
sio_alsa_write(struct sio_hdl *sh, const void *buf, size_t len)
{
struct sio_alsa_hdl *hdl = (struct sio_alsa_hdl *)sh;
ssize_t n, todo;
if (hdl->osil) {
if (!sio_alsa_wsil(hdl))
return 0;
return 0;
}
if (len < hdl->obpf) {
/*
* we can't just return, because sio_write() will loop
@ -960,9 +804,6 @@ sio_alsa_write(struct sio_hdl *sh, const void *buf, size_t len)
return 0;
}
DPRINTFN(2, "sio_alsa_write: wrote %zd\n", n);
#ifdef DEBUG
hdl->wpos += n;
#endif
hdl->odelta += n;
n *= hdl->obpf;
return n;
@ -973,11 +814,6 @@ sio_alsa_onmove(struct sio_alsa_hdl *hdl)
{
int delta;
if (hdl->sio.mode & SIO_PLAY)
DPRINTF("ostate = %d\n", snd_pcm_state(hdl->opcm));
if (hdl->sio.mode & SIO_REC)
DPRINTF("istate = %d\n", snd_pcm_state(hdl->ipcm));
if (hdl->running) {
switch (hdl->sio.mode & (SIO_PLAY | SIO_REC)) {
case SIO_PLAY:
@ -997,11 +833,6 @@ sio_alsa_onmove(struct sio_alsa_hdl *hdl)
delta = 0;
hdl->running = 1;
}
#ifdef DEBUG
hdl->cpos += delta;
if (sndio_debug >= 1)
sio_alsa_printpos(hdl);
#endif
sio_onmove_cb(&hdl->sio, delta);
if (hdl->sio.mode & SIO_PLAY)
hdl->odelta -= delta;
@ -1026,10 +857,14 @@ sio_alsa_pollfd(struct sio_hdl *sh, struct pollfd *pfd, int events)
if (hdl->sio.eof)
return 0;
hdl->events = events;
hdl->events = events & (POLLIN | POLLOUT);
if (!(hdl->sio.mode & SIO_PLAY))
hdl->events &= ~POLLOUT;
if (!(hdl->sio.mode & SIO_REC))
hdl->events &= ~POLLIN;
memset(pfd, 0, sizeof(struct pollfd) * hdl->nfds);
if ((events & POLLOUT) && (hdl->sio.mode & SIO_PLAY) &&
hdl->sio.started) {
if ((events & POLLOUT) && hdl->sio.started) {
if (!hdl->running &&
snd_pcm_state(hdl->opcm) == SND_PCM_STATE_RUNNING)
sio_alsa_onmove(hdl);
@ -1042,8 +877,7 @@ sio_alsa_pollfd(struct sio_hdl *sh, struct pollfd *pfd, int events)
}
} else
hdl->onfds = 0;
if ((events & POLLIN) && (hdl->sio.mode & SIO_REC) &&
hdl->sio.started) {
if ((events & POLLIN) && hdl->sio.started) {
if (!hdl->running &&
snd_pcm_state(hdl->ipcm) == SND_PCM_STATE_RUNNING)
sio_alsa_onmove(hdl);
@ -1079,50 +913,18 @@ sio_alsa_revents(struct sio_hdl *sh, struct pollfd *pfd)
return POLLHUP;
for (i = 0; i < hdl->onfds + hdl->infds; i++) {
DPRINTFN(3, "sio_alsa_revents: pfds[%d].events = %x\n",
DPRINTFN(3, "sio_alsa_revents: pfds[%d].revents = %x\n",
i, pfd[i].revents);
}
revents = nfds = 0;
if ((hdl->events & POLLOUT) && (hdl->sio.mode & SIO_PLAY)) {
if (hdl->sio.mode & SIO_PLAY) {
ostate = snd_pcm_state(hdl->opcm);
if (ostate == SND_PCM_STATE_XRUN) {
if (!sio_alsa_xrun(hdl))
return POLLHUP;
return 0;
}
err = snd_pcm_poll_descriptors_revents(hdl->opcm,
pfd, hdl->onfds, &r);
if (err < 0) {
DALSA("couldn't get play events", err);
hdl->sio.eof = 1;
return POLLHUP;
}
revents |= r;
nfds += hdl->onfds;
}
if ((hdl->events & POLLIN) && (hdl->sio.mode & SIO_REC)) {
istate = snd_pcm_state(hdl->ipcm);
if (istate == SND_PCM_STATE_XRUN) {
if (!sio_alsa_xrun(hdl))
return POLLHUP;
return 0;
}
err = snd_pcm_poll_descriptors_revents(hdl->ipcm,
pfd + nfds, hdl->infds, &r);
if (err < 0) {
DALSA("couldn't get rec events", err);
hdl->sio.eof = 1;
return POLLHUP;
}
revents |= r;
nfds += hdl->infds;
}
DPRINTFN(2, "sio_alsa_revents: revents = %x\n", revents);
if (revents & (POLLIN | POLLOUT)) {
if ((hdl->sio.mode & SIO_PLAY) &&
(ostate == SND_PCM_STATE_RUNNING ||
ostate == SND_PCM_STATE_PREPARED)) {
if (ostate == SND_PCM_STATE_RUNNING ||
ostate == SND_PCM_STATE_PREPARED) {
oavail = snd_pcm_avail_update(hdl->opcm);
if (oavail < 0) {
if (oavail == -EPIPE || oavail == -ESTRPIPE) {
@ -1138,9 +940,16 @@ sio_alsa_revents(struct sio_hdl *sh, struct pollfd *pfd)
hdl->odelta -= oused - hdl->oused;
hdl->oused = oused;
}
if ((hdl->sio.mode & SIO_REC) &&
(istate == SND_PCM_STATE_RUNNING ||
istate == SND_PCM_STATE_PREPARED)) {
}
if (hdl->sio.mode & SIO_REC) {
istate = snd_pcm_state(hdl->ipcm);
if (istate == SND_PCM_STATE_XRUN) {
if (!sio_alsa_xrun(hdl))
return POLLHUP;
return 0;
}
if (istate == SND_PCM_STATE_RUNNING ||
istate == SND_PCM_STATE_PREPARED) {
iused = snd_pcm_avail_update(hdl->ipcm);
if (iused < 0) {
if (iused == -EPIPE || iused == -ESTRPIPE) {
@ -1155,17 +964,33 @@ sio_alsa_revents(struct sio_hdl *sh, struct pollfd *pfd)
hdl->idelta += iused - hdl->iused;
hdl->iused = iused;
}
if (hdl->running ||
((hdl->sio.mode & SIO_PLAY) &&
ostate == SND_PCM_STATE_RUNNING) ||
((hdl->sio.mode & SIO_REC) &&
istate == SND_PCM_STATE_RUNNING))
sio_alsa_onmove(hdl);
}
if ((hdl->sio.mode & SIO_PLAY) && !sio_alsa_wsil(hdl))
revents &= ~POLLOUT;
if ((hdl->sio.mode & SIO_REC) && !sio_alsa_rdrop(hdl))
revents &= ~POLLIN;
revents = nfds = 0;
if (hdl->events & POLLOUT) {
err = snd_pcm_poll_descriptors_revents(hdl->opcm,
pfd, hdl->onfds, &r);
if (err < 0) {
DALSA("couldn't get play events", err);
hdl->sio.eof = 1;
return POLLHUP;
}
revents |= r;
nfds += hdl->onfds;
}
if (hdl->events & POLLIN) {
err = snd_pcm_poll_descriptors_revents(hdl->ipcm,
pfd + nfds, hdl->infds, &r);
if (err < 0) {
DALSA("couldn't get rec events", err);
hdl->sio.eof = 1;
return POLLHUP;
}
revents |= r;
nfds += hdl->infds;
}
if (revents & (POLLIN | POLLOUT))
sio_alsa_onmove(hdl);
return revents;
}
#endif /* defined USE_ALSA */

View File

@ -35,6 +35,8 @@ struct sio_hdl {
int started; /* true if started */
int nbio; /* true if non-blocking io */
int eof; /* true if error occured */
int rdrop; /* recorded bytes to drop */
int wsil; /* silence to play */
#ifdef DEBUG
unsigned long long pollcnt; /* times sio_revents was called */
long long wcnt; /* bytes written with sio_write() */
@ -75,5 +77,8 @@ void sio_create(struct sio_hdl *, struct sio_ops *, unsigned, int);
void sio_destroy(struct sio_hdl *);
void sio_onmove_cb(struct sio_hdl *, int);
void sio_onvol_cb(struct sio_hdl *, unsigned);
#ifdef DEBUG
void sio_printpos(struct sio_hdl *);
#endif
#endif /* !defined(SNDIO_PRIV_H) */

View File

@ -52,9 +52,7 @@ struct sio_sun_hdl {
unsigned int ibpf, obpf; /* bytes per frame */
unsigned int ibytes, obytes; /* bytes the hw transferred */
unsigned int ierr, oerr; /* frames the hw dropped */
int offset; /* frames play is ahead of record */
int idelta, odelta; /* position reported to client */
int mix_fd, mix_index; /* /dev/mixerN stuff */
};
static void sio_sun_close(struct sio_hdl *);
@ -452,7 +450,6 @@ sio_sun_start(struct sio_hdl *sh)
hdl->obytes = 0;
hdl->ierr = 0;
hdl->oerr = 0;
hdl->offset = 0;
hdl->idelta = 0;
hdl->odelta = 0;
@ -728,48 +725,12 @@ sio_sun_getpar(struct sio_hdl *sh, struct sio_par *par)
return 1;
}
/*
* drop recorded samples to compensate xruns
*/
static int
sio_sun_rdrop(struct sio_sun_hdl *hdl)
{
#define DROP_NMAX 0x1000
static char dropbuf[DROP_NMAX];
ssize_t n, todo;
while (hdl->offset > 0) {
todo = hdl->offset * hdl->ibpf;
if (todo > DROP_NMAX)
todo = DROP_NMAX - DROP_NMAX % hdl->ibpf;
while ((n = read(hdl->fd, dropbuf, todo)) < 0) {
if (errno == EINTR)
continue;
if (errno != EAGAIN) {
DPERROR("sio_sun_rdrop: read");
hdl->sio.eof = 1;
}
return 0;
}
if (n == 0) {
DPRINTF("sio_sun_rdrop: eof\n");
hdl->sio.eof = 1;
return 0;
}
hdl->offset -= (int)n / (int)hdl->ibpf;
DPRINTF("sio_sun_rdrop: dropped %ld/%ld bytes\n", n, todo);
}
return 1;
}
static size_t
sio_sun_read(struct sio_hdl *sh, void *buf, size_t len)
{
struct sio_sun_hdl *hdl = (struct sio_sun_hdl *)sh;
ssize_t n;
if (!sio_sun_rdrop(hdl))
return 0;
while ((n = read(hdl->fd, buf, len)) < 0) {
if (errno == EINTR)
continue;
@ -819,37 +780,6 @@ sio_sun_autostart(struct sio_sun_hdl *hdl)
return 1;
}
/*
* insert silence to play to compensate xruns
*/
static int
sio_sun_wsil(struct sio_sun_hdl *hdl)
{
#define ZERO_NMAX 0x1000
static char zero[ZERO_NMAX];
ssize_t n, todo;
while (hdl->offset < 0) {
todo = (int)-hdl->offset * (int)hdl->obpf;
if (todo > ZERO_NMAX)
todo = ZERO_NMAX - ZERO_NMAX % hdl->obpf;
while ((n = write(hdl->fd, zero, todo)) < 0) {
if (errno == EINTR)
continue;
if (errno != EAGAIN) {
DPERROR("sio_sun_wsil: write");
hdl->sio.eof = 1;
return 0;
}
return 0;
}
hdl->offset += (int)n / (int)hdl->obpf;
DPRINTF("sio_sun_wsil: inserted %ld/%ld bytes\n", n, todo);
}
return 1;
}
static size_t
sio_sun_write(struct sio_hdl *sh, const void *buf, size_t len)
{
@ -857,8 +787,6 @@ sio_sun_write(struct sio_hdl *sh, const void *buf, size_t len)
const unsigned char *data = buf;
ssize_t n, todo;
if (!sio_sun_wsil(hdl))
return 0;
todo = len;
while ((n = write(hdl->fd, data, todo)) < 0) {
if (errno == EINTR)
@ -897,7 +825,7 @@ sio_sun_revents(struct sio_hdl *sh, struct pollfd *pfd)
{
struct sio_sun_hdl *hdl = (struct sio_sun_hdl *)sh;
struct audio_offset ao;
int xrun, dmove, dierr = 0, doerr = 0, delta;
int xrun, dmove, dierr = 0, doerr = 0, offset, delta;
int revents = pfd->revents;
if (!hdl->sio.started)
@ -948,10 +876,17 @@ sio_sun_revents(struct sio_hdl *sh, struct pollfd *pfd)
if (!(hdl->sio.mode & SIO_PLAY))
doerr = dierr;
}
hdl->offset += doerr - dierr;
dmove = dierr > doerr ? dierr : doerr;
hdl->idelta -= dmove;
hdl->odelta -= dmove;
offset = doerr - dierr;
if (offset > 0) {
hdl->sio.rdrop += offset;
hdl->idelta -= doerr;
hdl->odelta -= doerr;
dmove = doerr;
} else if (offset < 0) {
hdl->sio.wsil += -offset;
hdl->idelta -= dierr;
hdl->odelta -= dierr;
}
delta = (hdl->idelta > hdl->odelta) ? hdl->idelta : hdl->odelta;
if (delta > 0) {
@ -960,17 +895,8 @@ sio_sun_revents(struct sio_hdl *sh, struct pollfd *pfd)
hdl->odelta -= delta;
}
/*
* drop recorded samples or insert silence to play
* right now to adjust revents, and avoid busy loops
* programs
*/
if (hdl->filling)
revents |= POLLOUT;
if ((hdl->sio.mode & SIO_PLAY) && !sio_sun_wsil(hdl))
revents &= ~POLLOUT;
if ((hdl->sio.mode & SIO_REC) && !sio_sun_rdrop(hdl))
revents &= ~POLLIN;
revents |= POLLOUT; /* XXX: is this necessary ? */
return revents;
}
#endif /* defined USE_SUN */