mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-29 05:40:25 -04:00
PCM: allow mmap-access conversion in plug
The plug plugin has a long-standing problem that it can handle only slaves that support mmap because of format/rate/access conversions (these corresponding plugins work only with mmap). This patch adds the support of automatic mmap->rw conversion via mmap_emul plugin. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
538726cc55
commit
1467f4e238
2 changed files with 79 additions and 10 deletions
|
|
@ -520,6 +520,9 @@ fi
|
||||||
if test "$build_pcm_alaw" = "yes"; then
|
if test "$build_pcm_alaw" = "yes"; then
|
||||||
AC_DEFINE([BUILD_PCM_PLUGIN_ALAW], "1", [Build PCM alaw plugin])
|
AC_DEFINE([BUILD_PCM_PLUGIN_ALAW], "1", [Build PCM alaw plugin])
|
||||||
fi
|
fi
|
||||||
|
if test "$build_pcm_mmap_emul" = "yes"; then
|
||||||
|
AC_DEFINE([BUILD_PCM_PLUGIN_MMAP_EMUL], "1", [Build PCM mmap-emul plugin])
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
dnl Create PCM plugin symbol list for static library
|
dnl Create PCM plugin symbol list for static library
|
||||||
|
|
|
||||||
|
|
@ -581,12 +581,44 @@ static int snd_pcm_plug_change_access(snd_pcm_t *pcm, snd_pcm_t **new, snd_pcm_p
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef BUILD_PCM_PLUGIN_MMAP_EMUL
|
||||||
|
static int snd_pcm_plug_change_mmap(snd_pcm_t *pcm, snd_pcm_t **new,
|
||||||
|
snd_pcm_plug_params_t *clt,
|
||||||
|
snd_pcm_plug_params_t *slv)
|
||||||
|
{
|
||||||
|
snd_pcm_plug_t *plug = pcm->private_data;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (clt->access == slv->access)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
switch (slv->access) {
|
||||||
|
case SND_PCM_ACCESS_MMAP_INTERLEAVED:
|
||||||
|
case SND_PCM_ACCESS_MMAP_NONINTERLEAVED:
|
||||||
|
case SND_PCM_ACCESS_MMAP_COMPLEX:
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = __snd_pcm_mmap_emul_open(new, NULL, plug->gen.slave,
|
||||||
|
plug->gen.slave != plug->req_slave);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
slv->access = clt->access;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int snd_pcm_plug_insert_plugins(snd_pcm_t *pcm,
|
static int snd_pcm_plug_insert_plugins(snd_pcm_t *pcm,
|
||||||
snd_pcm_plug_params_t *client,
|
snd_pcm_plug_params_t *client,
|
||||||
snd_pcm_plug_params_t *slave)
|
snd_pcm_plug_params_t *slave)
|
||||||
{
|
{
|
||||||
snd_pcm_plug_t *plug = pcm->private_data;
|
snd_pcm_plug_t *plug = pcm->private_data;
|
||||||
static int (*funcs[])(snd_pcm_t *_pcm, snd_pcm_t **new, snd_pcm_plug_params_t *s, snd_pcm_plug_params_t *d) = {
|
static int (*funcs[])(snd_pcm_t *_pcm, snd_pcm_t **new, snd_pcm_plug_params_t *s, snd_pcm_plug_params_t *d) = {
|
||||||
|
#ifdef BUILD_PCM_PLUGIN_MMAP_EMUL
|
||||||
|
snd_pcm_plug_change_mmap,
|
||||||
|
#endif
|
||||||
snd_pcm_plug_change_format,
|
snd_pcm_plug_change_format,
|
||||||
#ifdef BUILD_PCM_PLUGIN_ROUTE
|
#ifdef BUILD_PCM_PLUGIN_ROUTE
|
||||||
snd_pcm_plug_change_channels,
|
snd_pcm_plug_change_channels,
|
||||||
|
|
@ -693,6 +725,43 @@ static int snd_pcm_plug_hw_refine_sprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int check_access_change(snd_pcm_hw_params_t *cparams,
|
||||||
|
snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
snd_pcm_access_mask_t *smask;
|
||||||
|
#ifdef BUILD_PCM_PLUGIN_MMAP_EMUL
|
||||||
|
const snd_pcm_access_mask_t *cmask;
|
||||||
|
snd_pcm_access_mask_t mask;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
smask = (snd_pcm_access_mask_t *)
|
||||||
|
snd_pcm_hw_param_get_mask(sparams,
|
||||||
|
SND_PCM_HW_PARAM_ACCESS);
|
||||||
|
if (snd_pcm_access_mask_test(smask, SND_PCM_ACCESS_MMAP_INTERLEAVED) ||
|
||||||
|
snd_pcm_access_mask_test(smask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED) ||
|
||||||
|
snd_pcm_access_mask_test(smask, SND_PCM_ACCESS_MMAP_COMPLEX))
|
||||||
|
return 0; /* OK, we have mmap support */
|
||||||
|
#ifdef BUILD_PCM_PLUGIN_MMAP_EMUL
|
||||||
|
/* no mmap support - we need mmap emulation */
|
||||||
|
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);
|
||||||
|
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;
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
return -EINVAL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_pcm_plug_hw_refine_schange(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
static int snd_pcm_plug_hw_refine_schange(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
||||||
snd_pcm_hw_params_t *sparams)
|
snd_pcm_hw_params_t *sparams)
|
||||||
{
|
{
|
||||||
|
|
@ -764,18 +833,15 @@ static int snd_pcm_plug_hw_refine_schange(snd_pcm_t *pcm, snd_pcm_hw_params_t *p
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (snd_pcm_hw_param_never_eq(params, SND_PCM_HW_PARAM_FORMAT, sparams) ||
|
if (snd_pcm_hw_param_never_eq(params, SND_PCM_HW_PARAM_ACCESS, sparams)) {
|
||||||
snd_pcm_hw_param_never_eq(params, SND_PCM_HW_PARAM_CHANNELS, sparams) ||
|
err = check_access_change(params, sparams);
|
||||||
snd_pcm_hw_param_never_eq(params, SND_PCM_HW_PARAM_RATE, sparams) ||
|
if (err < 0) {
|
||||||
snd_pcm_hw_param_never_eq(params, SND_PCM_HW_PARAM_ACCESS, sparams)) {
|
SNDERR("Unable to find an usable access for '%s'",
|
||||||
snd_pcm_access_mask_t access_mask = { SND_PCM_ACCBIT_MMAP };
|
pcm->name);
|
||||||
_snd_pcm_hw_param_set_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
|
return err;
|
||||||
&access_mask);
|
|
||||||
if (snd_pcm_access_mask_empty(snd_pcm_hw_param_get_mask(sparams, SND_PCM_HW_PARAM_ACCESS))) {
|
|
||||||
SNDERR("Unable to find an usable access for '%s'", pcm->name);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((links & SND_PCM_HW_PARBIT_RATE) ||
|
if ((links & SND_PCM_HW_PARBIT_RATE) ||
|
||||||
snd_pcm_hw_param_always_eq(params, SND_PCM_HW_PARAM_RATE, sparams))
|
snd_pcm_hw_param_always_eq(params, SND_PCM_HW_PARAM_RATE, sparams))
|
||||||
links |= (SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
links |= (SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue