mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-29 05:40:25 -04:00
Major cleaning to hw_params mechanism for plugins
This commit is contained in:
parent
1747dc039f
commit
3126678e72
17 changed files with 1259 additions and 1044 deletions
|
|
@ -38,19 +38,28 @@ static inline void div64_32(u_int64_t *n, u_int32_t div, u_int32_t *rem)
|
||||||
static inline unsigned int div32(unsigned int a, unsigned int b,
|
static inline unsigned int div32(unsigned int a, unsigned int b,
|
||||||
unsigned int *r)
|
unsigned int *r)
|
||||||
{
|
{
|
||||||
|
if (b == 0) {
|
||||||
|
*r = 0;
|
||||||
|
return UINT_MAX;
|
||||||
|
}
|
||||||
*r = a % b;
|
*r = a % b;
|
||||||
return a / b;
|
return a / b;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned int div_down(unsigned int a, unsigned int b)
|
static inline unsigned int div_down(unsigned int a, unsigned int b)
|
||||||
{
|
{
|
||||||
|
if (b == 0)
|
||||||
|
return UINT_MAX;
|
||||||
return a / b;
|
return a / b;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned int div_up(unsigned int a, unsigned int b)
|
static inline unsigned int div_up(unsigned int a, unsigned int b)
|
||||||
{
|
{
|
||||||
unsigned int r;
|
unsigned int r;
|
||||||
unsigned int q = div32(a, b, &r);
|
unsigned int q;
|
||||||
|
if (b == 0)
|
||||||
|
return UINT_MAX;
|
||||||
|
q = div32(a, b, &r);
|
||||||
if (r)
|
if (r)
|
||||||
++q;
|
++q;
|
||||||
return q;
|
return q;
|
||||||
|
|
@ -83,6 +92,11 @@ static inline unsigned int muldiv32(unsigned int a, unsigned int b,
|
||||||
unsigned int c, unsigned int *r)
|
unsigned int c, unsigned int *r)
|
||||||
{
|
{
|
||||||
u_int64_t n = (u_int64_t) a * b;
|
u_int64_t n = (u_int64_t) a * b;
|
||||||
|
if (c == 0) {
|
||||||
|
assert(n > 0);
|
||||||
|
*r = 0;
|
||||||
|
return UINT_MAX;
|
||||||
|
}
|
||||||
div64_32(&n, c, r);
|
div64_32(&n, c, r);
|
||||||
if (n >= UINT_MAX) {
|
if (n >= UINT_MAX) {
|
||||||
*r = 0;
|
*r = 0;
|
||||||
|
|
@ -359,7 +373,7 @@ void interval_print(const interval_t *i, snd_output_t *out)
|
||||||
else if (i->min == 0 && i->openmin == 0 &&
|
else if (i->min == 0 && i->openmin == 0 &&
|
||||||
i->max == UINT_MAX && i->openmax == 0)
|
i->max == UINT_MAX && i->openmax == 0)
|
||||||
snd_output_printf(out, "ALL");
|
snd_output_printf(out, "ALL");
|
||||||
else if (interval_single(i))
|
else if (interval_single(i) && i->integer)
|
||||||
snd_output_printf(out, "%u", interval_value(i));
|
snd_output_printf(out, "%u", interval_value(i));
|
||||||
else
|
else
|
||||||
snd_output_printf(out, "%c%u %u%c",
|
snd_output_printf(out, "%c%u %u%c",
|
||||||
|
|
|
||||||
|
|
@ -329,103 +329,109 @@ static int snd_pcm_adpcm_close(snd_pcm_t *pcm)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_adpcm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
static int snd_pcm_adpcm_hw_refine_cprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
{
|
{
|
||||||
snd_pcm_adpcm_t *adpcm = pcm->private;
|
snd_pcm_adpcm_t *adpcm = pcm->private;
|
||||||
snd_pcm_t *slave = adpcm->plug.slave;
|
|
||||||
int err;
|
int err;
|
||||||
unsigned int cmask, lcmask;
|
|
||||||
snd_pcm_hw_params_t sparams;
|
|
||||||
mask_t *access_mask = alloca(mask_sizeof());
|
mask_t *access_mask = alloca(mask_sizeof());
|
||||||
mask_t *saccess_mask = alloca(mask_sizeof());
|
|
||||||
mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN);
|
mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN);
|
||||||
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
|
||||||
cmask = params->cmask;
|
|
||||||
params->cmask = 0;
|
|
||||||
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS,
|
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS,
|
||||||
access_mask);
|
access_mask);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
if (adpcm->sformat == SND_PCM_FORMAT_IMA_ADPCM) {
|
if (adpcm->sformat == SND_PCM_FORMAT_IMA_ADPCM) {
|
||||||
mask_t *format_mask = alloca(mask_sizeof());
|
mask_t *format_mask = alloca(mask_sizeof());
|
||||||
mask_load(format_mask, SND_PCM_FMTBIT_LINEAR);
|
mask_load(format_mask, SND_PCM_FMTBIT_LINEAR);
|
||||||
err = _snd_pcm_hw_param_mask(params,
|
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT,
|
||||||
SND_PCM_HW_PARAM_FORMAT,
|
format_mask);
|
||||||
format_mask);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
} else {
|
} else {
|
||||||
err = _snd_pcm_hw_param_set(params,
|
err = _snd_pcm_hw_param_set(params,
|
||||||
SND_PCM_HW_PARAM_FORMAT,
|
SND_PCM_HW_PARAM_FORMAT,
|
||||||
SND_PCM_FORMAT_IMA_ADPCM, 0);
|
SND_PCM_FORMAT_IMA_ADPCM, 0);
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_SUBFORMAT,
|
|
||||||
SND_PCM_SUBFORMAT_STD, 0);
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
lcmask = params->cmask;
|
err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_SUBFORMAT,
|
||||||
params->cmask |= cmask;
|
SND_PCM_SUBFORMAT_STD, 0);
|
||||||
|
|
||||||
_snd_pcm_hw_params_any(&sparams);
|
|
||||||
_snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS,
|
|
||||||
saccess_mask);
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_FORMAT,
|
|
||||||
adpcm->sformat, 0);
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_SUBFORMAT,
|
|
||||||
SND_PCM_SUBFORMAT_STD, 0);
|
|
||||||
err = snd_pcm_hw_refine2(params, &sparams,
|
|
||||||
snd_pcm_generic_hw_link, slave,
|
|
||||||
SND_PCM_HW_PARBIT_CHANNELS |
|
|
||||||
SND_PCM_HW_PARBIT_RATE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIODS |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_TICK_TIME);
|
|
||||||
params->cmask |= lcmask;
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
|
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_adpcm_hw_refine_sprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
snd_pcm_adpcm_t *adpcm = pcm->private;
|
||||||
|
mask_t *saccess_mask = alloca(mask_sizeof());
|
||||||
|
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
||||||
|
_snd_pcm_hw_params_any(sparams);
|
||||||
|
_snd_pcm_hw_param_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
|
||||||
|
saccess_mask);
|
||||||
|
_snd_pcm_hw_param_set(sparams, SND_PCM_HW_PARAM_FORMAT,
|
||||||
|
adpcm->sformat, 0);
|
||||||
|
_snd_pcm_hw_param_set(sparams, SND_PCM_HW_PARAM_SUBFORMAT,
|
||||||
|
SND_PCM_SUBFORMAT_STD, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_adpcm_hw_refine_schange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS |
|
||||||
|
SND_PCM_HW_PARBIT_RATE |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
||||||
|
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
||||||
|
SND_PCM_HW_PARBIT_PERIODS |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_TICK_TIME);
|
||||||
|
err = _snd_pcm_hw_params_refine(sparams, links, params);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_adpcm_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS |
|
||||||
|
SND_PCM_HW_PARBIT_RATE |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
||||||
|
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
||||||
|
SND_PCM_HW_PARBIT_PERIODS |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_TICK_TIME);
|
||||||
|
err = _snd_pcm_hw_params_refine(params, links, sparams);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_adpcm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
|
{
|
||||||
|
return snd_pcm_hw_refine_slave(pcm, params,
|
||||||
|
snd_pcm_adpcm_hw_refine_cprepare,
|
||||||
|
snd_pcm_adpcm_hw_refine_cchange,
|
||||||
|
snd_pcm_adpcm_hw_refine_sprepare,
|
||||||
|
snd_pcm_adpcm_hw_refine_schange,
|
||||||
|
snd_pcm_plugin_hw_refine_slave);
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_pcm_adpcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
|
static int snd_pcm_adpcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
|
||||||
{
|
{
|
||||||
snd_pcm_adpcm_t *adpcm = pcm->private;
|
snd_pcm_adpcm_t *adpcm = pcm->private;
|
||||||
snd_pcm_t *slave = adpcm->plug.slave;
|
int err = snd_pcm_hw_params_slave(pcm, params,
|
||||||
int err;
|
snd_pcm_adpcm_hw_refine_cchange,
|
||||||
snd_pcm_hw_params_t sparams;
|
snd_pcm_adpcm_hw_refine_sprepare,
|
||||||
unsigned int links;
|
snd_pcm_adpcm_hw_refine_schange,
|
||||||
mask_t *saccess_mask = alloca(mask_sizeof());
|
snd_pcm_plugin_hw_params_slave);
|
||||||
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
|
||||||
|
|
||||||
_snd_pcm_hw_params_any(&sparams);
|
|
||||||
_snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS,
|
|
||||||
saccess_mask);
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_FORMAT,
|
|
||||||
adpcm->sformat, 0);
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_SUBFORMAT,
|
|
||||||
SND_PCM_SUBFORMAT_STD, 0);
|
|
||||||
links = SND_PCM_HW_PARBIT_CHANNELS |
|
|
||||||
SND_PCM_HW_PARBIT_RATE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIODS |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_TICK_TIME;
|
|
||||||
err = snd_pcm_hw_params_refine(&sparams, links, params);
|
|
||||||
assert(err >= 0);
|
|
||||||
err = snd_pcm_hw_params(slave, &sparams);
|
|
||||||
params->cmask = 0;
|
|
||||||
sparams.cmask = ~0U;
|
|
||||||
snd_pcm_hw_params_refine(params, links, &sparams);
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
|
|
||||||
|
|
||||||
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
|
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
|
||||||
if (adpcm->sformat == SND_PCM_FORMAT_IMA_ADPCM) {
|
if (adpcm->sformat == SND_PCM_FORMAT_IMA_ADPCM) {
|
||||||
adpcm->getput_idx = get_index(snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT, 0), SND_PCM_FORMAT_S16);
|
adpcm->getput_idx = get_index(snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT, 0), SND_PCM_FORMAT_S16);
|
||||||
|
|
|
||||||
|
|
@ -211,103 +211,108 @@ static void alaw_encode(const snd_pcm_channel_area_t *src_areas,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_alaw_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
static int snd_pcm_alaw_hw_refine_cprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
{
|
{
|
||||||
snd_pcm_alaw_t *alaw = pcm->private;
|
snd_pcm_alaw_t *alaw = pcm->private;
|
||||||
snd_pcm_t *slave = alaw->plug.slave;
|
|
||||||
int err;
|
int err;
|
||||||
unsigned int cmask, lcmask;
|
|
||||||
snd_pcm_hw_params_t sparams;
|
|
||||||
mask_t *access_mask = alloca(mask_sizeof());
|
mask_t *access_mask = alloca(mask_sizeof());
|
||||||
mask_t *saccess_mask = alloca(mask_sizeof());
|
|
||||||
mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN);
|
mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN);
|
||||||
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
|
||||||
cmask = params->cmask;
|
|
||||||
params->cmask = 0;
|
|
||||||
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS,
|
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS,
|
||||||
access_mask);
|
access_mask);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
if (alaw->sformat == SND_PCM_FORMAT_A_LAW) {
|
if (alaw->sformat == SND_PCM_FORMAT_A_LAW) {
|
||||||
mask_t *format_mask = alloca(mask_sizeof());
|
mask_t *format_mask = alloca(mask_sizeof());
|
||||||
mask_load(format_mask, SND_PCM_FMTBIT_LINEAR);
|
mask_load(format_mask, SND_PCM_FMTBIT_LINEAR);
|
||||||
err = _snd_pcm_hw_param_mask(params,
|
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT,
|
||||||
SND_PCM_HW_PARAM_FORMAT,
|
format_mask);
|
||||||
format_mask);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
} else {
|
} else {
|
||||||
err = _snd_pcm_hw_param_set(params,
|
err = _snd_pcm_hw_param_set(params,
|
||||||
SND_PCM_HW_PARAM_FORMAT,
|
SND_PCM_HW_PARAM_FORMAT,
|
||||||
SND_PCM_FORMAT_A_LAW, 0);
|
SND_PCM_FORMAT_A_LAW, 0);
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_SUBFORMAT,
|
|
||||||
SND_PCM_SUBFORMAT_STD, 0);
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
lcmask = params->cmask;
|
err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_SUBFORMAT,
|
||||||
params->cmask |= cmask;
|
SND_PCM_SUBFORMAT_STD, 0);
|
||||||
|
|
||||||
_snd_pcm_hw_params_any(&sparams);
|
|
||||||
_snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS,
|
|
||||||
saccess_mask);
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_FORMAT,
|
|
||||||
alaw->sformat, 0);
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_SUBFORMAT,
|
|
||||||
SND_PCM_SUBFORMAT_STD, 0);
|
|
||||||
err = snd_pcm_hw_refine2(params, &sparams,
|
|
||||||
snd_pcm_generic_hw_link, slave,
|
|
||||||
SND_PCM_HW_PARBIT_CHANNELS |
|
|
||||||
SND_PCM_HW_PARBIT_RATE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIODS |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_TICK_TIME);
|
|
||||||
params->cmask |= lcmask;
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
|
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_alaw_hw_refine_sprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
snd_pcm_alaw_t *alaw = pcm->private;
|
||||||
|
mask_t *saccess_mask = alloca(mask_sizeof());
|
||||||
|
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
||||||
|
_snd_pcm_hw_params_any(sparams);
|
||||||
|
_snd_pcm_hw_param_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
|
||||||
|
saccess_mask);
|
||||||
|
_snd_pcm_hw_param_set(sparams, SND_PCM_HW_PARAM_FORMAT,
|
||||||
|
alaw->sformat, 0);
|
||||||
|
_snd_pcm_hw_param_set(sparams, SND_PCM_HW_PARAM_SUBFORMAT,
|
||||||
|
SND_PCM_SUBFORMAT_STD, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_alaw_hw_refine_schange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS |
|
||||||
|
SND_PCM_HW_PARBIT_RATE |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
||||||
|
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
||||||
|
SND_PCM_HW_PARBIT_PERIODS |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_TICK_TIME);
|
||||||
|
err = _snd_pcm_hw_params_refine(sparams, links, params);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_alaw_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS |
|
||||||
|
SND_PCM_HW_PARBIT_RATE |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
||||||
|
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
||||||
|
SND_PCM_HW_PARBIT_PERIODS |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_TICK_TIME);
|
||||||
|
err = _snd_pcm_hw_params_refine(params, links, sparams);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_alaw_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
|
{
|
||||||
|
return snd_pcm_hw_refine_slave(pcm, params,
|
||||||
|
snd_pcm_alaw_hw_refine_cprepare,
|
||||||
|
snd_pcm_alaw_hw_refine_cchange,
|
||||||
|
snd_pcm_alaw_hw_refine_sprepare,
|
||||||
|
snd_pcm_alaw_hw_refine_schange,
|
||||||
|
snd_pcm_plugin_hw_refine_slave);
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_pcm_alaw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
|
static int snd_pcm_alaw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
|
||||||
{
|
{
|
||||||
snd_pcm_alaw_t *alaw = pcm->private;
|
snd_pcm_alaw_t *alaw = pcm->private;
|
||||||
snd_pcm_t *slave = alaw->plug.slave;
|
int err = snd_pcm_hw_params_slave(pcm, params,
|
||||||
int err;
|
snd_pcm_alaw_hw_refine_cchange,
|
||||||
snd_pcm_hw_params_t sparams;
|
snd_pcm_alaw_hw_refine_sprepare,
|
||||||
unsigned int links;
|
snd_pcm_alaw_hw_refine_schange,
|
||||||
mask_t *saccess_mask = alloca(mask_sizeof());
|
snd_pcm_plugin_hw_params_slave);
|
||||||
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
|
||||||
|
|
||||||
_snd_pcm_hw_params_any(&sparams);
|
|
||||||
_snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS,
|
|
||||||
saccess_mask);
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_FORMAT,
|
|
||||||
alaw->sformat, 0);
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_SUBFORMAT,
|
|
||||||
SND_PCM_SUBFORMAT_STD, 0);
|
|
||||||
links = SND_PCM_HW_PARBIT_CHANNELS |
|
|
||||||
SND_PCM_HW_PARBIT_RATE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIODS |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_TICK_TIME;
|
|
||||||
err = snd_pcm_hw_params_refine(&sparams, links, params);
|
|
||||||
assert(err >= 0);
|
|
||||||
err = snd_pcm_hw_params(slave, &sparams);
|
|
||||||
params->cmask = 0;
|
|
||||||
sparams.cmask = ~0U;
|
|
||||||
snd_pcm_hw_params_refine(params, links, &sparams);
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
|
|
||||||
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
|
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
|
||||||
if (alaw->sformat == SND_PCM_FORMAT_A_LAW) {
|
if (alaw->sformat == SND_PCM_FORMAT_A_LAW) {
|
||||||
alaw->getput_idx = get_index(snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT, 0), SND_PCM_FORMAT_S16);
|
alaw->getput_idx = get_index(snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT, 0), SND_PCM_FORMAT_S16);
|
||||||
|
|
|
||||||
|
|
@ -28,62 +28,68 @@ typedef struct {
|
||||||
snd_pcm_plugin_t plug;
|
snd_pcm_plugin_t plug;
|
||||||
} snd_pcm_copy_t;
|
} snd_pcm_copy_t;
|
||||||
|
|
||||||
static int snd_pcm_copy_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
static int snd_pcm_copy_hw_refine_cprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params)
|
||||||
{
|
{
|
||||||
snd_pcm_copy_t *copy = pcm->private;
|
|
||||||
snd_pcm_t *slave = copy->plug.slave;
|
|
||||||
int err;
|
int err;
|
||||||
unsigned int cmask, lcmask;
|
|
||||||
snd_pcm_hw_params_t sparams;
|
|
||||||
mask_t *access_mask = alloca(mask_sizeof());
|
mask_t *access_mask = alloca(mask_sizeof());
|
||||||
mask_t *saccess_mask = alloca(mask_sizeof());
|
|
||||||
mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN);
|
mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN);
|
||||||
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
|
||||||
cmask = params->cmask;
|
|
||||||
params->cmask = 0;
|
|
||||||
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS,
|
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS,
|
||||||
access_mask);
|
access_mask);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
lcmask = params->cmask;
|
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
|
||||||
params->cmask |= cmask;
|
return 0;
|
||||||
_snd_pcm_hw_params_any(&sparams);
|
}
|
||||||
_snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS,
|
|
||||||
saccess_mask);
|
static int snd_pcm_copy_hw_refine_sprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *sparams)
|
||||||
err = snd_pcm_hw_refine2(params, &sparams,
|
{
|
||||||
snd_pcm_generic_hw_link, slave,
|
mask_t *saccess_mask = alloca(mask_sizeof());
|
||||||
~SND_PCM_HW_PARBIT_ACCESS);
|
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
||||||
params->cmask |= lcmask;
|
_snd_pcm_hw_params_any(sparams);
|
||||||
|
_snd_pcm_hw_param_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
|
||||||
|
saccess_mask);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_copy_hw_refine_schange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
unsigned int links = ~SND_PCM_HW_PARBIT_ACCESS;
|
||||||
|
err = _snd_pcm_hw_params_refine(sparams, links, params);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
|
return 0;
|
||||||
return err;
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_copy_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
unsigned int links = ~SND_PCM_HW_PARBIT_ACCESS;
|
||||||
|
err = _snd_pcm_hw_params_refine(params, links, sparams);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_copy_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
|
{
|
||||||
|
return snd_pcm_hw_refine_slave(pcm, params,
|
||||||
|
snd_pcm_copy_hw_refine_cprepare,
|
||||||
|
snd_pcm_copy_hw_refine_cchange,
|
||||||
|
snd_pcm_copy_hw_refine_sprepare,
|
||||||
|
snd_pcm_copy_hw_refine_schange,
|
||||||
|
snd_pcm_plugin_hw_refine_slave);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_copy_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
static int snd_pcm_copy_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
{
|
{
|
||||||
snd_pcm_copy_t *copy = pcm->private;
|
return snd_pcm_hw_params_slave(pcm, params,
|
||||||
snd_pcm_t *slave = copy->plug.slave;
|
snd_pcm_copy_hw_refine_cchange,
|
||||||
int err;
|
snd_pcm_copy_hw_refine_sprepare,
|
||||||
unsigned int links;
|
snd_pcm_copy_hw_refine_schange,
|
||||||
snd_pcm_hw_params_t sparams;
|
snd_pcm_plugin_hw_params_slave);
|
||||||
mask_t *saccess_mask = alloca(mask_sizeof());
|
|
||||||
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
|
||||||
|
|
||||||
_snd_pcm_hw_params_any(&sparams);
|
|
||||||
_snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS,
|
|
||||||
saccess_mask);
|
|
||||||
links = ~SND_PCM_HW_PARBIT_ACCESS;
|
|
||||||
err = snd_pcm_hw_params_refine(&sparams, links, params);
|
|
||||||
assert(err >= 0);
|
|
||||||
err = snd_pcm_hw_params(slave, &sparams);
|
|
||||||
params->cmask = 0;
|
|
||||||
sparams.cmask = ~0U;
|
|
||||||
snd_pcm_hw_params_refine(params, links, &sparams);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static snd_pcm_sframes_t snd_pcm_copy_write_areas(snd_pcm_t *pcm,
|
static snd_pcm_sframes_t snd_pcm_copy_write_areas(snd_pcm_t *pcm,
|
||||||
|
|
|
||||||
|
|
@ -72,94 +72,100 @@ static void linear_transfer(const snd_pcm_channel_area_t *src_areas, snd_pcm_ufr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_linear_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
static int snd_pcm_linear_hw_refine_cprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params)
|
||||||
{
|
{
|
||||||
snd_pcm_linear_t *linear = pcm->private;
|
|
||||||
snd_pcm_t *slave = linear->plug.slave;
|
|
||||||
int err;
|
int err;
|
||||||
unsigned int cmask, lcmask;
|
|
||||||
snd_pcm_hw_params_t sparams;
|
|
||||||
mask_t *access_mask = alloca(mask_sizeof());
|
mask_t *access_mask = alloca(mask_sizeof());
|
||||||
mask_t *format_mask = alloca(mask_sizeof());
|
mask_t *format_mask = alloca(mask_sizeof());
|
||||||
mask_t *saccess_mask = alloca(mask_sizeof());
|
|
||||||
mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN);
|
mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN);
|
||||||
mask_load(format_mask, SND_PCM_FMTBIT_LINEAR);
|
mask_load(format_mask, SND_PCM_FMTBIT_LINEAR);
|
||||||
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
|
||||||
cmask = params->cmask;
|
|
||||||
params->cmask = 0;
|
|
||||||
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS,
|
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS,
|
||||||
access_mask);
|
access_mask);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT,
|
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT,
|
||||||
format_mask);
|
format_mask);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_SUBFORMAT,
|
err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_SUBFORMAT,
|
||||||
SND_PCM_SUBFORMAT_STD, 0);
|
SND_PCM_SUBFORMAT_STD, 0);
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
lcmask = params->cmask;
|
|
||||||
params->cmask |= cmask;
|
|
||||||
|
|
||||||
_snd_pcm_hw_params_any(&sparams);
|
|
||||||
_snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS,
|
|
||||||
saccess_mask);
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_FORMAT,
|
|
||||||
linear->sformat, 0);
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_SUBFORMAT,
|
|
||||||
SND_PCM_SUBFORMAT_STD, 0);
|
|
||||||
err = snd_pcm_hw_refine2(params, &sparams,
|
|
||||||
snd_pcm_generic_hw_link, slave,
|
|
||||||
SND_PCM_HW_PARBIT_CHANNELS |
|
|
||||||
SND_PCM_HW_PARBIT_RATE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIODS |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_TICK_TIME);
|
|
||||||
params->cmask |= lcmask;
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
|
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_linear_hw_refine_sprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
snd_pcm_linear_t *linear = pcm->private;
|
||||||
|
mask_t *saccess_mask = alloca(mask_sizeof());
|
||||||
|
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
||||||
|
_snd_pcm_hw_params_any(sparams);
|
||||||
|
_snd_pcm_hw_param_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
|
||||||
|
saccess_mask);
|
||||||
|
_snd_pcm_hw_param_set(sparams, SND_PCM_HW_PARAM_FORMAT,
|
||||||
|
linear->sformat, 0);
|
||||||
|
_snd_pcm_hw_param_set(sparams, SND_PCM_HW_PARAM_SUBFORMAT,
|
||||||
|
SND_PCM_SUBFORMAT_STD, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_linear_hw_refine_schange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS |
|
||||||
|
SND_PCM_HW_PARBIT_RATE |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
||||||
|
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
||||||
|
SND_PCM_HW_PARBIT_PERIODS |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_TICK_TIME);
|
||||||
|
err = _snd_pcm_hw_params_refine(sparams, links, params);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_linear_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS |
|
||||||
|
SND_PCM_HW_PARBIT_RATE |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
||||||
|
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
||||||
|
SND_PCM_HW_PARBIT_PERIODS |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_TICK_TIME);
|
||||||
|
err = _snd_pcm_hw_params_refine(params, links, sparams);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_linear_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
|
{
|
||||||
|
return snd_pcm_hw_refine_slave(pcm, params,
|
||||||
|
snd_pcm_linear_hw_refine_cprepare,
|
||||||
|
snd_pcm_linear_hw_refine_cchange,
|
||||||
|
snd_pcm_linear_hw_refine_sprepare,
|
||||||
|
snd_pcm_linear_hw_refine_schange,
|
||||||
|
snd_pcm_plugin_hw_refine_slave);
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_pcm_linear_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
static int snd_pcm_linear_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
{
|
{
|
||||||
snd_pcm_linear_t *linear = pcm->private;
|
snd_pcm_linear_t *linear = pcm->private;
|
||||||
snd_pcm_t *slave = linear->plug.slave;
|
int err = snd_pcm_hw_params_slave(pcm, params,
|
||||||
int err;
|
snd_pcm_linear_hw_refine_cchange,
|
||||||
unsigned int links;
|
snd_pcm_linear_hw_refine_sprepare,
|
||||||
snd_pcm_hw_params_t sparams;
|
snd_pcm_linear_hw_refine_schange,
|
||||||
mask_t *saccess_mask = alloca(mask_sizeof());
|
snd_pcm_plugin_hw_params_slave);
|
||||||
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
|
||||||
|
|
||||||
_snd_pcm_hw_params_any(&sparams);
|
|
||||||
_snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS,
|
|
||||||
saccess_mask);
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_FORMAT,
|
|
||||||
linear->sformat, 0);
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_SUBFORMAT,
|
|
||||||
SND_PCM_SUBFORMAT_STD, 0);
|
|
||||||
links = SND_PCM_HW_PARBIT_CHANNELS |
|
|
||||||
SND_PCM_HW_PARBIT_RATE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIODS |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_TICK_TIME;
|
|
||||||
err = snd_pcm_hw_params_refine(&sparams, links, params);
|
|
||||||
assert(err >= 0);
|
|
||||||
err = snd_pcm_hw_params(slave, &sparams);
|
|
||||||
params->cmask = 0;
|
|
||||||
sparams.cmask = ~0U;
|
|
||||||
snd_pcm_hw_params_refine(params, links, &sparams);
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
|
|
||||||
if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
|
if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
|
||||||
linear->conv_idx = conv_index(snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT, 0),
|
linear->conv_idx = conv_index(snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT, 0),
|
||||||
linear->sformat);
|
linear->sformat);
|
||||||
|
|
|
||||||
|
|
@ -299,7 +299,33 @@ static inline int muldiv_near(int a, int b, int c)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _snd_pcm_hw_refine(snd_pcm_hw_params_t *params);
|
int snd_pcm_hw_refine_soft(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
|
||||||
|
int snd_pcm_hw_refine_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
||||||
|
int (*cprepare)(snd_pcm_t *pcm,
|
||||||
|
snd_pcm_hw_params_t *params),
|
||||||
|
int (*cchange)(snd_pcm_t *pcm,
|
||||||
|
snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams),
|
||||||
|
int (*sprepare)(snd_pcm_t *pcm,
|
||||||
|
snd_pcm_hw_params_t *params),
|
||||||
|
int (*schange)(snd_pcm_t *pcm,
|
||||||
|
snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams),
|
||||||
|
int (*srefine)(snd_pcm_t *pcm,
|
||||||
|
snd_pcm_hw_params_t *sparams));
|
||||||
|
int snd_pcm_hw_params_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
||||||
|
int (*cchange)(snd_pcm_t *pcm,
|
||||||
|
snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams),
|
||||||
|
int (*sprepare)(snd_pcm_t *pcm,
|
||||||
|
snd_pcm_hw_params_t *params),
|
||||||
|
int (*schange)(snd_pcm_t *pcm,
|
||||||
|
snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams),
|
||||||
|
int (*sparams)(snd_pcm_t *pcm,
|
||||||
|
snd_pcm_hw_params_t *sparams));
|
||||||
|
|
||||||
|
|
||||||
void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params);
|
void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params);
|
||||||
int _snd_pcm_hw_param_refine_interval(snd_pcm_hw_params_t *params,
|
int _snd_pcm_hw_param_refine_interval(snd_pcm_hw_params_t *params,
|
||||||
snd_pcm_hw_param_t var,
|
snd_pcm_hw_param_t var,
|
||||||
|
|
@ -316,34 +342,16 @@ int _snd_pcm_hw_param_min(snd_pcm_hw_params_t *params,
|
||||||
unsigned int var, unsigned int val, int dir);
|
unsigned int var, unsigned int val, int dir);
|
||||||
int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params,
|
int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params,
|
||||||
unsigned int var, unsigned int val, int dir);
|
unsigned int var, unsigned int val, int dir);
|
||||||
int snd_pcm_hw_param_refine(snd_pcm_hw_params_t *params,
|
int _snd_pcm_hw_param_refine(snd_pcm_hw_params_t *params,
|
||||||
snd_pcm_hw_param_t var,
|
snd_pcm_hw_param_t var,
|
||||||
const snd_pcm_hw_params_t *src);
|
|
||||||
int snd_pcm_hw_params_refine(snd_pcm_hw_params_t *params,
|
|
||||||
unsigned int vars,
|
|
||||||
const snd_pcm_hw_params_t *src);
|
const snd_pcm_hw_params_t *src);
|
||||||
int snd_pcm_generic_hw_link(snd_pcm_hw_params_t *params,
|
int _snd_pcm_hw_params_refine(snd_pcm_hw_params_t *params,
|
||||||
snd_pcm_hw_params_t *sparams,
|
unsigned int vars,
|
||||||
snd_pcm_t *slave,
|
const snd_pcm_hw_params_t *src);
|
||||||
unsigned long links);
|
void snd_pcm_hw_param_refine_near(snd_pcm_t *pcm,
|
||||||
int snd_pcm_hw_refine2(snd_pcm_hw_params_t *params,
|
snd_pcm_hw_params_t *params,
|
||||||
snd_pcm_hw_params_t *sparams,
|
snd_pcm_hw_param_t var,
|
||||||
int (*func)(snd_pcm_hw_params_t *params,
|
const snd_pcm_hw_params_t *src);
|
||||||
snd_pcm_hw_params_t *sparams,
|
|
||||||
snd_pcm_t *slave,
|
|
||||||
unsigned long private),
|
|
||||||
snd_pcm_t *slave,
|
|
||||||
unsigned long private);
|
|
||||||
int snd_pcm_hw_params2(snd_pcm_hw_params_t *params,
|
|
||||||
snd_pcm_hw_params_t *sparams,
|
|
||||||
int (*func)(snd_pcm_t *slave,
|
|
||||||
snd_pcm_hw_params_t *sparams),
|
|
||||||
snd_pcm_t *slave,
|
|
||||||
unsigned int links);
|
|
||||||
void snd_pcm_hw_param_near_copy(snd_pcm_t *pcm,
|
|
||||||
snd_pcm_hw_params_t *params,
|
|
||||||
snd_pcm_hw_param_t var,
|
|
||||||
const snd_pcm_hw_params_t *src);
|
|
||||||
int snd_pcm_hw_param_always_eq(const snd_pcm_hw_params_t *params,
|
int snd_pcm_hw_param_always_eq(const snd_pcm_hw_params_t *params,
|
||||||
snd_pcm_hw_param_t var,
|
snd_pcm_hw_param_t var,
|
||||||
const snd_pcm_hw_params_t *params1);
|
const snd_pcm_hw_params_t *params1);
|
||||||
|
|
|
||||||
|
|
@ -228,19 +228,12 @@ static void mulaw_encode(const snd_pcm_channel_area_t *src_areas,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_mulaw_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
static int snd_pcm_mulaw_hw_refine_cprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
{
|
{
|
||||||
snd_pcm_mulaw_t *mulaw = pcm->private;
|
snd_pcm_mulaw_t *mulaw = pcm->private;
|
||||||
snd_pcm_t *slave = mulaw->plug.slave;
|
|
||||||
int err;
|
int err;
|
||||||
unsigned int cmask, lcmask;
|
|
||||||
snd_pcm_hw_params_t sparams;
|
|
||||||
mask_t *access_mask = alloca(mask_sizeof());
|
mask_t *access_mask = alloca(mask_sizeof());
|
||||||
mask_t *saccess_mask = alloca(mask_sizeof());
|
|
||||||
mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN);
|
mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN);
|
||||||
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
|
||||||
cmask = params->cmask;
|
|
||||||
params->cmask = 0;
|
|
||||||
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS,
|
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS,
|
||||||
access_mask);
|
access_mask);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
|
@ -248,83 +241,93 @@ static int snd_pcm_mulaw_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
if (mulaw->sformat == SND_PCM_FORMAT_MU_LAW) {
|
if (mulaw->sformat == SND_PCM_FORMAT_MU_LAW) {
|
||||||
mask_t *format_mask = alloca(mask_sizeof());
|
mask_t *format_mask = alloca(mask_sizeof());
|
||||||
mask_load(format_mask, SND_PCM_FMTBIT_LINEAR);
|
mask_load(format_mask, SND_PCM_FMTBIT_LINEAR);
|
||||||
err = _snd_pcm_hw_param_mask(params,
|
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT,
|
||||||
SND_PCM_HW_PARAM_FORMAT,
|
|
||||||
format_mask);
|
format_mask);
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
} else {
|
} else {
|
||||||
err = _snd_pcm_hw_param_set(params,
|
err = _snd_pcm_hw_param_set(params,
|
||||||
SND_PCM_HW_PARAM_FORMAT,
|
SND_PCM_HW_PARAM_FORMAT,
|
||||||
SND_PCM_FORMAT_MU_LAW, 0);
|
SND_PCM_FORMAT_MU_LAW, 0);
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_SUBFORMAT,
|
err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_SUBFORMAT,
|
||||||
SND_PCM_SUBFORMAT_STD, 0);
|
SND_PCM_SUBFORMAT_STD, 0);
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
lcmask = params->cmask;
|
|
||||||
params->cmask |= cmask;
|
|
||||||
|
|
||||||
_snd_pcm_hw_params_any(&sparams);
|
|
||||||
_snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS,
|
|
||||||
saccess_mask);
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_FORMAT,
|
|
||||||
mulaw->sformat, 0);
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_SUBFORMAT,
|
|
||||||
SND_PCM_SUBFORMAT_STD, 0);
|
|
||||||
err = snd_pcm_hw_refine2(params, &sparams,
|
|
||||||
snd_pcm_generic_hw_link, slave,
|
|
||||||
SND_PCM_HW_PARBIT_CHANNELS |
|
|
||||||
SND_PCM_HW_PARBIT_RATE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIODS |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_TICK_TIME);
|
|
||||||
params->cmask |= lcmask;
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
|
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_mulaw_hw_refine_sprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
snd_pcm_mulaw_t *mulaw = pcm->private;
|
||||||
|
mask_t *saccess_mask = alloca(mask_sizeof());
|
||||||
|
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
||||||
|
_snd_pcm_hw_params_any(sparams);
|
||||||
|
_snd_pcm_hw_param_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
|
||||||
|
saccess_mask);
|
||||||
|
_snd_pcm_hw_param_set(sparams, SND_PCM_HW_PARAM_FORMAT,
|
||||||
|
mulaw->sformat, 0);
|
||||||
|
_snd_pcm_hw_param_set(sparams, SND_PCM_HW_PARAM_SUBFORMAT,
|
||||||
|
SND_PCM_SUBFORMAT_STD, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_mulaw_hw_refine_schange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS |
|
||||||
|
SND_PCM_HW_PARBIT_RATE |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
||||||
|
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
||||||
|
SND_PCM_HW_PARBIT_PERIODS |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_TICK_TIME);
|
||||||
|
err = _snd_pcm_hw_params_refine(sparams, links, params);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_mulaw_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS |
|
||||||
|
SND_PCM_HW_PARBIT_RATE |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
||||||
|
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
||||||
|
SND_PCM_HW_PARBIT_PERIODS |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_TICK_TIME);
|
||||||
|
err = _snd_pcm_hw_params_refine(params, links, sparams);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_mulaw_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
|
{
|
||||||
|
return snd_pcm_hw_refine_slave(pcm, params,
|
||||||
|
snd_pcm_mulaw_hw_refine_cprepare,
|
||||||
|
snd_pcm_mulaw_hw_refine_cchange,
|
||||||
|
snd_pcm_mulaw_hw_refine_sprepare,
|
||||||
|
snd_pcm_mulaw_hw_refine_schange,
|
||||||
|
snd_pcm_plugin_hw_refine_slave);
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_pcm_mulaw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
|
static int snd_pcm_mulaw_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
|
||||||
{
|
{
|
||||||
snd_pcm_mulaw_t *mulaw = pcm->private;
|
snd_pcm_mulaw_t *mulaw = pcm->private;
|
||||||
snd_pcm_t *slave = mulaw->plug.slave;
|
int err = snd_pcm_hw_params_slave(pcm, params,
|
||||||
int err;
|
snd_pcm_mulaw_hw_refine_cchange,
|
||||||
unsigned int links;
|
snd_pcm_mulaw_hw_refine_sprepare,
|
||||||
snd_pcm_hw_params_t sparams;
|
snd_pcm_mulaw_hw_refine_schange,
|
||||||
mask_t *saccess_mask = alloca(mask_sizeof());
|
snd_pcm_plugin_hw_params_slave);
|
||||||
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
|
||||||
|
|
||||||
_snd_pcm_hw_params_any(&sparams);
|
|
||||||
_snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS,
|
|
||||||
saccess_mask);
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_FORMAT,
|
|
||||||
mulaw->sformat, 0);
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_SUBFORMAT,
|
|
||||||
SND_PCM_SUBFORMAT_STD, 0);
|
|
||||||
links = SND_PCM_HW_PARBIT_CHANNELS |
|
|
||||||
SND_PCM_HW_PARBIT_RATE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIODS |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_TICK_TIME;
|
|
||||||
err = snd_pcm_hw_params_refine(&sparams, links, params);
|
|
||||||
assert(err >= 0);
|
|
||||||
err = snd_pcm_hw_params(slave, &sparams);
|
|
||||||
params->cmask = 0;
|
|
||||||
sparams.cmask = ~0U;
|
|
||||||
snd_pcm_hw_params_refine(params, links, &sparams);
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
|
|
||||||
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
|
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
|
||||||
if (mulaw->sformat == SND_PCM_FORMAT_MU_LAW) {
|
if (mulaw->sformat == SND_PCM_FORMAT_MU_LAW) {
|
||||||
mulaw->getput_idx = get_index(snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT, 0), SND_PCM_FORMAT_S16);
|
mulaw->getput_idx = get_index(snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT, 0), SND_PCM_FORMAT_S16);
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,10 @@ static int snd_pcm_multi_close(snd_pcm_t *pcm)
|
||||||
|
|
||||||
static int snd_pcm_multi_card(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
|
static int snd_pcm_multi_card(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
return -ENOENT; /* not available */
|
snd_pcm_multi_t *multi = pcm->private;
|
||||||
|
if (multi->slaves_count != 1)
|
||||||
|
return -ENOENT; /* not available */
|
||||||
|
return snd_pcm_card(multi->slaves[0].pcm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_multi_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED)
|
static int snd_pcm_multi_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED)
|
||||||
|
|
@ -96,135 +99,188 @@ static int snd_pcm_multi_info(snd_pcm_t *pcm, snd_pcm_info_t *info)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_multi_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
static int snd_pcm_multi_hw_refine_cprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
{
|
{
|
||||||
snd_pcm_multi_t *multi = pcm->private;
|
snd_pcm_multi_t *multi = pcm->private;
|
||||||
unsigned int k;
|
mask_t *access_mask = alloca(mask_sizeof());
|
||||||
snd_pcm_hw_params_t sparams;
|
int err;
|
||||||
int changed = 0;
|
mask_any(access_mask);
|
||||||
int err = 0;
|
mask_reset(access_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
|
||||||
unsigned int cmask, lcmask;
|
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS,
|
||||||
const mask_t *access_mask = snd_pcm_hw_param_value_mask(params, SND_PCM_HW_PARAM_ACCESS);
|
access_mask);
|
||||||
mask_t *saccess_mask = alloca(mask_sizeof());
|
if (err < 0)
|
||||||
if (mask_test(access_mask, SND_PCM_ACCESS_RW_INTERLEAVED) ||
|
return err;
|
||||||
mask_test(access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED))
|
|
||||||
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
|
||||||
else {
|
|
||||||
mask_none(saccess_mask);
|
|
||||||
if (mask_test(access_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED) &&
|
|
||||||
multi->slaves_count == 1)
|
|
||||||
mask_set(saccess_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
|
|
||||||
if (mask_test(access_mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED))
|
|
||||||
mask_set(saccess_mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
|
|
||||||
if (mask_test(access_mask, SND_PCM_ACCESS_MMAP_COMPLEX)) {
|
|
||||||
mask_set(saccess_mask, SND_PCM_ACCESS_MMAP_COMPLEX);
|
|
||||||
if (multi->slaves_count > 1)
|
|
||||||
mask_set(saccess_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cmask = params->cmask;
|
|
||||||
params->cmask = 0;
|
|
||||||
err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_CHANNELS,
|
err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_CHANNELS,
|
||||||
multi->channels_count, 0);
|
multi->channels_count, 0);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
lcmask = params->cmask;
|
params->info = ~0;
|
||||||
cmask |= params->cmask;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_multi_hw_refine_sprepare(snd_pcm_t *pcm, int slave_idx,
|
||||||
|
snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
snd_pcm_multi_t *multi = pcm->private;
|
||||||
|
snd_pcm_multi_slave_t *slave = &multi->slaves[slave_idx];
|
||||||
|
mask_t *saccess_mask = alloca(mask_sizeof());
|
||||||
|
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
||||||
|
_snd_pcm_hw_params_any(sparams);
|
||||||
|
_snd_pcm_hw_param_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
|
||||||
|
saccess_mask);
|
||||||
|
_snd_pcm_hw_param_set(sparams, SND_PCM_HW_PARAM_CHANNELS,
|
||||||
|
slave->channels_count, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_multi_hw_refine_schange(snd_pcm_t *pcm ATTRIBUTE_UNUSED,
|
||||||
|
int slave_idx ATTRIBUTE_UNUSED,
|
||||||
|
snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
unsigned int links = (SND_PCM_HW_PARBIT_FORMAT |
|
||||||
|
SND_PCM_HW_PARBIT_SUBFORMAT |
|
||||||
|
SND_PCM_HW_PARBIT_RATE |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_PERIODS |
|
||||||
|
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
||||||
|
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_TICK_TIME);
|
||||||
|
const mask_t *access_mask = snd_pcm_hw_param_value_mask(params, SND_PCM_HW_PARAM_ACCESS);
|
||||||
|
if (!mask_test(access_mask, SND_PCM_ACCESS_RW_INTERLEAVED) &&
|
||||||
|
!mask_test(access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED) &&
|
||||||
|
!mask_test(access_mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED)) {
|
||||||
|
mask_t *saccess_mask = alloca(mask_sizeof());
|
||||||
|
mask_any(saccess_mask);
|
||||||
|
mask_reset(saccess_mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
|
||||||
|
err = _snd_pcm_hw_param_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
|
||||||
|
saccess_mask);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
err = _snd_pcm_hw_params_refine(sparams, links, params);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
changed = 0;
|
static int snd_pcm_multi_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED,
|
||||||
do {
|
int slave_idx ATTRIBUTE_UNUSED,
|
||||||
for (k = 0; k < multi->slaves_count; ++k) {
|
snd_pcm_hw_params_t *params,
|
||||||
snd_pcm_t *slave = multi->slaves[k].pcm;
|
snd_pcm_hw_params_t *sparams)
|
||||||
params->cmask = cmask;
|
{
|
||||||
_snd_pcm_hw_params_any(&sparams);
|
int err;
|
||||||
_snd_pcm_hw_param_mask(&sparams,
|
unsigned int links = (SND_PCM_HW_PARBIT_FORMAT |
|
||||||
SND_PCM_HW_PARAM_ACCESS,
|
SND_PCM_HW_PARBIT_SUBFORMAT |
|
||||||
saccess_mask);
|
SND_PCM_HW_PARBIT_RATE |
|
||||||
_snd_pcm_hw_param_set(&sparams,
|
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
||||||
SND_PCM_HW_PARAM_CHANNELS,
|
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
||||||
multi->slaves[k].channels_count, 0);
|
SND_PCM_HW_PARBIT_PERIODS |
|
||||||
err = snd_pcm_hw_refine2(params, &sparams,
|
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
||||||
snd_pcm_generic_hw_link, slave,
|
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
||||||
SND_PCM_HW_PARBIT_FORMAT |
|
SND_PCM_HW_PARBIT_TICK_TIME);
|
||||||
SND_PCM_HW_PARBIT_SUBFORMAT |
|
mask_t *access_mask = alloca(mask_sizeof());
|
||||||
SND_PCM_HW_PARBIT_RATE |
|
const mask_t *saccess_mask = snd_pcm_hw_param_value_mask(sparams, SND_PCM_HW_PARAM_ACCESS);
|
||||||
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
mask_any(access_mask);
|
||||||
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
mask_reset(access_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
|
||||||
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
if (!mask_test(saccess_mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED))
|
||||||
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
mask_reset(access_mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
|
||||||
SND_PCM_HW_PARBIT_PERIODS |
|
if (!mask_test(saccess_mask, SND_PCM_ACCESS_MMAP_COMPLEX) &&
|
||||||
SND_PCM_HW_PARBIT_TICK_TIME);
|
!mask_test(saccess_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED))
|
||||||
if (params->cmask) {
|
mask_reset(access_mask, SND_PCM_ACCESS_MMAP_COMPLEX);
|
||||||
changed++;
|
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS,
|
||||||
lcmask |= params->cmask;
|
access_mask);
|
||||||
cmask |= params->cmask;
|
if (err < 0)
|
||||||
}
|
return err;
|
||||||
if (err < 0)
|
err = _snd_pcm_hw_params_refine(params, links, sparams);
|
||||||
goto _end;
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
params->info &= sparams->info;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_multi_hw_refine_slave(snd_pcm_t *pcm,
|
||||||
|
int slave_idx,
|
||||||
|
snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
snd_pcm_multi_t *multi = pcm->private;
|
||||||
|
snd_pcm_t *slave = multi->slaves[slave_idx].pcm;
|
||||||
|
return snd_pcm_hw_refine(slave, sparams);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_multi_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
|
{
|
||||||
|
snd_pcm_multi_t *multi = pcm->private;
|
||||||
|
unsigned int k;
|
||||||
|
snd_pcm_hw_params_t sparams[multi->slaves_count];
|
||||||
|
int err;
|
||||||
|
err = snd_pcm_multi_hw_refine_cprepare(pcm, params);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
for (k = 0; k < multi->slaves_count; ++k) {
|
||||||
|
err = snd_pcm_multi_hw_refine_sprepare(pcm, k, &sparams[k]);
|
||||||
|
if (err < 0) {
|
||||||
|
ERR("Slave PCM #%d not useable", k);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
} while (changed && multi->slaves_count > 1);
|
}
|
||||||
_end:
|
/* FIXME: loop begin? */
|
||||||
params->cmask = lcmask;
|
for (k = 0; k < multi->slaves_count; ++k) {
|
||||||
return err;
|
err = snd_pcm_multi_hw_refine_schange(pcm, k, params, &sparams[k]);
|
||||||
|
if (err >= 0)
|
||||||
|
err = snd_pcm_multi_hw_refine_slave(pcm, k, &sparams[k]);
|
||||||
|
if (err < 0) {
|
||||||
|
snd_pcm_multi_hw_refine_cchange(pcm, k, params, &sparams[k]);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
err = snd_pcm_multi_hw_refine_cchange(pcm, k, params, &sparams[k]);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
err = snd_pcm_hw_refine_soft(pcm, params);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
/* FIXME: do we need to loop? */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_multi_hw_params_slave(snd_pcm_t *pcm,
|
||||||
|
int slave_idx,
|
||||||
|
snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
snd_pcm_multi_t *multi = pcm->private;
|
||||||
|
snd_pcm_t *slave = multi->slaves[slave_idx].pcm;
|
||||||
|
int err = snd_pcm_hw_refine(slave, sparams);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
err = snd_pcm_areas_silence(slave->running_areas, 0, slave->channels, slave->buffer_size, slave->format);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
if (slave->stopped_areas) {
|
||||||
|
err = snd_pcm_areas_silence(slave->stopped_areas, 0, slave->channels, slave->buffer_size, slave->format);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_multi_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
static int snd_pcm_multi_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
{
|
{
|
||||||
snd_pcm_multi_t *multi = pcm->private;
|
snd_pcm_multi_t *multi = pcm->private;
|
||||||
unsigned int k;
|
unsigned int k;
|
||||||
|
snd_pcm_hw_params_t sparams[multi->slaves_count];
|
||||||
int err;
|
int err;
|
||||||
const mask_t *access_mask = snd_pcm_hw_param_value_mask(params, SND_PCM_HW_PARAM_ACCESS);
|
|
||||||
mask_t *saccess_mask = alloca(mask_sizeof());
|
|
||||||
unsigned int links;
|
|
||||||
links = SND_PCM_HW_PARBIT_FORMAT |
|
|
||||||
SND_PCM_HW_PARBIT_SUBFORMAT |
|
|
||||||
SND_PCM_HW_PARBIT_RATE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_PERIODS |
|
|
||||||
SND_PCM_HW_PARBIT_TICK_TIME;
|
|
||||||
if (mask_test(access_mask, SND_PCM_ACCESS_RW_INTERLEAVED) ||
|
|
||||||
mask_test(access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED))
|
|
||||||
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
|
||||||
else {
|
|
||||||
mask_none(saccess_mask);
|
|
||||||
if (mask_test(access_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED) &&
|
|
||||||
multi->slaves_count == 1)
|
|
||||||
mask_set(saccess_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
|
|
||||||
if (mask_test(access_mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED))
|
|
||||||
mask_set(saccess_mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
|
|
||||||
if (mask_test(access_mask, SND_PCM_ACCESS_MMAP_COMPLEX)) {
|
|
||||||
mask_set(saccess_mask, SND_PCM_ACCESS_MMAP_COMPLEX);
|
|
||||||
if (multi->slaves_count > 1)
|
|
||||||
mask_set(saccess_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (k = 0; k < multi->slaves_count; ++k) {
|
for (k = 0; k < multi->slaves_count; ++k) {
|
||||||
snd_pcm_t *slave = multi->slaves[k].pcm;
|
err = snd_pcm_multi_hw_refine_sprepare(pcm, k, &sparams[k]);
|
||||||
snd_pcm_hw_params_t sparams;
|
|
||||||
_snd_pcm_hw_params_any(&sparams);
|
|
||||||
_snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS,
|
|
||||||
saccess_mask);
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_CHANNELS,
|
|
||||||
multi->slaves[k].channels_count, 0);
|
|
||||||
err = snd_pcm_hw_params_refine(&sparams, links, params);
|
|
||||||
assert(err >= 0);
|
assert(err >= 0);
|
||||||
err = snd_pcm_hw_params(slave, &sparams);
|
err = snd_pcm_multi_hw_refine_schange(pcm, k, params, &sparams[k]);
|
||||||
params->cmask = 0;
|
assert(err >= 0);
|
||||||
sparams.cmask = ~0U;
|
err = snd_pcm_multi_hw_params_slave(pcm, k, &sparams[k]);
|
||||||
snd_pcm_hw_params_refine(params, links, &sparams);
|
if (err < 0) {
|
||||||
if (err < 0)
|
snd_pcm_multi_hw_refine_cchange(pcm, k, params, &sparams[k]);
|
||||||
return err;
|
return err;
|
||||||
err = snd_pcm_areas_silence(slave->running_areas, 0, slave->channels, slave->buffer_size, slave->format);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
if (slave->stopped_areas) {
|
|
||||||
err = snd_pcm_areas_silence(slave->stopped_areas, 0, slave->channels, slave->buffer_size, slave->format);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -231,7 +231,7 @@ static snd_pcm_sframes_t snd_pcm_null_avail_update(snd_pcm_t *pcm)
|
||||||
|
|
||||||
static int snd_pcm_null_hw_refine(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params)
|
static int snd_pcm_null_hw_refine(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params)
|
||||||
{
|
{
|
||||||
int err = _snd_pcm_hw_refine(params);
|
int err = snd_pcm_hw_refine_soft(pcm, params);
|
||||||
params->fifo_size = 0;
|
params->fifo_size = 0;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -115,11 +115,13 @@ void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var)
|
||||||
if (hw_is_mask(var)) {
|
if (hw_is_mask(var)) {
|
||||||
mask_any(hw_param_mask(params, var));
|
mask_any(hw_param_mask(params, var));
|
||||||
params->cmask |= 1 << var;
|
params->cmask |= 1 << var;
|
||||||
|
params->rmask |= 1 << var;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (hw_is_interval(var)) {
|
if (hw_is_interval(var)) {
|
||||||
interval_any(hw_param_interval(params, var));
|
interval_any(hw_param_interval(params, var));
|
||||||
params->cmask |= 1 << var;
|
params->cmask |= 1 << var;
|
||||||
|
params->rmask |= 1 << var;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert(0);
|
assert(0);
|
||||||
|
|
@ -241,8 +243,10 @@ int _snd_pcm_hw_param_refine_interval(snd_pcm_hw_params_t *params,
|
||||||
int changed;
|
int changed;
|
||||||
assert(hw_is_interval(var));
|
assert(hw_is_interval(var));
|
||||||
changed = interval_refine(hw_param_interval(params, var), val);
|
changed = interval_refine(hw_param_interval(params, var), val);
|
||||||
if (changed)
|
if (changed) {
|
||||||
params->cmask |= 1 << var;
|
params->cmask |= 1 << var;
|
||||||
|
params->rmask |= 1 << var;
|
||||||
|
}
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -252,8 +256,10 @@ int _snd_pcm_hw_param_setinteger(snd_pcm_hw_params_t *params,
|
||||||
int changed;
|
int changed;
|
||||||
assert(hw_is_interval(var));
|
assert(hw_is_interval(var));
|
||||||
changed = interval_setinteger(hw_param_interval(params, var));
|
changed = interval_setinteger(hw_param_interval(params, var));
|
||||||
if (changed)
|
if (changed) {
|
||||||
params->cmask |= 1 << var;
|
params->cmask |= 1 << var;
|
||||||
|
params->rmask |= 1 << var;
|
||||||
|
}
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -268,7 +274,7 @@ int snd_pcm_hw_param_setinteger(snd_pcm_t *pcm,
|
||||||
int changed = _snd_pcm_hw_param_setinteger(params, var);
|
int changed = _snd_pcm_hw_param_setinteger(params, var);
|
||||||
if (changed < 0)
|
if (changed < 0)
|
||||||
return changed;
|
return changed;
|
||||||
if (changed) {
|
if (params->rmask) {
|
||||||
int err = snd_pcm_hw_refine(pcm, params);
|
int err = snd_pcm_hw_refine(pcm, params);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
@ -288,8 +294,10 @@ int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params,
|
||||||
assert(0);
|
assert(0);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (changed)
|
if (changed) {
|
||||||
params->cmask |= 1 << var;
|
params->cmask |= 1 << var;
|
||||||
|
params->rmask |= 1 << var;
|
||||||
|
}
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -305,7 +313,7 @@ int snd_pcm_hw_param_first(snd_pcm_t *pcm,
|
||||||
int changed = _snd_pcm_hw_param_first(params, var);
|
int changed = _snd_pcm_hw_param_first(params, var);
|
||||||
if (changed < 0)
|
if (changed < 0)
|
||||||
return changed;
|
return changed;
|
||||||
if (changed) {
|
if (params->rmask) {
|
||||||
int err = snd_pcm_hw_refine(pcm, params);
|
int err = snd_pcm_hw_refine(pcm, params);
|
||||||
assert(err >= 0);
|
assert(err >= 0);
|
||||||
}
|
}
|
||||||
|
|
@ -324,8 +332,10 @@ int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params,
|
||||||
assert(0);
|
assert(0);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (changed)
|
if (changed) {
|
||||||
params->cmask |= 1 << var;
|
params->cmask |= 1 << var;
|
||||||
|
params->rmask |= 1 << var;
|
||||||
|
}
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -341,7 +351,7 @@ int snd_pcm_hw_param_last(snd_pcm_t *pcm,
|
||||||
int changed = _snd_pcm_hw_param_last(params, var);
|
int changed = _snd_pcm_hw_param_last(params, var);
|
||||||
if (changed < 0)
|
if (changed < 0)
|
||||||
return changed;
|
return changed;
|
||||||
if (changed) {
|
if (params->rmask) {
|
||||||
int err = snd_pcm_hw_refine(pcm, params);
|
int err = snd_pcm_hw_refine(pcm, params);
|
||||||
assert(err >= 0);
|
assert(err >= 0);
|
||||||
}
|
}
|
||||||
|
|
@ -371,8 +381,10 @@ int _snd_pcm_hw_param_min(snd_pcm_hw_params_t *params,
|
||||||
assert(0);
|
assert(0);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (changed)
|
if (changed) {
|
||||||
params->cmask |= 1 << var;
|
params->cmask |= 1 << var;
|
||||||
|
params->rmask |= 1 << var;
|
||||||
|
}
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -386,7 +398,7 @@ int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
||||||
int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0);
|
int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0);
|
||||||
if (changed < 0)
|
if (changed < 0)
|
||||||
return changed;
|
return changed;
|
||||||
if (changed) {
|
if (params->rmask) {
|
||||||
int err = snd_pcm_hw_refine(pcm, params);
|
int err = snd_pcm_hw_refine(pcm, params);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
@ -432,8 +444,10 @@ int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params,
|
||||||
assert(0);
|
assert(0);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (changed)
|
if (changed) {
|
||||||
params->cmask |= 1 << var;
|
params->cmask |= 1 << var;
|
||||||
|
params->rmask |= 1 << var;
|
||||||
|
}
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -447,7 +461,7 @@ int snd_pcm_hw_param_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
||||||
int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0);
|
int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0);
|
||||||
if (changed < 0)
|
if (changed < 0)
|
||||||
return changed;
|
return changed;
|
||||||
if (changed) {
|
if (params->rmask) {
|
||||||
int err = snd_pcm_hw_refine(pcm, params);
|
int err = snd_pcm_hw_refine(pcm, params);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
@ -527,8 +541,10 @@ int _snd_pcm_hw_param_minmax(snd_pcm_hw_params_t *params,
|
||||||
assert(0);
|
assert(0);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (changed)
|
if (changed) {
|
||||||
params->cmask |= 1 << var;
|
params->cmask |= 1 << var;
|
||||||
|
params->rmask |= 1 << var;
|
||||||
|
}
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -546,7 +562,7 @@ int snd_pcm_hw_param_minmax(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
||||||
*max, maxdir ? *maxdir : 0);
|
*max, maxdir ? *maxdir : 0);
|
||||||
if (changed < 0)
|
if (changed < 0)
|
||||||
return changed;
|
return changed;
|
||||||
if (changed) {
|
if (params->rmask) {
|
||||||
int err = snd_pcm_hw_refine(pcm, params);
|
int err = snd_pcm_hw_refine(pcm, params);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
@ -614,8 +630,10 @@ int _snd_pcm_hw_param_set(snd_pcm_hw_params_t *params,
|
||||||
assert(0);
|
assert(0);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (changed)
|
if (changed) {
|
||||||
params->cmask |= 1 << var;
|
params->cmask |= 1 << var;
|
||||||
|
params->rmask |= 1 << var;
|
||||||
|
}
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -629,7 +647,7 @@ int snd_pcm_hw_param_set(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
||||||
int changed = _snd_pcm_hw_param_set(params, var, val, dir);
|
int changed = _snd_pcm_hw_param_set(params, var, val, dir);
|
||||||
if (changed < 0)
|
if (changed < 0)
|
||||||
return changed;
|
return changed;
|
||||||
if (changed) {
|
if (params->rmask) {
|
||||||
int err = snd_pcm_hw_refine(pcm, params);
|
int err = snd_pcm_hw_refine(pcm, params);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
@ -655,8 +673,10 @@ int _snd_pcm_hw_param_mask(snd_pcm_hw_params_t *params,
|
||||||
int changed;
|
int changed;
|
||||||
assert(hw_is_mask(var));
|
assert(hw_is_mask(var));
|
||||||
changed = mask_refine(hw_param_mask(params, var), val);
|
changed = mask_refine(hw_param_mask(params, var), val);
|
||||||
if (changed)
|
if (changed) {
|
||||||
params->cmask |= 1 << var;
|
params->cmask |= 1 << var;
|
||||||
|
params->rmask |= 1 << var;
|
||||||
|
}
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -673,7 +693,7 @@ int snd_pcm_hw_param_mask(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
||||||
int changed = _snd_pcm_hw_param_mask(params, var, val);
|
int changed = _snd_pcm_hw_param_mask(params, var, val);
|
||||||
if (changed < 0)
|
if (changed < 0)
|
||||||
return changed;
|
return changed;
|
||||||
if (changed) {
|
if (params->rmask) {
|
||||||
int err = snd_pcm_hw_refine(pcm, params);
|
int err = snd_pcm_hw_refine(pcm, params);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
@ -706,7 +726,6 @@ int snd_pcm_hw_param_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
||||||
int v;
|
int v;
|
||||||
unsigned int saved_min;
|
unsigned int saved_min;
|
||||||
int last = 0;
|
int last = 0;
|
||||||
unsigned int cmask;
|
|
||||||
int min, max;
|
int min, max;
|
||||||
int mindir, maxdir;
|
int mindir, maxdir;
|
||||||
int valdir = dir ? *dir : 0;
|
int valdir = dir ? *dir : 0;
|
||||||
|
|
@ -747,12 +766,10 @@ int snd_pcm_hw_param_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
||||||
last = 1;
|
last = 1;
|
||||||
}
|
}
|
||||||
_end:
|
_end:
|
||||||
cmask = params->cmask;
|
|
||||||
if (last)
|
if (last)
|
||||||
v = snd_pcm_hw_param_last(pcm, params, var, dir);
|
v = snd_pcm_hw_param_last(pcm, params, var, dir);
|
||||||
else
|
else
|
||||||
v = snd_pcm_hw_param_first(pcm, params, var, dir);
|
v = snd_pcm_hw_param_first(pcm, params, var, dir);
|
||||||
params->cmask |= cmask;
|
|
||||||
assert(v >= 0);
|
assert(v >= 0);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
@ -773,7 +790,6 @@ int snd_pcm_hw_param_next(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
||||||
snd_pcm_hw_params_t save;
|
snd_pcm_hw_params_t save;
|
||||||
int v;
|
int v;
|
||||||
int last = 0;
|
int last = 0;
|
||||||
unsigned int cmask;
|
|
||||||
int min, max;
|
int min, max;
|
||||||
int mindir, maxdir;
|
int mindir, maxdir;
|
||||||
int diff, diffdir;
|
int diff, diffdir;
|
||||||
|
|
@ -821,12 +837,10 @@ int snd_pcm_hw_param_next(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
||||||
last = 1;
|
last = 1;
|
||||||
}
|
}
|
||||||
_end:
|
_end:
|
||||||
cmask = params->cmask;
|
|
||||||
if (last)
|
if (last)
|
||||||
v = snd_pcm_hw_param_last(pcm, params, var, dir);
|
v = snd_pcm_hw_param_last(pcm, params, var, dir);
|
||||||
else
|
else
|
||||||
v = snd_pcm_hw_param_first(pcm, params, var, dir);
|
v = snd_pcm_hw_param_first(pcm, params, var, dir);
|
||||||
params->cmask |= cmask;
|
|
||||||
assert(v >= 0);
|
assert(v >= 0);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
@ -857,10 +871,10 @@ void snd_pcm_hw_param_near_minmax(snd_pcm_t *pcm,
|
||||||
assert(err >= 0);
|
assert(err >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void snd_pcm_hw_param_near_copy(snd_pcm_t *pcm,
|
void snd_pcm_hw_param_refine_near(snd_pcm_t *pcm,
|
||||||
snd_pcm_hw_params_t *params,
|
snd_pcm_hw_params_t *params,
|
||||||
snd_pcm_hw_param_t var,
|
snd_pcm_hw_param_t var,
|
||||||
const snd_pcm_hw_params_t *src)
|
const snd_pcm_hw_params_t *src)
|
||||||
{
|
{
|
||||||
unsigned int min, max;
|
unsigned int min, max;
|
||||||
int mindir, maxdir;
|
int mindir, maxdir;
|
||||||
|
|
@ -963,41 +977,30 @@ int snd_pcm_hw_params_info_fifo_size(const snd_pcm_hw_params_t *params)
|
||||||
void snd_pcm_hw_params_choose(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
void snd_pcm_hw_params_choose(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
unsigned int cmask = params->cmask;
|
|
||||||
|
|
||||||
err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_ACCESS, 0);
|
err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_ACCESS, 0);
|
||||||
assert(err >= 0);
|
assert(err >= 0);
|
||||||
cmask |= params->cmask;
|
|
||||||
|
|
||||||
err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_FORMAT, 0);
|
err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_FORMAT, 0);
|
||||||
assert(err >= 0);
|
assert(err >= 0);
|
||||||
cmask |= params->cmask;
|
|
||||||
|
|
||||||
err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_SUBFORMAT, 0);
|
err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_SUBFORMAT, 0);
|
||||||
assert(err >= 0);
|
assert(err >= 0);
|
||||||
cmask |= params->cmask;
|
|
||||||
|
|
||||||
err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_CHANNELS, 0);
|
err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_CHANNELS, 0);
|
||||||
assert(err >= 0);
|
assert(err >= 0);
|
||||||
cmask |= params->cmask;
|
|
||||||
|
|
||||||
err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_RATE, 0);
|
err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_RATE, 0);
|
||||||
assert(err >= 0);
|
assert(err >= 0);
|
||||||
cmask |= params->cmask;
|
|
||||||
|
|
||||||
err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_PERIOD_TIME, 0);
|
err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_PERIOD_TIME, 0);
|
||||||
assert(err >= 0);
|
assert(err >= 0);
|
||||||
cmask |= params->cmask;
|
|
||||||
|
|
||||||
err = snd_pcm_hw_param_last(pcm, params, SND_PCM_HW_PARAM_BUFFER_SIZE, 0);
|
err = snd_pcm_hw_param_last(pcm, params, SND_PCM_HW_PARAM_BUFFER_SIZE, 0);
|
||||||
assert(err >= 0);
|
assert(err >= 0);
|
||||||
cmask |= params->cmask;
|
|
||||||
|
|
||||||
err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_TICK_TIME, 0);
|
err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_TICK_TIME, 0);
|
||||||
assert(err >= 0);
|
assert(err >= 0);
|
||||||
cmask |= params->cmask;
|
|
||||||
|
|
||||||
params->cmask = cmask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Strategies */
|
/* Strategies */
|
||||||
|
|
@ -1080,9 +1083,9 @@ unsigned int snd_pcm_hw_param_count(const snd_pcm_hw_params_t *params,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int snd_pcm_hw_param_refine(snd_pcm_hw_params_t *params,
|
int _snd_pcm_hw_param_refine(snd_pcm_hw_params_t *params,
|
||||||
snd_pcm_hw_param_t var,
|
snd_pcm_hw_param_t var,
|
||||||
const snd_pcm_hw_params_t *src)
|
const snd_pcm_hw_params_t *src)
|
||||||
{
|
{
|
||||||
int changed = 0;
|
int changed = 0;
|
||||||
if (hw_is_mask(var)) {
|
if (hw_is_mask(var)) {
|
||||||
|
|
@ -1095,23 +1098,29 @@ int snd_pcm_hw_param_refine(snd_pcm_hw_params_t *params,
|
||||||
changed = interval_refine(d, s);
|
changed = interval_refine(d, s);
|
||||||
} else
|
} else
|
||||||
assert(0);
|
assert(0);
|
||||||
if (changed)
|
if (changed) {
|
||||||
params->cmask |= 1 << var;
|
params->cmask |= 1 << var;
|
||||||
|
params->rmask |= 1 << var;
|
||||||
|
}
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void snd_pcm_hw_param_copy(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var,
|
void _snd_pcm_hw_param_copy(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var,
|
||||||
const snd_pcm_hw_params_t *src)
|
const snd_pcm_hw_params_t *src)
|
||||||
{
|
{
|
||||||
if (hw_is_mask(var)) {
|
if (hw_is_mask(var)) {
|
||||||
mask_t *d = hw_param_mask(params, var);
|
mask_t *d = hw_param_mask(params, var);
|
||||||
const mask_t *s = hw_param_mask_c(src, var);
|
const mask_t *s = hw_param_mask_c(src, var);
|
||||||
mask_copy(d, s);
|
mask_copy(d, s);
|
||||||
|
params->cmask |= 1 << var;
|
||||||
|
params->rmask |= 1 << var;
|
||||||
}
|
}
|
||||||
if (hw_is_interval(var)) {
|
if (hw_is_interval(var)) {
|
||||||
interval_t *d = hw_param_interval(params, var);
|
interval_t *d = hw_param_interval(params, var);
|
||||||
const interval_t *s = hw_param_interval_c(src, var);
|
const interval_t *s = hw_param_interval_c(src, var);
|
||||||
interval_copy(d, s);
|
interval_copy(d, s);
|
||||||
|
params->cmask |= 1 << var;
|
||||||
|
params->rmask |= 1 << var;
|
||||||
}
|
}
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
@ -1138,8 +1147,11 @@ void snd_pcm_hw_param_dump(const snd_pcm_hw_params_t *params,
|
||||||
assert(f);
|
assert(f);
|
||||||
for (k = 0; k <= MASK_MAX; ++k) {
|
for (k = 0; k <= MASK_MAX; ++k) {
|
||||||
if (mask_test(mask, k)) {
|
if (mask_test(mask, k)) {
|
||||||
snd_output_putc(out, ' ');
|
const char *s = f(k);
|
||||||
snd_output_puts(out, f(k));
|
if (s) {
|
||||||
|
snd_output_putc(out, ' ');
|
||||||
|
snd_output_puts(out, s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1188,14 +1200,11 @@ int snd_pcm_hw_params_strategy(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
||||||
best_badness = UINT_MAX;
|
best_badness = UINT_MAX;
|
||||||
value = -1;
|
value = -1;
|
||||||
while (1) {
|
while (1) {
|
||||||
unsigned int cmask;
|
|
||||||
params1 = *params;
|
params1 = *params;
|
||||||
value = strategy->next_value(¶ms1, var, value, &dir, pcm, strategy);
|
value = strategy->next_value(¶ms1, var, value, &dir, pcm, strategy);
|
||||||
if (value < 0)
|
if (value < 0)
|
||||||
break;
|
break;
|
||||||
cmask = params1.cmask;
|
|
||||||
badness = snd_pcm_hw_params_strategy(pcm, ¶ms1, strategy, badness_min, badness_max);
|
badness = snd_pcm_hw_params_strategy(pcm, ¶ms1, strategy, badness_min, badness_max);
|
||||||
params1.cmask |= cmask;
|
|
||||||
if (badness >= 0) {
|
if (badness >= 0) {
|
||||||
if ((unsigned int) badness <= badness_min) {
|
if ((unsigned int) badness <= badness_min) {
|
||||||
*params = params1;
|
*params = params1;
|
||||||
|
|
@ -1475,7 +1484,7 @@ int snd_pcm_hw_params_try_explain_failure1(snd_pcm_t *pcm,
|
||||||
for (var = 0; var <= SND_PCM_HW_PARAM_LAST; var++) {
|
for (var = 0; var <= SND_PCM_HW_PARAM_LAST; var++) {
|
||||||
int err;
|
int err;
|
||||||
i = *success;
|
i = *success;
|
||||||
snd_pcm_hw_param_copy(&i, var, fail);
|
_snd_pcm_hw_param_copy(&i, var, fail);
|
||||||
err = snd_pcm_hw_refine(pcm, &i);
|
err = snd_pcm_hw_refine(pcm, &i);
|
||||||
if (err == 0 &&
|
if (err == 0 &&
|
||||||
snd_pcm_hw_params_try_explain_failure1(pcm, fail, &i, depth - 1, out) < 0)
|
snd_pcm_hw_params_try_explain_failure1(pcm, fail, &i, depth - 1, out) < 0)
|
||||||
|
|
@ -1836,50 +1845,53 @@ static interval_t refine_intervals[SND_PCM_HW_PARAM_LAST_INTERVAL - SND_PCM_HW_P
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#undef RULES_DEBUG
|
||||||
|
|
||||||
|
int snd_pcm_hw_refine_soft(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params)
|
||||||
int _snd_pcm_hw_refine(snd_pcm_hw_params_t *params)
|
|
||||||
{
|
{
|
||||||
unsigned int k;
|
unsigned int k;
|
||||||
interval_t *i;
|
interval_t *i;
|
||||||
unsigned int rstamps[RULES];
|
unsigned int rstamps[RULES];
|
||||||
unsigned int vstamps[SND_PCM_HW_PARAM_LAST + 1];
|
unsigned int vstamps[SND_PCM_HW_PARAM_LAST + 1];
|
||||||
unsigned int stamp = 2;
|
unsigned int stamp = 2;
|
||||||
int err, changed;
|
int changed, again;
|
||||||
|
#ifdef RULES_DEBUG
|
||||||
|
snd_output_t *log;
|
||||||
|
snd_output_stdio_attach(&log, stderr, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (k = SND_PCM_HW_PARAM_FIRST_MASK; k <= SND_PCM_HW_PARAM_LAST_MASK; k++) {
|
for (k = SND_PCM_HW_PARAM_FIRST_MASK; k <= SND_PCM_HW_PARAM_LAST_MASK; k++) {
|
||||||
if (!(params->cmask & (1 << k)))
|
if (!(params->rmask & (1 << k)))
|
||||||
continue;
|
continue;
|
||||||
err = mask_refine(hw_param_mask(params, k),
|
changed = mask_refine(hw_param_mask(params, k),
|
||||||
&refine_masks[k - SND_PCM_HW_PARAM_FIRST_MASK]);
|
&refine_masks[k - SND_PCM_HW_PARAM_FIRST_MASK]);
|
||||||
if (err < 0)
|
if (changed)
|
||||||
return err;
|
params->cmask |= 1 << k;
|
||||||
|
if (changed < 0)
|
||||||
|
goto _err;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (k = SND_PCM_HW_PARAM_FIRST_INTERVAL; k <= SND_PCM_HW_PARAM_LAST_INTERVAL; k++) {
|
for (k = SND_PCM_HW_PARAM_FIRST_INTERVAL; k <= SND_PCM_HW_PARAM_LAST_INTERVAL; k++) {
|
||||||
if (!(params->cmask & (1 << k)))
|
if (!(params->rmask & (1 << k)))
|
||||||
continue;
|
continue;
|
||||||
err = interval_refine(hw_param_interval(params, k),
|
changed = interval_refine(hw_param_interval(params, k),
|
||||||
&refine_intervals[k - SND_PCM_HW_PARAM_FIRST_INTERVAL]);
|
&refine_intervals[k - SND_PCM_HW_PARAM_FIRST_INTERVAL]);
|
||||||
if (err < 0)
|
if (changed)
|
||||||
return err;
|
params->cmask |= 1 << k;
|
||||||
|
if (changed < 0)
|
||||||
|
goto _err;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (k = 0; k < RULES; k++)
|
for (k = 0; k < RULES; k++)
|
||||||
rstamps[k] = 0;
|
rstamps[k] = 0;
|
||||||
for (k = 0; k <= SND_PCM_HW_PARAM_LAST; k++)
|
for (k = 0; k <= SND_PCM_HW_PARAM_LAST; k++)
|
||||||
vstamps[k] = (params->cmask & (1 << k)) ? 1 : 0;
|
vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0;
|
||||||
params->cmask = 0;
|
do {
|
||||||
changed = 1;
|
again = 0;
|
||||||
while (changed) {
|
|
||||||
changed = 0;
|
|
||||||
for (k = 0; k < RULES; k++) {
|
for (k = 0; k < RULES; k++) {
|
||||||
snd_pcm_hw_rule_t *r = &refine_rules[k];
|
snd_pcm_hw_rule_t *r = &refine_rules[k];
|
||||||
unsigned int d;
|
unsigned int d;
|
||||||
int doit = 0;
|
int doit = 0;
|
||||||
#ifdef RULES_DEBUG
|
|
||||||
interval_t *i;
|
|
||||||
#endif
|
|
||||||
for (d = 0; r->deps[d] >= 0; d++) {
|
for (d = 0; r->deps[d] >= 0; d++) {
|
||||||
if (vstamps[r->deps[d]] > rstamps[k]) {
|
if (vstamps[r->deps[d]] > rstamps[k]) {
|
||||||
doit = 1;
|
doit = 1;
|
||||||
|
|
@ -1889,26 +1901,35 @@ int _snd_pcm_hw_refine(snd_pcm_hw_params_t *params)
|
||||||
if (!doit)
|
if (!doit)
|
||||||
continue;
|
continue;
|
||||||
#ifdef RULES_DEBUG
|
#ifdef RULES_DEBUG
|
||||||
i = hw_param_interval(params, r->var);
|
snd_output_printf(log, "Rule %d: ", k);
|
||||||
fprintf(stderr, "Rule %d: %u ", k, r->var);
|
if (r->var >= 0) {
|
||||||
interval_print(i, stderr);
|
snd_output_printf(log, "%s=", snd_pcm_hw_param_name(r->var));
|
||||||
|
snd_pcm_hw_param_dump(params, r->var, log);
|
||||||
|
snd_output_puts(log, " -> ");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
err = r->func(params, r);
|
changed = r->func(params, r);
|
||||||
#ifdef RULES_DEBUG
|
#ifdef RULES_DEBUG
|
||||||
interval_print(i, stderr);
|
if (r->var >= 0)
|
||||||
putc('\n', stderr);
|
snd_pcm_hw_param_dump(params, r->var, log);
|
||||||
|
snd_output_putc(log, ' ');
|
||||||
|
for (d = 0; r->deps[d] >= 0; d++) {
|
||||||
|
snd_output_printf(log, "%s=", snd_pcm_hw_param_name(r->deps[d]));
|
||||||
|
snd_pcm_hw_param_dump(params, r->deps[d], log);
|
||||||
|
}
|
||||||
|
snd_output_putc(log, '\n');
|
||||||
#endif
|
#endif
|
||||||
rstamps[k] = stamp;
|
rstamps[k] = stamp;
|
||||||
if (err && r->var >= 0) {
|
if (changed && r->var >= 0) {
|
||||||
params->cmask |= 1 << r->var;
|
params->cmask |= 1 << r->var;
|
||||||
vstamps[r->var] = stamp;
|
vstamps[r->var] = stamp;
|
||||||
changed = 1;
|
again = 1;
|
||||||
}
|
}
|
||||||
if (err < 0)
|
if (changed < 0)
|
||||||
return err;
|
goto _err;
|
||||||
stamp++;
|
stamp++;
|
||||||
}
|
}
|
||||||
}
|
} while (again);
|
||||||
if (!params->msbits) {
|
if (!params->msbits) {
|
||||||
i = hw_param_interval(params, SND_PCM_HW_PARAM_SAMPLE_BITS);
|
i = hw_param_interval(params, SND_PCM_HW_PARAM_SAMPLE_BITS);
|
||||||
if (interval_single(i))
|
if (interval_single(i))
|
||||||
|
|
@ -1922,69 +1943,97 @@ int _snd_pcm_hw_refine(snd_pcm_hw_params_t *params)
|
||||||
params->rate_den = 1;
|
params->rate_den = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
params->rmask = 0;
|
||||||
return 0;
|
return 0;
|
||||||
|
_err:
|
||||||
|
#ifdef RULES_DEBUG
|
||||||
|
snd_output_close(log);
|
||||||
|
#endif
|
||||||
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
int snd_pcm_hw_params_refine(snd_pcm_hw_params_t *params,
|
int _snd_pcm_hw_params_refine(snd_pcm_hw_params_t *params,
|
||||||
unsigned int vars,
|
unsigned int vars,
|
||||||
const snd_pcm_hw_params_t *src)
|
const snd_pcm_hw_params_t *src)
|
||||||
{
|
{
|
||||||
int changed, err = 0;
|
int changed, err = 0;
|
||||||
unsigned int k;
|
unsigned int k;
|
||||||
for (k = 0; k <= SND_PCM_HW_PARAM_LAST; ++k) {
|
for (k = 0; k <= SND_PCM_HW_PARAM_LAST; ++k) {
|
||||||
if (!(vars & (1 << k)) ||
|
if (!(vars & (1 << k)))
|
||||||
!((src->cmask & (1 << k))))
|
|
||||||
continue;
|
continue;
|
||||||
changed = snd_pcm_hw_param_refine(params, k, src);
|
changed = _snd_pcm_hw_param_refine(params, k, src);
|
||||||
if (changed < 0)
|
if (changed < 0)
|
||||||
err = changed;
|
err = changed;
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Accumulate to params->cmask */
|
int snd_pcm_hw_refine_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
||||||
/* Reset sparams->cmask */
|
int (*cprepare)(snd_pcm_t *pcm,
|
||||||
int snd_pcm_generic_hw_link(snd_pcm_hw_params_t *params,
|
snd_pcm_hw_params_t *params),
|
||||||
snd_pcm_hw_params_t *sparams,
|
int (*cchange)(snd_pcm_t *pcm,
|
||||||
snd_pcm_t *slave,
|
snd_pcm_hw_params_t *params,
|
||||||
unsigned long links)
|
snd_pcm_hw_params_t *sparams),
|
||||||
|
int (*sprepare)(snd_pcm_t *pcm,
|
||||||
|
snd_pcm_hw_params_t *params),
|
||||||
|
int (*schange)(snd_pcm_t *pcm,
|
||||||
|
snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams),
|
||||||
|
int (*srefine)(snd_pcm_t *pcm,
|
||||||
|
snd_pcm_hw_params_t *sparams))
|
||||||
|
|
||||||
{
|
{
|
||||||
int err1, err = 0;
|
snd_pcm_hw_params_t sparams;
|
||||||
err = snd_pcm_hw_params_refine(sparams, links, params);
|
int err;
|
||||||
if (err >= 0) {
|
err = cprepare(pcm, params);
|
||||||
unsigned int cmask = sparams->cmask;
|
if (err < 0)
|
||||||
err = snd_pcm_hw_refine(slave, sparams);
|
return err;
|
||||||
sparams->cmask |= cmask;
|
err = sprepare(pcm, &sparams);
|
||||||
|
if (err < 0) {
|
||||||
|
ERR("Slave PCM not useable");
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
err1 = snd_pcm_hw_params_refine(params, links, sparams);
|
/* FIXME: loop begin? */
|
||||||
if (err1 < 0)
|
err = schange(pcm, params, &sparams);
|
||||||
err = err1;
|
if (err >= 0) {
|
||||||
sparams->cmask = 0;
|
err = srefine(pcm, &sparams);
|
||||||
return err;
|
}
|
||||||
|
if (err < 0) {
|
||||||
|
cchange(pcm, params, &sparams);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
err = cchange(pcm, params, &sparams);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
err = snd_pcm_hw_refine_soft(pcm, params);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
/* FIXME: do we need to loop? */
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int snd_pcm_hw_refine2(snd_pcm_hw_params_t *params,
|
int snd_pcm_hw_params_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
||||||
snd_pcm_hw_params_t *sparams,
|
int (*cchange)(snd_pcm_t *pcm,
|
||||||
int (*func)(snd_pcm_hw_params_t *params,
|
snd_pcm_hw_params_t *params,
|
||||||
snd_pcm_hw_params_t *sparams,
|
snd_pcm_hw_params_t *sparams),
|
||||||
snd_pcm_t *slave,
|
int (*sprepare)(snd_pcm_t *pcm,
|
||||||
unsigned long private),
|
snd_pcm_hw_params_t *params),
|
||||||
snd_pcm_t *slave,
|
int (*schange)(snd_pcm_t *pcm,
|
||||||
unsigned long private)
|
snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams),
|
||||||
|
int (*sparams)(snd_pcm_t *pcm,
|
||||||
|
snd_pcm_hw_params_t *sparams))
|
||||||
|
|
||||||
{
|
{
|
||||||
int err = 0;
|
snd_pcm_hw_params_t slave_params;
|
||||||
unsigned int cmask = 0;
|
int err;
|
||||||
while (params->cmask) {
|
err = sprepare(pcm, &slave_params);
|
||||||
err = func(params, sparams, slave, private);
|
assert(err >= 0);
|
||||||
cmask |= params->cmask;
|
err = schange(pcm, params, &slave_params);
|
||||||
if (err < 0)
|
assert(err >= 0);
|
||||||
break;
|
err = sparams(pcm, &slave_params);
|
||||||
err = _snd_pcm_hw_refine(params);
|
if (err < 0)
|
||||||
cmask |= params->cmask;
|
cchange(pcm, params, &slave_params);
|
||||||
if (err < 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
params->cmask = cmask;
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -192,182 +192,6 @@ static int snd_pcm_plug_slave_format(int format, const mask_t *format_mask)
|
||||||
(1 << SND_PCM_FORMAT_IMA_ADPCM))
|
(1 << SND_PCM_FORMAT_IMA_ADPCM))
|
||||||
|
|
||||||
|
|
||||||
/* Accumulate to params->cmask */
|
|
||||||
/* Reset sparams->cmask */
|
|
||||||
static int snd_pcm_plug_hw_link(snd_pcm_hw_params_t *params,
|
|
||||||
snd_pcm_hw_params_t *sparams,
|
|
||||||
snd_pcm_t *slave,
|
|
||||||
unsigned long private ATTRIBUTE_UNUSED)
|
|
||||||
{
|
|
||||||
int rate_always, channels_always, format_always;
|
|
||||||
int rate_never, channels_never, format_never;
|
|
||||||
unsigned int links = (SND_PCM_HW_PARBIT_PERIOD_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_TICK_TIME);
|
|
||||||
const mask_t *format_mask, *sformat_mask;
|
|
||||||
mask_t *fmt_mask = alloca(mask_sizeof());
|
|
||||||
mask_t *sfmt_mask = alloca(mask_sizeof());
|
|
||||||
mask_t *access_mask = alloca(mask_sizeof());
|
|
||||||
int err;
|
|
||||||
unsigned int format;
|
|
||||||
unsigned int scmask = sparams->cmask;
|
|
||||||
snd_pcm_hw_param_near_copy(slave, sparams, SND_PCM_HW_PARAM_RATE,
|
|
||||||
params);
|
|
||||||
scmask |= sparams->cmask;
|
|
||||||
snd_pcm_hw_param_near_copy(slave, sparams, SND_PCM_HW_PARAM_CHANNELS,
|
|
||||||
params);
|
|
||||||
scmask |= sparams->cmask;
|
|
||||||
format_mask = snd_pcm_hw_param_value_mask(params,
|
|
||||||
SND_PCM_HW_PARAM_FORMAT);
|
|
||||||
sformat_mask = snd_pcm_hw_param_value_mask(sparams,
|
|
||||||
SND_PCM_HW_PARAM_FORMAT);
|
|
||||||
mask_none(sfmt_mask);
|
|
||||||
mask_none(fmt_mask);
|
|
||||||
for (format = 0; format <= SND_PCM_FORMAT_LAST; format++) {
|
|
||||||
int f;
|
|
||||||
if (!mask_test(format_mask, format))
|
|
||||||
continue;
|
|
||||||
if (mask_test(sformat_mask, format))
|
|
||||||
f = format;
|
|
||||||
else {
|
|
||||||
f = snd_pcm_plug_slave_format(format, sformat_mask);
|
|
||||||
if (f < 0)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
mask_set(sfmt_mask, f);
|
|
||||||
mask_set(fmt_mask, format);
|
|
||||||
}
|
|
||||||
|
|
||||||
err = _snd_pcm_hw_param_mask(params,
|
|
||||||
SND_PCM_HW_PARAM_FORMAT, fmt_mask);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
err = _snd_pcm_hw_param_mask(sparams,
|
|
||||||
SND_PCM_HW_PARAM_FORMAT, sfmt_mask);
|
|
||||||
assert(err >= 0);
|
|
||||||
|
|
||||||
format_always = snd_pcm_hw_param_always_eq(params,
|
|
||||||
SND_PCM_HW_PARAM_FORMAT,
|
|
||||||
sparams);
|
|
||||||
format_never = (!format_always &&
|
|
||||||
snd_pcm_hw_param_never_eq(params,
|
|
||||||
SND_PCM_HW_PARAM_FORMAT,
|
|
||||||
sparams));
|
|
||||||
|
|
||||||
channels_always = snd_pcm_hw_param_always_eq(params,
|
|
||||||
SND_PCM_HW_PARAM_CHANNELS,
|
|
||||||
sparams);
|
|
||||||
channels_never = (!channels_always &&
|
|
||||||
snd_pcm_hw_param_never_eq(params,
|
|
||||||
SND_PCM_HW_PARAM_CHANNELS,
|
|
||||||
sparams));
|
|
||||||
|
|
||||||
rate_always = snd_pcm_hw_param_always_eq(params,
|
|
||||||
SND_PCM_HW_PARAM_RATE,
|
|
||||||
sparams);
|
|
||||||
rate_never = (!rate_always &&
|
|
||||||
snd_pcm_hw_param_never_eq(params,
|
|
||||||
SND_PCM_HW_PARAM_RATE,
|
|
||||||
sparams));
|
|
||||||
|
|
||||||
if (rate_always)
|
|
||||||
links |= (SND_PCM_HW_PARBIT_RATE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIODS |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_SIZE);
|
|
||||||
else {
|
|
||||||
interval_t t;
|
|
||||||
const interval_t *sbuffer_size, *buffer_size;
|
|
||||||
const interval_t *srate, *rate;
|
|
||||||
buffer_size = snd_pcm_hw_param_value_interval(params, SND_PCM_HW_PARAM_BUFFER_SIZE);
|
|
||||||
sbuffer_size = snd_pcm_hw_param_value_interval(sparams, SND_PCM_HW_PARAM_BUFFER_SIZE);
|
|
||||||
rate = snd_pcm_hw_param_value_interval(params, SND_PCM_HW_PARAM_RATE);
|
|
||||||
srate = snd_pcm_hw_param_value_interval(sparams, SND_PCM_HW_PARAM_RATE);
|
|
||||||
interval_muldiv(sbuffer_size, rate, srate, &t);
|
|
||||||
interval_round(&t);
|
|
||||||
err = _snd_pcm_hw_param_refine_interval(params, SND_PCM_HW_PARAM_BUFFER_SIZE, &t);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
interval_muldiv(buffer_size, srate, rate, &t);
|
|
||||||
interval_round(&t);
|
|
||||||
err = _snd_pcm_hw_param_refine_interval(sparams, SND_PCM_HW_PARAM_BUFFER_SIZE, &t);
|
|
||||||
assert(err >= 0);
|
|
||||||
scmask |= sparams->cmask;
|
|
||||||
}
|
|
||||||
if (channels_always)
|
|
||||||
links |= SND_PCM_HW_PARBIT_CHANNELS;
|
|
||||||
if (format_always) {
|
|
||||||
links |= (SND_PCM_HW_PARBIT_FORMAT |
|
|
||||||
SND_PCM_HW_PARBIT_SUBFORMAT |
|
|
||||||
SND_PCM_HW_PARBIT_SAMPLE_BITS);
|
|
||||||
if (channels_always) {
|
|
||||||
links |= SND_PCM_HW_PARBIT_FRAME_BITS;
|
|
||||||
if (rate_always)
|
|
||||||
links |= (SND_PCM_HW_PARBIT_PERIOD_BYTES |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_BYTES);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN);
|
|
||||||
if (format_never || channels_never || rate_never) {
|
|
||||||
mask_t *mmap_mask = alloca(mask_sizeof());
|
|
||||||
mask_load(mmap_mask, SND_PCM_ACCBIT_MMAP);
|
|
||||||
err = _snd_pcm_hw_param_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
|
|
||||||
mmap_mask);
|
|
||||||
assert(err >= 0);
|
|
||||||
} else
|
|
||||||
mask_union(access_mask, snd_pcm_hw_param_value_mask(sparams, SND_PCM_HW_PARAM_ACCESS));
|
|
||||||
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS,
|
|
||||||
access_mask);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
sparams->cmask |= scmask;
|
|
||||||
return snd_pcm_generic_hw_link(params, sparams, slave, links);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int snd_pcm_plug_hw_refine1(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
|
||||||
snd_pcm_hw_params_t *sparams)
|
|
||||||
{
|
|
||||||
snd_pcm_plug_t *plug = pcm->private;
|
|
||||||
snd_pcm_t *slave = plug->req_slave;
|
|
||||||
unsigned int cmask, lcmask;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
cmask = params->cmask;
|
|
||||||
params->cmask = 0;
|
|
||||||
err = _snd_pcm_hw_param_min(params, SND_PCM_HW_PARAM_CHANNELS, 1, 0);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
err = _snd_pcm_hw_param_max(params, SND_PCM_HW_PARAM_CHANNELS, 1024, 0);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
err = _snd_pcm_hw_param_min(params, SND_PCM_HW_PARAM_RATE, RATE_MIN, 0);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
err = _snd_pcm_hw_param_max(params, SND_PCM_HW_PARAM_RATE, RATE_MAX, 0);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
lcmask = params->cmask;
|
|
||||||
params->cmask |= cmask;
|
|
||||||
|
|
||||||
_snd_pcm_hw_params_any(sparams);
|
|
||||||
err = snd_pcm_hw_refine2(params, sparams,
|
|
||||||
snd_pcm_plug_hw_link, slave, 0);
|
|
||||||
params->cmask |= lcmask;
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int snd_pcm_plug_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
|
||||||
{
|
|
||||||
snd_pcm_hw_params_t sparams;
|
|
||||||
return snd_pcm_plug_hw_refine1(pcm, params, &sparams);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void snd_pcm_plug_clear(snd_pcm_t *pcm)
|
static void snd_pcm_plug_clear(snd_pcm_t *pcm)
|
||||||
{
|
{
|
||||||
snd_pcm_plug_t *plug = pcm->private;
|
snd_pcm_plug_t *plug = pcm->private;
|
||||||
|
|
@ -580,13 +404,164 @@ static int snd_pcm_plug_insert_plugins(snd_pcm_t *pcm,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_plug_hw_refine_cprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_plug_hw_refine_sprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
snd_pcm_plug_t *plug = pcm->private;
|
||||||
|
snd_pcm_t *slave = plug->req_slave;
|
||||||
|
return snd_pcm_hw_params_any(slave, sparams);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_plug_t *plug = pcm->private;
|
||||||
|
snd_pcm_t *slave = plug->req_slave;
|
||||||
|
unsigned int links = (SND_PCM_HW_PARBIT_PERIOD_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_TICK_TIME);
|
||||||
|
const mask_t *format_mask, *sformat_mask;
|
||||||
|
mask_t *sfmt_mask = alloca(mask_sizeof());
|
||||||
|
int err;
|
||||||
|
unsigned int format;
|
||||||
|
interval_t t;
|
||||||
|
const interval_t *buffer_size;
|
||||||
|
const interval_t *srate, *crate;
|
||||||
|
err = _snd_pcm_hw_params_refine(sparams, links, params);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
snd_pcm_hw_param_refine_near(slave, sparams, SND_PCM_HW_PARAM_RATE,
|
||||||
|
params);
|
||||||
|
snd_pcm_hw_param_refine_near(slave, sparams, SND_PCM_HW_PARAM_CHANNELS,
|
||||||
|
params);
|
||||||
|
format_mask = snd_pcm_hw_param_value_mask(params,
|
||||||
|
SND_PCM_HW_PARAM_FORMAT);
|
||||||
|
sformat_mask = snd_pcm_hw_param_value_mask(sparams,
|
||||||
|
SND_PCM_HW_PARAM_FORMAT);
|
||||||
|
mask_none(sfmt_mask);
|
||||||
|
for (format = 0; format <= SND_PCM_FORMAT_LAST; format++) {
|
||||||
|
int f;
|
||||||
|
if (!mask_test(format_mask, format))
|
||||||
|
continue;
|
||||||
|
if (mask_test(sformat_mask, format))
|
||||||
|
f = format;
|
||||||
|
else {
|
||||||
|
f = snd_pcm_plug_slave_format(format, sformat_mask);
|
||||||
|
if (f < 0)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
mask_set(sfmt_mask, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = snd_pcm_hw_param_mask(slave, sparams,
|
||||||
|
SND_PCM_HW_PARAM_FORMAT, sfmt_mask);
|
||||||
|
assert(err >= 0);
|
||||||
|
|
||||||
|
if (snd_pcm_hw_param_never_eq(params, SND_PCM_HW_PARAM_FORMAT, sparams) ||
|
||||||
|
snd_pcm_hw_param_never_eq(params, SND_PCM_HW_PARAM_CHANNELS, sparams) ||
|
||||||
|
snd_pcm_hw_param_never_eq(params, SND_PCM_HW_PARAM_RATE, sparams) ||
|
||||||
|
snd_pcm_hw_param_never_eq(params, SND_PCM_HW_PARAM_ACCESS, sparams)) {
|
||||||
|
mask_t *access_mask = alloca(mask_sizeof());
|
||||||
|
mask_load(access_mask, SND_PCM_ACCBIT_MMAP);
|
||||||
|
_snd_pcm_hw_param_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
|
||||||
|
access_mask);
|
||||||
|
}
|
||||||
|
buffer_size = snd_pcm_hw_param_value_interval(params, SND_PCM_HW_PARAM_BUFFER_SIZE);
|
||||||
|
crate = snd_pcm_hw_param_value_interval(params, SND_PCM_HW_PARAM_RATE);
|
||||||
|
srate = snd_pcm_hw_param_value_interval(sparams, SND_PCM_HW_PARAM_RATE);
|
||||||
|
interval_muldiv(buffer_size, srate, crate, &t);
|
||||||
|
interval_round(&t);
|
||||||
|
err = _snd_pcm_hw_param_refine_interval(sparams, SND_PCM_HW_PARAM_BUFFER_SIZE, &t);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_plug_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED,
|
||||||
|
snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
unsigned int links = (SND_PCM_HW_PARBIT_PERIOD_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_TICK_TIME);
|
||||||
|
const mask_t *format_mask, *sformat_mask;
|
||||||
|
mask_t *fmt_mask = alloca(mask_sizeof());
|
||||||
|
int err;
|
||||||
|
unsigned int format;
|
||||||
|
interval_t t;
|
||||||
|
const interval_t *sbuffer_size;
|
||||||
|
const interval_t *srate, *crate;
|
||||||
|
format_mask = snd_pcm_hw_param_value_mask(params,
|
||||||
|
SND_PCM_HW_PARAM_FORMAT);
|
||||||
|
sformat_mask = snd_pcm_hw_param_value_mask(sparams,
|
||||||
|
SND_PCM_HW_PARAM_FORMAT);
|
||||||
|
mask_none(fmt_mask);
|
||||||
|
for (format = 0; format <= SND_PCM_FORMAT_LAST; format++) {
|
||||||
|
int f;
|
||||||
|
if (!mask_test(format_mask, format))
|
||||||
|
continue;
|
||||||
|
if (mask_test(sformat_mask, format))
|
||||||
|
f = format;
|
||||||
|
else {
|
||||||
|
f = snd_pcm_plug_slave_format(format, sformat_mask);
|
||||||
|
if (f < 0)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
mask_set(fmt_mask, format);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = _snd_pcm_hw_param_mask(params,
|
||||||
|
SND_PCM_HW_PARAM_FORMAT, fmt_mask);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
sbuffer_size = snd_pcm_hw_param_value_interval(sparams, SND_PCM_HW_PARAM_BUFFER_SIZE);
|
||||||
|
crate = snd_pcm_hw_param_value_interval(params, SND_PCM_HW_PARAM_RATE);
|
||||||
|
srate = snd_pcm_hw_param_value_interval(sparams, SND_PCM_HW_PARAM_RATE);
|
||||||
|
interval_muldiv(sbuffer_size, crate, srate, &t);
|
||||||
|
interval_round(&t);
|
||||||
|
err = _snd_pcm_hw_param_refine_interval(params, SND_PCM_HW_PARAM_BUFFER_SIZE, &t);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
err = _snd_pcm_hw_params_refine(params, links, sparams);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
/* FIXME */
|
||||||
|
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_plug_hw_refine_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
|
{
|
||||||
|
snd_pcm_plug_t *plug = pcm->private;
|
||||||
|
return snd_pcm_hw_refine(plug->req_slave, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_plug_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
|
{
|
||||||
|
return snd_pcm_hw_refine_slave(pcm, params,
|
||||||
|
snd_pcm_plug_hw_refine_cprepare,
|
||||||
|
snd_pcm_plug_hw_refine_cchange,
|
||||||
|
snd_pcm_plug_hw_refine_sprepare,
|
||||||
|
snd_pcm_plug_hw_refine_schange,
|
||||||
|
snd_pcm_plug_hw_refine_slave);
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_pcm_plug_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
static int snd_pcm_plug_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
{
|
{
|
||||||
snd_pcm_plug_t *plug = pcm->private;
|
snd_pcm_plug_t *plug = pcm->private;
|
||||||
snd_pcm_t *slave = plug->req_slave;
|
snd_pcm_t *slave = plug->req_slave;
|
||||||
snd_pcm_plug_params_t clt_params, slv_params;
|
snd_pcm_plug_params_t clt_params, slv_params;
|
||||||
snd_pcm_hw_params_t sparams;
|
snd_pcm_hw_params_t sparams;
|
||||||
int err = snd_pcm_plug_hw_refine1(pcm, params, &sparams);
|
int err;
|
||||||
|
|
||||||
|
err = snd_pcm_plug_hw_refine_sprepare(pcm, &sparams);
|
||||||
|
assert(err >= 0);
|
||||||
|
err = snd_pcm_plug_hw_refine_schange(pcm, params, &sparams);
|
||||||
|
assert(err >= 0);
|
||||||
|
err = snd_pcm_hw_refine_soft(slave, &sparams);
|
||||||
assert(err >= 0);
|
assert(err >= 0);
|
||||||
|
|
||||||
clt_params.access = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_ACCESS, 0);
|
clt_params.access = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_ACCESS, 0);
|
||||||
|
|
@ -594,21 +569,14 @@ static int snd_pcm_plug_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
clt_params.channels = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_CHANNELS, 0);
|
clt_params.channels = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_CHANNELS, 0);
|
||||||
clt_params.rate = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_RATE, 0);
|
clt_params.rate = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_RATE, 0);
|
||||||
|
|
||||||
|
slv_params.access = snd_pcm_hw_param_first(slave, &sparams, SND_PCM_HW_PARAM_ACCESS, 0);
|
||||||
slv_params.format = snd_pcm_hw_param_value(&sparams, SND_PCM_HW_PARAM_FORMAT, 0);
|
slv_params.format = snd_pcm_hw_param_value(&sparams, SND_PCM_HW_PARAM_FORMAT, 0);
|
||||||
slv_params.channels = snd_pcm_hw_param_value(&sparams, SND_PCM_HW_PARAM_CHANNELS, 0);
|
slv_params.channels = snd_pcm_hw_param_value(&sparams, SND_PCM_HW_PARAM_CHANNELS, 0);
|
||||||
slv_params.rate = snd_pcm_hw_param_value(&sparams, SND_PCM_HW_PARAM_RATE, 0);
|
slv_params.rate = snd_pcm_hw_param_value(&sparams, SND_PCM_HW_PARAM_RATE, 0);
|
||||||
snd_pcm_plug_clear(pcm);
|
snd_pcm_plug_clear(pcm);
|
||||||
if (clt_params.format == slv_params.format &&
|
err = snd_pcm_plug_insert_plugins(pcm, &clt_params, &slv_params);
|
||||||
clt_params.channels == slv_params.channels &&
|
if (err < 0)
|
||||||
clt_params.rate == slv_params.rate &&
|
return err;
|
||||||
snd_pcm_hw_param_test(params, SND_PCM_HW_PARAM_ACCESS, clt_params.access))
|
|
||||||
slv_params.access = clt_params.access;
|
|
||||||
else {
|
|
||||||
slv_params.access = snd_pcm_hw_param_first(slave, &sparams, SND_PCM_HW_PARAM_ACCESS, 0);
|
|
||||||
err = snd_pcm_plug_insert_plugins(pcm, &clt_params, &slv_params);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
err = snd_pcm_hw_params(plug->slave, params);
|
err = snd_pcm_hw_params(plug->slave, params);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
snd_pcm_plug_clear(pcm);
|
snd_pcm_plug_clear(pcm);
|
||||||
|
|
|
||||||
|
|
@ -340,6 +340,18 @@ int snd_pcm_plugin_poll_descriptor(snd_pcm_t *pcm)
|
||||||
return snd_pcm_poll_descriptor(plugin->slave);
|
return snd_pcm_poll_descriptor(plugin->slave);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int snd_pcm_plugin_hw_refine_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
|
{
|
||||||
|
snd_pcm_plugin_t *plugin = pcm->private;
|
||||||
|
return snd_pcm_hw_refine(plugin->slave, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
int snd_pcm_plugin_hw_params_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
|
{
|
||||||
|
snd_pcm_plugin_t *plugin = pcm->private;
|
||||||
|
return snd_pcm_hw_params(plugin->slave, params);
|
||||||
|
}
|
||||||
|
|
||||||
int conv_index(int src_format, int dst_format)
|
int conv_index(int src_format, int dst_format)
|
||||||
{
|
{
|
||||||
int src_endian, dst_endian, sign, src_width, dst_width;
|
int src_endian, dst_endian, sign, src_width, dst_width;
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,8 @@ int snd_pcm_plugin_poll_descriptor(snd_pcm_t *pcm);
|
||||||
int get_index(int src_format, int dst_format);
|
int get_index(int src_format, int dst_format);
|
||||||
int put_index(int src_format, int dst_format);
|
int put_index(int src_format, int dst_format);
|
||||||
int conv_index(int src_format, int dst_format);
|
int conv_index(int src_format, int dst_format);
|
||||||
|
int snd_pcm_plugin_hw_params_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
|
||||||
|
int snd_pcm_plugin_hw_refine_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
|
||||||
|
|
||||||
#define SND_PCM_FMTBIT_LINEAR \
|
#define SND_PCM_FMTBIT_LINEAR \
|
||||||
((1 << SND_PCM_FORMAT_S8 ) | (1 << SND_PCM_FORMAT_U8) | \
|
((1 << SND_PCM_FORMAT_S8 ) | (1 << SND_PCM_FORMAT_U8) | \
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#include <byteswap.h>
|
#include <byteswap.h>
|
||||||
#include "pcm_local.h"
|
#include "pcm_local.h"
|
||||||
#include "pcm_plugin.h"
|
#include "pcm_plugin.h"
|
||||||
|
#include "interval.h"
|
||||||
|
|
||||||
#define DIV (1<<16)
|
#define DIV (1<<16)
|
||||||
|
|
||||||
|
|
@ -233,30 +234,23 @@ static int snd_pcm_rate_close(snd_pcm_t *pcm)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_rate_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
static int snd_pcm_rate_hw_refine_cprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params)
|
||||||
{
|
{
|
||||||
snd_pcm_rate_t *rate = pcm->private;
|
|
||||||
snd_pcm_t *slave = rate->plug.slave;
|
|
||||||
int err;
|
int err;
|
||||||
unsigned int cmask, lcmask;
|
|
||||||
snd_pcm_hw_params_t sparams;
|
|
||||||
unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_TICK_TIME);
|
|
||||||
mask_t *access_mask = alloca(mask_sizeof());
|
mask_t *access_mask = alloca(mask_sizeof());
|
||||||
mask_t *format_mask = alloca(mask_sizeof());
|
mask_t *format_mask = alloca(mask_sizeof());
|
||||||
mask_t *saccess_mask = alloca(mask_sizeof());
|
|
||||||
mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN);
|
mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN);
|
||||||
mask_load(format_mask, SND_PCM_FMTBIT_LINEAR);
|
mask_load(format_mask, SND_PCM_FMTBIT_LINEAR);
|
||||||
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
|
||||||
cmask = params->cmask;
|
|
||||||
params->cmask = 0;
|
|
||||||
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS,
|
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS,
|
||||||
access_mask);
|
access_mask);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT,
|
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT,
|
||||||
format_mask);
|
format_mask);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_SUBFORMAT,
|
||||||
|
SND_PCM_SUBFORMAT_STD, 0);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
err = _snd_pcm_hw_param_min(params,
|
err = _snd_pcm_hw_param_min(params,
|
||||||
|
|
@ -267,81 +261,114 @@ static int snd_pcm_rate_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
SND_PCM_HW_PARAM_RATE, RATE_MAX, 0);
|
SND_PCM_HW_PARAM_RATE, RATE_MAX, 0);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
lcmask = params->cmask;
|
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
|
||||||
params->cmask |= cmask;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
_snd_pcm_hw_params_any(&sparams);
|
static int snd_pcm_rate_hw_refine_sprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *sparams)
|
||||||
_snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS,
|
{
|
||||||
|
snd_pcm_rate_t *rate = pcm->private;
|
||||||
|
mask_t *saccess_mask = alloca(mask_sizeof());
|
||||||
|
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
||||||
|
_snd_pcm_hw_params_any(sparams);
|
||||||
|
_snd_pcm_hw_param_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
|
||||||
saccess_mask);
|
saccess_mask);
|
||||||
snd_pcm_hw_param_near_copy(slave, &sparams,
|
|
||||||
SND_PCM_HW_PARAM_BUFFER_TIME,
|
|
||||||
params);
|
|
||||||
if (rate->sformat >= 0) {
|
if (rate->sformat >= 0) {
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_FORMAT,
|
_snd_pcm_hw_param_set(sparams, SND_PCM_HW_PARAM_FORMAT,
|
||||||
rate->sformat, 0);
|
rate->sformat, 0);
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_SUBFORMAT,
|
_snd_pcm_hw_param_set(sparams, SND_PCM_HW_PARAM_SUBFORMAT,
|
||||||
SND_PCM_SUBFORMAT_STD, 0);
|
SND_PCM_SUBFORMAT_STD, 0);
|
||||||
} else
|
}
|
||||||
|
_snd_pcm_hw_param_set(sparams, SND_PCM_HW_PARAM_RATE,
|
||||||
|
rate->srate, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_rate_hw_refine_schange(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
snd_pcm_rate_t *rate = pcm->private;
|
||||||
|
interval_t t;
|
||||||
|
const interval_t *buffer_size;
|
||||||
|
const interval_t *srate, *crate;
|
||||||
|
int err;
|
||||||
|
unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_TICK_TIME);
|
||||||
|
if (rate->sformat < 0)
|
||||||
links |= (SND_PCM_HW_PARBIT_FORMAT |
|
links |= (SND_PCM_HW_PARBIT_FORMAT |
|
||||||
SND_PCM_HW_PARBIT_SUBFORMAT |
|
SND_PCM_HW_PARBIT_SUBFORMAT |
|
||||||
SND_PCM_HW_PARBIT_SAMPLE_BITS |
|
SND_PCM_HW_PARBIT_SAMPLE_BITS |
|
||||||
SND_PCM_HW_PARBIT_FRAME_BITS);
|
SND_PCM_HW_PARBIT_FRAME_BITS);
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_RATE,
|
buffer_size = snd_pcm_hw_param_value_interval(params, SND_PCM_HW_PARAM_BUFFER_SIZE);
|
||||||
rate->srate, 0);
|
crate = snd_pcm_hw_param_value_interval(params, SND_PCM_HW_PARAM_RATE);
|
||||||
|
srate = snd_pcm_hw_param_value_interval(sparams, SND_PCM_HW_PARAM_RATE);
|
||||||
err = snd_pcm_hw_refine2(params, &sparams,
|
interval_muldiv(buffer_size, srate, crate, &t);
|
||||||
snd_pcm_generic_hw_link, slave, links);
|
interval_round(&t);
|
||||||
params->cmask |= lcmask;
|
err = _snd_pcm_hw_param_refine_interval(sparams, SND_PCM_HW_PARAM_BUFFER_SIZE, &t);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
err = _snd_pcm_hw_params_refine(sparams, links, params);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_rate_hw_refine_cchange(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
snd_pcm_rate_t *rate = pcm->private;
|
||||||
|
interval_t t;
|
||||||
|
const interval_t *sbuffer_size;
|
||||||
|
const interval_t *srate, *crate;
|
||||||
|
int err;
|
||||||
|
unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_TICK_TIME);
|
||||||
|
if (rate->sformat < 0)
|
||||||
|
links |= (SND_PCM_HW_PARBIT_FORMAT |
|
||||||
|
SND_PCM_HW_PARBIT_SUBFORMAT |
|
||||||
|
SND_PCM_HW_PARBIT_SAMPLE_BITS |
|
||||||
|
SND_PCM_HW_PARBIT_FRAME_BITS);
|
||||||
|
sbuffer_size = snd_pcm_hw_param_value_interval(sparams, SND_PCM_HW_PARAM_BUFFER_SIZE);
|
||||||
|
crate = snd_pcm_hw_param_value_interval(params, SND_PCM_HW_PARAM_RATE);
|
||||||
|
srate = snd_pcm_hw_param_value_interval(sparams, SND_PCM_HW_PARAM_RATE);
|
||||||
|
interval_muldiv(sbuffer_size, crate, srate, &t);
|
||||||
|
interval_round(&t);
|
||||||
|
err = _snd_pcm_hw_param_refine_interval(params, SND_PCM_HW_PARAM_BUFFER_SIZE, &t);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
err = _snd_pcm_hw_params_refine(params, links, sparams);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_rate_hw_refine(snd_pcm_t *pcm,
|
||||||
|
snd_pcm_hw_params_t *params)
|
||||||
|
{
|
||||||
|
return snd_pcm_hw_refine_slave(pcm, params,
|
||||||
|
snd_pcm_rate_hw_refine_cprepare,
|
||||||
|
snd_pcm_rate_hw_refine_cchange,
|
||||||
|
snd_pcm_rate_hw_refine_sprepare,
|
||||||
|
snd_pcm_rate_hw_refine_schange,
|
||||||
|
snd_pcm_plugin_hw_refine_slave);
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
|
static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
|
||||||
{
|
{
|
||||||
snd_pcm_rate_t *rate = pcm->private;
|
snd_pcm_rate_t *rate = pcm->private;
|
||||||
snd_pcm_t *slave = rate->plug.slave;
|
snd_pcm_t *slave = rate->plug.slave;
|
||||||
int err;
|
|
||||||
snd_pcm_hw_params_t sparams;
|
|
||||||
unsigned int links = (SND_PCM_HW_PARBIT_CHANNELS |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_TICK_TIME);
|
|
||||||
unsigned int src_format, dst_format;
|
unsigned int src_format, dst_format;
|
||||||
unsigned int src_rate, dst_rate;
|
unsigned int src_rate, dst_rate;
|
||||||
mask_t *saccess_mask = alloca(mask_sizeof());
|
int err = snd_pcm_hw_params_slave(pcm, params,
|
||||||
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
snd_pcm_rate_hw_refine_cchange,
|
||||||
|
snd_pcm_rate_hw_refine_sprepare,
|
||||||
_snd_pcm_hw_params_any(&sparams);
|
snd_pcm_rate_hw_refine_schange,
|
||||||
_snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS,
|
snd_pcm_plugin_hw_params_slave);
|
||||||
saccess_mask);
|
|
||||||
if (rate->sformat >= 0) {
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_FORMAT,
|
|
||||||
rate->sformat, 0);
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_SUBFORMAT,
|
|
||||||
SND_PCM_SUBFORMAT_STD, 0);
|
|
||||||
} else
|
|
||||||
links |= (SND_PCM_HW_PARBIT_FORMAT |
|
|
||||||
SND_PCM_HW_PARBIT_SUBFORMAT |
|
|
||||||
SND_PCM_HW_PARBIT_SAMPLE_BITS |
|
|
||||||
SND_PCM_HW_PARBIT_FRAME_BITS);
|
|
||||||
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_RATE,
|
|
||||||
rate->srate, 0);
|
|
||||||
|
|
||||||
snd_pcm_hw_param_near_copy(slave, &sparams,
|
|
||||||
SND_PCM_HW_PARAM_BUFFER_TIME,
|
|
||||||
params);
|
|
||||||
|
|
||||||
err = snd_pcm_hw_params_refine(&sparams, links, params);
|
|
||||||
assert(err >= 0);
|
|
||||||
err = snd_pcm_hw_params(slave, &sparams);
|
|
||||||
params->cmask = 0;
|
|
||||||
sparams.cmask = ~0U;
|
|
||||||
snd_pcm_hw_params_refine(params, links, &sparams);
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
|
|
||||||
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
|
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
|
||||||
src_format = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT, 0);
|
src_format = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT, 0);
|
||||||
dst_format = slave->format;
|
dst_format = slave->format;
|
||||||
|
|
|
||||||
|
|
@ -425,80 +425,58 @@ static int snd_pcm_route_close(snd_pcm_t *pcm)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_route_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
static int snd_pcm_route_hw_refine_cprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params)
|
||||||
{
|
{
|
||||||
snd_pcm_route_t *route = pcm->private;
|
|
||||||
snd_pcm_t *slave = route->plug.slave;
|
|
||||||
int err;
|
int err;
|
||||||
unsigned int cmask, lcmask;
|
|
||||||
snd_pcm_hw_params_t sparams;
|
|
||||||
unsigned int links = (SND_PCM_HW_PARBIT_RATE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIODS |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_TICK_TIME);
|
|
||||||
mask_t *access_mask = alloca(mask_sizeof());
|
mask_t *access_mask = alloca(mask_sizeof());
|
||||||
mask_t *format_mask = alloca(mask_sizeof());
|
mask_t *format_mask = alloca(mask_sizeof());
|
||||||
mask_t *saccess_mask = alloca(mask_sizeof());
|
|
||||||
mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN);
|
mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN);
|
||||||
mask_load(format_mask, SND_PCM_FMTBIT_LINEAR);
|
mask_load(format_mask, SND_PCM_FMTBIT_LINEAR);
|
||||||
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
|
||||||
cmask = params->cmask;
|
|
||||||
params->cmask = 0;
|
|
||||||
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS,
|
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS,
|
||||||
access_mask);
|
access_mask);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT,
|
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT,
|
||||||
format_mask);
|
format_mask);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_SUBFORMAT,
|
||||||
|
SND_PCM_SUBFORMAT_STD, 0);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
err = _snd_pcm_hw_param_min(params, SND_PCM_HW_PARAM_CHANNELS, 1, 0);
|
err = _snd_pcm_hw_param_min(params, SND_PCM_HW_PARAM_CHANNELS, 1, 0);
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
lcmask = params->cmask;
|
|
||||||
params->cmask |= cmask;
|
|
||||||
|
|
||||||
_snd_pcm_hw_params_any(&sparams);
|
|
||||||
_snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS,
|
|
||||||
saccess_mask);
|
|
||||||
if (route->sformat >= 0) {
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_FORMAT,
|
|
||||||
route->sformat, 0);
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_SUBFORMAT,
|
|
||||||
SND_PCM_SUBFORMAT_STD, 0);
|
|
||||||
} else
|
|
||||||
links |= (SND_PCM_HW_PARBIT_FORMAT |
|
|
||||||
SND_PCM_HW_PARBIT_SUBFORMAT |
|
|
||||||
SND_PCM_HW_PARBIT_SAMPLE_BITS);
|
|
||||||
if (route->schannels >= 0) {
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_CHANNELS,
|
|
||||||
route->schannels, 0);
|
|
||||||
} else {
|
|
||||||
links |= SND_PCM_HW_PARBIT_CHANNELS;
|
|
||||||
if (route->sformat < 0)
|
|
||||||
links |= (SND_PCM_HW_PARBIT_FRAME_BITS |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_BYTES |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_BYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
err = snd_pcm_hw_refine2(params, &sparams,
|
|
||||||
snd_pcm_generic_hw_link, slave, links);
|
|
||||||
params->cmask |= lcmask;
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
|
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_route_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
|
static int snd_pcm_route_hw_refine_sprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
snd_pcm_route_t *route = pcm->private;
|
||||||
|
mask_t *saccess_mask = alloca(mask_sizeof());
|
||||||
|
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
||||||
|
_snd_pcm_hw_params_any(sparams);
|
||||||
|
_snd_pcm_hw_param_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
|
||||||
|
saccess_mask);
|
||||||
|
if (route->sformat >= 0) {
|
||||||
|
_snd_pcm_hw_param_set(sparams, SND_PCM_HW_PARAM_FORMAT,
|
||||||
|
route->sformat, 0);
|
||||||
|
_snd_pcm_hw_param_set(sparams, SND_PCM_HW_PARAM_SUBFORMAT,
|
||||||
|
SND_PCM_SUBFORMAT_STD, 0);
|
||||||
|
}
|
||||||
|
if (route->schannels >= 0) {
|
||||||
|
_snd_pcm_hw_param_set(sparams, SND_PCM_HW_PARAM_CHANNELS,
|
||||||
|
route->schannels, 0);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_route_hw_refine_schange(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams)
|
||||||
{
|
{
|
||||||
snd_pcm_route_t *route = pcm->private;
|
snd_pcm_route_t *route = pcm->private;
|
||||||
snd_pcm_t *slave = route->plug.slave;
|
|
||||||
int err;
|
int err;
|
||||||
snd_pcm_hw_params_t sparams;
|
|
||||||
unsigned int links = (SND_PCM_HW_PARBIT_RATE |
|
unsigned int links = (SND_PCM_HW_PARBIT_RATE |
|
||||||
SND_PCM_HW_PARBIT_PERIODS |
|
SND_PCM_HW_PARBIT_PERIODS |
|
||||||
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
||||||
|
|
@ -506,42 +484,65 @@ static int snd_pcm_route_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
|
||||||
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
||||||
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
||||||
SND_PCM_HW_PARBIT_TICK_TIME);
|
SND_PCM_HW_PARBIT_TICK_TIME);
|
||||||
unsigned int src_format, dst_format;
|
if (route->sformat < 0)
|
||||||
mask_t *saccess_mask = alloca(mask_sizeof());
|
|
||||||
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
|
||||||
|
|
||||||
_snd_pcm_hw_params_any(&sparams);
|
|
||||||
_snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS,
|
|
||||||
saccess_mask);
|
|
||||||
if (route->sformat >= 0) {
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_FORMAT,
|
|
||||||
route->sformat, 0);
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_SUBFORMAT,
|
|
||||||
SND_PCM_SUBFORMAT_STD, 0);
|
|
||||||
} else
|
|
||||||
links |= (SND_PCM_HW_PARBIT_FORMAT |
|
links |= (SND_PCM_HW_PARBIT_FORMAT |
|
||||||
SND_PCM_HW_PARBIT_SUBFORMAT |
|
SND_PCM_HW_PARBIT_SUBFORMAT |
|
||||||
SND_PCM_HW_PARBIT_SAMPLE_BITS);
|
SND_PCM_HW_PARBIT_SAMPLE_BITS);
|
||||||
if (route->schannels >= 0) {
|
if (route->schannels < 0)
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_CHANNELS,
|
|
||||||
route->schannels, 0);
|
|
||||||
} else {
|
|
||||||
links |= SND_PCM_HW_PARBIT_CHANNELS;
|
links |= SND_PCM_HW_PARBIT_CHANNELS;
|
||||||
if (route->sformat < 0)
|
err = _snd_pcm_hw_params_refine(sparams, links, params);
|
||||||
links |= (SND_PCM_HW_PARBIT_FRAME_BITS |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_BYTES |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_BYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
err = snd_pcm_hw_params_refine(&sparams, links, params);
|
|
||||||
assert(err >= 0);
|
|
||||||
err = snd_pcm_hw_params(slave, &sparams);
|
|
||||||
params->cmask = 0;
|
|
||||||
sparams.cmask = ~0U;
|
|
||||||
snd_pcm_hw_params_refine(params, links, &sparams);
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_route_hw_refine_cchange(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
snd_pcm_route_t *route = pcm->private;
|
||||||
|
int err;
|
||||||
|
unsigned int links = (SND_PCM_HW_PARBIT_RATE |
|
||||||
|
SND_PCM_HW_PARBIT_PERIODS |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
||||||
|
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_TICK_TIME);
|
||||||
|
if (route->sformat < 0)
|
||||||
|
links |= (SND_PCM_HW_PARBIT_FORMAT |
|
||||||
|
SND_PCM_HW_PARBIT_SUBFORMAT |
|
||||||
|
SND_PCM_HW_PARBIT_SAMPLE_BITS);
|
||||||
|
if (route->schannels < 0)
|
||||||
|
links |= SND_PCM_HW_PARBIT_CHANNELS;
|
||||||
|
err = _snd_pcm_hw_params_refine(params, links, sparams);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_route_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
|
{
|
||||||
|
return snd_pcm_hw_refine_slave(pcm, params,
|
||||||
|
snd_pcm_route_hw_refine_cprepare,
|
||||||
|
snd_pcm_route_hw_refine_cchange,
|
||||||
|
snd_pcm_route_hw_refine_sprepare,
|
||||||
|
snd_pcm_route_hw_refine_schange,
|
||||||
|
snd_pcm_plugin_hw_refine_slave);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_route_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
|
||||||
|
{
|
||||||
|
snd_pcm_route_t *route = pcm->private;
|
||||||
|
snd_pcm_t *slave = route->plug.slave;
|
||||||
|
unsigned int src_format, dst_format;
|
||||||
|
int err = snd_pcm_hw_params_slave(pcm, params,
|
||||||
|
snd_pcm_route_hw_refine_cchange,
|
||||||
|
snd_pcm_route_hw_refine_sprepare,
|
||||||
|
snd_pcm_route_hw_refine_schange,
|
||||||
|
snd_pcm_plugin_hw_params_slave);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
|
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
|
||||||
src_format = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT, 0);
|
src_format = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT, 0);
|
||||||
dst_format = slave->format;
|
dst_format = slave->format;
|
||||||
|
|
|
||||||
|
|
@ -427,7 +427,8 @@ static void _snd_pcm_share_update(snd_pcm_t *pcm)
|
||||||
|
|
||||||
static int snd_pcm_share_card(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
|
static int snd_pcm_share_card(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
return -ENOENT; /* not available */
|
snd_pcm_share_t *share = pcm->private;
|
||||||
|
return snd_pcm_card(share->slave->pcm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_share_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED)
|
static int snd_pcm_share_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED)
|
||||||
|
|
@ -455,25 +456,22 @@ static int snd_pcm_share_info(snd_pcm_t *pcm, snd_pcm_info_t *info)
|
||||||
return snd_pcm_info(share->slave->pcm, info);
|
return snd_pcm_info(share->slave->pcm, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_share_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
static int snd_pcm_share_hw_refine_cprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
{
|
{
|
||||||
snd_pcm_share_t *share = pcm->private;
|
snd_pcm_share_t *share = pcm->private;
|
||||||
snd_pcm_share_slave_t *slave = share->slave;
|
snd_pcm_share_slave_t *slave = share->slave;
|
||||||
snd_pcm_hw_params_t sparams;
|
|
||||||
int err;
|
|
||||||
unsigned int cmask, lcmask;
|
|
||||||
mask_t *access_mask = alloca(mask_sizeof());
|
mask_t *access_mask = alloca(mask_sizeof());
|
||||||
const mask_t *mmap_mask;
|
int err;
|
||||||
mask_t *saccess_mask = alloca(mask_sizeof());
|
mask_any(access_mask);
|
||||||
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
mask_reset(access_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
|
||||||
|
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS,
|
||||||
cmask = params->cmask;
|
access_mask);
|
||||||
params->cmask = 0;
|
if (err < 0)
|
||||||
|
return err;
|
||||||
err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_CHANNELS,
|
err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_CHANNELS,
|
||||||
share->channels_count, 0);
|
share->channels_count, 0);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
if (slave->format >= 0) {
|
if (slave->format >= 0) {
|
||||||
err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_FORMAT,
|
err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_FORMAT,
|
||||||
slave->format, 0);
|
slave->format, 0);
|
||||||
|
|
@ -487,44 +485,109 @@ static int snd_pcm_share_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
lcmask = params->cmask;
|
|
||||||
params->cmask |= cmask;
|
|
||||||
|
|
||||||
_snd_pcm_hw_params_any(&sparams);
|
|
||||||
_snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS,
|
|
||||||
saccess_mask);
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_CHANNELS,
|
|
||||||
slave->channels_count, 0);
|
|
||||||
err = snd_pcm_hw_refine2(params, &sparams,
|
|
||||||
snd_pcm_generic_hw_link, slave->pcm,
|
|
||||||
SND_PCM_HW_PARBIT_FORMAT |
|
|
||||||
SND_PCM_HW_PARBIT_SUBFORMAT |
|
|
||||||
SND_PCM_HW_PARBIT_RATE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_PERIODS |
|
|
||||||
SND_PCM_HW_PARBIT_TICK_TIME);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
mmap_mask = snd_pcm_hw_param_value_mask(&sparams, SND_PCM_HW_PARAM_ACCESS);
|
|
||||||
mask_any(access_mask);
|
|
||||||
mask_reset(access_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
|
|
||||||
if (!mask_test(mmap_mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED))
|
|
||||||
mask_reset(access_mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
|
|
||||||
if (!mask_test(mmap_mask, SND_PCM_ACCESS_MMAP_COMPLEX) &&
|
|
||||||
!mask_test(mmap_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED))
|
|
||||||
mask_reset(access_mask, SND_PCM_ACCESS_MMAP_COMPLEX);
|
|
||||||
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS,
|
|
||||||
access_mask);
|
|
||||||
params->cmask |= lcmask;
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
params->info |= SND_PCM_INFO_DOUBLE;
|
params->info |= SND_PCM_INFO_DOUBLE;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_share_hw_refine_sprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
snd_pcm_share_t *share = pcm->private;
|
||||||
|
snd_pcm_share_slave_t *slave = share->slave;
|
||||||
|
mask_t *saccess_mask = alloca(mask_sizeof());
|
||||||
|
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
||||||
|
_snd_pcm_hw_params_any(sparams);
|
||||||
|
_snd_pcm_hw_param_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
|
||||||
|
saccess_mask);
|
||||||
|
_snd_pcm_hw_param_set(sparams, SND_PCM_HW_PARAM_CHANNELS,
|
||||||
|
slave->channels_count, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_share_hw_refine_schange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
unsigned int links = (SND_PCM_HW_PARBIT_FORMAT |
|
||||||
|
SND_PCM_HW_PARBIT_SUBFORMAT |
|
||||||
|
SND_PCM_HW_PARBIT_RATE |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
||||||
|
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_PERIODS |
|
||||||
|
SND_PCM_HW_PARBIT_TICK_TIME);
|
||||||
|
const mask_t *access_mask = snd_pcm_hw_param_value_mask(params, SND_PCM_HW_PARAM_ACCESS);
|
||||||
|
if (!mask_test(access_mask, SND_PCM_ACCESS_RW_INTERLEAVED) &&
|
||||||
|
!mask_test(access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED) &&
|
||||||
|
!mask_test(access_mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED)) {
|
||||||
|
mask_t *saccess_mask = alloca(mask_sizeof());
|
||||||
|
mask_any(saccess_mask);
|
||||||
|
mask_reset(saccess_mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
|
||||||
|
err = _snd_pcm_hw_param_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
|
||||||
|
saccess_mask);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
err = _snd_pcm_hw_params_refine(sparams, links, params);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_share_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
unsigned int links = (SND_PCM_HW_PARBIT_FORMAT |
|
||||||
|
SND_PCM_HW_PARBIT_SUBFORMAT |
|
||||||
|
SND_PCM_HW_PARBIT_RATE |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
||||||
|
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
||||||
|
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
||||||
|
SND_PCM_HW_PARBIT_PERIODS |
|
||||||
|
SND_PCM_HW_PARBIT_TICK_TIME);
|
||||||
|
mask_t *access_mask = alloca(mask_sizeof());
|
||||||
|
const mask_t *saccess_mask = snd_pcm_hw_param_value_mask(sparams, SND_PCM_HW_PARAM_ACCESS);
|
||||||
|
mask_any(access_mask);
|
||||||
|
mask_reset(access_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
|
||||||
|
if (!mask_test(saccess_mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED))
|
||||||
|
mask_reset(access_mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
|
||||||
|
if (!mask_test(saccess_mask, SND_PCM_ACCESS_MMAP_COMPLEX) &&
|
||||||
|
!mask_test(saccess_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED))
|
||||||
|
mask_reset(access_mask, SND_PCM_ACCESS_MMAP_COMPLEX);
|
||||||
|
err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS,
|
||||||
|
access_mask);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
err = _snd_pcm_hw_params_refine(params, links, sparams);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_share_hw_refine_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
|
{
|
||||||
|
snd_pcm_share_t *share = pcm->private;
|
||||||
|
return snd_pcm_hw_refine(share->slave->pcm, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_share_hw_params_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
|
{
|
||||||
|
snd_pcm_share_t *share = pcm->private;
|
||||||
|
return snd_pcm_hw_params(share->slave->pcm, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_share_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
|
{
|
||||||
|
return snd_pcm_hw_refine_slave(pcm, params,
|
||||||
|
snd_pcm_share_hw_refine_cprepare,
|
||||||
|
snd_pcm_share_hw_refine_cchange,
|
||||||
|
snd_pcm_share_hw_refine_sprepare,
|
||||||
|
snd_pcm_share_hw_refine_schange,
|
||||||
|
snd_pcm_share_hw_refine_slave);
|
||||||
|
}
|
||||||
|
|
||||||
static int snd_pcm_share_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
static int snd_pcm_share_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
{
|
{
|
||||||
snd_pcm_share_t *share = pcm->private;
|
snd_pcm_share_t *share = pcm->private;
|
||||||
|
|
@ -534,7 +597,6 @@ static int snd_pcm_share_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
Pthread_mutex_lock(&slave->mutex);
|
Pthread_mutex_lock(&slave->mutex);
|
||||||
if (slave->setup_count > 1 ||
|
if (slave->setup_count > 1 ||
|
||||||
(slave->setup_count == 1 && !pcm->setup)) {
|
(slave->setup_count == 1 && !pcm->setup)) {
|
||||||
params->cmask = 0;
|
|
||||||
err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_FORMAT,
|
err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_FORMAT,
|
||||||
spcm->format, 0);
|
spcm->format, 0);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
|
|
@ -564,30 +626,11 @@ static int snd_pcm_share_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
goto _end;
|
goto _end;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
snd_pcm_hw_params_t sparams;
|
err = snd_pcm_hw_params_slave(pcm, params,
|
||||||
unsigned int links;
|
snd_pcm_share_hw_refine_cchange,
|
||||||
mask_t *saccess_mask = alloca(mask_sizeof());
|
snd_pcm_share_hw_refine_sprepare,
|
||||||
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
snd_pcm_share_hw_refine_schange,
|
||||||
links = SND_PCM_HW_PARBIT_FORMAT |
|
snd_pcm_share_hw_params_slave);
|
||||||
SND_PCM_HW_PARBIT_SUBFORMAT |
|
|
||||||
SND_PCM_HW_PARBIT_RATE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_PERIOD_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_SIZE |
|
|
||||||
SND_PCM_HW_PARBIT_BUFFER_TIME |
|
|
||||||
SND_PCM_HW_PARBIT_PERIODS |
|
|
||||||
SND_PCM_HW_PARBIT_TICK_TIME;
|
|
||||||
_snd_pcm_hw_params_any(&sparams);
|
|
||||||
_snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS,
|
|
||||||
saccess_mask);
|
|
||||||
_snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_CHANNELS,
|
|
||||||
share->channels_count, 0);
|
|
||||||
err = snd_pcm_hw_params_refine(&sparams, links, params);
|
|
||||||
assert(err >= 0);
|
|
||||||
err = snd_pcm_hw_params(slave->pcm, &sparams);
|
|
||||||
params->cmask = 0;
|
|
||||||
sparams.cmask = ~0U;
|
|
||||||
snd_pcm_hw_params_refine(params, links, &sparams);
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto _end;
|
goto _end;
|
||||||
snd_pcm_sw_params_current(slave->pcm, &slave->sw_params);
|
snd_pcm_sw_params_current(slave->pcm, &slave->sw_params);
|
||||||
|
|
|
||||||
|
|
@ -155,8 +155,61 @@ static int snd_pcm_shm_info(snd_pcm_t *pcm, snd_pcm_info_t * info)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _snd_pcm_shm_hw_refine(snd_pcm_t *pcm,
|
static int snd_pcm_shm_hw_refine_cprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params ATTRIBUTE_UNUSED)
|
||||||
snd_pcm_hw_params_t *params)
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_shm_hw_refine_sprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
mask_t *saccess_mask = alloca(mask_sizeof());
|
||||||
|
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
||||||
|
_snd_pcm_hw_params_any(sparams);
|
||||||
|
_snd_pcm_hw_param_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
|
||||||
|
saccess_mask);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_shm_hw_refine_schange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
unsigned int links = ~SND_PCM_HW_PARBIT_ACCESS;
|
||||||
|
const mask_t *access_mask = snd_pcm_hw_param_value_mask(params, SND_PCM_HW_PARAM_ACCESS);
|
||||||
|
if (!mask_test(access_mask, SND_PCM_ACCESS_RW_INTERLEAVED) &&
|
||||||
|
!mask_test(access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED)) {
|
||||||
|
err = _snd_pcm_hw_param_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
|
||||||
|
access_mask);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
err = _snd_pcm_hw_params_refine(sparams, links, params);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_shm_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
|
||||||
|
snd_pcm_hw_params_t *sparams)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
unsigned int links = ~SND_PCM_HW_PARBIT_ACCESS;
|
||||||
|
mask_t *access_mask = alloca(mask_sizeof());
|
||||||
|
mask_copy(access_mask, snd_pcm_hw_param_value_mask(sparams, SND_PCM_HW_PARAM_ACCESS));
|
||||||
|
mask_set(access_mask, SND_PCM_ACCESS_RW_INTERLEAVED);
|
||||||
|
mask_set(access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED);
|
||||||
|
err = _snd_pcm_hw_param_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
|
||||||
|
access_mask);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
err = _snd_pcm_hw_params_refine(params, links, sparams);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int snd_pcm_shm_hw_refine_slave(snd_pcm_t *pcm,
|
||||||
|
snd_pcm_hw_params_t *params)
|
||||||
{
|
{
|
||||||
snd_pcm_shm_t *shm = pcm->private;
|
snd_pcm_shm_t *shm = pcm->private;
|
||||||
volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
|
volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
|
||||||
|
|
@ -168,46 +221,18 @@ static int _snd_pcm_shm_hw_refine(snd_pcm_t *pcm,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Accumulate to params->cmask */
|
|
||||||
/* Reset sparams->cmask */
|
|
||||||
int snd_pcm_shm_hw_link(snd_pcm_hw_params_t *params,
|
|
||||||
snd_pcm_hw_params_t *sparams,
|
|
||||||
snd_pcm_t *slave,
|
|
||||||
unsigned long links)
|
|
||||||
{
|
|
||||||
int err1, err = 0;
|
|
||||||
err = snd_pcm_hw_params_refine(sparams, links, params);
|
|
||||||
if (err >= 0) {
|
|
||||||
unsigned int cmask = sparams->cmask;
|
|
||||||
err = _snd_pcm_shm_hw_refine(slave, sparams);
|
|
||||||
sparams->cmask |= cmask;
|
|
||||||
}
|
|
||||||
err1 = snd_pcm_hw_params_refine(params, links, sparams);
|
|
||||||
if (err1 < 0)
|
|
||||||
err = err1;
|
|
||||||
sparams->cmask = 0;
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int snd_pcm_shm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
static int snd_pcm_shm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
|
||||||
{
|
{
|
||||||
snd_pcm_hw_params_t sparams;
|
return snd_pcm_hw_refine_slave(pcm, params,
|
||||||
const mask_t *access_mask = snd_pcm_hw_param_value_mask(params, SND_PCM_HW_PARAM_ACCESS);
|
snd_pcm_shm_hw_refine_cprepare,
|
||||||
mask_t *saccess_mask = alloca(mask_sizeof());
|
snd_pcm_shm_hw_refine_cchange,
|
||||||
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
snd_pcm_shm_hw_refine_sprepare,
|
||||||
if (!mask_test(access_mask, SND_PCM_ACCESS_RW_INTERLEAVED) &&
|
snd_pcm_shm_hw_refine_schange,
|
||||||
!mask_test(access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED))
|
snd_pcm_shm_hw_refine_slave);
|
||||||
mask_intersect(saccess_mask, access_mask);
|
|
||||||
_snd_pcm_hw_params_any(&sparams);
|
|
||||||
_snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS,
|
|
||||||
saccess_mask);
|
|
||||||
return snd_pcm_hw_refine2(params, &sparams,
|
|
||||||
snd_pcm_shm_hw_link, pcm,
|
|
||||||
~SND_PCM_HW_PARBIT_ACCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _snd_pcm_shm_hw_params(snd_pcm_t *pcm,
|
static int snd_pcm_shm_hw_params_slave(snd_pcm_t *pcm,
|
||||||
snd_pcm_hw_params_t *params)
|
snd_pcm_hw_params_t *params)
|
||||||
{
|
{
|
||||||
snd_pcm_shm_t *shm = pcm->private;
|
snd_pcm_shm_t *shm = pcm->private;
|
||||||
volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
|
volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
|
||||||
|
|
@ -221,27 +246,11 @@ static int _snd_pcm_shm_hw_params(snd_pcm_t *pcm,
|
||||||
|
|
||||||
static int snd_pcm_shm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
|
static int snd_pcm_shm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
|
||||||
{
|
{
|
||||||
snd_pcm_hw_params_t sparams;
|
return snd_pcm_hw_params_slave(pcm, params,
|
||||||
unsigned int links = ~SND_PCM_HW_PARBIT_ACCESS;
|
snd_pcm_shm_hw_refine_cchange,
|
||||||
const mask_t *access_mask = snd_pcm_hw_param_value_mask(params, SND_PCM_HW_PARAM_ACCESS);
|
snd_pcm_shm_hw_refine_sprepare,
|
||||||
mask_t *saccess_mask = alloca(mask_sizeof());
|
snd_pcm_shm_hw_refine_schange,
|
||||||
int err;
|
snd_pcm_shm_hw_params_slave);
|
||||||
mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
|
|
||||||
if (!mask_test(access_mask, SND_PCM_ACCESS_RW_INTERLEAVED) &&
|
|
||||||
!mask_test(access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED))
|
|
||||||
mask_intersect(saccess_mask, access_mask);
|
|
||||||
_snd_pcm_hw_params_any(&sparams);
|
|
||||||
_snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS,
|
|
||||||
saccess_mask);
|
|
||||||
err = snd_pcm_hw_params_refine(&sparams, links, params);
|
|
||||||
assert(err >= 0);
|
|
||||||
err = _snd_pcm_shm_hw_params(pcm, &sparams);
|
|
||||||
params->cmask = 0;
|
|
||||||
sparams.cmask = ~0U;
|
|
||||||
snd_pcm_hw_params_refine(params, links, &sparams);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snd_pcm_shm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
|
static int snd_pcm_shm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue