static inline unsigned int div32(unsigned int a, unsigned int b,
unsigned int *r)
{
+ if (b == 0) {
+ *r = 0;
+ return UINT_MAX;
+ }
*r = a % b;
return a / b;
}
static inline unsigned int div_down(unsigned int a, unsigned int b)
{
+ if (b == 0)
+ return UINT_MAX;
return a / b;
}
static inline unsigned int div_up(unsigned int a, unsigned int b)
{
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)
++q;
return q;
unsigned int c, unsigned int *r)
{
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);
if (n >= UINT_MAX) {
*r = 0;
else if (i->min == 0 && i->openmin == 0 &&
i->max == UINT_MAX && i->openmax == 0)
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));
else
snd_output_printf(out, "%c%u %u%c",
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_t *slave = adpcm->plug.slave;
int err;
- unsigned int cmask, lcmask;
- snd_pcm_hw_params_t sparams;
mask_t *access_mask = alloca(mask_sizeof());
- mask_t *saccess_mask = alloca(mask_sizeof());
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,
- access_mask);
+ access_mask);
if (err < 0)
return err;
if (adpcm->sformat == SND_PCM_FORMAT_IMA_ADPCM) {
mask_t *format_mask = alloca(mask_sizeof());
mask_load(format_mask, SND_PCM_FMTBIT_LINEAR);
- err = _snd_pcm_hw_param_mask(params,
- SND_PCM_HW_PARAM_FORMAT,
- format_mask);
- if (err < 0)
- return err;
+ err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT,
+ format_mask);
} else {
err = _snd_pcm_hw_param_set(params,
SND_PCM_HW_PARAM_FORMAT,
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)
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,
- 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;
+ err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_SUBFORMAT,
+ SND_PCM_SUBFORMAT_STD, 0);
if (err < 0)
return err;
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
return 0;
}
-static int snd_pcm_adpcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
+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;
- snd_pcm_t *slave = adpcm->plug.slave;
- int err;
- snd_pcm_hw_params_t sparams;
- unsigned int links;
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,
+ _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,
+ _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_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);
+ 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;
- params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
+ 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)
+{
+ snd_pcm_adpcm_t *adpcm = pcm->private;
+ int err = snd_pcm_hw_params_slave(pcm, params,
+ snd_pcm_adpcm_hw_refine_cchange,
+ snd_pcm_adpcm_hw_refine_sprepare,
+ snd_pcm_adpcm_hw_refine_schange,
+ snd_pcm_plugin_hw_params_slave);
+ if (err < 0)
+ return err;
+
+
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
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);
}
}
-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_t *slave = alaw->plug.slave;
int err;
- unsigned int cmask, lcmask;
- snd_pcm_hw_params_t sparams;
mask_t *access_mask = alloca(mask_sizeof());
- mask_t *saccess_mask = alloca(mask_sizeof());
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,
- access_mask);
+ access_mask);
if (err < 0)
return err;
if (alaw->sformat == SND_PCM_FORMAT_A_LAW) {
mask_t *format_mask = alloca(mask_sizeof());
mask_load(format_mask, SND_PCM_FMTBIT_LINEAR);
- err = _snd_pcm_hw_param_mask(params,
- SND_PCM_HW_PARAM_FORMAT,
- format_mask);
- if (err < 0)
- return err;
+ err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_FORMAT,
+ format_mask);
} else {
err = _snd_pcm_hw_param_set(params,
- SND_PCM_HW_PARAM_FORMAT,
- SND_PCM_FORMAT_A_LAW, 0);
- if (err < 0)
- return err;
+ SND_PCM_HW_PARAM_FORMAT,
+ 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)
return err;
- lcmask = params->cmask;
- params->cmask |= cmask;
+ params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
+ return 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,
+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_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;
+ 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;
- params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
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)
{
snd_pcm_alaw_t *alaw = pcm->private;
- snd_pcm_t *slave = alaw->plug.slave;
- int err;
- snd_pcm_hw_params_t sparams;
- unsigned int links;
- 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);
- 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);
+ int err = snd_pcm_hw_params_slave(pcm, params,
+ snd_pcm_alaw_hw_refine_cchange,
+ snd_pcm_alaw_hw_refine_sprepare,
+ snd_pcm_alaw_hw_refine_schange,
+ snd_pcm_plugin_hw_params_slave);
if (err < 0)
return err;
- params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
+
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
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);
snd_pcm_plugin_t plug;
} 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;
- unsigned int cmask, lcmask;
- snd_pcm_hw_params_t sparams;
mask_t *access_mask = alloca(mask_sizeof());
- mask_t *saccess_mask = alloca(mask_sizeof());
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,
access_mask);
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);
- err = snd_pcm_hw_refine2(params, &sparams,
- snd_pcm_generic_hw_link, slave,
- ~SND_PCM_HW_PARBIT_ACCESS);
- params->cmask |= lcmask;
- if (err < 0)
- return err;
params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
- return err;
+ return 0;
}
-static int snd_pcm_copy_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
+static int snd_pcm_copy_hw_refine_sprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *sparams)
{
- snd_pcm_copy_t *copy = pcm->private;
- snd_pcm_t *slave = copy->plug.slave;
- int err;
- unsigned int links;
- 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;
+}
- _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);
+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)
return err;
- params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
- return err;
+ return 0;
+}
+
+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)
+{
+ return snd_pcm_hw_params_slave(pcm, params,
+ snd_pcm_copy_hw_refine_cchange,
+ snd_pcm_copy_hw_refine_sprepare,
+ snd_pcm_copy_hw_refine_schange,
+ snd_pcm_plugin_hw_params_slave);
}
static snd_pcm_sframes_t snd_pcm_copy_write_areas(snd_pcm_t *pcm,
}
}
-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;
- unsigned int cmask, lcmask;
- snd_pcm_hw_params_t sparams;
mask_t *access_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(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,
- access_mask);
+ access_mask);
if (err < 0)
return err;
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);
+ SND_PCM_SUBFORMAT_STD, 0);
if (err < 0)
return err;
- lcmask = params->cmask;
- params->cmask |= cmask;
+ params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
+ return 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,
+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_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;
+ 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;
- params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
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)
{
snd_pcm_linear_t *linear = pcm->private;
- snd_pcm_t *slave = linear->plug.slave;
- int err;
- unsigned int links;
- 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);
- _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);
+ int err = snd_pcm_hw_params_slave(pcm, params,
+ snd_pcm_linear_hw_refine_cchange,
+ snd_pcm_linear_hw_refine_sprepare,
+ snd_pcm_linear_hw_refine_schange,
+ snd_pcm_plugin_hw_params_slave);
if (err < 0)
return err;
- params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
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->sformat);
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);
int _snd_pcm_hw_param_refine_interval(snd_pcm_hw_params_t *params,
snd_pcm_hw_param_t var,
unsigned int var, unsigned int val, int dir);
int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params,
unsigned int var, unsigned int val, int dir);
-int snd_pcm_hw_param_refine(snd_pcm_hw_params_t *params,
- 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,
+int _snd_pcm_hw_param_refine(snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var,
const snd_pcm_hw_params_t *src);
-int snd_pcm_generic_hw_link(snd_pcm_hw_params_t *params,
- snd_pcm_hw_params_t *sparams,
- snd_pcm_t *slave,
- unsigned long links);
-int snd_pcm_hw_refine2(snd_pcm_hw_params_t *params,
- snd_pcm_hw_params_t *sparams,
- int (*func)(snd_pcm_hw_params_t *params,
- 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_params_refine(snd_pcm_hw_params_t *params,
+ unsigned int vars,
+ const snd_pcm_hw_params_t *src);
+void snd_pcm_hw_param_refine_near(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,
snd_pcm_hw_param_t var,
const snd_pcm_hw_params_t *params1);
}
}
-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_t *slave = mulaw->plug.slave;
int err;
- unsigned int cmask, lcmask;
- snd_pcm_hw_params_t sparams;
mask_t *access_mask = alloca(mask_sizeof());
- mask_t *saccess_mask = alloca(mask_sizeof());
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,
access_mask);
if (err < 0)
if (mulaw->sformat == SND_PCM_FORMAT_MU_LAW) {
mask_t *format_mask = alloca(mask_sizeof());
mask_load(format_mask, SND_PCM_FMTBIT_LINEAR);
- 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);
- if (err < 0)
- return err;
} else {
err = _snd_pcm_hw_param_set(params,
SND_PCM_HW_PARAM_FORMAT,
SND_PCM_FORMAT_MU_LAW, 0);
- if (err < 0)
- return err;
}
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;
+ params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
+ return 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,
+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_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;
+ 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;
- params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
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)
{
snd_pcm_mulaw_t *mulaw = pcm->private;
- snd_pcm_t *slave = mulaw->plug.slave;
- int err;
- unsigned int links;
- 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);
- _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);
+ int err = snd_pcm_hw_params_slave(pcm, params,
+ snd_pcm_mulaw_hw_refine_cchange,
+ snd_pcm_mulaw_hw_refine_sprepare,
+ snd_pcm_mulaw_hw_refine_schange,
+ snd_pcm_plugin_hw_params_slave);
if (err < 0)
return err;
- params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
+
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
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);
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)
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;
- unsigned int k;
- snd_pcm_hw_params_t sparams;
- int changed = 0;
- int err = 0;
- unsigned int cmask, lcmask;
- const mask_t *access_mask = snd_pcm_hw_param_value_mask(params, SND_PCM_HW_PARAM_ACCESS);
- mask_t *saccess_mask = alloca(mask_sizeof());
- 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);
- }
- }
-
- cmask = params->cmask;
- params->cmask = 0;
+ mask_t *access_mask = alloca(mask_sizeof());
+ int err;
+ mask_any(access_mask);
+ mask_reset(access_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
+ err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS,
+ access_mask);
+ if (err < 0)
+ return err;
err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_CHANNELS,
multi->channels_count, 0);
if (err < 0)
return err;
- lcmask = params->cmask;
- cmask |= params->cmask;
+ params->info = ~0;
+ 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;
- do {
- for (k = 0; k < multi->slaves_count; ++k) {
- snd_pcm_t *slave = multi->slaves[k].pcm;
- 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,
- multi->slaves[k].channels_count, 0);
- err = snd_pcm_hw_refine2(params, &sparams,
- snd_pcm_generic_hw_link, slave,
- 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 (params->cmask) {
- changed++;
- lcmask |= params->cmask;
- cmask |= params->cmask;
- }
- if (err < 0)
- goto _end;
- }
- } while (changed && multi->slaves_count > 1);
- _end:
- params->cmask = lcmask;
- return err;
+static int snd_pcm_multi_hw_refine_cchange(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);
+ 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;
+ params->info &= sparams->info;
+ 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_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;
- 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);
+ 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;
}
}
+ /* FIXME: loop begin? */
for (k = 0; k < multi->slaves_count; ++k) {
- snd_pcm_t *slave = multi->slaves[k].pcm;
- 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);
- err = snd_pcm_hw_params(slave, &sparams);
- params->cmask = 0;
- sparams.cmask = ~0U;
- snd_pcm_hw_params_refine(params, links, &sparams);
+ 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_areas_silence(slave->running_areas, 0, slave->channels, slave->buffer_size, slave->format);
+ }
+ 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;
- 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)
+{
+ snd_pcm_multi_t *multi = pcm->private;
+ unsigned int k;
+ snd_pcm_hw_params_t sparams[multi->slaves_count];
+ int err;
+ for (k = 0; k < multi->slaves_count; ++k) {
+ err = snd_pcm_multi_hw_refine_sprepare(pcm, k, &sparams[k]);
+ assert(err >= 0);
+ err = snd_pcm_multi_hw_refine_schange(pcm, k, params, &sparams[k]);
+ assert(err >= 0);
+ err = snd_pcm_multi_hw_params_slave(pcm, k, &sparams[k]);
+ if (err < 0) {
+ snd_pcm_multi_hw_refine_cchange(pcm, k, params, &sparams[k]);
+ return err;
}
}
return 0;
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;
return err;
}
if (hw_is_mask(var)) {
mask_any(hw_param_mask(params, var));
params->cmask |= 1 << var;
+ params->rmask |= 1 << var;
return;
}
if (hw_is_interval(var)) {
interval_any(hw_param_interval(params, var));
params->cmask |= 1 << var;
+ params->rmask |= 1 << var;
return;
}
assert(0);
int changed;
assert(hw_is_interval(var));
changed = interval_refine(hw_param_interval(params, var), val);
- if (changed)
+ if (changed) {
params->cmask |= 1 << var;
+ params->rmask |= 1 << var;
+ }
return changed;
}
int changed;
assert(hw_is_interval(var));
changed = interval_setinteger(hw_param_interval(params, var));
- if (changed)
+ if (changed) {
params->cmask |= 1 << var;
+ params->rmask |= 1 << var;
+ }
return changed;
}
int changed = _snd_pcm_hw_param_setinteger(params, var);
if (changed < 0)
return changed;
- if (changed) {
+ if (params->rmask) {
int err = snd_pcm_hw_refine(pcm, params);
if (err < 0)
return err;
assert(0);
return -EINVAL;
}
- if (changed)
+ if (changed) {
params->cmask |= 1 << var;
+ params->rmask |= 1 << var;
+ }
return changed;
}
int changed = _snd_pcm_hw_param_first(params, var);
if (changed < 0)
return changed;
- if (changed) {
+ if (params->rmask) {
int err = snd_pcm_hw_refine(pcm, params);
assert(err >= 0);
}
assert(0);
return -EINVAL;
}
- if (changed)
+ if (changed) {
params->cmask |= 1 << var;
+ params->rmask |= 1 << var;
+ }
return changed;
}
int changed = _snd_pcm_hw_param_last(params, var);
if (changed < 0)
return changed;
- if (changed) {
+ if (params->rmask) {
int err = snd_pcm_hw_refine(pcm, params);
assert(err >= 0);
}
assert(0);
return -EINVAL;
}
- if (changed)
+ if (changed) {
params->cmask |= 1 << var;
+ params->rmask |= 1 << var;
+ }
return changed;
}
int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0);
if (changed < 0)
return changed;
- if (changed) {
+ if (params->rmask) {
int err = snd_pcm_hw_refine(pcm, params);
if (err < 0)
return err;
assert(0);
return -EINVAL;
}
- if (changed)
+ if (changed) {
params->cmask |= 1 << var;
+ params->rmask |= 1 << var;
+ }
return changed;
}
int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0);
if (changed < 0)
return changed;
- if (changed) {
+ if (params->rmask) {
int err = snd_pcm_hw_refine(pcm, params);
if (err < 0)
return err;
assert(0);
return -EINVAL;
}
- if (changed)
+ if (changed) {
params->cmask |= 1 << var;
+ params->rmask |= 1 << var;
+ }
return changed;
}
*max, maxdir ? *maxdir : 0);
if (changed < 0)
return changed;
- if (changed) {
+ if (params->rmask) {
int err = snd_pcm_hw_refine(pcm, params);
if (err < 0)
return err;
assert(0);
return -EINVAL;
}
- if (changed)
+ if (changed) {
params->cmask |= 1 << var;
+ params->rmask |= 1 << var;
+ }
return changed;
}
int changed = _snd_pcm_hw_param_set(params, var, val, dir);
if (changed < 0)
return changed;
- if (changed) {
+ if (params->rmask) {
int err = snd_pcm_hw_refine(pcm, params);
if (err < 0)
return err;
int changed;
assert(hw_is_mask(var));
changed = mask_refine(hw_param_mask(params, var), val);
- if (changed)
+ if (changed) {
params->cmask |= 1 << var;
+ params->rmask |= 1 << var;
+ }
return changed;
}
int changed = _snd_pcm_hw_param_mask(params, var, val);
if (changed < 0)
return changed;
- if (changed) {
+ if (params->rmask) {
int err = snd_pcm_hw_refine(pcm, params);
if (err < 0)
return err;
int v;
unsigned int saved_min;
int last = 0;
- unsigned int cmask;
int min, max;
int mindir, maxdir;
int valdir = dir ? *dir : 0;
last = 1;
}
_end:
- cmask = params->cmask;
if (last)
v = snd_pcm_hw_param_last(pcm, params, var, dir);
else
v = snd_pcm_hw_param_first(pcm, params, var, dir);
- params->cmask |= cmask;
assert(v >= 0);
return v;
}
snd_pcm_hw_params_t save;
int v;
int last = 0;
- unsigned int cmask;
int min, max;
int mindir, maxdir;
int diff, diffdir;
last = 1;
}
_end:
- cmask = params->cmask;
if (last)
v = snd_pcm_hw_param_last(pcm, params, var, dir);
else
v = snd_pcm_hw_param_first(pcm, params, var, dir);
- params->cmask |= cmask;
assert(v >= 0);
return v;
}
assert(err >= 0);
}
-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)
+void snd_pcm_hw_param_refine_near(snd_pcm_t *pcm,
+ snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var,
+ const snd_pcm_hw_params_t *src)
{
unsigned int min, max;
int mindir, maxdir;
void snd_pcm_hw_params_choose(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
{
int err;
- unsigned int cmask = params->cmask;
err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_ACCESS, 0);
assert(err >= 0);
- cmask |= params->cmask;
err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_FORMAT, 0);
assert(err >= 0);
- cmask |= params->cmask;
err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_SUBFORMAT, 0);
assert(err >= 0);
- cmask |= params->cmask;
err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_CHANNELS, 0);
assert(err >= 0);
- cmask |= params->cmask;
err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_RATE, 0);
assert(err >= 0);
- cmask |= params->cmask;
err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_PERIOD_TIME, 0);
assert(err >= 0);
- cmask |= params->cmask;
err = snd_pcm_hw_param_last(pcm, params, SND_PCM_HW_PARAM_BUFFER_SIZE, 0);
assert(err >= 0);
- cmask |= params->cmask;
err = snd_pcm_hw_param_first(pcm, params, SND_PCM_HW_PARAM_TICK_TIME, 0);
assert(err >= 0);
- cmask |= params->cmask;
-
- params->cmask = cmask;
}
/* Strategies */
return 0;
}
-int snd_pcm_hw_param_refine(snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var,
- const snd_pcm_hw_params_t *src)
+int _snd_pcm_hw_param_refine(snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var,
+ const snd_pcm_hw_params_t *src)
{
int changed = 0;
if (hw_is_mask(var)) {
changed = interval_refine(d, s);
} else
assert(0);
- if (changed)
+ if (changed) {
params->cmask |= 1 << var;
+ params->rmask |= 1 << var;
+ }
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)
{
if (hw_is_mask(var)) {
mask_t *d = hw_param_mask(params, var);
const mask_t *s = hw_param_mask_c(src, var);
mask_copy(d, s);
+ params->cmask |= 1 << var;
+ params->rmask |= 1 << var;
}
if (hw_is_interval(var)) {
interval_t *d = hw_param_interval(params, var);
const interval_t *s = hw_param_interval_c(src, var);
interval_copy(d, s);
+ params->cmask |= 1 << var;
+ params->rmask |= 1 << var;
}
assert(0);
}
assert(f);
for (k = 0; k <= MASK_MAX; ++k) {
if (mask_test(mask, k)) {
- snd_output_putc(out, ' ');
- snd_output_puts(out, f(k));
+ const char *s = f(k);
+ if (s) {
+ snd_output_putc(out, ' ');
+ snd_output_puts(out, s);
+ }
}
}
}
best_badness = UINT_MAX;
value = -1;
while (1) {
- unsigned int cmask;
params1 = *params;
value = strategy->next_value(¶ms1, var, value, &dir, pcm, strategy);
if (value < 0)
break;
- cmask = params1.cmask;
badness = snd_pcm_hw_params_strategy(pcm, ¶ms1, strategy, badness_min, badness_max);
- params1.cmask |= cmask;
if (badness >= 0) {
if ((unsigned int) badness <= badness_min) {
*params = params1;
for (var = 0; var <= SND_PCM_HW_PARAM_LAST; var++) {
int err;
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);
if (err == 0 &&
snd_pcm_hw_params_try_explain_failure1(pcm, fail, &i, depth - 1, out) < 0)
},
};
+#undef RULES_DEBUG
-
-int _snd_pcm_hw_refine(snd_pcm_hw_params_t *params)
+int snd_pcm_hw_refine_soft(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params)
{
unsigned int k;
interval_t *i;
unsigned int rstamps[RULES];
unsigned int vstamps[SND_PCM_HW_PARAM_LAST + 1];
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++) {
- if (!(params->cmask & (1 << k)))
+ if (!(params->rmask & (1 << k)))
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]);
- if (err < 0)
- return err;
+ if (changed)
+ 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++) {
- if (!(params->cmask & (1 << k)))
+ if (!(params->rmask & (1 << k)))
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]);
- if (err < 0)
- return err;
+ if (changed)
+ params->cmask |= 1 << k;
+ if (changed < 0)
+ goto _err;
}
for (k = 0; k < RULES; k++)
rstamps[k] = 0;
for (k = 0; k <= SND_PCM_HW_PARAM_LAST; k++)
- vstamps[k] = (params->cmask & (1 << k)) ? 1 : 0;
- params->cmask = 0;
- changed = 1;
- while (changed) {
- changed = 0;
+ vstamps[k] = (params->rmask & (1 << k)) ? 1 : 0;
+ do {
+ again = 0;
for (k = 0; k < RULES; k++) {
snd_pcm_hw_rule_t *r = &refine_rules[k];
unsigned int d;
int doit = 0;
-#ifdef RULES_DEBUG
- interval_t *i;
-#endif
for (d = 0; r->deps[d] >= 0; d++) {
if (vstamps[r->deps[d]] > rstamps[k]) {
doit = 1;
if (!doit)
continue;
#ifdef RULES_DEBUG
- i = hw_param_interval(params, r->var);
- fprintf(stderr, "Rule %d: %u ", k, r->var);
- interval_print(i, stderr);
+ snd_output_printf(log, "Rule %d: ", k);
+ if (r->var >= 0) {
+ 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
- err = r->func(params, r);
+ changed = r->func(params, r);
#ifdef RULES_DEBUG
- interval_print(i, stderr);
- putc('\n', stderr);
+ if (r->var >= 0)
+ 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
rstamps[k] = stamp;
- if (err && r->var >= 0) {
+ if (changed && r->var >= 0) {
params->cmask |= 1 << r->var;
vstamps[r->var] = stamp;
- changed = 1;
+ again = 1;
}
- if (err < 0)
- return err;
+ if (changed < 0)
+ goto _err;
stamp++;
}
- }
+ } while (again);
if (!params->msbits) {
i = hw_param_interval(params, SND_PCM_HW_PARAM_SAMPLE_BITS);
if (interval_single(i))
params->rate_den = 1;
}
}
+ params->rmask = 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,
- unsigned int vars,
- 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)
{
int changed, err = 0;
unsigned int k;
for (k = 0; k <= SND_PCM_HW_PARAM_LAST; ++k) {
- if (!(vars & (1 << k)) ||
- !((src->cmask & (1 << k))))
+ if (!(vars & (1 << k)))
continue;
- changed = snd_pcm_hw_param_refine(params, k, src);
+ changed = _snd_pcm_hw_param_refine(params, k, src);
if (changed < 0)
err = changed;
}
return err;
}
-/* Accumulate to params->cmask */
-/* Reset sparams->cmask */
-int snd_pcm_generic_hw_link(snd_pcm_hw_params_t *params,
- snd_pcm_hw_params_t *sparams,
- snd_pcm_t *slave,
- unsigned long links)
+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 err1, err = 0;
- err = snd_pcm_hw_params_refine(sparams, links, params);
+ snd_pcm_hw_params_t sparams;
+ int err;
+ err = cprepare(pcm, params);
+ if (err < 0)
+ return err;
+ err = sprepare(pcm, &sparams);
+ if (err < 0) {
+ ERR("Slave PCM not useable");
+ return err;
+ }
+ /* FIXME: loop begin? */
+ err = schange(pcm, params, &sparams);
if (err >= 0) {
- unsigned int cmask = sparams->cmask;
- err = snd_pcm_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;
+ err = srefine(pcm, &sparams);
+ }
+ 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,
- snd_pcm_hw_params_t *sparams,
- int (*func)(snd_pcm_hw_params_t *params,
- snd_pcm_hw_params_t *sparams,
- snd_pcm_t *slave,
- unsigned long private),
- snd_pcm_t *slave,
- unsigned long private)
-{
- int err = 0;
- unsigned int cmask = 0;
- while (params->cmask) {
- err = func(params, sparams, slave, private);
- cmask |= params->cmask;
- if (err < 0)
- break;
- err = _snd_pcm_hw_refine(params);
- cmask |= params->cmask;
- if (err < 0)
- break;
- }
- params->cmask = cmask;
+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))
+
+{
+ snd_pcm_hw_params_t slave_params;
+ int err;
+ err = sprepare(pcm, &slave_params);
+ assert(err >= 0);
+ err = schange(pcm, params, &slave_params);
+ assert(err >= 0);
+ err = sparams(pcm, &slave_params);
+ if (err < 0)
+ cchange(pcm, params, &slave_params);
return err;
}
(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)
{
snd_pcm_plug_t *plug = pcm->private;
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)
{
snd_pcm_plug_t *plug = pcm->private;
snd_pcm_t *slave = plug->req_slave;
snd_pcm_plug_params_t clt_params, slv_params;
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);
clt_params.access = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_ACCESS, 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);
+ 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.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);
snd_pcm_plug_clear(pcm);
- if (clt_params.format == slv_params.format &&
- clt_params.channels == slv_params.channels &&
- clt_params.rate == slv_params.rate &&
- 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_plug_insert_plugins(pcm, &clt_params, &slv_params);
+ if (err < 0)
+ return err;
err = snd_pcm_hw_params(plug->slave, params);
if (err < 0) {
snd_pcm_plug_clear(pcm);
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 src_endian, dst_endian, sign, src_width, dst_width;
int get_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 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 \
((1 << SND_PCM_FORMAT_S8 ) | (1 << SND_PCM_FORMAT_U8) | \
#include <byteswap.h>
#include "pcm_local.h"
#include "pcm_plugin.h"
+#include "interval.h"
#define DIV (1<<16)
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;
- 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 *format_mask = alloca(mask_sizeof());
- mask_t *saccess_mask = alloca(mask_sizeof());
mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN);
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,
- access_mask);
+ access_mask);
if (err < 0)
return err;
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)
return err;
err = _snd_pcm_hw_param_min(params,
SND_PCM_HW_PARAM_RATE, RATE_MAX, 0);
if (err < 0)
return err;
- lcmask = params->cmask;
- params->cmask |= cmask;
+ params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
+ return 0;
+}
- _snd_pcm_hw_params_any(&sparams);
- _snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS,
+static int snd_pcm_rate_hw_refine_sprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *sparams)
+{
+ 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);
- snd_pcm_hw_param_near_copy(slave, &sparams,
- SND_PCM_HW_PARAM_BUFFER_TIME,
- params);
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);
- _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);
- } 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 |
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);
-
- err = snd_pcm_hw_refine2(params, &sparams,
- snd_pcm_generic_hw_link, slave, links);
- params->cmask |= lcmask;
+ 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;
+ err = _snd_pcm_hw_params_refine(sparams, links, params);
if (err < 0)
return err;
- params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
return 0;
}
-
-static int snd_pcm_rate_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
+
+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;
- snd_pcm_t *slave = rate->plug.slave;
+ interval_t t;
+ const interval_t *sbuffer_size;
+ const interval_t *srate, *crate;
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_rate, dst_rate;
- 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 (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
+ 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;
+}
- _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_RATE,
- rate->srate, 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);
+}
- 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);
+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_t *slave = rate->plug.slave;
+ unsigned int src_format, dst_format;
+ unsigned int src_rate, dst_rate;
+ int err = snd_pcm_hw_params_slave(pcm, params,
+ snd_pcm_rate_hw_refine_cchange,
+ snd_pcm_rate_hw_refine_sprepare,
+ snd_pcm_rate_hw_refine_schange,
+ snd_pcm_plugin_hw_params_slave);
if (err < 0)
return err;
- params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
+
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
src_format = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT, 0);
dst_format = slave->format;
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;
- 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 *format_mask = alloca(mask_sizeof());
- mask_t *saccess_mask = alloca(mask_sizeof());
mask_load(access_mask, SND_PCM_ACCBIT_PLUGIN);
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,
- access_mask);
+ access_mask);
if (err < 0)
return err;
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)
return err;
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;
+ params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
+ return 0;
+}
- _snd_pcm_hw_params_any(&sparams);
- _snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS,
+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,
+ _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_hw_param_set(sparams, SND_PCM_HW_PARAM_SUBFORMAT,
SND_PCM_SUBFORMAT_STD, 0);
- } else
+ }
+ 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;
+ 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) {
- _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_CHANNELS,
- route->schannels, 0);
- } else {
+ if (route->schannels < 0)
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;
+ err = _snd_pcm_hw_params_refine(sparams, links, params);
if (err < 0)
return err;
- params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
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_cchange(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_t *slave = route->plug.slave;
int err;
- 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_BUFFER_SIZE |
SND_PCM_HW_PARBIT_BUFFER_TIME |
SND_PCM_HW_PARBIT_TICK_TIME);
- unsigned int src_format, dst_format;
- 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
+ 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) {
- _snd_pcm_hw_param_set(&sparams, SND_PCM_HW_PARAM_CHANNELS,
- route->schannels, 0);
- } else {
+ if (route->schannels < 0)
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_params_refine(params, links, sparams);
+ if (err < 0)
+ return err;
+ return 0;
+}
- 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);
+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;
- params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);
+
if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
src_format = snd_pcm_hw_param_value(params, SND_PCM_HW_PARAM_FORMAT, 0);
dst_format = slave->format;
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)
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_slave_t *slave = share->slave;
- snd_pcm_hw_params_t sparams;
- int err;
- unsigned int cmask, lcmask;
mask_t *access_mask = alloca(mask_sizeof());
- const mask_t *mmap_mask;
- mask_t *saccess_mask = alloca(mask_sizeof());
- mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
-
- cmask = params->cmask;
- params->cmask = 0;
+ int err;
+ mask_any(access_mask);
+ mask_reset(access_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
+ err = _snd_pcm_hw_param_mask(params, SND_PCM_HW_PARAM_ACCESS,
+ access_mask);
+ if (err < 0)
+ return err;
err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_CHANNELS,
share->channels_count, 0);
if (err < 0)
return err;
-
if (slave->format >= 0) {
err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_FORMAT,
slave->format, 0);
if (err < 0)
return err;
}
- lcmask = params->cmask;
- params->cmask |= cmask;
+ params->info |= SND_PCM_INFO_DOUBLE;
+ return 0;
+}
- _snd_pcm_hw_params_any(&sparams);
- _snd_pcm_hw_param_mask(&sparams, SND_PCM_HW_PARAM_ACCESS,
+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,
+ _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);
+ 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;
- mmap_mask = snd_pcm_hw_param_value_mask(&sparams, SND_PCM_HW_PARAM_ACCESS);
+ 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(mmap_mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED))
+ if (!mask_test(saccess_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))
+ 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);
- params->cmask |= lcmask;
+ access_mask);
+ if (err < 0)
+ return err;
+ err = _snd_pcm_hw_params_refine(params, links, sparams);
if (err < 0)
return err;
- params->info |= SND_PCM_INFO_DOUBLE;
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)
{
snd_pcm_share_t *share = pcm->private;
Pthread_mutex_lock(&slave->mutex);
if (slave->setup_count > 1 ||
(slave->setup_count == 1 && !pcm->setup)) {
- params->cmask = 0;
err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_FORMAT,
spcm->format, 0);
if (err < 0)
goto _end;
}
} else {
- snd_pcm_hw_params_t sparams;
- unsigned int links;
- mask_t *saccess_mask = alloca(mask_sizeof());
- mask_load(saccess_mask, SND_PCM_ACCBIT_MMAP);
- 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;
- _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);
+ err = snd_pcm_hw_params_slave(pcm, params,
+ snd_pcm_share_hw_refine_cchange,
+ snd_pcm_share_hw_refine_sprepare,
+ snd_pcm_share_hw_refine_schange,
+ snd_pcm_share_hw_params_slave);
if (err < 0)
goto _end;
snd_pcm_sw_params_current(slave->pcm, &slave->sw_params);
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_cprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params ATTRIBUTE_UNUSED)
+{
+ 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;
volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
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)
{
- snd_pcm_hw_params_t sparams;
- const mask_t *access_mask = snd_pcm_hw_param_value_mask(params, SND_PCM_HW_PARAM_ACCESS);
- mask_t *saccess_mask = alloca(mask_sizeof());
- 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);
- return snd_pcm_hw_refine2(params, &sparams,
- snd_pcm_shm_hw_link, pcm,
- ~SND_PCM_HW_PARBIT_ACCESS);
+ return snd_pcm_hw_refine_slave(pcm, params,
+ snd_pcm_shm_hw_refine_cprepare,
+ snd_pcm_shm_hw_refine_cchange,
+ snd_pcm_shm_hw_refine_sprepare,
+ snd_pcm_shm_hw_refine_schange,
+ snd_pcm_shm_hw_refine_slave);
}
-static int _snd_pcm_shm_hw_params(snd_pcm_t *pcm,
- snd_pcm_hw_params_t *params)
+static int snd_pcm_shm_hw_params_slave(snd_pcm_t *pcm,
+ snd_pcm_hw_params_t *params)
{
snd_pcm_shm_t *shm = pcm->private;
volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
static int snd_pcm_shm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
{
- snd_pcm_hw_params_t sparams;
- 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);
- mask_t *saccess_mask = alloca(mask_sizeof());
- int err;
- 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;
+ return snd_pcm_hw_params_slave(pcm, params,
+ snd_pcm_shm_hw_refine_cchange,
+ snd_pcm_shm_hw_refine_sprepare,
+ snd_pcm_shm_hw_refine_schange,
+ snd_pcm_shm_hw_params_slave);
}
static int snd_pcm_shm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)