On Thu, 22 Mar 2018 14:48:55 +0100, twischer@de.adit-jv.com wrote:
Hi Takashi,
Why not poll()?
IOW, why ioplug must be handled specially regarding the non-blocking operation? The normal kernel driver behaves like that (returning -EAGAIN, and let apps to sync with poll()).
What do you think about the following solution?
(I thought the whole time that you have to use snd_pcm_wait() to wait for drain in nonblocking mode but you have to use the poll_descriptors directly.)
Know I am expecting that the user is calling poll() if snd_pcm_drain() returns -EAGAIN and the user has to call snd_pcm_drain() again after poll returns to check if drain is done.
Well, the drain callback *should* block and wait until drained. That was the intention of the callback.
What I suggested instead is that ioctl shouldn't call drain callback in non-blocking mode, but it should return -EAGAIN there.
That said, a change like below. And in the plugin side, it can assume the blocking mode and simply waits until drained.
thanks,
Takashi
---
diff --git a/src/pcm/pcm_ioplug.c b/src/pcm/pcm_ioplug.c index 8c0ed4836365..33f7c5c27b6f 100644 --- a/src/pcm/pcm_ioplug.c +++ b/src/pcm/pcm_ioplug.c @@ -494,12 +494,37 @@ static int snd_pcm_ioplug_drain(snd_pcm_t *pcm) ioplug_priv_t *io = pcm->private_data; int err;
- if (io->data->state == SND_PCM_STATE_OPEN) + switch (io->data->state) { + case SND_PCM_STATE_OPEN: + case SND_PCM_STATE_DISCONNECTED: + case SND_PCM_STATE_SUSPENDED: return -EBADFD; + case SND_PCM_STATE_PREPARED: + if (pcm->stream == SND_PCM_STREAM_PLAYBACK) { + snd_pcm_lock(pcm); + err = snd_pcm_ioplug_start(pcm); + snd_pcm_unlock(pcm); + if (err < 0) + return err; + io->data->state = SND_PCM_STATE_DRAINING; + } + break; + case SND_PCM_STATE_RUNNING: + io->data->state = SND_PCM_STATE_DRAINING; + break; + } + + if (io->data->state == SND_PCM_STATE_DRAINING) { + if (io->data->nonblock) + return -EAGAIN; + + if (io->data->callback->drain) { + err = io->data->callback->drain(io->data); + if (err < 0) + return err; + } + }
- io->data->state = SND_PCM_STATE_DRAINING; - if (io->data->callback->drain) - io->data->callback->drain(io->data); snd_pcm_lock(pcm); err = snd_pcm_ioplug_drop(pcm); snd_pcm_unlock(pcm);