[alsa-devel] [PATCH - IOPLUG DRAIN 0/2]
Takashi Iwai
tiwai at suse.de
Thu Mar 22 15:28:35 CET 2018
On Thu, 22 Mar 2018 14:48:55 +0100,
<twischer at 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);
More information about the Alsa-devel
mailing list