]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Fix plug conversion with mmap emulation
authorTakashi Iwai <tiwai@suse.de>
Tue, 27 Jan 2009 16:21:34 +0000 (17:21 +0100)
committerTakashi Iwai <tiwai@suse.de>
Tue, 27 Jan 2009 16:21:34 +0000 (17:21 +0100)
If the slave PCM supports only another type of interleaved format,
plug did convert it wrongly and resulted in an unused access type
error.  For example, if a slave PCM supporst only RW_NONINTERLEAVE
access and you try to play an interleaved format file, it resulted
in an error.

This patch fixes the conversion rule.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
src/pcm/pcm_plug.c

index abd3d437bfc20a47d40f7636cc6c73a4ba37cf24..09028c9869dcf22cc3abd9f423f84cc0f4097669 100644 (file)
@@ -605,7 +605,14 @@ static int snd_pcm_plug_change_mmap(snd_pcm_t *pcm, snd_pcm_t **new,
                                       plug->gen.slave != plug->req_slave);
        if (err < 0)
                return err;
-       slv->access = clt->access;
+       switch (slv->access) {
+       case SND_PCM_ACCESS_RW_INTERLEAVED:
+               slv->access = SND_PCM_ACCESS_MMAP_INTERLEAVED;
+               break;
+       case SND_PCM_ACCESS_RW_NONINTERLEAVED:
+               slv->access = SND_PCM_ACCESS_MMAP_NONINTERLEAVED;
+               break;
+       }
        return 1;
 }
 #endif
@@ -743,19 +750,29 @@ static int check_access_change(snd_pcm_hw_params_t *cparams,
                return 0; /* OK, we have mmap support */
 #ifdef BUILD_PCM_PLUGIN_MMAP_EMUL
        /* no mmap support - we need mmap emulation */
+
+       if (!snd_pcm_access_mask_test(smask, SND_PCM_ACCESS_RW_INTERLEAVED) &&
+           !snd_pcm_access_mask_test(smask, SND_PCM_ACCESS_RW_NONINTERLEAVED)) 
+               return -EINVAL; /* even no RW access?  no way! */
+
        cmask = (const snd_pcm_access_mask_t *)
                snd_pcm_hw_param_get_mask(cparams,
                                          SND_PCM_HW_PARAM_ACCESS);
        snd_mask_none(&mask);
        if (snd_pcm_access_mask_test(cmask, SND_PCM_ACCESS_RW_INTERLEAVED) ||
-           snd_pcm_access_mask_test(cmask, SND_PCM_ACCESS_MMAP_INTERLEAVED))
-               snd_pcm_access_mask_set(&mask,
-                                       SND_PCM_ACCESS_RW_INTERLEAVED);
+           snd_pcm_access_mask_test(cmask, SND_PCM_ACCESS_MMAP_INTERLEAVED)) {
+               if (snd_pcm_access_mask_test(smask, SND_PCM_ACCESS_RW_INTERLEAVED))
+                       snd_pcm_access_mask_set(&mask,
+                                               SND_PCM_ACCESS_RW_INTERLEAVED);
+       }
        if (snd_pcm_access_mask_test(cmask, SND_PCM_ACCESS_RW_NONINTERLEAVED) ||
-           snd_pcm_access_mask_test(cmask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED))
-               snd_pcm_access_mask_set(&mask,
-                                       SND_PCM_ACCESS_RW_NONINTERLEAVED);
-       *smask = mask;
+           snd_pcm_access_mask_test(cmask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED)) {
+               if (snd_pcm_access_mask_test(smask, SND_PCM_ACCESS_RW_NONINTERLEAVED))
+                       snd_pcm_access_mask_set(&mask,
+                                               SND_PCM_ACCESS_RW_NONINTERLEAVED);
+       }
+       if (!snd_mask_empty(&mask))
+               *smask = mask; /* prefer the straight conversion */
        return 0;
 #else
        return -EINVAL;