summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-01-27 17:21:34 +0100
committerTakashi Iwai <tiwai@suse.de>2009-01-27 17:21:34 +0100
commitd3a8e853fb0780ecf85b54eba0926698970b3934 (patch)
tree3cffe85b7fbaa7ded9b67445a684be4ed414a01e
parent777a869769f064c84ef38211c090f31bda169129 (diff)
downloadalsa-lib-d3a8e853fb0780ecf85b54eba0926698970b3934.tar.gz
Fix plug conversion with mmap emulation
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>
-rw-r--r--src/pcm/pcm_plug.c33
1 files changed, 25 insertions, 8 deletions
diff --git a/src/pcm/pcm_plug.c b/src/pcm/pcm_plug.c
index abd3d437..09028c98 100644
--- a/src/pcm/pcm_plug.c
+++ b/src/pcm/pcm_plug.c
@@ -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;