mirror of https://github.com/ericonr/sndio.git
for alsa, POLL{IN,OUT} events mean that a block can be read or
written (not a byte as unix files expect). Use "tickets" counters that are reset to hdl->par.round on each POLL{IN,OUT} event. Limit read() and write() to one block to ensure poll is always called at block boundaries.
This commit is contained in:
parent
0441c58c62
commit
0e0511c762
|
@ -54,6 +54,7 @@ struct sio_alsa_hdl {
|
|||
int running;
|
||||
int events;
|
||||
int ipartial, opartial;
|
||||
int canread, canwrite;
|
||||
char *itmpbuf, *otmpbuf;
|
||||
};
|
||||
|
||||
|
@ -379,6 +380,8 @@ sio_alsa_start(struct sio_hdl *sh)
|
|||
hdl->infds = 0;
|
||||
hdl->onfds = 0;
|
||||
hdl->running = 0;
|
||||
hdl->canread = 0;
|
||||
hdl->canwrite = 0;
|
||||
|
||||
if (hdl->sio.mode & SIO_PLAY) {
|
||||
err = snd_pcm_prepare(hdl->opcm);
|
||||
|
@ -932,7 +935,12 @@ sio_alsa_read(struct sio_hdl *sh, void *buf, size_t len)
|
|||
len = hdl->ibpf;
|
||||
}
|
||||
}
|
||||
while ((n = snd_pcm_readi(hdl->ipcm, buf, len / hdl->ibpf)) < 0) {
|
||||
todo = len / hdl->ibpf;
|
||||
if (todo > hdl->canread)
|
||||
todo = hdl->canread;
|
||||
if (todo == 0)
|
||||
return 0;
|
||||
while ((n = snd_pcm_readi(hdl->ipcm, buf, todo)) < 0) {
|
||||
if (n == -EINTR)
|
||||
continue;
|
||||
if (n == -EPIPE || n == -ESTRPIPE) {
|
||||
|
@ -950,6 +958,7 @@ sio_alsa_read(struct sio_hdl *sh, void *buf, size_t len)
|
|||
hdl->sio.eof = 1;
|
||||
return 0;
|
||||
}
|
||||
hdl->canread -= n;
|
||||
hdl->idelta += n;
|
||||
if (buf == hdl->itmpbuf) {
|
||||
hdl->ipartial = hdl->ibpf;
|
||||
|
@ -977,7 +986,12 @@ sio_alsa_write(struct sio_hdl *sh, const void *buf, size_t len)
|
|||
len = hdl->obpf;
|
||||
buf = hdl->otmpbuf;
|
||||
}
|
||||
while ((n = snd_pcm_writei(hdl->opcm, buf, len / hdl->obpf)) < 0) {
|
||||
todo = len / hdl->obpf;
|
||||
if (todo > hdl->canwrite)
|
||||
todo = hdl->canwrite;
|
||||
if (todo == 0)
|
||||
return 0;
|
||||
while ((n = snd_pcm_writei(hdl->opcm, buf, todo)) < 0) {
|
||||
if (n == -EINTR)
|
||||
continue;
|
||||
if (n == -ESTRPIPE || n == -EPIPE) {
|
||||
|
@ -990,6 +1004,7 @@ sio_alsa_write(struct sio_hdl *sh, const void *buf, size_t len)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
hdl->canwrite -= n;
|
||||
hdl->odelta += n;
|
||||
if (buf == hdl->otmpbuf) {
|
||||
if (n > 0)
|
||||
|
@ -1054,32 +1069,37 @@ sio_alsa_pollfd(struct sio_hdl *sh, struct pollfd *pfd, int events)
|
|||
if (!hdl->sio.started)
|
||||
hdl->events = 0;
|
||||
memset(pfd, 0, sizeof(struct pollfd) * hdl->nfds);
|
||||
hdl->onfds = hdl->infds = 0;
|
||||
if (hdl->events & POLLOUT) {
|
||||
if (!hdl->running &&
|
||||
snd_pcm_state(hdl->opcm) == SND_PCM_STATE_RUNNING)
|
||||
sio_alsa_onmove(hdl);
|
||||
hdl->onfds = snd_pcm_poll_descriptors(hdl->opcm,
|
||||
pfd, hdl->nfds);
|
||||
if (hdl->onfds < 0) {
|
||||
DALSA("couldn't poll play descriptors", hdl->onfds);
|
||||
hdl->sio.eof = 1;
|
||||
return 0;
|
||||
if (hdl->canwrite == 0) {
|
||||
hdl->onfds = snd_pcm_poll_descriptors(hdl->opcm,
|
||||
pfd, hdl->nfds);
|
||||
if (hdl->onfds < 0) {
|
||||
DALSA("couldn't poll play descriptors",
|
||||
hdl->onfds);
|
||||
hdl->sio.eof = 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else
|
||||
hdl->onfds = 0;
|
||||
}
|
||||
if (hdl->events & POLLIN) {
|
||||
if (!hdl->running &&
|
||||
snd_pcm_state(hdl->ipcm) == SND_PCM_STATE_RUNNING)
|
||||
sio_alsa_onmove(hdl);
|
||||
hdl->infds = snd_pcm_poll_descriptors(hdl->ipcm,
|
||||
pfd + hdl->onfds, hdl->nfds - hdl->onfds);
|
||||
if (hdl->infds < 0) {
|
||||
DALSA("couldn't poll rec descriptors", hdl->infds);
|
||||
hdl->sio.eof = 1;
|
||||
return 0;
|
||||
if (hdl->canread == 0) {
|
||||
hdl->infds = snd_pcm_poll_descriptors(hdl->ipcm,
|
||||
pfd + hdl->onfds, hdl->nfds - hdl->onfds);
|
||||
if (hdl->infds < 0) {
|
||||
DALSA("couldn't poll rec descriptors",
|
||||
hdl->infds);
|
||||
hdl->sio.eof = 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else
|
||||
hdl->infds = 0;
|
||||
}
|
||||
DPRINTFN(4, "sio_alsa_pollfd: events = %x, nfds = %d + %d\n",
|
||||
events, hdl->onfds, hdl->infds);
|
||||
|
||||
|
@ -1097,7 +1117,7 @@ sio_alsa_revents(struct sio_hdl *sh, struct pollfd *pfd)
|
|||
snd_pcm_sframes_t iused, oavail, oused;
|
||||
snd_pcm_state_t istate, ostate;
|
||||
unsigned short revents, r;
|
||||
int nfds, err, i;
|
||||
int nfds, err, i, cycle;
|
||||
|
||||
if (hdl->sio.eof)
|
||||
return POLLHUP;
|
||||
|
@ -1106,27 +1126,41 @@ sio_alsa_revents(struct sio_hdl *sh, struct pollfd *pfd)
|
|||
DPRINTFN(4, "sio_alsa_revents: pfds[%d].revents = %x\n",
|
||||
i, pfd[i].revents);
|
||||
}
|
||||
revents = nfds = 0;
|
||||
cycle = 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;
|
||||
}
|
||||
if (hdl->canwrite == 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;
|
||||
}
|
||||
if (r & POLLOUT) {
|
||||
hdl->canwrite = hdl->par.round;
|
||||
cycle = 1;
|
||||
}
|
||||
} else
|
||||
r = POLLOUT;
|
||||
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;
|
||||
}
|
||||
if (hdl->canread == 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;
|
||||
}
|
||||
if (r & POLLIN) {
|
||||
hdl->canread = hdl->par.round;
|
||||
cycle = 1;
|
||||
}
|
||||
} else
|
||||
r = POLLIN;
|
||||
revents |= r;
|
||||
nfds += hdl->infds;
|
||||
}
|
||||
|
@ -1179,7 +1213,7 @@ sio_alsa_revents(struct sio_hdl *sh, struct pollfd *pfd)
|
|||
hdl->iused = iused;
|
||||
}
|
||||
}
|
||||
if (revents & (POLLIN | POLLOUT))
|
||||
if (cycle && hdl->running)
|
||||
sio_alsa_onmove(hdl);
|
||||
return revents;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue