[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