diff options
author | Abramo Bagnara <abramo@alsa-project.org> | 2000-07-11 12:33:42 +0000 |
---|---|---|
committer | Abramo Bagnara <abramo@alsa-project.org> | 2000-07-11 12:33:42 +0000 |
commit | 6c5be90f2d797db5046fac5936d96d8911ce2296 (patch) | |
tree | 16ca5e269aa688e905b11632a26069dae7a24539 | |
parent | 8f18ae95ac39951839519964b2a07a53f65956b2 (diff) | |
download | alsa-lib-6c5be90f2d797db5046fac5936d96d8911ce2296.tar.gz |
Fixed format plugins insertions in case of setup different from params
-rw-r--r-- | TODO | 1 | ||||
-rw-r--r-- | src/pcm/pcm_common.c | 227 | ||||
-rw-r--r-- | src/pcm/pcm_local.h | 14 | ||||
-rw-r--r-- | src/pcm/pcm_plug.c | 102 |
4 files changed, 183 insertions, 161 deletions
@@ -1,4 +1,3 @@ -M move plugin insertion after slave params setting (and setup check) M plug sync and pos problems 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 diff --git a/src/pcm/pcm_common.c b/src/pcm/pcm_common.c index 13f43e98..d33ab8cd 100644 --- a/src/pcm/pcm_common.c +++ b/src/pcm/pcm_common.c @@ -324,7 +324,7 @@ static int preferred_formats[] = { 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) return -EINVAL; @@ -429,116 +429,113 @@ int snd_pcm_plug_slave_rate(unsigned int rate, snd_pcm_params_info_t *slave_info 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_params_info_t *slave_params_info, - snd_pcm_params_t *slave_params) + snd_pcm_format_t *slave_format) { int slave_rate; - *slave_params = *params; - if ((slave_params_info->formats & (1 << params->format.format)) == 0) { - int slave_format = snd_pcm_plug_slave_format(params->format.format, slave_params_info); - if (slave_format < 0) - return slave_format; - slave_params->format.format = slave_format; + *slave_format = *format; + if ((slave_params_info->formats & (1 << format->format)) == 0) { + int slave_fmt = snd_pcm_plug_slave_fmt(format->format, slave_params_info); + if (slave_fmt < 0) + return slave_fmt; + slave_format->format = slave_fmt; } /* channels */ - if (params->format.channels < slave_params_info->min_channels) - slave_params->format.channels = slave_params_info->min_channels; - else if (params->format.channels > slave_params_info->max_channels) - slave_params->format.channels = slave_params_info->max_channels; + if (format->channels < slave_params_info->min_channels) + slave_format->channels = slave_params_info->min_channels; + else if (format->channels > slave_params_info->max_channels) + slave_format->channels = slave_params_info->max_channels; /* 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) return slave_rate; - slave_params->format.rate = slave_rate; + slave_format->rate = slave_rate; /* 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)) - slave_params->format.interleave = 1; + slave_format->interleave = 1; return 0; } -int snd_pcm_plug_format(snd_pcm_plug_t *plug, - snd_pcm_params_t *params, - snd_pcm_params_t *slave_params) +int snd_pcm_plug_format_plugins(snd_pcm_plug_t *plug, + snd_pcm_format_t *format, + snd_pcm_format_t *slave_format) { - snd_pcm_params_t tmpparams; - snd_pcm_params_t dstparams; - snd_pcm_params_t *srcparams; + snd_pcm_format_t tmpformat; + snd_pcm_format_t dstformat; + snd_pcm_format_t *srcformat; snd_pcm_plugin_t *plugin; int err; switch (snd_pcm_plug_stream(plug)) { case SND_PCM_STREAM_PLAYBACK: - dstparams = *slave_params; - srcparams = slave_params; - *srcparams = *params; + dstformat = *slave_format; + srcformat = slave_format; + *srcformat = *format; break; case SND_PCM_STREAM_CAPTURE: - dstparams = *params; - srcparams = params; - *srcparams = *slave_params; + dstformat = *format; + srcformat = format; + *srcformat = *slave_format; break; default: assert(0); return -EINVAL; } - tmpparams = *srcparams; + tmpformat = *srcformat; - pdprintf("srcparams: interleave=%i, format=%i, rate=%i, channels=%i\n", - srcparams->format.interleave, - srcparams->format.format, - srcparams->format.rate, - srcparams->format.channels); - pdprintf("dstparams: interleave=%i, format=%i, rate=%i, channels=%i\n", - dstparams.format.interleave, - dstparams.format.format, - dstparams.format.rate, - dstparams.format.channels); + pdprintf("srcformat: interleave=%i, format=%i, rate=%i, channels=%i\n", + srcformat->interleave, + srcformat->format, + srcformat->rate, + srcformat->channels); + pdprintf("dstformat: interleave=%i, format=%i, rate=%i, channels=%i\n", + dstformat.interleave, + dstformat.format, + dstformat.rate, + dstformat.channels); - if (srcparams->format.channels == 1) - srcparams->format.interleave = dstparams.format.interleave; + if (srcformat->channels == 1) + srcformat->interleave = dstformat.interleave; /* Format change (linearization) */ - if ((srcparams->format.format != dstparams.format.format || - srcparams->format.rate != dstparams.format.rate || - srcparams->format.channels != dstparams.format.channels) && - !snd_pcm_format_linear(srcparams->format.format)) { - if (snd_pcm_format_linear(dstparams.format.format)) - tmpparams.format.format = dstparams.format.format; + if ((srcformat->format != dstformat.format || + srcformat->rate != dstformat.rate || + srcformat->channels != dstformat.channels) && + !snd_pcm_format_linear(srcformat->format)) { + if (snd_pcm_format_linear(dstformat.format)) + tmpformat.format = dstformat.format; else - tmpparams.format.format = SND_PCM_SFMT_S16; - tmpparams.format.interleave = dstparams.format.interleave; - switch (srcparams->format.format) { + tmpformat.format = SND_PCM_SFMT_S16; + tmpformat.interleave = dstformat.interleave; + switch (srcformat->format) { case SND_PCM_SFMT_MU_LAW: err = snd_pcm_plugin_build_mulaw(plug, - &srcparams->format, - &tmpparams.format, + srcformat, &tmpformat, &plugin); break; #ifndef __KERNEL__ case SND_PCM_SFMT_A_LAW: err = snd_pcm_plugin_build_alaw(plug, - &srcparams->format, - &tmpparams.format, + srcformat, &tmpformat, &plugin); break; case SND_PCM_SFMT_IMA_ADPCM: err = snd_pcm_plugin_build_adpcm(plug, - &srcparams->format, - &tmpparams.format, + srcformat, &tmpformat, &plugin); break; #endif default: 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) return err; 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); return err; } - srcparams->format = tmpparams.format; + *srcformat = tmpformat; } /* channels reduction */ - if (srcparams->format.channels > dstparams.format.channels) { - int sv = srcparams->format.channels; - int dv = dstparams.format.channels; + if (srcformat->channels > dstformat.channels) { + int sv = srcformat->channels; + int dv = dstformat.channels; route_ttable_entry_t *ttable = calloc(1, dv*sv*sizeof(*ttable)); #if 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) ttable[v * sv + v] = FULL; } - tmpparams.format.channels = dstparams.format.channels; - tmpparams.format.interleave = dstparams.format.interleave; - if (srcparams->format.rate == dstparams.format.rate && - snd_pcm_format_linear(dstparams.format.format)) - tmpparams.format.format = dstparams.format.format; + tmpformat.channels = dstformat.channels; + tmpformat.interleave = dstformat.interleave; + if (srcformat->rate == dstformat.rate && + snd_pcm_format_linear(dstformat.format)) + tmpformat.format = dstformat.format; err = snd_pcm_plugin_build_route(plug, - &srcparams->format, - &tmpparams.format, - ttable, - &plugin); + srcformat, &tmpformat, + ttable, &plugin); 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) { snd_pcm_plugin_free(plugin); return err; @@ -586,21 +581,20 @@ int snd_pcm_plug_format(snd_pcm_plug_t *plug, snd_pcm_plugin_free(plugin); return err; } - srcparams->format = tmpparams.format; + *srcformat = tmpformat; } /* rate resampling */ - if (srcparams->format.rate != dstparams.format.rate) { - tmpparams.format.rate = dstparams.format.rate; - tmpparams.format.interleave = dstparams.format.interleave; - if (srcparams->format.channels == dstparams.format.channels && - snd_pcm_format_linear(dstparams.format.format)) - tmpparams.format.format = dstparams.format.format; + if (srcformat->rate != dstformat.rate) { + tmpformat.rate = dstformat.rate; + tmpformat.interleave = dstformat.interleave; + if (srcformat->channels == dstformat.channels && + snd_pcm_format_linear(dstformat.format)) + tmpformat.format = dstformat.format; err = snd_pcm_plugin_build_rate(plug, - &srcparams->format, - &tmpparams.format, + srcformat, &tmpformat, &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) { snd_pcm_plugin_free(plugin); return err; @@ -610,13 +604,13 @@ int snd_pcm_plug_format(snd_pcm_plug_t *plug, snd_pcm_plugin_free(plugin); return err; } - srcparams->format = tmpparams.format; + *srcformat = tmpformat; } /* channels extension */ - if (srcparams->format.channels < dstparams.format.channels) { - int sv = srcparams->format.channels; - int dv = dstparams.format.channels; + if (srcformat->channels < dstformat.channels) { + int sv = srcformat->channels; + int dv = dstformat.channels; route_ttable_entry_t *ttable = calloc(1, dv * sv * sizeof(*ttable)); #if 0 { @@ -636,17 +630,15 @@ int snd_pcm_plug_format(snd_pcm_plug_t *plug, } } #endif - tmpparams.format.channels = dstparams.format.channels; - tmpparams.format.interleave = dstparams.format.interleave; - if (snd_pcm_format_linear(dstparams.format.format)) - tmpparams.format.format = dstparams.format.format; + tmpformat.channels = dstformat.channels; + tmpformat.interleave = dstformat.interleave; + if (snd_pcm_format_linear(dstformat.format)) + tmpformat.format = dstformat.format; err = snd_pcm_plugin_build_route(plug, - &srcparams->format, - &tmpparams.format, - ttable, - &plugin); + srcformat, &tmpformat, + ttable, &plugin); 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) { snd_pcm_plugin_free(plugin); return err; @@ -656,43 +648,39 @@ int snd_pcm_plug_format(snd_pcm_plug_t *plug, snd_pcm_plugin_free(plugin); return err; } - srcparams->format = tmpparams.format; + *srcformat = tmpformat; } /* format change */ - if (srcparams->format.format != dstparams.format.format) { - tmpparams.format.format = dstparams.format.format; - tmpparams.format.interleave = dstparams.format.interleave; - if (tmpparams.format.format == SND_PCM_SFMT_MU_LAW) { + if (srcformat->format != dstformat.format) { + tmpformat.format = dstformat.format; + tmpformat.interleave = dstformat.interleave; + if (tmpformat.format == SND_PCM_SFMT_MU_LAW) { err = snd_pcm_plugin_build_mulaw(plug, - &srcparams->format, - &tmpparams.format, + srcformat, &tmpformat, &plugin); } #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, - &srcparams->format, - &tmpparams.format, + srcformat, &tmpformat, &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, - &srcparams->format, - &tmpparams.format, + srcformat, &tmpformat, &plugin); } #endif - else if (snd_pcm_format_linear(srcparams->format.format) && - snd_pcm_format_linear(tmpparams.format.format)) { + else if (snd_pcm_format_linear(srcformat->format) && + snd_pcm_format_linear(tmpformat.format)) { err = snd_pcm_plugin_build_linear(plug, - &srcparams->format, - &tmpparams.format, + srcformat, &tmpformat, &plugin); } else 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) return err; 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); return err; } - srcparams->format = tmpparams.format; + *srcformat = tmpformat; } /* interleave */ - if (srcparams->format.interleave != dstparams.format.interleave) { - tmpparams.format.interleave = dstparams.format.interleave; + if (srcformat->interleave != dstformat.interleave) { + tmpformat.interleave = dstformat.interleave; err = snd_pcm_plugin_build_copy(plug, - &srcparams->format, - &tmpparams.format, + srcformat, &tmpformat, &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) return err; 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); return err; } - srcparams->format = tmpparams.format; + *srcformat = tmpformat; } return 0; diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h index 65743a9e..dedaa7b0 100644 --- a/src/pcm/pcm_local.h +++ b/src/pcm/pcm_local.h @@ -81,16 +81,16 @@ typedef struct snd_pcm_plug { size_t frames_alloc; } snd_pcm_plug_t; -unsigned int snd_pcm_plug_formats(unsigned int formats); -int snd_pcm_plug_slave_format(int format, snd_pcm_params_info_t *slave_info); +unsigned int snd_pcm_plug_formats(unsigned int slave_formats); +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_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_params_info_t *slave_params_info, - snd_pcm_params_t *slave_params); -int snd_pcm_plug_format(snd_pcm_plug_t *plug, - snd_pcm_params_t *params, - snd_pcm_params_t *slave_params); + snd_pcm_format_t *slave_format); +int snd_pcm_plug_format_plugins(snd_pcm_plug_t *plug, + snd_pcm_format_t *format, + 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_read_transfer(snd_pcm_plug_t *plug, snd_pcm_plugin_channel_t *dst_channels_final, size_t size); diff --git a/src/pcm/pcm_plug.c b/src/pcm/pcm_plug.c index 0ed01bfd..5aa2ea4a 100644 --- a/src/pcm/pcm_plug.c +++ b/src/pcm/pcm_plug.c @@ -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)) 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) { info->req.fail_mask = SND_PCM_PARAMS_FORMAT; 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, }; +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) { - snd_pcm_params_t slave_params, params1; + snd_pcm_params_t slave_params; 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_plugin_t *plugin; snd_pcm_plug_t *plug; int err; + int first = 1; 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; } - 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(¶ms->format, &slave_info, &slave_params_info, &slave_params.format)) < 0) return err; - - snd_pcm_plug_clear(plug); - + retry: /* add necessary plugins */ - params1 = *params; - if ((err = snd_pcm_plug_format(plug, ¶ms1, &slave_params)) < 0) + format1 = params->format; + snd_pcm_plug_clear(plug); + if ((err = snd_pcm_plug_format_plugins(plug, &format1, + &slave_params.format)) < 0) return err; if (!plug->first) { err = snd_pcm_params(plug->slave, params); if (err < 0) return err; + req_format = ¶ms->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->params = snd_pcm_plug_params; 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->op_arg = plug->slave->op_arg; 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 */ - slave_params.frag_size = snd_pcm_plug_slave_size(plug, params1.frag_size); - 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); - slave_params.frames_min = snd_pcm_plug_slave_size(plug, params1.frames_min); - slave_params.frames_xrun_max = snd_pcm_plug_slave_size(plug, params1.frames_xrun_max); - slave_params.frames_align = snd_pcm_plug_slave_size(plug, params1.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; + snd_pcm_plug_slave_params(plug, params, &slave_params); + + 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; + } + + req_format = &slave_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; + } /* * I/O plugins @@ -699,14 +743,6 @@ static int snd_pcm_plug_params(void *private, snd_pcm_params_t *params) 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); if (err < 0) return err; |