[alsa-devel] SNDRV_PCM_TRIGGER_STOP and audio still queued in the driver
Takashi Iwai
tiwai at suse.de
Wed Aug 19 14:14:04 CEST 2009
At Sat, 15 Aug 2009 23:40:36 -0400,
Jon Smirl wrote:
>
> On Sat, Aug 15, 2009 at 11:53 AM, Jon Smirl<jonsmirl at gmail.com> wrote:
> > void
> > bfio_synch_stop(void)
> > {
> > int n;
> >
> > if (base_handle == NULL) {
> > return;
> > }
> > FOR_IN_AND_OUT {
> > for (n = 0; n < n_handles[IO]; n++) {
>
> I added:
> snd_pcm_nonblock(handles[IO][n], 0)
> snd_pcm_drain(handles[IO][n])
> snd_pcm_nonblock(handles[IO][n], SND_PCM_NONBLOCK )
>
> > snd_pcm_close(handles[IO][n]);
> > }
> > }
> > }
>
> This is not working correctly.
> snd_pcm_nonblock(handles[IO][n], 0)
> It does not remove O_NONBLOCK for some unknown reason.
>
> I added printf() to snd_pcm_hw_nonblock()
> The fcntl is not getting an error.
> if (fcntl(fd, F_SETFL, flags) < 0) {
> Flags being set are 2 (O_RDWR).
>
> But when I get over to snd_pcm_pre_drain_init(), I get the -EAGAIN error.
> static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream,
> int state)
> {
> printk("snd_pcm_pre_drain_init\n");
> if (substream->f_flags & O_NONBLOCK)
> return -EAGAIN;
> printk("snd_pcm_pre_drain_init 1\n");
> substream->runtime->trigger_master = substream;
> return 0;
> }
> So I have to conclude that fcntl(fd, F_SETFL, flags) is not removing
> the O_NONBLOCK flag.
Yeah, you found a long-standing bug :)
Honestly, I think the current designed behavior is just annoying.
An ioctl may be blocked, thus there is no real merit to return -EAGAIN
with DRAIN ioctl.
So, my preferred solution is simply to remove the O_NONBLOCK check
in the code path above.
Another solution would be a patch like below (totally untested)...
Comments?
thanks,
Takashi
---
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index d89c816..5d6b9ad 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1343,8 +1343,6 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state)
{
- if (substream->f_flags & O_NONBLOCK)
- return -EAGAIN;
substream->runtime->trigger_master = substream;
return 0;
}
@@ -1404,7 +1402,8 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream);
* After this call, all streams are supposed to be either SETUP or DRAINING
* (capture only) state.
*/
-static int snd_pcm_drain(struct snd_pcm_substream *substream)
+static int snd_pcm_drain(struct snd_pcm_substream *substream,
+ struct file *file)
{
struct snd_card *card;
struct snd_pcm_runtime *runtime;
@@ -1412,6 +1411,14 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream)
int result = 0;
int i, num_drecs;
struct drain_rec *drec, drec_tmp, *d;
+ int f_flags;
+
+ if (file)
+ f_flags = file->f_flags;
+ else
+ f_flags = substream->f_flags;
+ if (f_flags & O_NONBLOCK)
+ return -EAGAIN;
card = substream->pcm->card;
runtime = substream->runtime;
@@ -2556,7 +2563,7 @@ static int snd_pcm_common_ioctl1(struct file *file,
return snd_pcm_hw_params_old_user(substream, arg);
#endif
case SNDRV_PCM_IOCTL_DRAIN:
- return snd_pcm_drain(substream);
+ return snd_pcm_drain(substream, file);
case SNDRV_PCM_IOCTL_DROP:
return snd_pcm_drop(substream);
case SNDRV_PCM_IOCTL_PAUSE:
More information about the Alsa-devel
mailing list