From b312f52b762a43a9683215b11527a6b86cfd56e5 Mon Sep 17 00:00:00 2001 From: Abramo Bagnara Date: Wed, 21 Jun 2000 15:03:06 +0000 Subject: [PATCH] pcm handle split. Moved buffer to plugin struct --- src/pcm/pcm_common.c | 387 +++++++++--------- src/pcm/pcm_plug.c | 874 +++++++++++++++++----------------------- src/pcm/plugin/adpcm.c | 9 +- src/pcm/plugin/alaw.c | 12 +- src/pcm/plugin/copy.c | 11 +- src/pcm/plugin/io.c | 137 ++++--- src/pcm/plugin/linear.c | 12 +- src/pcm/plugin/mmap.c | 105 +++-- src/pcm/plugin/mulaw.c | 12 +- src/pcm/plugin/rate.c | 9 +- src/pcm/plugin/route.c | 9 +- 11 files changed, 704 insertions(+), 873 deletions(-) diff --git a/src/pcm/pcm_common.c b/src/pcm/pcm_common.c index 01f7458f..cdf8d2ac 100644 --- a/src/pcm/pcm_common.c +++ b/src/pcm/pcm_common.c @@ -26,8 +26,10 @@ #ifdef __KERNEL__ #include "../../include/driver.h" #include "../../include/pcm.h" -#define snd_pcm_plug_first(handle, stream) ((handle)->runtime->oss.plugin_first) -#define snd_pcm_plug_last(handle, stream) ((handle)->runtime->oss.plugin_last) +#define snd_pcm_plug_first(plug) ((plug)->runtime->oss.plugin_first) +#define snd_pcm_plug_last(plug) ((plug)->runtime->oss.plugin_last) +#define vmalloc snd_vmalloc +#define vfree snd_vfree #else #include #include @@ -35,11 +37,15 @@ #include #include #include "pcm_local.h" +#define snd_pcm_plug_first(plug) ((plug)->first) +#define snd_pcm_plug_last(plug) ((plug)->last) +#define vmalloc malloc +#define vfree free #endif static int snd_pcm_plugin_src_channels_mask(snd_pcm_plugin_t *plugin, - bitset_t *dst_vmask, - bitset_t **src_vmask) + bitset_t *dst_vmask, + bitset_t **src_vmask) { bitset_t *vmask = plugin->src_vmask; bitset_copy(vmask, dst_vmask, plugin->src_format.channels); @@ -48,8 +54,8 @@ static int snd_pcm_plugin_src_channels_mask(snd_pcm_plugin_t *plugin, } static int snd_pcm_plugin_dst_channels_mask(snd_pcm_plugin_t *plugin, - bitset_t *src_vmask, - bitset_t **dst_vmask) + bitset_t *src_vmask, + bitset_t **dst_vmask) { bitset_t *vmask = plugin->dst_vmask; bitset_copy(vmask, src_vmask, plugin->dst_format.channels); @@ -57,71 +63,97 @@ static int snd_pcm_plugin_dst_channels_mask(snd_pcm_plugin_t *plugin, return 0; } -static ssize_t snd_pcm_plugin_side_channels(snd_pcm_plugin_t *plugin, - int client_side, - size_t frames, - snd_pcm_plugin_channel_t **channels) +static int snd_pcm_plugin_alloc(snd_pcm_plugin_t *plugin, size_t frames) { - char *ptr; - int width; - unsigned int channel; - long size; - snd_pcm_plugin_channel_t *v; snd_pcm_format_t *format; - if ((plugin->stream == SND_PCM_STREAM_PLAYBACK && client_side) || - (plugin->stream == SND_PCM_STREAM_CAPTURE && !client_side)) { + ssize_t width; + size_t size; + unsigned int channel; + snd_pcm_plugin_channel_t *c; + if (plugin->stream == SND_PCM_STREAM_PLAYBACK) format = &plugin->src_format; - v = plugin->src_channels; - } else { + else format = &plugin->dst_format; - v = plugin->dst_channels; - } - - *channels = v; if ((width = snd_pcm_format_physical_width(format->format)) < 0) - return width; + return width; size = frames * format->channels * width; assert(size % 8 == 0); size /= 8; - ptr = (char *)snd_pcm_plug_buf_alloc(plugin->handle, plugin->stream, size); - if (ptr == NULL) + if (plugin->buf_frames < frames) { + if (plugin->buf) + vfree(plugin->buf); + plugin->buf = vmalloc(size); + plugin->buf_frames = frames; + } + if (!plugin->buf) return -ENOMEM; - assert(size % format->channels == 0); - size /= format->channels; - for (channel = 0; channel < format->channels; channel++, v++) { - v->enabled = 1; - v->wanted = 0; - v->aptr = ptr; - if (format->interleave) { - v->area.addr = ptr; - v->area.first = channel * width; - v->area.step = format->channels * width; - } else { - v->area.addr = ptr + (channel * size); - v->area.first = 0; - v->area.step = width; + c = plugin->buf_channels; + if (format->interleave) { + for (channel = 0; channel < format->channels; channel++, c++) { + c->enabled = 1; + c->wanted = 0; + c->area.addr = plugin->buf; + c->area.first = channel * width; + c->area.step = format->channels * width; + } + } else { + assert(size % format->channels == 0); + size /= format->channels; + for (channel = 0; channel < format->channels; channel++, c++) { + c->enabled = 1; + c->wanted = 0; + c->area.addr = plugin->buf + (channel * size); + c->area.first = 0; + c->area.step = width; } } - return frames; + return 0; } -ssize_t snd_pcm_plugin_client_channels(snd_pcm_plugin_t *plugin, - size_t frames, - snd_pcm_plugin_channel_t **channels) +int snd_pcm_plug_alloc(snd_pcm_plug_t *plug, size_t frames) { - return snd_pcm_plugin_side_channels(plugin, 1, frames, channels); + int err; +#ifndef __KERNEL__ + plug->frames_alloc = frames; +#endif + assert(snd_pcm_plug_first(plug)); + if (snd_pcm_plug_stream(plug) == SND_PCM_STREAM_PLAYBACK) { + snd_pcm_plugin_t *plugin = snd_pcm_plug_first(plug); + while (plugin->next) { + if (plugin->dst_frames) + frames = plugin->dst_frames(plugin, frames); + assert(frames > 0); + plugin = plugin->next; + err = snd_pcm_plugin_alloc(plugin, frames); + if (err < 0) + return err; + } + } else { + snd_pcm_plugin_t *plugin = snd_pcm_plug_last(plug); + while (plugin->prev) { + if (plugin->dst_frames) + frames = plugin->dst_frames(plugin, frames); + assert(frames > 0); + plugin = plugin->prev; + err = snd_pcm_plugin_alloc(plugin, frames); + if (err < 0) + return err; + } + } + return 0; } -ssize_t snd_pcm_plugin_slave_channels(snd_pcm_plugin_t *plugin, - size_t frames, - snd_pcm_plugin_channel_t **channels) + +ssize_t snd_pcm_plugin_client_channels(snd_pcm_plugin_t *plugin, + size_t frames, + snd_pcm_plugin_channel_t **channels) { - return snd_pcm_plugin_side_channels(plugin, 0, frames, channels); + assert(frames <= plugin->buf_frames); + *channels = plugin->buf_channels; + return frames; } - -int snd_pcm_plugin_build(snd_pcm_plugin_handle_t *handle, - int stream, +int snd_pcm_plugin_build(snd_pcm_plug_t *plug, const char *name, snd_pcm_format_t *src_format, snd_pcm_format_t *dst_format, @@ -129,44 +161,40 @@ int snd_pcm_plugin_build(snd_pcm_plugin_handle_t *handle, snd_pcm_plugin_t **ret) { snd_pcm_plugin_t *plugin; + size_t channels; - assert(handle); - assert(stream >= 0 && stream <= 1); + assert(plug); assert(src_format && dst_format); plugin = (snd_pcm_plugin_t *)calloc(1, sizeof(*plugin) + extra); if (plugin == NULL) return -ENOMEM; plugin->name = name ? strdup(name) : NULL; - plugin->handle = handle; - plugin->stream = stream; + plugin->plug = plug; + plugin->stream = snd_pcm_plug_stream(plug); plugin->src_format = *src_format; plugin->src_width = snd_pcm_format_physical_width(src_format->format); assert(plugin->src_width > 0); plugin->dst_format = *dst_format; plugin->dst_width = snd_pcm_format_physical_width(dst_format->format); assert(plugin->dst_width > 0); - plugin->src_channels = calloc(src_format->channels, sizeof(snd_pcm_plugin_channel_t)); - if (plugin->src_channels == NULL) { - free(plugin); - return -ENOMEM; - } - plugin->dst_channels = calloc(dst_format->channels, sizeof(snd_pcm_plugin_channel_t)); - if (plugin->dst_channels == NULL) { - free(plugin->src_channels); + if (plugin->stream == SND_PCM_STREAM_PLAYBACK) + channels = src_format->channels; + else + channels = dst_format->channels; + plugin->buf_channels = calloc(channels, sizeof(*plugin->buf_channels)); + if (plugin->buf_channels == NULL) { free(plugin); return -ENOMEM; } plugin->src_vmask = bitset_alloc(src_format->channels); if (plugin->src_vmask == NULL) { - free(plugin->src_channels); - free(plugin->dst_channels); + free(plugin->buf_channels); free(plugin); return -ENOMEM; } plugin->dst_vmask = bitset_alloc(dst_format->channels); if (plugin->dst_vmask == NULL) { - free(plugin->src_channels); - free(plugin->dst_channels); + free(plugin->buf_channels); free(plugin->src_vmask); free(plugin); return -ENOMEM; @@ -180,29 +208,30 @@ int snd_pcm_plugin_build(snd_pcm_plugin_handle_t *handle, int snd_pcm_plugin_free(snd_pcm_plugin_t *plugin) { - if (plugin) { - if (plugin->private_free) - plugin->private_free(plugin, plugin->private_data); - if (plugin->name) - free(plugin->name); - free(plugin->src_channels); - free(plugin->dst_channels); - free(plugin->src_vmask); - free(plugin->dst_vmask); - free(plugin); - } + assert(plugin); + if (plugin->private_free) + plugin->private_free(plugin, plugin->private_data); + if (plugin->name) + free(plugin->name); + free(plugin->buf_channels); + if (plugin->buf) + vfree(plugin->buf); + free(plugin->src_vmask); + free(plugin->dst_vmask); + free(plugin); return 0; } -ssize_t snd_pcm_plug_client_size(snd_pcm_plugin_handle_t *handle, int stream, size_t drv_frames) +ssize_t snd_pcm_plug_client_size(snd_pcm_plug_t *plug, size_t drv_frames) { snd_pcm_plugin_t *plugin, *plugin_prev, *plugin_next; - - assert(handle); + int stream = snd_pcm_plug_stream(plug); + + assert(plug); if (drv_frames == 0) return 0; if (stream == SND_PCM_STREAM_PLAYBACK) { - plugin = snd_pcm_plug_last(handle, SND_PCM_STREAM_PLAYBACK); + plugin = snd_pcm_plug_last(plug); while (plugin && drv_frames > 0) { plugin_prev = plugin->prev; if (plugin->src_frames) @@ -210,7 +239,7 @@ ssize_t snd_pcm_plug_client_size(snd_pcm_plugin_handle_t *handle, int stream, si plugin = plugin_prev; } } else if (stream == SND_PCM_STREAM_CAPTURE) { - plugin = snd_pcm_plug_first(handle, SND_PCM_STREAM_CAPTURE); + plugin = snd_pcm_plug_first(plug); while (plugin && drv_frames > 0) { plugin_next = plugin->next; if (plugin->dst_frames) @@ -222,17 +251,18 @@ ssize_t snd_pcm_plug_client_size(snd_pcm_plugin_handle_t *handle, int stream, si return drv_frames; } -ssize_t snd_pcm_plug_slave_size(snd_pcm_plugin_handle_t *handle, int stream, size_t clt_frames) +ssize_t snd_pcm_plug_slave_size(snd_pcm_plug_t *plug, size_t clt_frames) { snd_pcm_plugin_t *plugin, *plugin_prev, *plugin_next; ssize_t frames; + int stream = snd_pcm_plug_stream(plug); - assert(handle); + assert(plug); if (clt_frames == 0) return 0; frames = clt_frames; if (stream == SND_PCM_STREAM_PLAYBACK) { - plugin = snd_pcm_plug_first(handle, SND_PCM_STREAM_PLAYBACK); + plugin = snd_pcm_plug_first(plug); while (plugin && frames > 0) { plugin_next = plugin->next; if (plugin->dst_frames) { @@ -243,7 +273,7 @@ ssize_t snd_pcm_plug_slave_size(snd_pcm_plugin_handle_t *handle, int stream, siz plugin = plugin_next; } } else if (stream == SND_PCM_STREAM_CAPTURE) { - plugin = snd_pcm_plug_last(handle, SND_PCM_STREAM_CAPTURE); + plugin = snd_pcm_plug_last(plug); while (plugin) { plugin_prev = plugin->prev; if (plugin->src_frames) { @@ -294,9 +324,9 @@ static int preferred_formats[] = { SND_PCM_SFMT_U8 }; -int snd_pcm_plug_slave_params(snd_pcm_stream_params_t *params, - snd_pcm_stream_info_t *slave_info, - snd_pcm_stream_params_t *slave_params) +int snd_pcm_plug_slave_params(snd_pcm_params_t *params, + snd_pcm_info_t *slave_info, + snd_pcm_params_t *slave_params) { *slave_params = *params; if ((slave_info->formats & (1 << params->format.format)) == 0) { @@ -373,24 +403,24 @@ int snd_pcm_plug_slave_params(snd_pcm_stream_params_t *params, } /* interleave */ - if (!(slave_info->flags & SND_PCM_STREAM_INFO_INTERLEAVE)) + if (!(slave_info->flags & SND_PCM_INFO_INTERLEAVE)) slave_params->format.interleave = 0; - if (!(slave_info->flags & SND_PCM_STREAM_INFO_NONINTERLEAVE)) + if (!(slave_info->flags & SND_PCM_INFO_NONINTERLEAVE)) slave_params->format.interleave = 1; return 0; } -int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle, - snd_pcm_stream_params_t *params, - snd_pcm_stream_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_stream_params_t tmpparams; - snd_pcm_stream_params_t dstparams; - snd_pcm_stream_params_t *srcparams; + snd_pcm_params_t tmpparams; + snd_pcm_params_t dstparams; + snd_pcm_params_t *srcparams; snd_pcm_plugin_t *plugin; int err; - switch (params->stream) { + switch (snd_pcm_plug_stream(plug)) { case SND_PCM_STREAM_PLAYBACK: dstparams = *slave_params; srcparams = slave_params; @@ -433,23 +463,20 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle, tmpparams.format.interleave = dstparams.format.interleave; switch (srcparams->format.format) { case SND_PCM_SFMT_MU_LAW: - err = snd_pcm_plugin_build_mulaw(handle, - params->stream, + err = snd_pcm_plugin_build_mulaw(plug, &srcparams->format, &tmpparams.format, &plugin); break; #ifndef __KERNEL__ case SND_PCM_SFMT_A_LAW: - err = snd_pcm_plugin_build_alaw(handle, - params->stream, + err = snd_pcm_plugin_build_alaw(plug, &srcparams->format, &tmpparams.format, &plugin); break; case SND_PCM_SFMT_IMA_ADPCM: - err = snd_pcm_plugin_build_adpcm(handle, - params->stream, + err = snd_pcm_plugin_build_adpcm(plug, &srcparams->format, &tmpparams.format, &plugin); @@ -490,8 +517,7 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle, if (srcparams->format.rate == dstparams.format.rate && snd_pcm_format_linear(dstparams.format.format)) tmpparams.format.format = dstparams.format.format; - err = snd_pcm_plugin_build_route(handle, - params->stream, + err = snd_pcm_plugin_build_route(plug, &srcparams->format, &tmpparams.format, ttable, @@ -517,8 +543,7 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle, if (srcparams->format.channels == dstparams.format.channels && snd_pcm_format_linear(dstparams.format.format)) tmpparams.format.format = dstparams.format.format; - err = snd_pcm_plugin_build_rate(handle, - params->stream, + err = snd_pcm_plugin_build_rate(plug, &srcparams->format, &tmpparams.format, &plugin); @@ -562,8 +587,7 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle, tmpparams.format.interleave = dstparams.format.interleave; if (snd_pcm_format_linear(dstparams.format.format)) tmpparams.format.format = dstparams.format.format; - err = snd_pcm_plugin_build_route(handle, - params->stream, + err = snd_pcm_plugin_build_route(plug, &srcparams->format, &tmpparams.format, ttable, @@ -587,23 +611,20 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle, tmpparams.format.format = dstparams.format.format; tmpparams.format.interleave = dstparams.format.interleave; if (tmpparams.format.format == SND_PCM_SFMT_MU_LAW) { - err = snd_pcm_plugin_build_mulaw(handle, - params->stream, + err = snd_pcm_plugin_build_mulaw(plug, &srcparams->format, &tmpparams.format, &plugin); } #ifndef __KERNEL__ else if (tmpparams.format.format == SND_PCM_SFMT_A_LAW) { - err = snd_pcm_plugin_build_alaw(handle, - params->stream, + err = snd_pcm_plugin_build_alaw(plug, &srcparams->format, &tmpparams.format, &plugin); } else if (tmpparams.format.format == SND_PCM_SFMT_IMA_ADPCM) { - err = snd_pcm_plugin_build_adpcm(handle, - params->stream, + err = snd_pcm_plugin_build_adpcm(plug, &srcparams->format, &tmpparams.format, &plugin); @@ -611,8 +632,7 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle, #endif else if (snd_pcm_format_linear(srcparams->format.format) && snd_pcm_format_linear(tmpparams.format.format)) { - err = snd_pcm_plugin_build_linear(handle, - params->stream, + err = snd_pcm_plugin_build_linear(plug, &srcparams->format, &tmpparams.format, &plugin); @@ -633,8 +653,7 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle, /* interleave */ if (srcparams->format.interleave != dstparams.format.interleave) { tmpparams.format.interleave = dstparams.format.interleave; - err = snd_pcm_plugin_build_copy(handle, - params->stream, + err = snd_pcm_plugin_build_copy(plug, &srcparams->format, &tmpparams.format, &plugin); @@ -652,8 +671,7 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle, return 0; } -ssize_t snd_pcm_plug_client_channels_buf(snd_pcm_plugin_handle_t *handle, - int stream, +ssize_t snd_pcm_plug_client_channels_buf(snd_pcm_plug_t *plug, char *buf, size_t count, snd_pcm_plugin_channel_t **channels) @@ -662,18 +680,18 @@ ssize_t snd_pcm_plug_client_channels_buf(snd_pcm_plugin_handle_t *handle, snd_pcm_plugin_channel_t *v; snd_pcm_format_t *format; int width, nchannels, channel; + int stream = snd_pcm_plug_stream(plug); assert(buf); if (stream == SND_PCM_STREAM_PLAYBACK) { - plugin = snd_pcm_plug_first(handle, stream); + plugin = snd_pcm_plug_first(plug); format = &plugin->src_format; - v = plugin->src_channels; } else { - plugin = snd_pcm_plug_last(handle, stream); + plugin = snd_pcm_plug_last(plug); format = &plugin->dst_format; - v = plugin->dst_channels; } + v = plugin->buf_channels; *channels = v; if ((width = snd_pcm_format_physical_width(format->format)) < 0) return width; @@ -682,7 +700,6 @@ ssize_t snd_pcm_plug_client_channels_buf(snd_pcm_plugin_handle_t *handle, for (channel = 0; channel < nchannels; channel++, v++) { v->enabled = 1; v->wanted = (stream == SND_PCM_STREAM_CAPTURE); - v->aptr = NULL; v->area.addr = buf; v->area.first = channel * width; v->area.step = nchannels * width; @@ -690,8 +707,7 @@ ssize_t snd_pcm_plug_client_channels_buf(snd_pcm_plugin_handle_t *handle, return count; } -ssize_t snd_pcm_plug_client_channels_iovec(snd_pcm_plugin_handle_t *handle, - int stream, +ssize_t snd_pcm_plug_client_channels_iovec(snd_pcm_plug_t *plug, const struct iovec *vector, unsigned long count, snd_pcm_plugin_channel_t **channels) @@ -701,17 +717,17 @@ ssize_t snd_pcm_plug_client_channels_iovec(snd_pcm_plugin_handle_t *handle, snd_pcm_format_t *format; int width; unsigned int nchannels, channel; + int stream = snd_pcm_plug_stream(plug); if (stream == SND_PCM_STREAM_PLAYBACK) { - plugin = snd_pcm_plug_first(handle, stream); + plugin = snd_pcm_plug_first(plug); format = &plugin->src_format; - v = plugin->src_channels; } else { - plugin = snd_pcm_plug_last(handle, stream); + plugin = snd_pcm_plug_last(plug); format = &plugin->dst_format; - v = plugin->dst_channels; } + v = plugin->buf_channels; *channels = v; if ((width = snd_pcm_format_physical_width(format->format)) < 0) return width; @@ -722,7 +738,6 @@ ssize_t snd_pcm_plug_client_channels_iovec(snd_pcm_plugin_handle_t *handle, for (channel = 0; channel < nchannels; channel++, v++) { v->enabled = 1; v->wanted = (stream == SND_PCM_STREAM_CAPTURE); - v->aptr = NULL; v->area.addr = vector->iov_base; v->area.first = channel * width; v->area.step = nchannels * width; @@ -736,7 +751,6 @@ ssize_t snd_pcm_plug_client_channels_iovec(snd_pcm_plugin_handle_t *handle, assert(vector->iov_len == len); v->enabled = (vector->iov_base != NULL); v->wanted = (v->enabled && (stream == SND_PCM_STREAM_CAPTURE)); - v->aptr = NULL; v->area.addr = vector->iov_base; v->area.first = 0; v->area.step = width; @@ -745,16 +759,13 @@ ssize_t snd_pcm_plug_client_channels_iovec(snd_pcm_plugin_handle_t *handle, } } -int snd_pcm_plug_playback_channels_mask(snd_pcm_plugin_handle_t *handle, +int snd_pcm_plug_playback_channels_mask(snd_pcm_plug_t *plug, bitset_t *client_vmask) { -#ifndef __KERNEL__ - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &handle->private; -#endif - snd_pcm_plugin_t *plugin = snd_pcm_plug_last(handle, SND_PCM_STREAM_PLAYBACK); + snd_pcm_plugin_t *plugin = snd_pcm_plug_last(plug); if (plugin == NULL) { #ifndef __KERNEL__ - return snd_pcm_channels_mask(plug->slave, SND_PCM_STREAM_PLAYBACK, client_vmask); + return snd_pcm_channels_mask(plug->slave, client_vmask); #else return 0; #endif @@ -766,7 +777,7 @@ int snd_pcm_plug_playback_channels_mask(snd_pcm_plugin_handle_t *handle, int err; bitset_one(dstmask, schannels); #ifndef __KERNEL__ - err = snd_pcm_channels_mask(plug->slave, SND_PCM_STREAM_PLAYBACK, dstmask); + err = snd_pcm_channels_mask(plug->slave, dstmask); if (err < 0) return err; #endif @@ -788,16 +799,13 @@ int snd_pcm_plug_playback_channels_mask(snd_pcm_plugin_handle_t *handle, } } -int snd_pcm_plug_capture_channels_mask(snd_pcm_plugin_handle_t *handle, +int snd_pcm_plug_capture_channels_mask(snd_pcm_plug_t *plug, bitset_t *client_vmask) { -#ifndef __KERNEL__ - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &handle->private; -#endif - snd_pcm_plugin_t *plugin = snd_pcm_plug_first(handle, SND_PCM_STREAM_CAPTURE); + snd_pcm_plugin_t *plugin = snd_pcm_plug_first(plug); if (plugin == NULL) { #ifndef __KERNEL__ - return snd_pcm_channels_mask(plug->slave, SND_PCM_STREAM_CAPTURE, client_vmask); + return snd_pcm_channels_mask(plug->slave, client_vmask); #else return 0; #endif @@ -809,7 +817,7 @@ int snd_pcm_plug_capture_channels_mask(snd_pcm_plugin_handle_t *handle, int err; bitset_one(srcmask, schannels); #ifndef __KERNEL__ - err = snd_pcm_channels_mask(plug->slave, SND_PCM_STREAM_CAPTURE, srcmask); + err = snd_pcm_channels_mask(plug->slave, srcmask); if (err < 0) return err; #endif @@ -827,10 +835,10 @@ int snd_pcm_plug_capture_channels_mask(snd_pcm_plugin_handle_t *handle, } } -static int snd_pcm_plug_playback_disable_useless_channels(snd_pcm_plugin_handle_t *handle, +static int snd_pcm_plug_playback_disable_useless_channels(snd_pcm_plug_t *plug, snd_pcm_plugin_channel_t *src_channels) { - snd_pcm_plugin_t *plugin = snd_pcm_plug_first(handle, SND_PCM_STREAM_PLAYBACK); + snd_pcm_plugin_t *plugin = snd_pcm_plug_first(plug); unsigned int nchannels = plugin->src_format.channels; bitset_t bs[bitset_size(nchannels)]; bitset_t *srcmask = bs; @@ -842,7 +850,7 @@ static int snd_pcm_plug_playback_disable_useless_channels(snd_pcm_plugin_handle_ else bitset_reset(srcmask, channel); } - err = snd_pcm_plug_playback_channels_mask(handle, srcmask); + err = snd_pcm_plug_playback_channels_mask(plug, srcmask); if (err < 0) return err; for (channel = 0; channel < nchannels; channel++) { @@ -852,14 +860,11 @@ static int snd_pcm_plug_playback_disable_useless_channels(snd_pcm_plugin_handle_ return 0; } -static int snd_pcm_plug_capture_disable_useless_channels(snd_pcm_plugin_handle_t *handle, +static int snd_pcm_plug_capture_disable_useless_channels(snd_pcm_plug_t *plug, snd_pcm_plugin_channel_t *src_channels, snd_pcm_plugin_channel_t *client_channels) { -#ifndef __KERNEL__ - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &handle->private; -#endif - snd_pcm_plugin_t *plugin = snd_pcm_plug_last(handle, SND_PCM_STREAM_CAPTURE); + snd_pcm_plugin_t *plugin = snd_pcm_plug_last(plug); unsigned int nchannels = plugin->dst_format.channels; bitset_t bs[bitset_size(nchannels)]; bitset_t *dstmask = bs; @@ -880,11 +885,11 @@ static int snd_pcm_plug_capture_disable_useless_channels(snd_pcm_plugin_handle_t plugin = plugin->prev; } #ifndef __KERNEL__ - err = snd_pcm_channels_mask(plug->slave, SND_PCM_STREAM_CAPTURE, dstmask); + err = snd_pcm_channels_mask(plug->slave, dstmask); if (err < 0) return err; #endif - plugin = snd_pcm_plug_first(handle, SND_PCM_STREAM_CAPTURE); + plugin = snd_pcm_plug_first(plug); nchannels = plugin->src_format.channels; for (channel = 0; channel < nchannels; channel++) { if (!bitset_get(dstmask, channel)) @@ -893,24 +898,23 @@ static int snd_pcm_plug_capture_disable_useless_channels(snd_pcm_plugin_handle_t return 0; } -ssize_t snd_pcm_plug_write_transfer(snd_pcm_plugin_handle_t *handle, 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) { snd_pcm_plugin_t *plugin, *next; snd_pcm_plugin_channel_t *dst_channels; int err; ssize_t frames = size; - if ((err = snd_pcm_plug_playback_disable_useless_channels(handle, src_channels)) < 0) + if ((err = snd_pcm_plug_playback_disable_useless_channels(plug, src_channels)) < 0) return err; - plugin = snd_pcm_plug_first(handle, SND_PCM_STREAM_PLAYBACK); + plugin = snd_pcm_plug_first(plug); while (plugin && frames > 0) { if ((next = plugin->next) != NULL) { ssize_t frames1 = frames; if (plugin->dst_frames) frames1 = plugin->dst_frames(plugin, frames); if ((err = next->client_channels(next, frames1, &dst_channels)) < 0) { - snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_PLAYBACK, src_channels->aptr); return err; } if (err != frames1) { @@ -918,76 +922,49 @@ ssize_t snd_pcm_plug_write_transfer(snd_pcm_plugin_handle_t *handle, snd_pcm_plu if (plugin->src_frames) frames = plugin->src_frames(plugin, frames1); } - } else { - if ((err = snd_pcm_plugin_slave_channels(plugin, frames, &dst_channels)) < 0) - return err; - } + } else + dst_channels = 0; pdprintf("write plugin: %s, %i\n", plugin->name, frames); - if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0) { - snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_PLAYBACK, src_channels->aptr); - snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_PLAYBACK, dst_channels->aptr); + if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0) return frames; - } - snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_PLAYBACK, src_channels->aptr); src_channels = dst_channels; plugin = next; } - snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_PLAYBACK, src_channels->aptr); - return snd_pcm_plug_client_size(handle, SND_PCM_STREAM_PLAYBACK, frames); + return snd_pcm_plug_client_size(plug, frames); } -ssize_t snd_pcm_plug_read_transfer(snd_pcm_plugin_handle_t *handle, 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) { snd_pcm_plugin_t *plugin, *next; snd_pcm_plugin_channel_t *src_channels, *dst_channels; ssize_t frames = size; int err; - plugin = snd_pcm_plug_last(handle, SND_PCM_STREAM_CAPTURE); - frames = snd_pcm_plug_slave_size(handle, SND_PCM_STREAM_CAPTURE, frames); + frames = snd_pcm_plug_slave_size(plug, frames); if (frames < 0) return frames; - plugin = snd_pcm_plug_first(handle, SND_PCM_STREAM_CAPTURE); - if ((err = snd_pcm_plugin_slave_channels(plugin, frames, &src_channels)) < 0) - return err; - if ((err = snd_pcm_plug_capture_disable_useless_channels(handle, src_channels, dst_channels_final) < 0)) - return err; - + src_channels = 0; + plugin = snd_pcm_plug_first(plug); while (plugin && frames > 0) { if ((next = plugin->next) != NULL) { if ((err = plugin->client_channels(plugin, frames, &dst_channels)) < 0) { - snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_CAPTURE, src_channels->aptr); return err; } frames = err; + if (!plugin->prev) { + if ((err = snd_pcm_plug_capture_disable_useless_channels(plug, dst_channels, dst_channels_final) < 0)) + return err; + } } else { dst_channels = dst_channels_final; } pdprintf("read plugin: %s, %i\n", plugin->name, frames); - if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0) { - snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_CAPTURE, src_channels->aptr); - snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_CAPTURE, dst_channels->aptr); + if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0) return frames; - } -#if 0 - { - unsigned int channel; - for (channel = 0; channel < plugin->src_format.channels; ++channel) { - fprintf(stderr, "%d%d ", src_channels[channel].enabled, src_channels[channel].wanted); - } - fprintf(stderr, " -> "); - for (channel = 0; channel < plugin->dst_format.channels; ++channel) { - fprintf(stderr, "%d%d ", dst_channels[channel].enabled, dst_channels[channel].wanted); - } - fprintf(stderr, "\n"); - } -#endif - snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_CAPTURE, src_channels->aptr); plugin = next; src_channels = dst_channels; } - snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_CAPTURE, src_channels->aptr); return frames; } diff --git a/src/pcm/pcm_plug.c b/src/pcm/pcm_plug.c index 8cc74651..d4e9a4fa 100644 --- a/src/pcm/pcm_plug.c +++ b/src/pcm/pcm_plug.c @@ -28,76 +28,21 @@ #include #include "pcm_local.h" -/* snd_pcm_plug helpers */ - -void *snd_pcm_plug_buf_alloc(snd_pcm_t *pcm, int stream, size_t size) -{ - int idx; - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; - snd_pcm_plug_stream_t *plugstr = &plug->stream[stream]; - - for (idx = 0; idx < 2; idx++) { - if (plugstr->alloc_lock[idx]) - continue; - if (plugstr->alloc_size[idx] >= size) { - plugstr->alloc_lock[idx] = 1; - return plugstr->alloc_ptr[idx]; - } - } - for (idx = 0; idx < 2; idx++) { - if (plugstr->alloc_lock[idx]) - continue; - if (plugstr->alloc_ptr[idx] != NULL) - free(plugstr->alloc_ptr[idx]); - plugstr->alloc_ptr[idx] = malloc(size); - if (plugstr->alloc_ptr[idx] == NULL) - return NULL; - plugstr->alloc_size[idx] = size; - plugstr->alloc_lock[idx] = 1; - return plugstr->alloc_ptr[idx]; - } - return NULL; -} - -void snd_pcm_plug_buf_unlock(snd_pcm_t *pcm, int stream, void *ptr) -{ - int idx; - - snd_pcm_plug_t *plug; - snd_pcm_plug_stream_t *plugstr; - - if (!ptr) - return; - plug = (snd_pcm_plug_t*) &pcm->private; - plugstr = &plug->stream[stream]; - - for (idx = 0; idx < 2; idx++) { - if (plugstr->alloc_ptr[idx] == ptr) { - plugstr->alloc_lock[idx] = 0; - return; - } - } -} - /* snd_pcm_plugin externs */ int snd_pcm_plugin_insert(snd_pcm_plugin_t *plugin) { snd_pcm_plug_t *plug; - snd_pcm_plug_stream_t *plugstr; - snd_pcm_t *pcm; assert(plugin); - pcm = plugin->handle; - plug = (snd_pcm_plug_t*) &pcm->private; - plugstr = &plug->stream[plugin->stream]; - plugin->next = plugstr->first; + plug = plugin->plug; + plugin->next = plug->first; plugin->prev = NULL; - if (plugstr->first) { - plugstr->first->prev = plugin; - plugstr->first = plugin; + if (plug->first) { + plug->first->prev = plugin; + plug->first = plugin; } else { - plugstr->last = - plugstr->first = plugin; + plug->last = + plug->first = plugin; } return 0; } @@ -105,181 +50,78 @@ int snd_pcm_plugin_insert(snd_pcm_plugin_t *plugin) int snd_pcm_plugin_append(snd_pcm_plugin_t *plugin) { snd_pcm_plug_t *plug; - snd_pcm_plug_stream_t *plugstr; - snd_pcm_t *pcm; assert(plugin); - pcm = plugin->handle; - plug = (snd_pcm_plug_t*) &pcm->private; - plugstr = &plug->stream[plugin->stream]; - + plug = plugin->plug; plugin->next = NULL; - plugin->prev = plugstr->last; - if (plugstr->last) { - plugstr->last->next = plugin; - plugstr->last = plugin; + plugin->prev = plug->last; + if (plug->last) { + plug->last->next = plugin; + plug->last = plugin; } else { - plugstr->last = - plugstr->first = plugin; + plug->last = + plug->first = plugin; } return 0; } -#if 0 -int snd_pcm_plugin_remove_to(snd_pcm_plugin_t *plugin) -{ - snd_pcm_plugin_t *plugin1, *plugin1_prev; - snd_pcm_plug_t *plug; - snd_pcm_t *pcm; - snd_pcm_plug_stream_t *plugstr; - assert(plugin); - pcm = plugin->handle; - - plug = (snd_pcm_plug_t*) &pcm->private; - plugstr = &plug->stream[plugin->stream]; - - plugin1 = plugin; - while (plugin1->prev) - plugin1 = plugin1->prev; - if (plugstr->first != plugin1) - return -EINVAL; - plugstr->first = plugin; - plugin1 = plugin->prev; - plugin->prev = NULL; - while (plugin1) { - plugin1_prev = plugin1->prev; - snd_pcm_plugin_free(plugin1); - plugin1 = plugin1_prev; - } - return 0; -} - -int snd_pcm_plug_remove_first(snd_pcm_t *pcm, int stream) -{ - snd_pcm_plugin_t *plugin; - snd_pcm_plug_t *plug; - snd_pcm_plug_stream_t *plugstr; - assert(pcm); - assert(stream >= 0 && stream <= 1); - assert(pcm->stream[stream].open); - - plug = (snd_pcm_plug_t*) &pcm->private; - plugstr = &plug->stream[stream]; - - plugin = plugstr->first; - if (plugin->next) { - plugin = plugin->next; - } else { - return snd_pcm_plug_clear(pcm, stream); - } - return snd_pcm_plugin_remove_to(plugin); -} -#endif - /* snd_pcm_plug externs */ -int snd_pcm_plug_clear(snd_pcm_t *pcm, int stream) +int snd_pcm_plug_clear(snd_pcm_plug_t *plug) { snd_pcm_plugin_t *plugin, *plugin_next; - snd_pcm_plug_t *plug; - snd_pcm_plug_stream_t *plugstr; - int idx; - assert(pcm); - assert(stream >= 0 && stream <= 1); - assert(pcm->stream[stream].open); - - plug = (snd_pcm_plug_t*) &pcm->private; - plugstr = &plug->stream[stream]; - plugin = plugstr->first; - plugstr->first = NULL; - plugstr->last = NULL; + assert(plug); + + plugin = plug->first; + plug->first = NULL; + plug->last = NULL; while (plugin) { plugin_next = plugin->next; snd_pcm_plugin_free(plugin); plugin = plugin_next; } - for (idx = 0; idx < 2; idx++) { - if (plugstr->alloc_ptr[idx]) { - free(plugstr->alloc_ptr[idx]); - plugstr->alloc_ptr[idx] = 0; - } - plugstr->alloc_size[idx] = 0; - plugstr->alloc_lock[idx] = 0; - } return 0; } -snd_pcm_plugin_t *snd_pcm_plug_first(snd_pcm_t *pcm, int stream) +snd_pcm_plugin_t *snd_pcm_plug_first(snd_pcm_plug_t *plug) { - snd_pcm_plug_t *plug; - snd_pcm_plug_stream_t *plugstr; - if (!pcm) - return NULL; - if (stream < 0 || stream > 1) - return NULL; - if (!pcm->stream[stream].open) - return NULL; - - plug = (snd_pcm_plug_t*) &pcm->private; - plugstr = &plug->stream[stream]; - - return plugstr->first; + assert(plug); + return plug->first; } -snd_pcm_plugin_t *snd_pcm_plug_last(snd_pcm_t *pcm, int stream) +snd_pcm_plugin_t *snd_pcm_plug_last(snd_pcm_plug_t *plug) { - snd_pcm_plug_t *plug; - snd_pcm_plug_stream_t *plugstr; - if (!pcm) - return NULL; - if (stream < 0 || stream > 1) - return NULL; - if (!pcm->stream[stream].open) - return NULL; - - plug = (snd_pcm_plug_t*) &pcm->private; - plugstr = &plug->stream[stream]; - - return plugstr->last; -} - -int snd_pcm_plug_direct(snd_pcm_t *pcm, int stream) -{ - return snd_pcm_plug_first(pcm, stream) == NULL; + assert(plug); + return plug->last; } /* * */ -static int snd_pcm_plug_stream_close(snd_pcm_t *pcm, int stream) +static int snd_pcm_plug_close(void *private) { - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; - snd_pcm_plug_clear(pcm, stream); + snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private; + snd_pcm_plug_clear(plug); + free(plug->handle->ops); if (plug->close_slave) - return snd_pcm_stream_close(plug->slave, stream); + return snd_pcm_close(plug->slave); + free(private); return 0; } -static int snd_pcm_plug_stream_nonblock(snd_pcm_t *pcm, int stream, int nonblock) -{ - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; - return snd_pcm_stream_nonblock(plug->slave, stream, nonblock); -} - -static int snd_pcm_plug_info(snd_pcm_t *pcm, int stream UNUSED, snd_pcm_info_t * info) +static int snd_pcm_plug_nonblock(void *private, int nonblock) { - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; - return snd_pcm_info(plug->slave, info); + snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private; + return snd_pcm_nonblock(plug->slave, nonblock); } -static int snd_pcm_plug_stream_info(snd_pcm_t *pcm, snd_pcm_stream_info_t *info) +static int snd_pcm_plug_info(void *private, snd_pcm_info_t *info) { int err; - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; - snd_pcm_stream_t *str; + snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private; - if ((err = snd_pcm_stream_info(plug->slave, info)) < 0) + if ((err = snd_pcm_info(plug->slave, info)) < 0) return err; info->formats = snd_pcm_plug_formats(info->formats); info->min_rate = 4000; @@ -287,37 +129,26 @@ static int snd_pcm_plug_stream_info(snd_pcm_t *pcm, snd_pcm_stream_info_t *info) info->min_channels = 1; info->max_channels = 32; info->rates = SND_PCM_RATE_CONTINUOUS | SND_PCM_RATE_8000_192000; - info->flags |= SND_PCM_STREAM_INFO_INTERLEAVE | SND_PCM_STREAM_INFO_NONINTERLEAVE; - - str = &pcm->stream[info->stream]; - if (pcm->stream[info->stream].valid_setup) { - info->buffer_size = snd_pcm_plug_client_size(pcm, info->stream, info->buffer_size); - info->min_fragment_size = snd_pcm_plug_client_size(pcm, info->stream, info->min_fragment_size); - info->max_fragment_size = snd_pcm_plug_client_size(pcm, info->stream, info->max_fragment_size); - info->fragment_align = snd_pcm_plug_client_size(pcm, info->stream, info->fragment_align); - info->fifo_size = snd_pcm_plug_client_size(pcm, info->stream, info->fifo_size); - info->transfer_block_size = snd_pcm_plug_client_size(pcm, info->stream, info->transfer_block_size); - if (str->setup.mode == SND_PCM_MODE_FRAGMENT) - info->mmap_size = str->setup.buffer_size; - else - info->mmap_size = snd_pcm_plug_client_size(pcm, info->stream, info->mmap_size); + info->flags |= SND_PCM_INFO_INTERLEAVE | SND_PCM_INFO_NONINTERLEAVE; + + if (plug->slave->valid_setup) { + info->buffer_size = snd_pcm_plug_client_size(plug, info->buffer_size); + info->min_fragment_size = snd_pcm_plug_client_size(plug, info->min_fragment_size); + info->max_fragment_size = snd_pcm_plug_client_size(plug, info->max_fragment_size); + info->fragment_align = snd_pcm_plug_client_size(plug, info->fragment_align); + info->fifo_size = snd_pcm_plug_client_size(plug, info->fifo_size); + info->transfer_block_size = snd_pcm_plug_client_size(plug, info->transfer_block_size); } - if (!snd_pcm_plug_direct(pcm, info->stream)) - info->flags &= ~(SND_PCM_STREAM_INFO_MMAP | SND_PCM_STREAM_INFO_MMAP_VALID); + info->mmap_size = 0; + info->flags &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID); return 0; } -static int snd_pcm_plug_action(snd_pcm_t *pcm, int stream, int action, +static int snd_pcm_plug_action(snd_pcm_plug_t *plug, int action, unsigned long data) { - snd_pcm_plugin_t *plugin; int err; - snd_pcm_plug_t *plug; - snd_pcm_plug_stream_t *plugstr; - plug = (snd_pcm_plug_t*) &pcm->private; - plugstr = &plug->stream[stream]; - - plugin = plugstr->first; + snd_pcm_plugin_t *plugin = plug->first; while (plugin) { if (plugin->action) { if ((err = plugin->action(plugin, action, data))<0) @@ -328,291 +159,204 @@ static int snd_pcm_plug_action(snd_pcm_t *pcm, int stream, int action, return 0; } -static int snd_pcm_plug_stream_params(snd_pcm_t *pcm, snd_pcm_stream_params_t *params) +static int snd_pcm_plug_setup(void *private, snd_pcm_setup_t *setup) { - snd_pcm_stream_params_t slave_params, params1; - snd_pcm_stream_info_t slave_info; - snd_pcm_plugin_t *plugin; - snd_pcm_plug_t *plug; int err; - int stream = params->stream; - - plug = (snd_pcm_plug_t*) &pcm->private; - - /* - * try to decide, if a conversion is required - */ + snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private; - memset(&slave_info, 0, sizeof(slave_info)); - slave_info.stream = stream; - if ((err = snd_pcm_stream_info(plug->slave, &slave_info)) < 0) { - snd_pcm_plug_clear(pcm, stream); - return err; - } - - if ((err = snd_pcm_plug_slave_params(params, &slave_info, &slave_params)) < 0) - return err; - - - snd_pcm_plug_clear(pcm, stream); - - /* add necessary plugins */ - params1 = *params; - if ((err = snd_pcm_plug_format(pcm, ¶ms1, &slave_params)) < 0) - return err; - - if (snd_pcm_plug_direct(pcm, stream)) - return snd_pcm_stream_params(plug->slave, params); - - /* compute right sizes */ - slave_params.frag_size = snd_pcm_plug_slave_size(pcm, stream, params1.frag_size); - slave_params.buffer_size = snd_pcm_plug_slave_size(pcm, stream, params1.buffer_size); - slave_params.frames_fill_max = snd_pcm_plug_slave_size(pcm, stream, params1.frames_fill_max); - slave_params.frames_min = snd_pcm_plug_slave_size(pcm, stream, params1.frames_min); - slave_params.frames_xrun_max = snd_pcm_plug_slave_size(pcm, stream, params1.frames_xrun_max); - slave_params.frames_align = snd_pcm_plug_slave_size(pcm, stream, params1.frames_align); - if (slave_params.frame_boundary == 0 || slave_params.frame_boundary > INT_MAX) - slave_params.frame_boundary = INT_MAX; - 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; - - /* - * I/O plugins - */ - - if (slave_info.flags & SND_PCM_STREAM_INFO_MMAP) { - pdprintf("params mmap plugin\n"); - err = snd_pcm_plugin_build_mmap(pcm, stream, plug->slave, &slave_params.format, &plugin); - } else { - pdprintf("params I/O plugin\n"); - err = snd_pcm_plugin_build_io(pcm, stream, plug->slave, &slave_params.format, &plugin); - } - if (err < 0) - return err; - if (stream == SND_PCM_STREAM_PLAYBACK) { - err = snd_pcm_plugin_append(plugin); - } else { - err = snd_pcm_plugin_insert(plugin); - } - if (err < 0) { - snd_pcm_plugin_free(plugin); - 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_stream_params(plug->slave, &slave_params); + err = snd_pcm_setup(plug->slave, setup); if (err < 0) return err; - - err = snd_pcm_plug_action(pcm, stream, INIT, 0); - if (err < 0) - return err; - return 0; -} - -static int snd_pcm_plug_stream_setup(snd_pcm_t *pcm, snd_pcm_stream_setup_t *setup) -{ - int err; - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; - snd_pcm_plug_stream_t *plugstr; - - err = snd_pcm_stream_setup(plug->slave, setup); - if (err < 0) - return err; - if (snd_pcm_plug_direct(pcm, setup->stream)) + if (!plug->first) return 0; setup->frame_boundary /= setup->frag_size; - setup->frag_size = snd_pcm_plug_client_size(pcm, setup->stream, setup->frag_size); + setup->frag_size = snd_pcm_plug_client_size(plug, setup->frag_size); setup->frame_boundary *= setup->frag_size; setup->buffer_size = setup->frags * setup->frag_size; - setup->frames_min = snd_pcm_plug_client_size(pcm, setup->stream, setup->frames_min); - setup->frames_align = snd_pcm_plug_client_size(pcm, setup->stream, setup->frames_align); - setup->frames_xrun_max = snd_pcm_plug_client_size(pcm, setup->stream, setup->frames_xrun_max); - setup->frames_fill_max = snd_pcm_plug_client_size(pcm, setup->stream, setup->frames_fill_max); - - plugstr = &plug->stream[setup->stream]; - if (setup->stream == SND_PCM_STREAM_PLAYBACK) - setup->format = plugstr->first->src_format; + setup->frames_min = snd_pcm_plug_client_size(plug, setup->frames_min); + setup->frames_align = snd_pcm_plug_client_size(plug, setup->frames_align); + setup->frames_xrun_max = snd_pcm_plug_client_size(plug, setup->frames_xrun_max); + setup->frames_fill_max = snd_pcm_plug_client_size(plug, setup->frames_fill_max); + + if (plug->handle->stream == SND_PCM_STREAM_PLAYBACK) + setup->format = plug->first->src_format; else - setup->format = plugstr->last->dst_format; + setup->format = plug->last->dst_format; + err = snd_pcm_plug_alloc(plug, setup->frag_size); + if (err < 0) + return err; return 0; } -static int snd_pcm_plug_stream_status(snd_pcm_t *pcm, snd_pcm_stream_status_t *status) +static int snd_pcm_plug_status(void *private, snd_pcm_status_t *status) { int err; - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; + snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private; - err = snd_pcm_stream_status(plug->slave, status); + err = snd_pcm_status(plug->slave, status); if (err < 0) return err; - if (snd_pcm_plug_direct(pcm, status->stream)) - return 0; - status->frame_io = snd_pcm_plug_client_size(pcm, status->stream, status->frame_io); - status->frame_data = snd_pcm_plug_client_size(pcm, status->stream, status->frame_data); - status->frames_avail = snd_pcm_plug_client_size(pcm, status->stream, status->frames_avail); - status->frames_avail_max = snd_pcm_plug_client_size(pcm, status->stream, status->frames_avail_max); + status->frame_io = snd_pcm_plug_client_size(plug, status->frame_io); + status->frame_data = snd_pcm_plug_client_size(plug, status->frame_data); + status->frames_avail = snd_pcm_plug_client_size(plug, status->frames_avail); + status->frames_avail_max = snd_pcm_plug_client_size(plug, status->frames_avail_max); return 0; } -static int snd_pcm_plug_stream_state(snd_pcm_t *pcm, int stream) +static int snd_pcm_plug_state(void *private) { - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; - return snd_pcm_stream_state(plug->slave, stream); + snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private; + return snd_pcm_state(plug->slave); } -static int snd_pcm_plug_stream_frame_io(snd_pcm_t *pcm, int stream, int update) +static int snd_pcm_plug_frame_io(void *private, int update) { - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; - return snd_pcm_stream_frame_io(plug->slave, stream, update); + snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private; + ssize_t frame_io = snd_pcm_frame_io(plug->slave, update); + if (frame_io < 0) + return frame_io; + return snd_pcm_plug_client_size(plug, frame_io); } -static int snd_pcm_plug_stream_prepare(snd_pcm_t *pcm, int stream) +static int snd_pcm_plug_prepare(void *private) { - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; + snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private; int err; - err = snd_pcm_stream_prepare(plug->slave, stream); + err = snd_pcm_prepare(plug->slave); if (err < 0) return err; - if (snd_pcm_plug_direct(pcm, stream)) - return 0; - if ((err = snd_pcm_plug_action(pcm, stream, PREPARE, 0))<0) + if ((err = snd_pcm_plug_action(plug, PREPARE, 0))<0) return err; return 0; } -static int snd_pcm_plug_stream_go(snd_pcm_t *pcm, int stream) +static int snd_pcm_plug_go(void *private) { - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; - return snd_pcm_stream_go(plug->slave, stream); + snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private; + return snd_pcm_go(plug->slave); } -static int snd_pcm_plug_sync_go(snd_pcm_t *pcm, int stream UNUSED, snd_pcm_sync_t *sync) +static int snd_pcm_plug_sync_go(void *private, snd_pcm_sync_t *sync) { - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; + snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private; return snd_pcm_sync_go(plug->slave, sync); } -static int snd_pcm_plug_stream_drain(snd_pcm_t *pcm, int stream) +static int snd_pcm_plug_drain(void *private) { - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; + snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private; int err; - if ((err = snd_pcm_stream_drain(plug->slave, stream)) < 0) + if ((err = snd_pcm_drain(plug->slave)) < 0) return err; - if (snd_pcm_plug_direct(pcm, stream)) - return 0; - if ((err = snd_pcm_plug_action(pcm, stream, DRAIN, 0))<0) + if ((err = snd_pcm_plug_action(plug, DRAIN, 0))<0) return err; return 0; } -static int snd_pcm_plug_stream_flush(snd_pcm_t *pcm, int stream) +static int snd_pcm_plug_flush(void *private) { - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; + snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private; int err; - if ((err = snd_pcm_stream_flush(plug->slave, stream)) < 0) + if ((err = snd_pcm_flush(plug->slave)) < 0) return err; - if (snd_pcm_plug_direct(pcm, stream)) - return 0; - if ((err = snd_pcm_plug_action(pcm, stream, FLUSH, 0))<0) + if ((err = snd_pcm_plug_action(plug, FLUSH, 0))<0) return err; return 0; } -static int snd_pcm_plug_stream_pause(snd_pcm_t *pcm, int stream, int enable) +static int snd_pcm_plug_pause(void *private, int enable) { - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; + snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private; int err; - if ((err = snd_pcm_stream_pause(plug->slave, stream, enable)) < 0) + if ((err = snd_pcm_pause(plug->slave, enable)) < 0) return err; - if ((err = snd_pcm_plug_action(pcm, stream, PAUSE, 0))<0) + if ((err = snd_pcm_plug_action(plug, PAUSE, 0))<0) return err; return 0; } -static int snd_pcm_plug_channel_setup(snd_pcm_t *pcm, int stream, snd_pcm_channel_setup_t *setup) +static int snd_pcm_plug_channel_setup(void *private UNUSED, snd_pcm_channel_setup_t *setup UNUSED) { - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; - - if (snd_pcm_plug_direct(pcm, stream)) - return snd_pcm_channel_setup(plug->slave, stream, setup); /* FIXME: non mmap setups */ return -ENXIO; } -static ssize_t snd_pcm_plug_stream_frame_data(snd_pcm_t *pcm, int stream, off_t offset) +static ssize_t snd_pcm_plug_frame_data(void *private, off_t offset) { ssize_t ret; - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; - if (snd_pcm_plug_direct(pcm, stream)) - return snd_pcm_stream_frame_data(plug->slave, stream, offset); + snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private; if (offset < 0) { - offset = snd_pcm_plug_slave_size(pcm, stream, -offset); + offset = snd_pcm_plug_slave_size(plug, -offset); if (offset < 0) return offset; offset = -offset; } else { - offset = snd_pcm_plug_slave_size(pcm, stream, offset); + offset = snd_pcm_plug_slave_size(plug, offset); if (offset < 0) return offset; } - ret = snd_pcm_stream_frame_data(plug->slave, stream, offset); + ret = snd_pcm_frame_data(plug->slave, offset); if (ret < 0) return ret; - return snd_pcm_plug_client_size(pcm, stream, ret); + return snd_pcm_plug_client_size(plug, ret); } -ssize_t snd_pcm_plug_writev(snd_pcm_t *pcm, const struct iovec *vector, unsigned long count) +ssize_t snd_pcm_plug_writev(void *private, const struct iovec *vector, unsigned long count) { - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; - snd_pcm_stream_t *str = &pcm->stream[SND_PCM_STREAM_PLAYBACK]; + snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private; + snd_pcm_t *handle = plug->handle; unsigned int k, step, channels; - int size = 0; - if (snd_pcm_plug_direct(pcm, SND_PCM_STREAM_PLAYBACK)) - return snd_pcm_writev(plug->slave, vector, count); - channels = str->setup.format.channels; - if (str->setup.format.interleave) + size_t size = 0; + assert(plug->frames_alloc); + channels = handle->setup.format.channels; + if (handle->setup.format.interleave) step = 1; else { step = channels; assert(count % channels == 0); } - for (k = 0; k < count; k += step, vector += step) { + for (k = 0; k < count; k += step) { snd_pcm_plugin_channel_t *channels; - int expected, ret; - expected = snd_pcm_plug_client_channels_iovec(pcm, SND_PCM_STREAM_PLAYBACK, vector, count, &channels); - if (expected < 0) - return expected; - ret = snd_pcm_plug_write_transfer(pcm, channels, expected); - if (ret < 0) { - if (size > 0) - return size; - return ret; + ssize_t frames; + frames = snd_pcm_plug_client_channels_iovec(plug, vector, count, &channels); + if (frames < 0) + return frames; + while (1) { + unsigned int c; + ssize_t ret; + size_t frames1 = frames; + if (frames1 > plug->frames_alloc) + frames1 = plug->frames_alloc; + ret = snd_pcm_plug_write_transfer(plug, channels, frames1); + if (ret < 0) { + if (size > 0) + return size; + return ret; + } + size += ret; + frames -= ret; + if (frames == 0) + break; + for (c = 0; c < handle->setup.format.channels; ++c) + channels[c].area.addr += ret * channels[c].area.step / 8; } - size += ret; - if (ret != expected) - return size; } return size; } -ssize_t snd_pcm_plug_readv(snd_pcm_t *pcm, const struct iovec *vector, unsigned long count) +ssize_t snd_pcm_plug_readv(void *private, const struct iovec *vector, unsigned long count) { - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; - snd_pcm_stream_t *str = &pcm->stream[SND_PCM_STREAM_CAPTURE]; + snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private; + snd_pcm_t *handle = plug->handle; unsigned int k, step, channels; - int size = 0; - if (snd_pcm_plug_direct(pcm, SND_PCM_STREAM_CAPTURE)) - return snd_pcm_readv(plug->slave, vector, count); - channels = str->setup.format.channels; - if (str->setup.format.interleave) + size_t size = 0; + assert(plug->frames_alloc); + channels = handle->setup.format.channels; + if (handle->setup.format.interleave) step = 1; else { step = channels; @@ -620,135 +364,166 @@ ssize_t snd_pcm_plug_readv(snd_pcm_t *pcm, const struct iovec *vector, unsigned } for (k = 0; k < count; k += step) { snd_pcm_plugin_channel_t *channels; - int expected, ret; - expected = snd_pcm_plug_client_channels_iovec(pcm, SND_PCM_STREAM_CAPTURE, vector, count, &channels); - if (expected < 0) - return expected; - ret = snd_pcm_plug_read_transfer(pcm, channels, expected); + ssize_t frames; + frames = snd_pcm_plug_client_channels_iovec(plug, vector, count, &channels); + if (frames < 0) + return frames; + while (1) { + unsigned int c; + ssize_t ret; + size_t frames1 = frames; + if (frames1 > plug->frames_alloc) + frames1 = plug->frames_alloc; + ret = snd_pcm_plug_read_transfer(plug, channels, frames1); + if (ret < 0) { + if (size > 0) + return size; + return ret; + } + size += ret; + frames -= ret; + if (frames == 0) + break; + for (c = 0; c < handle->setup.format.channels; ++c) + channels[c].area.addr += ret * channels[c].area.step / 8; + } + } + return size; +} + +ssize_t snd_pcm_plug_write(void *private, const void *buf, size_t count) +{ + snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private; + snd_pcm_t *handle = plug->handle; + ssize_t frames; + snd_pcm_plugin_channel_t *channels; + size_t size = 0; + assert(plug->frames_alloc); + frames = snd_pcm_plug_client_channels_buf(plug, (char *)buf, count, &channels); + if (frames < 0) + return frames; + + while (1) { + unsigned int c; + ssize_t ret; + size_t frames1 = frames; + if (frames1 > plug->frames_alloc) + frames1 = plug->frames_alloc; + ret = snd_pcm_plug_write_transfer(plug, channels, frames1); if (ret < 0) { if (size > 0) return size; return ret; } size += ret; - if (ret != expected) - return size; + frames -= ret; + if (frames == 0) + break; + for (c = 0; c < handle->setup.format.channels; ++c) + channels[c].area.addr += ret * channels[c].area.step / 8; } return size; } -ssize_t snd_pcm_plug_write(snd_pcm_t *pcm, const void *buf, size_t count) +ssize_t snd_pcm_plug_read(void *private, void *buf, size_t count) { - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; - int expected; + snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private; + snd_pcm_t *handle = plug->handle; + ssize_t frames; snd_pcm_plugin_channel_t *channels; - - if (snd_pcm_plug_direct(pcm, SND_PCM_STREAM_PLAYBACK)) - return snd_pcm_write(plug->slave, buf, count); - expected = snd_pcm_plug_client_channels_buf(pcm, SND_PCM_STREAM_PLAYBACK, (char *)buf, count, &channels); - if (expected < 0) - return expected; - return snd_pcm_plug_write_transfer(pcm, channels, expected); -} - -ssize_t snd_pcm_plug_read(snd_pcm_t *pcm, void *buf, size_t count) -{ - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; - int expected; - snd_pcm_plugin_channel_t *channels; - - if (snd_pcm_plug_direct(pcm, SND_PCM_STREAM_CAPTURE)) - return snd_pcm_read(plug->slave, buf, count); - expected = snd_pcm_plug_client_channels_buf(pcm, SND_PCM_STREAM_CAPTURE, buf, count, &channels); - if (expected < 0) - return expected; - return snd_pcm_plug_read_transfer(pcm, channels, expected); + size_t size = 0; + assert(plug->frames_alloc); + frames = snd_pcm_plug_client_channels_buf(plug, buf, count, &channels); + if (frames < 0) + return frames; + + while (1) { + unsigned int c; + ssize_t ret; + size_t frames1 = frames; + if (frames1 > plug->frames_alloc) + frames1 = plug->frames_alloc; + ret = snd_pcm_plug_read_transfer(plug, channels, frames1); + if (ret < 0) { + if (size > 0) + return size; + return ret; + } + size += ret; + frames -= ret; + if (frames == 0) + break; + for (c = 0; c < handle->setup.format.channels; ++c) + channels[c].area.addr += ret * channels[c].area.step / 8; + } + return size; } -static int snd_pcm_plug_mmap_status(snd_pcm_t *pcm, int stream, snd_pcm_mmap_status_t **status) +static int snd_pcm_plug_mmap_status(void *private UNUSED, snd_pcm_mmap_status_t **status UNUSED) { - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; - if (snd_pcm_plug_direct(pcm, stream)) - return snd_pcm_mmap_status(plug->slave, stream, status); return -EBADFD; } -static int snd_pcm_plug_mmap_control(snd_pcm_t *pcm, int stream, snd_pcm_mmap_control_t **control) +static int snd_pcm_plug_mmap_control(void *private UNUSED, snd_pcm_mmap_control_t **control UNUSED) { - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; - if (snd_pcm_plug_direct(pcm, stream)) - return snd_pcm_mmap_control(plug->slave, stream, control); return -EBADFD; } -static int snd_pcm_plug_mmap_data(snd_pcm_t *pcm, int stream, void **buffer, size_t bsize UNUSED) +static int snd_pcm_plug_mmap_data(void *private UNUSED, void **buffer UNUSED, size_t bsize UNUSED) { - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; - if (snd_pcm_plug_direct(pcm, stream)) - return snd_pcm_mmap_data(plug->slave, stream, buffer); return -EBADFD; } -static int snd_pcm_plug_munmap_status(snd_pcm_t *pcm, int stream, snd_pcm_mmap_status_t *status UNUSED) +static int snd_pcm_plug_munmap_status(void *private UNUSED, snd_pcm_mmap_status_t *status UNUSED) { - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; - if (snd_pcm_plug_direct(pcm, stream)) - return snd_pcm_munmap_status(plug->slave, stream); return -EBADFD; } -static int snd_pcm_plug_munmap_control(snd_pcm_t *pcm, int stream, snd_pcm_mmap_control_t *control UNUSED) +static int snd_pcm_plug_munmap_control(void *private UNUSED, snd_pcm_mmap_control_t *control UNUSED) { - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; - if (snd_pcm_plug_direct(pcm, stream)) - return snd_pcm_munmap_control(plug->slave, stream); return -EBADFD; } -static int snd_pcm_plug_munmap_data(snd_pcm_t *pcm, int stream, void *buffer UNUSED, size_t size UNUSED) +static int snd_pcm_plug_munmap_data(void *private UNUSED, void *buffer UNUSED, size_t size UNUSED) { - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; - if (snd_pcm_plug_direct(pcm, stream)) - return snd_pcm_munmap_data(plug->slave, stream); return -EBADFD; } -static int snd_pcm_plug_channels_mask(snd_pcm_t *pcm, int stream, +static int snd_pcm_plug_channels_mask(void *private, bitset_t *client_vmask) { - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; - if (snd_pcm_plug_direct(pcm, stream)) - return snd_pcm_channels_mask(plug->slave, stream, client_vmask); - if (stream == SND_PCM_STREAM_PLAYBACK) - return snd_pcm_plug_playback_channels_mask(pcm, client_vmask); + snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private; + if (plug->handle->stream == SND_PCM_STREAM_PLAYBACK) + return snd_pcm_plug_playback_channels_mask(plug, client_vmask); else - return snd_pcm_plug_capture_channels_mask(pcm, client_vmask); + return snd_pcm_plug_capture_channels_mask(plug, client_vmask); } -int snd_pcm_plug_file_descriptor(snd_pcm_t* pcm, int stream) +int snd_pcm_plug_file_descriptor(void *private) { - snd_pcm_plug_t *plug = (snd_pcm_plug_t*) &pcm->private; - return snd_pcm_file_descriptor(plug->slave, stream); + snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private; + return snd_pcm_file_descriptor(plug->slave); } +static int snd_pcm_plug_params(void *private, snd_pcm_params_t *params); + struct snd_pcm_ops snd_pcm_plug_ops = { - stream_close: snd_pcm_plug_stream_close, - stream_nonblock: snd_pcm_plug_stream_nonblock, + close: snd_pcm_plug_close, + nonblock: snd_pcm_plug_nonblock, info: snd_pcm_plug_info, - stream_info: snd_pcm_plug_stream_info, - stream_params: snd_pcm_plug_stream_params, - stream_setup: snd_pcm_plug_stream_setup, + params: snd_pcm_plug_params, + setup: snd_pcm_plug_setup, channel_setup: snd_pcm_plug_channel_setup, - stream_status: snd_pcm_plug_stream_status, - stream_frame_io: snd_pcm_plug_stream_frame_io, - stream_state: snd_pcm_plug_stream_state, - stream_prepare: snd_pcm_plug_stream_prepare, - stream_go: snd_pcm_plug_stream_go, + status: snd_pcm_plug_status, + frame_io: snd_pcm_plug_frame_io, + state: snd_pcm_plug_state, + prepare: snd_pcm_plug_prepare, + go: snd_pcm_plug_go, sync_go: snd_pcm_plug_sync_go, - stream_drain: snd_pcm_plug_stream_drain, - stream_flush: snd_pcm_plug_stream_flush, - stream_pause: snd_pcm_plug_stream_pause, - stream_frame_data: snd_pcm_plug_stream_frame_data, + drain: snd_pcm_plug_drain, + flush: snd_pcm_plug_flush, + pause: snd_pcm_plug_pause, + frame_data: snd_pcm_plug_frame_data, write: snd_pcm_plug_write, writev: snd_pcm_plug_writev, read: snd_pcm_plug_read, @@ -763,38 +538,145 @@ struct snd_pcm_ops snd_pcm_plug_ops = { channels_mask: snd_pcm_plug_channels_mask, }; -int snd_pcm_plug_connect(snd_pcm_t **handle, snd_pcm_t *slave, int mode, int close_slave) +static int snd_pcm_plug_params(void *private, snd_pcm_params_t *params) { - snd_pcm_t *pcm; + snd_pcm_params_t slave_params, params1; + snd_pcm_info_t slave_info; + snd_pcm_plugin_t *plugin; snd_pcm_plug_t *plug; int err; - err = snd_pcm_abstract_open(handle, mode, SND_PCM_TYPE_PLUG, sizeof(snd_pcm_plug_t)); + + plug = (snd_pcm_plug_t*) private; + + /* + * try to decide, if a conversion is required + */ + + memset(&slave_info, 0, sizeof(slave_info)); + slave_info.stream = plug->slave->stream; + if ((err = snd_pcm_info(plug->slave, &slave_info)) < 0) { + snd_pcm_plug_clear(plug); + return err; + } + + if ((err = snd_pcm_plug_slave_params(params, &slave_info, &slave_params)) < 0) + return err; + + + snd_pcm_plug_clear(plug); + + /* add necessary plugins */ + params1 = *params; + if ((err = snd_pcm_plug_format(plug, ¶ms1, &slave_params)) < 0) + return err; + + if (!plug->first) { + err = snd_pcm_params(plug->slave, params); + if (err < 0) + return err; + *plug->handle->ops = *plug->slave->ops; + plug->handle->ops->params = snd_pcm_plug_params; + plug->handle->ops->setup = snd_pcm_plug_setup; + plug->handle->ops->info = snd_pcm_plug_info; + plug->handle->op_arg = plug->slave->op_arg; + return 0; + } else { + *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; + + /* + * I/O plugins + */ + + if (slave_info.flags & SND_PCM_INFO_MMAP) { + pdprintf("params mmap plugin\n"); + err = snd_pcm_plugin_build_mmap(plug, &slave_params.format, &plugin); + } else { + pdprintf("params I/O plugin\n"); + err = snd_pcm_plugin_build_io(plug, &slave_params.format, &plugin); + } + if (err < 0) + return err; + if (plug->slave->stream == SND_PCM_STREAM_PLAYBACK) { + err = snd_pcm_plugin_append(plugin); + } else { + err = snd_pcm_plugin_insert(plugin); + } if (err < 0) { - if (close_slave) - snd_pcm_close(slave); + snd_pcm_plugin_free(plugin); return err; } - pcm = *handle; - pcm->ops = &snd_pcm_plug_ops; - plug = (snd_pcm_plug_t*) &pcm->private; + + 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) + return err; + + err = snd_pcm_plug_action(plug, INIT, 0); + if (err < 0) + return err; + return 0; +} + +int snd_pcm_plug_create(snd_pcm_t **handlep, snd_pcm_t *slave, int close_slave) +{ + snd_pcm_t *handle; + snd_pcm_plug_t *plug; + handle = calloc(1, sizeof(snd_pcm_t)); + if (!handle) + return -ENOMEM; + plug = calloc(1, sizeof(snd_pcm_plug_t)); + if (!plug) { + free(handle); + return -ENOMEM; + } + plug->handle = handle; plug->slave = slave; plug->close_slave = close_slave; + handle->type = SND_PCM_TYPE_PLUG; + handle->stream = slave->stream; + handle->ops = malloc(sizeof(*handle->ops)); + *handle->ops = *slave->ops; + handle->ops->params = snd_pcm_plug_params; + handle->ops->setup = snd_pcm_plug_setup; + handle->ops->info = snd_pcm_plug_info; + handle->op_arg = slave->op_arg; + handle->mode = slave->mode; + handle->private = plug; + *handlep = handle; return 0; } -int snd_pcm_plug_open_subdevice(snd_pcm_t **handle, int card, int device, int subdevice, int mode) +int snd_pcm_plug_open_subdevice(snd_pcm_t **handlep, int card, int device, int subdevice, int stream, int mode) { snd_pcm_t *slave; int err; - err = snd_pcm_open_subdevice(&slave, card, device, subdevice, mode); + err = snd_pcm_hw_open_subdevice(&slave, card, device, subdevice, stream, mode); if (err < 0) return err; - return snd_pcm_plug_connect(handle, slave, mode, 1); + return snd_pcm_plug_create(handlep, slave, 1); } -int snd_pcm_plug_open(snd_pcm_t **handle, int card, int device, int mode) +int snd_pcm_plug_open(snd_pcm_t **handlep, int card, int device, int stream, int mode) { - return snd_pcm_plug_open_subdevice(handle, card, device, -1, mode); + return snd_pcm_plug_open_subdevice(handlep, card, device, -1, stream, mode); } diff --git a/src/pcm/plugin/adpcm.c b/src/pcm/plugin/adpcm.c index 13cb76d1..4b7a9ce2 100644 --- a/src/pcm/plugin/adpcm.c +++ b/src/pcm/plugin/adpcm.c @@ -372,8 +372,7 @@ static int adpcm_action(snd_pcm_plugin_t * plugin, return 0; /* silenty ignore other actions */ } -int snd_pcm_plugin_build_adpcm(snd_pcm_plugin_handle_t *handle, - int stream, +int snd_pcm_plugin_build_adpcm(snd_pcm_plug_t *plug, snd_pcm_format_t *src_format, snd_pcm_format_t *dst_format, snd_pcm_plugin_t **r_plugin) @@ -402,10 +401,8 @@ int snd_pcm_plugin_build_adpcm(snd_pcm_plugin_handle_t *handle, assert(0); assert(snd_pcm_format_linear(format->format)); - err = snd_pcm_plugin_build(handle, stream, - "Ima-ADPCM<->linear conversion", - src_format, - dst_format, + err = snd_pcm_plugin_build(plug, "Ima-ADPCM<->linear conversion", + src_format, dst_format, sizeof(adpcm_t) + src_format->channels * sizeof(adpcm_channel_t), &plugin); if (err < 0) diff --git a/src/pcm/plugin/alaw.c b/src/pcm/plugin/alaw.c index 5357c207..b563b01b 100644 --- a/src/pcm/plugin/alaw.c +++ b/src/pcm/plugin/alaw.c @@ -248,8 +248,7 @@ static ssize_t alaw_transfer(snd_pcm_plugin_t *plugin, return frames; } -int snd_pcm_plugin_build_alaw(snd_pcm_plugin_handle_t *handle, - int stream, +int snd_pcm_plugin_build_alaw(snd_pcm_plug_t *plug, snd_pcm_format_t *src_format, snd_pcm_format_t *dst_format, snd_pcm_plugin_t **r_plugin) @@ -278,12 +277,9 @@ int snd_pcm_plugin_build_alaw(snd_pcm_plugin_handle_t *handle, assert(0); assert(snd_pcm_format_linear(format->format)); - err = snd_pcm_plugin_build(handle, stream, - "A-Law<->linear conversion", - src_format, - dst_format, - sizeof(alaw_t), - &plugin); + err = snd_pcm_plugin_build(plug, "A-Law<->linear conversion", + src_format, dst_format, + sizeof(alaw_t), &plugin); if (err < 0) return err; data = (alaw_t*)plugin->extra_data; diff --git a/src/pcm/plugin/copy.c b/src/pcm/plugin/copy.c index 63ef714b..de4762dd 100644 --- a/src/pcm/plugin/copy.c +++ b/src/pcm/plugin/copy.c @@ -65,8 +65,7 @@ static ssize_t copy_transfer(snd_pcm_plugin_t *plugin, return frames; } -int snd_pcm_plugin_build_copy(snd_pcm_plugin_handle_t *handle, - int stream, +int snd_pcm_plugin_build_copy(snd_pcm_plug_t *plug, snd_pcm_format_t *src_format, snd_pcm_format_t *dst_format, snd_pcm_plugin_t **r_plugin) @@ -85,12 +84,8 @@ int snd_pcm_plugin_build_copy(snd_pcm_plugin_handle_t *handle, width = snd_pcm_format_physical_width(src_format->format); assert(width > 0); - err = snd_pcm_plugin_build(handle, stream, - "copy", - src_format, - dst_format, - 0, - &plugin); + err = snd_pcm_plugin_build(plug, "copy", src_format, dst_format, + 0, &plugin); if (err < 0) return err; plugin->transfer = copy_transfer; diff --git a/src/pcm/plugin/io.c b/src/pcm/plugin/io.c index d7c7e4b8..a449ec67 100644 --- a/src/pcm/plugin/io.c +++ b/src/pcm/plugin/io.c @@ -23,10 +23,10 @@ #include "../../include/driver.h" #include "../../include/pcm.h" #include "../../include/pcm_plugin.h" -#define snd_pcm_write(handle,buf,count) snd_pcm_oss_write3(handle,buf,count,1) -#define snd_pcm_writev(handle,vec,count) snd_pcm_oss_writev3(handle,vec,count,1) -#define snd_pcm_read(handle,buf,count) snd_pcm_oss_read3(handle,buf,count,1) -#define snd_pcm_readv(handle,vec,count) snd_pcm_oss_readv3(handle,vec,count,1) +#define pcm_write(plug,buf,count) snd_pcm_oss_write3(plug,buf,count,1) +#define pcm_writev(plug,vec,count) snd_pcm_oss_writev3(plug,vec,count,1) +#define pcm_read(plug,buf,count) snd_pcm_oss_read3(plug,buf,count,1) +#define pcm_readv(plug,vec,count) snd_pcm_oss_readv3(plug,vec,count,1) #else #include #include @@ -35,65 +35,67 @@ #include #include #include "../pcm_local.h" +#define pcm_write(plug,buf,count) snd_pcm_write(plug->slave,buf,count) +#define pcm_writev(plug,vec,count) snd_pcm_writev(plug->slave,vec,count) +#define pcm_read(plug,buf,count) snd_pcm_read(plug->slave,buf,count) +#define pcm_readv(plug,vec,count) snd_pcm_readv(plug->slave,vec,count) #endif /* * Basic io plugin */ -typedef struct io_private_data { - snd_pcm_plugin_handle_t *slave; -} io_t; - -static ssize_t io_transfer(snd_pcm_plugin_t *plugin, - const snd_pcm_plugin_channel_t *src_channels, - snd_pcm_plugin_channel_t *dst_channels, - size_t frames) +static ssize_t io_playback_transfer(snd_pcm_plugin_t *plugin, + const snd_pcm_plugin_channel_t *src_channels, + snd_pcm_plugin_channel_t *dst_channels UNUSED, + size_t frames) { - io_t *data; struct iovec *vec; int count, channel; assert(plugin); - data = (io_t *)plugin->extra_data; - assert(data); - vec = (struct iovec *)((char *)data + sizeof(*data)); - if (plugin->stream == SND_PCM_STREAM_PLAYBACK) { - assert(src_channels); - count = plugin->src_format.channels; - if (plugin->src_format.interleave) { - return snd_pcm_write(data->slave, src_channels->area.addr, frames); - } else { - for (channel = 0; channel < count; channel++) { - if (src_channels[channel].enabled) - vec[channel].iov_base = src_channels[channel].area.addr; - else - vec[channel].iov_base = 0; - vec[channel].iov_len = frames; - } - return snd_pcm_writev(data->slave, vec, count); - } - } else if (plugin->stream == SND_PCM_STREAM_CAPTURE) { - assert(dst_channels); - count = plugin->dst_format.channels; - if (plugin->dst_format.interleave) { - for (channel = 0; channel < count; channel++) { - dst_channels[channel].enabled = src_channels[channel].enabled; - } - return snd_pcm_read(data->slave, dst_channels->area.addr, frames); - } else { - for (channel = 0; channel < count; channel++) { - dst_channels[channel].enabled = src_channels[channel].enabled; - if (dst_channels[channel].enabled) - vec[channel].iov_base = dst_channels[channel].area.addr; - else - vec[channel].iov_base = 0; - vec[channel].iov_len = frames; - } - return snd_pcm_readv(data->slave, vec, count); + vec = (struct iovec *)plugin->extra_data; + assert(vec); + assert(src_channels); + count = plugin->src_format.channels; + if (plugin->src_format.interleave) { + return pcm_write(plugin->plug, src_channels->area.addr, frames); + } else { + for (channel = 0; channel < count; channel++) { + if (src_channels[channel].enabled) + vec[channel].iov_base = src_channels[channel].area.addr; + else + vec[channel].iov_base = 0; + vec[channel].iov_len = frames; } + return pcm_writev(plugin->plug, vec, count); + } +} + +static ssize_t io_capture_transfer(snd_pcm_plugin_t *plugin, + const snd_pcm_plugin_channel_t *src_channels UNUSED, + snd_pcm_plugin_channel_t *dst_channels, + size_t frames) +{ + struct iovec *vec; + int count, channel; + + assert(plugin); + vec = (struct iovec *)plugin->extra_data; + assert(vec); + assert(dst_channels); + count = plugin->dst_format.channels; + if (plugin->dst_format.interleave) { + return pcm_read(plugin->plug, dst_channels->area.addr, frames); } else { - assert(0); + for (channel = 0; channel < count; channel++) { + if (dst_channels[channel].enabled) + vec[channel].iov_base = dst_channels[channel].area.addr; + else + vec[channel].iov_base = 0; + vec[channel].iov_len = frames; + } + return pcm_readv(plugin->plug, vec, count); } return 0; } @@ -109,36 +111,37 @@ static ssize_t io_src_channels(snd_pcm_plugin_t *plugin, if (err < 0) return err; *channels = v; - for (channel = 0; channel < plugin->src_format.channels; ++channel, ++v) - v->wanted = 1; + if (plugin->src_format.interleave) { + for (channel = 0; channel < plugin->src_format.channels; ++channel, ++v) + v->wanted = 1; + } return frames; } -int snd_pcm_plugin_build_io(snd_pcm_plugin_handle_t *pcm, - int stream, - snd_pcm_plugin_handle_t *slave, - snd_pcm_format_t *format, - snd_pcm_plugin_t **r_plugin) +int snd_pcm_plugin_build_io(snd_pcm_plug_t *plug, + snd_pcm_format_t *format, + snd_pcm_plugin_t **r_plugin) { int err; - io_t *data; snd_pcm_plugin_t *plugin; assert(r_plugin); *r_plugin = NULL; - assert(pcm && format); - err = snd_pcm_plugin_build(pcm, stream, - "I/O io", + assert(plug && format); + err = snd_pcm_plugin_build(plug, "I/O io", format, format, - sizeof(io_t) + sizeof(struct iovec) * format->channels, + sizeof(struct iovec) * format->channels, &plugin); if (err < 0) return err; - data = (io_t *)plugin->extra_data; - data->slave = slave; - plugin->transfer = io_transfer; - if (format->interleave && stream == SND_PCM_STREAM_PLAYBACK) - plugin->client_channels = io_src_channels; + if (snd_pcm_plug_stream(plug) == SND_PCM_STREAM_PLAYBACK) { + plugin->transfer = io_playback_transfer; + if (format->interleave) + plugin->client_channels = io_src_channels; + } else { + plugin->transfer = io_capture_transfer; + } + *r_plugin = plugin; return 0; } diff --git a/src/pcm/plugin/linear.c b/src/pcm/plugin/linear.c index 2ede815e..83b5e9b7 100644 --- a/src/pcm/plugin/linear.c +++ b/src/pcm/plugin/linear.c @@ -131,8 +131,7 @@ int conv_index(int src_format, int dst_format) return src_width * 32 + src_endian * 16 + sign * 8 + dst_width * 2 + dst_endian; } -int snd_pcm_plugin_build_linear(snd_pcm_plugin_handle_t *handle, - int stream, +int snd_pcm_plugin_build_linear(snd_pcm_plug_t *plug, snd_pcm_format_t *src_format, snd_pcm_format_t *dst_format, snd_pcm_plugin_t **r_plugin) @@ -149,12 +148,9 @@ int snd_pcm_plugin_build_linear(snd_pcm_plugin_handle_t *handle, assert(snd_pcm_format_linear(src_format->format) && snd_pcm_format_linear(dst_format->format)); - err = snd_pcm_plugin_build(handle, stream, - "linear format conversion", - src_format, - dst_format, - sizeof(linear_t), - &plugin); + err = snd_pcm_plugin_build(plug, "linear format conversion", + src_format, dst_format, + sizeof(linear_t), &plugin); if (err < 0) return err; data = (linear_t *)plugin->extra_data; diff --git a/src/pcm/plugin/mmap.c b/src/pcm/plugin/mmap.c index 2f46bd9b..5bfb2193 100644 --- a/src/pcm/plugin/mmap.c +++ b/src/pcm/plugin/mmap.c @@ -34,7 +34,6 @@ */ typedef struct mmap_private_data { - snd_pcm_t *slave; void *buffer; #if 0 char *silence; @@ -49,42 +48,42 @@ static ssize_t mmap_src_channels(snd_pcm_plugin_t *plugin, mmap_t *data; snd_pcm_plugin_channel_t *sv; snd_pcm_channel_area_t *dv; - snd_pcm_stream_t *stream; - snd_pcm_stream_setup_t *setup; + snd_pcm_t *stream; + snd_pcm_setup_t *setup; size_t pos; int ready; unsigned int channel; assert(plugin && channels); data = (mmap_t *)plugin->extra_data; - stream = &data->slave->stream[plugin->stream]; + stream = plugin->plug->slave; setup = &stream->setup; - if (snd_pcm_mmap_stream_state(data->slave, plugin->stream) < SND_PCM_STATE_PREPARED) + if (snd_pcm_mmap_state(stream) < SND_PCM_STATE_PREPARED) return -EBADFD; - ready = snd_pcm_mmap_ready(data->slave, plugin->stream); + ready = snd_pcm_mmap_ready(stream); if (ready < 0) return ready; if (!ready) { struct pollfd pfd; - if (snd_pcm_mmap_stream_state(data->slave, plugin->stream) != SND_PCM_STATE_RUNNING) + if (snd_pcm_mmap_state(stream) != SND_PCM_STATE_RUNNING) return -EPIPE; if (stream->mode & SND_PCM_NONBLOCK) return -EAGAIN; - pfd.fd = snd_pcm_file_descriptor(data->slave, plugin->stream); + pfd.fd = snd_pcm_file_descriptor(stream); pfd.events = POLLOUT | POLLERR; ready = poll(&pfd, 1, 10000); if (ready < 0) return ready; if (ready && pfd.revents & POLLERR) return -EPIPE; - assert(snd_pcm_mmap_ready(data->slave, plugin->stream)); + assert(snd_pcm_mmap_ready(stream)); } - pos = snd_pcm_mmap_frames_offset(data->slave, plugin->stream); + pos = snd_pcm_mmap_frames_offset(stream); assert(pos % setup->frames_align == 0); - sv = plugin->src_channels; + sv = plugin->buf_channels; dv = stream->channels; *channels = sv; for (channel = 0; channel < plugin->src_format.channels; ++channel) { @@ -94,78 +93,76 @@ static ssize_t mmap_src_channels(snd_pcm_plugin_t *plugin, #else sv->wanted = 1; #endif - sv->aptr = 0; sv->area.addr = dv->addr + dv->step * pos / 8; sv->area.first = dv->first; sv->area.step = dv->step; ++sv; ++dv; } - return snd_pcm_mmap_frames_xfer(data->slave, plugin->stream, frames); + return snd_pcm_mmap_frames_xfer(stream, frames); } static ssize_t mmap_dst_channels(snd_pcm_plugin_t *plugin, - size_t frames, - snd_pcm_plugin_channel_t **channels) + size_t frames, + snd_pcm_plugin_channel_t **channels) { mmap_t *data; int err; unsigned int channel; snd_pcm_plugin_channel_t *dv; snd_pcm_channel_area_t *sv; - snd_pcm_stream_t *stream; - snd_pcm_stream_setup_t *setup; + snd_pcm_t *stream; + snd_pcm_setup_t *setup; size_t pos; int ready; assert(plugin && channels); data = (mmap_t *)plugin->extra_data; - stream = &data->slave->stream[plugin->stream]; + stream = plugin->plug->slave; setup = &stream->setup; - if (snd_pcm_mmap_stream_state(data->slave, plugin->stream) < SND_PCM_STATE_PREPARED) + if (snd_pcm_mmap_state(stream) < SND_PCM_STATE_PREPARED) return -EBADFD; - if (snd_pcm_mmap_stream_state(data->slave, plugin->stream) == SND_PCM_STATE_PREPARED && + if (snd_pcm_mmap_state(stream) == SND_PCM_STATE_PREPARED && stream->setup.start_mode == SND_PCM_START_DATA) { - err = snd_pcm_stream_go(data->slave, plugin->stream); + err = snd_pcm_go(stream); if (err < 0) return err; } - ready = snd_pcm_mmap_ready(data->slave, plugin->stream); + ready = snd_pcm_mmap_ready(stream); if (ready < 0) return ready; if (!ready) { struct pollfd pfd; - if (snd_pcm_mmap_stream_state(data->slave, plugin->stream) != SND_PCM_STATE_RUNNING) + if (snd_pcm_mmap_state(stream) != SND_PCM_STATE_RUNNING) return -EPIPE; if (stream->mode & SND_PCM_NONBLOCK) return -EAGAIN; - pfd.fd = snd_pcm_file_descriptor(data->slave, plugin->stream); + pfd.fd = snd_pcm_file_descriptor(stream); pfd.events = POLLIN | POLLERR; ready = poll(&pfd, 1, 10000); if (ready < 0) return ready; if (ready && pfd.revents & POLLERR) return -EPIPE; - assert(snd_pcm_mmap_ready(data->slave, plugin->stream)); + assert(snd_pcm_mmap_ready(stream)); } - pos = snd_pcm_mmap_frames_offset(data->slave, plugin->stream); + pos = snd_pcm_mmap_frames_offset(stream); assert(pos % setup->frames_align == 0); sv = stream->channels; - dv = plugin->dst_channels; + dv = plugin->buf_channels; *channels = dv; for (channel = 0; channel < plugin->dst_format.channels; ++channel) { dv->enabled = 1; dv->wanted = 0; - dv->aptr = 0; dv->area.addr = sv->addr + sv->step * pos / 8; dv->area.first = sv->first; dv->area.step = sv->step; ++sv; ++dv; } - return snd_pcm_mmap_frames_xfer(data->slave, plugin->stream, frames); + return snd_pcm_mmap_frames_xfer(stream, frames); } static ssize_t mmap_playback_transfer(snd_pcm_plugin_t *plugin, @@ -174,15 +171,15 @@ static ssize_t mmap_playback_transfer(snd_pcm_plugin_t *plugin, size_t frames) { mmap_t *data; - snd_pcm_stream_setup_t *setup; - snd_pcm_stream_t *str; + snd_pcm_setup_t *setup; + snd_pcm_t *stream; int err; assert(plugin && plugin->prev); assert(src_channels); data = (mmap_t *)plugin->extra_data; - str = &data->slave->stream[SND_PCM_STREAM_PLAYBACK]; - setup = &str->setup; + stream = plugin->plug->slave; + setup = &stream->setup; #if 0 for (channel = 0; channel < plugin->src_format.channels; channel++) { @@ -191,12 +188,12 @@ static ssize_t mmap_playback_transfer(snd_pcm_plugin_t *plugin, } #endif - snd_pcm_mmap_stream_frame_data(data->slave, SND_PCM_STREAM_PLAYBACK, frames); - if (snd_pcm_mmap_stream_state(data->slave, plugin->stream) == SND_PCM_STATE_PREPARED && - (str->setup.start_mode == SND_PCM_START_DATA || - (str->setup.start_mode == SND_PCM_START_FULL && - !snd_pcm_mmap_ready(data->slave, plugin->stream)))) { - err = snd_pcm_stream_go(data->slave, plugin->stream); + snd_pcm_frame_data(stream, frames); + if (snd_pcm_mmap_state(stream) == SND_PCM_STATE_PREPARED && + (setup->start_mode == SND_PCM_START_DATA || + (setup->start_mode == SND_PCM_START_FULL && + !snd_pcm_mmap_ready(stream)))) { + err = snd_pcm_go(stream); if (err < 0) return err; } @@ -209,14 +206,14 @@ static ssize_t mmap_capture_transfer(snd_pcm_plugin_t *plugin, size_t frames) { mmap_t *data; - snd_pcm_stream_t *str; + snd_pcm_t *stream; assert(plugin && plugin->next); data = (mmap_t *)plugin->extra_data; - str = &data->slave->stream[SND_PCM_STREAM_CAPTURE]; + stream = plugin->plug->slave; /* FIXME: not here the increment */ - snd_pcm_mmap_stream_frame_data(data->slave, SND_PCM_STREAM_CAPTURE, frames); + snd_pcm_frame_data(stream, frames); return frames; } @@ -226,21 +223,23 @@ static int mmap_action(snd_pcm_plugin_t *plugin, unsigned long udata UNUSED) { struct mmap_private_data *data; + snd_pcm_t *stream; assert(plugin); + stream = plugin->plug->slave; data = (mmap_t *)plugin->extra_data; if (action == INIT) { - snd_pcm_stream_setup_t *setup; + snd_pcm_setup_t *setup; int result; if (data->buffer) { - snd_pcm_munmap(data->slave, plugin->stream); + snd_pcm_munmap(stream); data->buffer = 0; } - result = snd_pcm_mmap(data->slave, plugin->stream, NULL, NULL, (void **)&data->buffer); + result = snd_pcm_mmap(stream, NULL, NULL, (void **)&data->buffer); if (result < 0) return result; - setup = &data->slave->stream[plugin->stream].setup; + setup = &stream->setup; #if 0 if (plugin->stream == SND_PCM_STREAM_PLAYBACK) { @@ -266,12 +265,10 @@ static void mmap_free(snd_pcm_plugin_t *plugin, void *private_data UNUSED) free(data->silence); #endif if (data->buffer) - snd_pcm_munmap(data->slave, plugin->stream); + snd_pcm_munmap(plugin->plug->slave); } -int snd_pcm_plugin_build_mmap(snd_pcm_plugin_handle_t *pcm, - int stream, - snd_pcm_t *slave, +int snd_pcm_plugin_build_mmap(snd_pcm_plug_t *plug, snd_pcm_format_t *format, snd_pcm_plugin_t **r_plugin) { @@ -281,17 +278,15 @@ int snd_pcm_plugin_build_mmap(snd_pcm_plugin_handle_t *pcm, assert(r_plugin); *r_plugin = NULL; - assert(pcm); - err = snd_pcm_plugin_build(pcm, stream, - "I/O mmap", + assert(plug); + err = snd_pcm_plugin_build(plug, "I/O mmap", format, format, sizeof(mmap_t) + sizeof(snd_pcm_plugin_channel_t) * format->channels, &plugin); if (err < 0) return err; data = (mmap_t *)plugin->extra_data; - data->slave = slave; - if (stream == SND_PCM_STREAM_PLAYBACK) { + if (plug->handle->stream == SND_PCM_STREAM_PLAYBACK) { plugin->client_channels = mmap_src_channels; plugin->transfer = mmap_playback_transfer; } else { diff --git a/src/pcm/plugin/mulaw.c b/src/pcm/plugin/mulaw.c index cc461592..74beeb30 100644 --- a/src/pcm/plugin/mulaw.c +++ b/src/pcm/plugin/mulaw.c @@ -264,8 +264,7 @@ static ssize_t mulaw_transfer(snd_pcm_plugin_t *plugin, return frames; } -int snd_pcm_plugin_build_mulaw(snd_pcm_plugin_handle_t *handle, - int stream, +int snd_pcm_plugin_build_mulaw(snd_pcm_plug_t *plug, snd_pcm_format_t *src_format, snd_pcm_format_t *dst_format, snd_pcm_plugin_t **r_plugin) @@ -296,12 +295,9 @@ int snd_pcm_plugin_build_mulaw(snd_pcm_plugin_handle_t *handle, } assert(snd_pcm_format_linear(format->format)); - err = snd_pcm_plugin_build(handle, stream, - "Mu-Law<->linear conversion", - src_format, - dst_format, - sizeof(mulaw_t), - &plugin); + err = snd_pcm_plugin_build(plug, "Mu-Law<->linear conversion", + src_format, dst_format, + sizeof(mulaw_t), &plugin); if (err < 0) return err; data = (mulaw_t*)plugin->extra_data; diff --git a/src/pcm/plugin/rate.c b/src/pcm/plugin/rate.c index 2383ddbd..a7853075 100644 --- a/src/pcm/plugin/rate.c +++ b/src/pcm/plugin/rate.c @@ -343,8 +343,7 @@ static int rate_action(snd_pcm_plugin_t *plugin, return 0; /* silenty ignore other actions */ } -int snd_pcm_plugin_build_rate(snd_pcm_plugin_handle_t *handle, - int stream, +int snd_pcm_plugin_build_rate(snd_pcm_plug_t *plug, snd_pcm_format_t *src_format, snd_pcm_format_t *dst_format, snd_pcm_plugin_t **r_plugin) @@ -362,10 +361,8 @@ int snd_pcm_plugin_build_rate(snd_pcm_plugin_handle_t *handle, assert(snd_pcm_format_linear(dst_format->format) > 0); assert(src_format->rate != dst_format->rate); - err = snd_pcm_plugin_build(handle, stream, - "rate conversion", - src_format, - dst_format, + err = snd_pcm_plugin_build(plug, "rate conversion", + src_format, dst_format, sizeof(rate_t) + src_format->channels * sizeof(rate_channel_t), &plugin); if (err < 0) diff --git a/src/pcm/plugin/route.c b/src/pcm/plugin/route.c index 4112e1f6..b7a21d1c 100644 --- a/src/pcm/plugin/route.c +++ b/src/pcm/plugin/route.c @@ -534,8 +534,7 @@ int getput_index(int format) return width * 4 + endian * 2 + sign; } -int snd_pcm_plugin_build_route(snd_pcm_plugin_handle_t *handle, - int stream, +int snd_pcm_plugin_build_route(snd_pcm_plug_t *plug, snd_pcm_format_t *src_format, snd_pcm_format_t *dst_format, route_ttable_entry_t *ttable, @@ -551,10 +550,8 @@ int snd_pcm_plugin_build_route(snd_pcm_plugin_handle_t *handle, assert(snd_pcm_format_linear(src_format->format) && snd_pcm_format_linear(dst_format->format)); - err = snd_pcm_plugin_build(handle, stream, - "attenuated route conversion", - src_format, - dst_format, + err = snd_pcm_plugin_build(plug, "attenuated route conversion", + src_format, dst_format, sizeof(route_t) + sizeof(data->ttable[0]) * dst_format->channels, &plugin); if (err < 0) -- 2.47.1