Fixed format plugins insertions in case of setup different from params

This commit is contained in:
Abramo Bagnara 2000-07-11 12:33:42 +00:00
parent 8f18ae95ac
commit 6c5be90f2d
4 changed files with 183 additions and 161 deletions

1
TODO
View file

@ -1,4 +1,3 @@
M move plugin insertion after slave params setting (and setup check)
M plug sync and pos problems M plug sync and pos problems
M Loopback implementation? M Loopback implementation?
M Implement PCM alias via ~/.asound.conf to permit snd_pcm_open(name) and this compose pcm_hw, pcm_plug, pcm_multi according to the definition M Implement PCM alias via ~/.asound.conf to permit snd_pcm_open(name) and this compose pcm_hw, pcm_plug, pcm_multi according to the definition

View file

@ -324,7 +324,7 @@ static int preferred_formats[] = {
SND_PCM_SFMT_U8 SND_PCM_SFMT_U8
}; };
int snd_pcm_plug_slave_format(int format, snd_pcm_params_info_t *slave_info) int snd_pcm_plug_slave_fmt(int format, snd_pcm_params_info_t *slave_info)
{ {
if ((snd_pcm_plug_formats(slave_info->formats) & (1 << format)) == 0) if ((snd_pcm_plug_formats(slave_info->formats) & (1 << format)) == 0)
return -EINVAL; return -EINVAL;
@ -429,116 +429,113 @@ int snd_pcm_plug_slave_rate(unsigned int rate, snd_pcm_params_info_t *slave_info
return rate; return rate;
} }
int snd_pcm_plug_slave_params(snd_pcm_params_t *params, int snd_pcm_plug_slave_format(snd_pcm_format_t *format,
snd_pcm_info_t *slave_info, snd_pcm_info_t *slave_info,
snd_pcm_params_info_t *slave_params_info, snd_pcm_params_info_t *slave_params_info,
snd_pcm_params_t *slave_params) snd_pcm_format_t *slave_format)
{ {
int slave_rate; int slave_rate;
*slave_params = *params; *slave_format = *format;
if ((slave_params_info->formats & (1 << params->format.format)) == 0) { if ((slave_params_info->formats & (1 << format->format)) == 0) {
int slave_format = snd_pcm_plug_slave_format(params->format.format, slave_params_info); int slave_fmt = snd_pcm_plug_slave_fmt(format->format, slave_params_info);
if (slave_format < 0) if (slave_fmt < 0)
return slave_format; return slave_fmt;
slave_params->format.format = slave_format; slave_format->format = slave_fmt;
} }
/* channels */ /* channels */
if (params->format.channels < slave_params_info->min_channels) if (format->channels < slave_params_info->min_channels)
slave_params->format.channels = slave_params_info->min_channels; slave_format->channels = slave_params_info->min_channels;
else if (params->format.channels > slave_params_info->max_channels) else if (format->channels > slave_params_info->max_channels)
slave_params->format.channels = slave_params_info->max_channels; slave_format->channels = slave_params_info->max_channels;
/* rate */ /* rate */
slave_rate = snd_pcm_plug_slave_rate(params->format.rate, slave_params_info); slave_rate = snd_pcm_plug_slave_rate(format->rate, slave_params_info);
if (slave_rate < 0) if (slave_rate < 0)
return slave_rate; return slave_rate;
slave_params->format.rate = slave_rate; slave_format->rate = slave_rate;
/* interleave */ /* interleave */
if (!(slave_info->flags & SND_PCM_INFO_INTERLEAVE)) if (!(slave_info->flags & SND_PCM_INFO_INTERLEAVE))
slave_params->format.interleave = 0; slave_format->interleave = 0;
if (!(slave_info->flags & SND_PCM_INFO_NONINTERLEAVE)) if (!(slave_info->flags & SND_PCM_INFO_NONINTERLEAVE))
slave_params->format.interleave = 1; slave_format->interleave = 1;
return 0; return 0;
} }
int snd_pcm_plug_format(snd_pcm_plug_t *plug, int snd_pcm_plug_format_plugins(snd_pcm_plug_t *plug,
snd_pcm_params_t *params, snd_pcm_format_t *format,
snd_pcm_params_t *slave_params) snd_pcm_format_t *slave_format)
{ {
snd_pcm_params_t tmpparams; snd_pcm_format_t tmpformat;
snd_pcm_params_t dstparams; snd_pcm_format_t dstformat;
snd_pcm_params_t *srcparams; snd_pcm_format_t *srcformat;
snd_pcm_plugin_t *plugin; snd_pcm_plugin_t *plugin;
int err; int err;
switch (snd_pcm_plug_stream(plug)) { switch (snd_pcm_plug_stream(plug)) {
case SND_PCM_STREAM_PLAYBACK: case SND_PCM_STREAM_PLAYBACK:
dstparams = *slave_params; dstformat = *slave_format;
srcparams = slave_params; srcformat = slave_format;
*srcparams = *params; *srcformat = *format;
break; break;
case SND_PCM_STREAM_CAPTURE: case SND_PCM_STREAM_CAPTURE:
dstparams = *params; dstformat = *format;
srcparams = params; srcformat = format;
*srcparams = *slave_params; *srcformat = *slave_format;
break; break;
default: default:
assert(0); assert(0);
return -EINVAL; return -EINVAL;
} }
tmpparams = *srcparams; tmpformat = *srcformat;
pdprintf("srcparams: interleave=%i, format=%i, rate=%i, channels=%i\n", pdprintf("srcformat: interleave=%i, format=%i, rate=%i, channels=%i\n",
srcparams->format.interleave, srcformat->interleave,
srcparams->format.format, srcformat->format,
srcparams->format.rate, srcformat->rate,
srcparams->format.channels); srcformat->channels);
pdprintf("dstparams: interleave=%i, format=%i, rate=%i, channels=%i\n", pdprintf("dstformat: interleave=%i, format=%i, rate=%i, channels=%i\n",
dstparams.format.interleave, dstformat.interleave,
dstparams.format.format, dstformat.format,
dstparams.format.rate, dstformat.rate,
dstparams.format.channels); dstformat.channels);
if (srcparams->format.channels == 1) if (srcformat->channels == 1)
srcparams->format.interleave = dstparams.format.interleave; srcformat->interleave = dstformat.interleave;
/* Format change (linearization) */ /* Format change (linearization) */
if ((srcparams->format.format != dstparams.format.format || if ((srcformat->format != dstformat.format ||
srcparams->format.rate != dstparams.format.rate || srcformat->rate != dstformat.rate ||
srcparams->format.channels != dstparams.format.channels) && srcformat->channels != dstformat.channels) &&
!snd_pcm_format_linear(srcparams->format.format)) { !snd_pcm_format_linear(srcformat->format)) {
if (snd_pcm_format_linear(dstparams.format.format)) if (snd_pcm_format_linear(dstformat.format))
tmpparams.format.format = dstparams.format.format; tmpformat.format = dstformat.format;
else else
tmpparams.format.format = SND_PCM_SFMT_S16; tmpformat.format = SND_PCM_SFMT_S16;
tmpparams.format.interleave = dstparams.format.interleave; tmpformat.interleave = dstformat.interleave;
switch (srcparams->format.format) { switch (srcformat->format) {
case SND_PCM_SFMT_MU_LAW: case SND_PCM_SFMT_MU_LAW:
err = snd_pcm_plugin_build_mulaw(plug, err = snd_pcm_plugin_build_mulaw(plug,
&srcparams->format, srcformat, &tmpformat,
&tmpparams.format,
&plugin); &plugin);
break; break;
#ifndef __KERNEL__ #ifndef __KERNEL__
case SND_PCM_SFMT_A_LAW: case SND_PCM_SFMT_A_LAW:
err = snd_pcm_plugin_build_alaw(plug, err = snd_pcm_plugin_build_alaw(plug,
&srcparams->format, srcformat, &tmpformat,
&tmpparams.format,
&plugin); &plugin);
break; break;
case SND_PCM_SFMT_IMA_ADPCM: case SND_PCM_SFMT_IMA_ADPCM:
err = snd_pcm_plugin_build_adpcm(plug, err = snd_pcm_plugin_build_adpcm(plug,
&srcparams->format, srcformat, &tmpformat,
&tmpparams.format,
&plugin); &plugin);
break; break;
#endif #endif
default: default:
return -EINVAL; return -EINVAL;
} }
pdprintf("params format change: src=%i, dst=%i returns %i\n", srcparams->format.format, tmpparams.format.format, err); pdprintf("format format change: src=%i, dst=%i returns %i\n", srcformat->format, tmpformat.format, err);
if (err < 0) if (err < 0)
return err; return err;
err = snd_pcm_plugin_append(plugin); err = snd_pcm_plugin_append(plugin);
@ -546,13 +543,13 @@ int snd_pcm_plug_format(snd_pcm_plug_t *plug,
snd_pcm_plugin_free(plugin); snd_pcm_plugin_free(plugin);
return err; return err;
} }
srcparams->format = tmpparams.format; *srcformat = tmpformat;
} }
/* channels reduction */ /* channels reduction */
if (srcparams->format.channels > dstparams.format.channels) { if (srcformat->channels > dstformat.channels) {
int sv = srcparams->format.channels; int sv = srcformat->channels;
int dv = dstparams.format.channels; int dv = dstformat.channels;
route_ttable_entry_t *ttable = calloc(1, dv*sv*sizeof(*ttable)); route_ttable_entry_t *ttable = calloc(1, dv*sv*sizeof(*ttable));
#if 1 #if 1
if (sv == 2 && dv == 1) { if (sv == 2 && dv == 1) {
@ -565,18 +562,16 @@ int snd_pcm_plug_format(snd_pcm_plug_t *plug,
for (v = 0; v < dv; ++v) for (v = 0; v < dv; ++v)
ttable[v * sv + v] = FULL; ttable[v * sv + v] = FULL;
} }
tmpparams.format.channels = dstparams.format.channels; tmpformat.channels = dstformat.channels;
tmpparams.format.interleave = dstparams.format.interleave; tmpformat.interleave = dstformat.interleave;
if (srcparams->format.rate == dstparams.format.rate && if (srcformat->rate == dstformat.rate &&
snd_pcm_format_linear(dstparams.format.format)) snd_pcm_format_linear(dstformat.format))
tmpparams.format.format = dstparams.format.format; tmpformat.format = dstformat.format;
err = snd_pcm_plugin_build_route(plug, err = snd_pcm_plugin_build_route(plug,
&srcparams->format, srcformat, &tmpformat,
&tmpparams.format, ttable, &plugin);
ttable,
&plugin);
free(ttable); free(ttable);
pdprintf("params channels reduction: src=%i, dst=%i returns %i\n", srcparams->format.channels, tmpparams.format.channels, err); pdprintf("format channels reduction: src=%i, dst=%i returns %i\n", srcformat->channels, tmpformat.channels, err);
if (err < 0) { if (err < 0) {
snd_pcm_plugin_free(plugin); snd_pcm_plugin_free(plugin);
return err; return err;
@ -586,21 +581,20 @@ int snd_pcm_plug_format(snd_pcm_plug_t *plug,
snd_pcm_plugin_free(plugin); snd_pcm_plugin_free(plugin);
return err; return err;
} }
srcparams->format = tmpparams.format; *srcformat = tmpformat;
} }
/* rate resampling */ /* rate resampling */
if (srcparams->format.rate != dstparams.format.rate) { if (srcformat->rate != dstformat.rate) {
tmpparams.format.rate = dstparams.format.rate; tmpformat.rate = dstformat.rate;
tmpparams.format.interleave = dstparams.format.interleave; tmpformat.interleave = dstformat.interleave;
if (srcparams->format.channels == dstparams.format.channels && if (srcformat->channels == dstformat.channels &&
snd_pcm_format_linear(dstparams.format.format)) snd_pcm_format_linear(dstformat.format))
tmpparams.format.format = dstparams.format.format; tmpformat.format = dstformat.format;
err = snd_pcm_plugin_build_rate(plug, err = snd_pcm_plugin_build_rate(plug,
&srcparams->format, srcformat, &tmpformat,
&tmpparams.format,
&plugin); &plugin);
pdprintf("params rate down resampling: src=%i, dst=%i returns %i\n", srcparams->format.rate, tmpparams.format.rate, err); pdprintf("format rate down resampling: src=%i, dst=%i returns %i\n", srcformat->rate, tmpformat.rate, err);
if (err < 0) { if (err < 0) {
snd_pcm_plugin_free(plugin); snd_pcm_plugin_free(plugin);
return err; return err;
@ -610,13 +604,13 @@ int snd_pcm_plug_format(snd_pcm_plug_t *plug,
snd_pcm_plugin_free(plugin); snd_pcm_plugin_free(plugin);
return err; return err;
} }
srcparams->format = tmpparams.format; *srcformat = tmpformat;
} }
/* channels extension */ /* channels extension */
if (srcparams->format.channels < dstparams.format.channels) { if (srcformat->channels < dstformat.channels) {
int sv = srcparams->format.channels; int sv = srcformat->channels;
int dv = dstparams.format.channels; int dv = dstformat.channels;
route_ttable_entry_t *ttable = calloc(1, dv * sv * sizeof(*ttable)); route_ttable_entry_t *ttable = calloc(1, dv * sv * sizeof(*ttable));
#if 0 #if 0
{ {
@ -636,17 +630,15 @@ int snd_pcm_plug_format(snd_pcm_plug_t *plug,
} }
} }
#endif #endif
tmpparams.format.channels = dstparams.format.channels; tmpformat.channels = dstformat.channels;
tmpparams.format.interleave = dstparams.format.interleave; tmpformat.interleave = dstformat.interleave;
if (snd_pcm_format_linear(dstparams.format.format)) if (snd_pcm_format_linear(dstformat.format))
tmpparams.format.format = dstparams.format.format; tmpformat.format = dstformat.format;
err = snd_pcm_plugin_build_route(plug, err = snd_pcm_plugin_build_route(plug,
&srcparams->format, srcformat, &tmpformat,
&tmpparams.format, ttable, &plugin);
ttable,
&plugin);
free(ttable); free(ttable);
pdprintf("params channels extension: src=%i, dst=%i returns %i\n", srcparams->format.channels, tmpparams.format.channels, err); pdprintf("format channels extension: src=%i, dst=%i returns %i\n", srcformat->channels, tmpformat.channels, err);
if (err < 0) { if (err < 0) {
snd_pcm_plugin_free(plugin); snd_pcm_plugin_free(plugin);
return err; return err;
@ -656,43 +648,39 @@ int snd_pcm_plug_format(snd_pcm_plug_t *plug,
snd_pcm_plugin_free(plugin); snd_pcm_plugin_free(plugin);
return err; return err;
} }
srcparams->format = tmpparams.format; *srcformat = tmpformat;
} }
/* format change */ /* format change */
if (srcparams->format.format != dstparams.format.format) { if (srcformat->format != dstformat.format) {
tmpparams.format.format = dstparams.format.format; tmpformat.format = dstformat.format;
tmpparams.format.interleave = dstparams.format.interleave; tmpformat.interleave = dstformat.interleave;
if (tmpparams.format.format == SND_PCM_SFMT_MU_LAW) { if (tmpformat.format == SND_PCM_SFMT_MU_LAW) {
err = snd_pcm_plugin_build_mulaw(plug, err = snd_pcm_plugin_build_mulaw(plug,
&srcparams->format, srcformat, &tmpformat,
&tmpparams.format,
&plugin); &plugin);
} }
#ifndef __KERNEL__ #ifndef __KERNEL__
else if (tmpparams.format.format == SND_PCM_SFMT_A_LAW) { else if (tmpformat.format == SND_PCM_SFMT_A_LAW) {
err = snd_pcm_plugin_build_alaw(plug, err = snd_pcm_plugin_build_alaw(plug,
&srcparams->format, srcformat, &tmpformat,
&tmpparams.format,
&plugin); &plugin);
} }
else if (tmpparams.format.format == SND_PCM_SFMT_IMA_ADPCM) { else if (tmpformat.format == SND_PCM_SFMT_IMA_ADPCM) {
err = snd_pcm_plugin_build_adpcm(plug, err = snd_pcm_plugin_build_adpcm(plug,
&srcparams->format, srcformat, &tmpformat,
&tmpparams.format,
&plugin); &plugin);
} }
#endif #endif
else if (snd_pcm_format_linear(srcparams->format.format) && else if (snd_pcm_format_linear(srcformat->format) &&
snd_pcm_format_linear(tmpparams.format.format)) { snd_pcm_format_linear(tmpformat.format)) {
err = snd_pcm_plugin_build_linear(plug, err = snd_pcm_plugin_build_linear(plug,
&srcparams->format, srcformat, &tmpformat,
&tmpparams.format,
&plugin); &plugin);
} }
else else
return -EINVAL; return -EINVAL;
pdprintf("params format change: src=%i, dst=%i returns %i\n", srcparams->format.format, tmpparams.format.format, err); pdprintf("format format change: src=%i, dst=%i returns %i\n", srcformat->format, tmpformat.format, err);
if (err < 0) if (err < 0)
return err; return err;
err = snd_pcm_plugin_append(plugin); err = snd_pcm_plugin_append(plugin);
@ -700,17 +688,16 @@ int snd_pcm_plug_format(snd_pcm_plug_t *plug,
snd_pcm_plugin_free(plugin); snd_pcm_plugin_free(plugin);
return err; return err;
} }
srcparams->format = tmpparams.format; *srcformat = tmpformat;
} }
/* interleave */ /* interleave */
if (srcparams->format.interleave != dstparams.format.interleave) { if (srcformat->interleave != dstformat.interleave) {
tmpparams.format.interleave = dstparams.format.interleave; tmpformat.interleave = dstformat.interleave;
err = snd_pcm_plugin_build_copy(plug, err = snd_pcm_plugin_build_copy(plug,
&srcparams->format, srcformat, &tmpformat,
&tmpparams.format,
&plugin); &plugin);
pdprintf("interleave change: src=%i, dst=%i returns %i\n", srcparams->format.interleave, tmpparams.format.interleave, err); pdprintf("interleave change: src=%i, dst=%i returns %i\n", srcformat->interleave, tmpformat.interleave, err);
if (err < 0) if (err < 0)
return err; return err;
err = snd_pcm_plugin_append(plugin); err = snd_pcm_plugin_append(plugin);
@ -718,7 +705,7 @@ int snd_pcm_plug_format(snd_pcm_plug_t *plug,
snd_pcm_plugin_free(plugin); snd_pcm_plugin_free(plugin);
return err; return err;
} }
srcparams->format = tmpparams.format; *srcformat = tmpformat;
} }
return 0; return 0;

View file

@ -81,16 +81,16 @@ typedef struct snd_pcm_plug {
size_t frames_alloc; size_t frames_alloc;
} snd_pcm_plug_t; } snd_pcm_plug_t;
unsigned int snd_pcm_plug_formats(unsigned int formats); unsigned int snd_pcm_plug_formats(unsigned int slave_formats);
int snd_pcm_plug_slave_format(int format, snd_pcm_params_info_t *slave_info); int snd_pcm_plug_slave_fmt(int format, snd_pcm_params_info_t *slave_info);
int snd_pcm_plug_slave_rate(unsigned int rate, snd_pcm_params_info_t *slave_info); int snd_pcm_plug_slave_rate(unsigned int rate, snd_pcm_params_info_t *slave_info);
int snd_pcm_plug_slave_params(snd_pcm_params_t *params, int snd_pcm_plug_slave_format(snd_pcm_format_t *format,
snd_pcm_info_t *slave_info, snd_pcm_info_t *slave_info,
snd_pcm_params_info_t *slave_params_info, snd_pcm_params_info_t *slave_params_info,
snd_pcm_params_t *slave_params); snd_pcm_format_t *slave_format);
int snd_pcm_plug_format(snd_pcm_plug_t *plug, int snd_pcm_plug_format_plugins(snd_pcm_plug_t *plug,
snd_pcm_params_t *params, snd_pcm_format_t *format,
snd_pcm_params_t *slave_params); snd_pcm_format_t *slave_format);
ssize_t snd_pcm_plug_write_transfer(snd_pcm_plug_t *plug, snd_pcm_plugin_channel_t *src_channels, size_t size); ssize_t snd_pcm_plug_write_transfer(snd_pcm_plug_t *plug, snd_pcm_plugin_channel_t *src_channels, size_t size);
ssize_t snd_pcm_plug_read_transfer(snd_pcm_plug_t *plug, snd_pcm_plugin_channel_t *dst_channels_final, size_t size); ssize_t snd_pcm_plug_read_transfer(snd_pcm_plug_t *plug, snd_pcm_plugin_channel_t *dst_channels_final, size_t size);

View file

@ -173,7 +173,7 @@ static int snd_pcm_plug_params_info(void *private, snd_pcm_params_info_t *info)
if (!(info->req_mask & SND_PCM_PARAMS_FORMAT)) if (!(info->req_mask & SND_PCM_PARAMS_FORMAT))
return 0; return 0;
slave_format = snd_pcm_plug_slave_format(info->req.format.format, &slave_info); slave_format = snd_pcm_plug_slave_fmt(info->req.format.format, &slave_info);
if (slave_format < 0) { if (slave_format < 0) {
info->req.fail_mask = SND_PCM_PARAMS_FORMAT; info->req.fail_mask = SND_PCM_PARAMS_FORMAT;
info->req.fail_reason = SND_PCM_PARAMS_FAIL_INVAL; info->req.fail_reason = SND_PCM_PARAMS_FAIL_INVAL;
@ -607,14 +607,39 @@ struct snd_pcm_ops snd_pcm_plug_ops = {
channels_mask: snd_pcm_plug_channels_mask, channels_mask: snd_pcm_plug_channels_mask,
}; };
static void snd_pcm_plug_slave_params(snd_pcm_plug_t *plug,
snd_pcm_params_t *params,
snd_pcm_params_t *slave_params)
{
/* compute right sizes */
slave_params->frag_size = snd_pcm_plug_slave_size(plug, params->frag_size);
slave_params->buffer_size = snd_pcm_plug_slave_size(plug, params->buffer_size);
slave_params->frames_fill_max = snd_pcm_plug_slave_size(plug, params->frames_fill_max);
slave_params->frames_min = snd_pcm_plug_slave_size(plug, params->frames_min);
slave_params->frames_xrun_max = snd_pcm_plug_slave_size(plug, params->frames_xrun_max);
slave_params->frames_align = snd_pcm_plug_slave_size(plug, params->frames_align);
if (slave_params->frame_boundary == 0 || slave_params->frame_boundary > INT_MAX)
slave_params->frame_boundary = INT_MAX;
assert(params->buffer_size > 0);
slave_params->frame_boundary /= params->buffer_size;
if (slave_params->frame_boundary > INT_MAX / slave_params->buffer_size)
slave_params->frame_boundary = INT_MAX;
else
slave_params->frame_boundary *= slave_params->buffer_size;
}
static int snd_pcm_plug_params(void *private, snd_pcm_params_t *params) static int snd_pcm_plug_params(void *private, snd_pcm_params_t *params)
{ {
snd_pcm_params_t slave_params, params1; snd_pcm_params_t slave_params;
snd_pcm_info_t slave_info; snd_pcm_info_t slave_info;
snd_pcm_format_t *req_format, *real_format, format1;
snd_pcm_params_info_t slave_params_info; snd_pcm_params_info_t slave_params_info;
snd_pcm_plugin_t *plugin; snd_pcm_plugin_t *plugin;
snd_pcm_plug_t *plug; snd_pcm_plug_t *plug;
int err; int err;
int first = 1;
plug = (snd_pcm_plug_t*) private; plug = (snd_pcm_plug_t*) private;
@ -633,21 +658,33 @@ static int snd_pcm_plug_params(void *private, snd_pcm_params_t *params)
return err; return err;
} }
if ((err = snd_pcm_plug_slave_params(params, &slave_info, &slave_params_info, &slave_params)) < 0) slave_params = *params;
if ((err = snd_pcm_plug_slave_format(&params->format, &slave_info, &slave_params_info, &slave_params.format)) < 0)
return err; return err;
retry:
snd_pcm_plug_clear(plug);
/* add necessary plugins */ /* add necessary plugins */
params1 = *params; format1 = params->format;
if ((err = snd_pcm_plug_format(plug, &params1, &slave_params)) < 0) snd_pcm_plug_clear(plug);
if ((err = snd_pcm_plug_format_plugins(plug, &format1,
&slave_params.format)) < 0)
return err; return err;
if (!plug->first) { if (!plug->first) {
err = snd_pcm_params(plug->slave, params); err = snd_pcm_params(plug->slave, params);
if (err < 0) if (err < 0)
return err; return err;
req_format = &params->format;
real_format = &plug->slave->setup.format;
if (real_format->interleave != req_format->interleave ||
real_format->format != req_format->format ||
real_format->rate != req_format->rate ||
real_format->channels != req_format->channels) {
assert(first);
slave_params.format = *real_format;
first = 0;
goto retry;
}
*plug->handle->ops = *plug->slave->ops; *plug->handle->ops = *plug->slave->ops;
plug->handle->ops->params = snd_pcm_plug_params; plug->handle->ops->params = snd_pcm_plug_params;
plug->handle->ops->setup = snd_pcm_plug_setup; plug->handle->ops->setup = snd_pcm_plug_setup;
@ -655,26 +692,33 @@ static int snd_pcm_plug_params(void *private, snd_pcm_params_t *params)
plug->handle->ops->params_info = snd_pcm_plug_params_info; plug->handle->ops->params_info = snd_pcm_plug_params_info;
plug->handle->op_arg = plug->slave->op_arg; plug->handle->op_arg = plug->slave->op_arg;
return 0; return 0;
} else {
*plug->handle->ops = snd_pcm_plug_ops;
plug->handle->op_arg = plug;
} }
*plug->handle->ops = snd_pcm_plug_ops;
plug->handle->op_arg = plug;
/* compute right sizes */ /* compute right sizes */
slave_params.frag_size = snd_pcm_plug_slave_size(plug, params1.frag_size); snd_pcm_plug_slave_params(plug, params, &slave_params);
slave_params.buffer_size = snd_pcm_plug_slave_size(plug, params1.buffer_size);
slave_params.frames_fill_max = snd_pcm_plug_slave_size(plug, params1.frames_fill_max); pdprintf("params requested params: format = %i, rate = %i, channels = %i\n", slave_params.format.format, slave_params.format.rate, slave_params.format.channels);
slave_params.frames_min = snd_pcm_plug_slave_size(plug, params1.frames_min); err = snd_pcm_params(plug->slave, &slave_params);
slave_params.frames_xrun_max = snd_pcm_plug_slave_size(plug, params1.frames_xrun_max); if (err < 0) {
slave_params.frames_align = snd_pcm_plug_slave_size(plug, params1.frames_align); params->fail_mask = slave_params.fail_mask;
if (slave_params.frame_boundary == 0 || slave_params.frame_boundary > INT_MAX) params->fail_reason = slave_params.fail_reason;
slave_params.frame_boundary = INT_MAX; return err;
assert(params->buffer_size > 0); }
slave_params.frame_boundary /= params->buffer_size;
if (slave_params.frame_boundary > INT_MAX / slave_params.buffer_size) req_format = &slave_params.format;
slave_params.frame_boundary = INT_MAX; real_format = &plug->slave->setup.format;
else if (real_format->interleave != req_format->interleave ||
slave_params.frame_boundary *= slave_params.buffer_size; real_format->format != req_format->format ||
real_format->rate != req_format->rate ||
real_format->channels != req_format->channels) {
assert(first);
slave_params.format = *real_format;
first = 0;
goto retry;
}
/* /*
* I/O plugins * I/O plugins
@ -699,14 +743,6 @@ static int snd_pcm_plug_params(void *private, snd_pcm_params_t *params)
return err; return err;
} }
pdprintf("params requested params: format = %i, rate = %i, channels = %i\n", slave_params.format.format, slave_params.format.rate, slave_params.format.channels);
err = snd_pcm_params(plug->slave, &slave_params);
if (err < 0) {
params->fail_mask = slave_params.fail_mask;
params->fail_reason = slave_params.fail_reason;
return err;
}
err = snd_pcm_plug_action(plug, INIT, 0); err = snd_pcm_plug_action(plug, INIT, 0);
if (err < 0) if (err < 0)
return err; return err;