pcm handle split. Moved buffer to plugin struct

This commit is contained in:
Abramo Bagnara 2000-06-21 15:03:06 +00:00
parent 4c24f6925e
commit b312f52b76
11 changed files with 722 additions and 891 deletions

View file

@ -26,8 +26,10 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
#include "../../include/driver.h" #include "../../include/driver.h"
#include "../../include/pcm.h" #include "../../include/pcm.h"
#define snd_pcm_plug_first(handle, stream) ((handle)->runtime->oss.plugin_first) #define snd_pcm_plug_first(plug) ((plug)->runtime->oss.plugin_first)
#define snd_pcm_plug_last(handle, stream) ((handle)->runtime->oss.plugin_last) #define snd_pcm_plug_last(plug) ((plug)->runtime->oss.plugin_last)
#define vmalloc snd_vmalloc
#define vfree snd_vfree
#else #else
#include <malloc.h> #include <malloc.h>
#include <errno.h> #include <errno.h>
@ -35,11 +37,15 @@
#include <string.h> #include <string.h>
#include <sys/uio.h> #include <sys/uio.h>
#include "pcm_local.h" #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 #endif
static int snd_pcm_plugin_src_channels_mask(snd_pcm_plugin_t *plugin, static int snd_pcm_plugin_src_channels_mask(snd_pcm_plugin_t *plugin,
bitset_t *dst_vmask, bitset_t *dst_vmask,
bitset_t **src_vmask) bitset_t **src_vmask)
{ {
bitset_t *vmask = plugin->src_vmask; bitset_t *vmask = plugin->src_vmask;
bitset_copy(vmask, dst_vmask, plugin->src_format.channels); 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, static int snd_pcm_plugin_dst_channels_mask(snd_pcm_plugin_t *plugin,
bitset_t *src_vmask, bitset_t *src_vmask,
bitset_t **dst_vmask) bitset_t **dst_vmask)
{ {
bitset_t *vmask = plugin->dst_vmask; bitset_t *vmask = plugin->dst_vmask;
bitset_copy(vmask, src_vmask, plugin->dst_format.channels); 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; return 0;
} }
static ssize_t snd_pcm_plugin_side_channels(snd_pcm_plugin_t *plugin, static int snd_pcm_plugin_alloc(snd_pcm_plugin_t *plugin, size_t frames)
int client_side,
size_t frames,
snd_pcm_plugin_channel_t **channels)
{ {
char *ptr;
int width;
unsigned int channel;
long size;
snd_pcm_plugin_channel_t *v;
snd_pcm_format_t *format; snd_pcm_format_t *format;
if ((plugin->stream == SND_PCM_STREAM_PLAYBACK && client_side) || ssize_t width;
(plugin->stream == SND_PCM_STREAM_CAPTURE && !client_side)) { size_t size;
unsigned int channel;
snd_pcm_plugin_channel_t *c;
if (plugin->stream == SND_PCM_STREAM_PLAYBACK)
format = &plugin->src_format; format = &plugin->src_format;
v = plugin->src_channels; else
} else {
format = &plugin->dst_format; format = &plugin->dst_format;
v = plugin->dst_channels;
}
*channels = v;
if ((width = snd_pcm_format_physical_width(format->format)) < 0) if ((width = snd_pcm_format_physical_width(format->format)) < 0)
return width; return width;
size = frames * format->channels * width; size = frames * format->channels * width;
assert(size % 8 == 0); assert(size % 8 == 0);
size /= 8; size /= 8;
ptr = (char *)snd_pcm_plug_buf_alloc(plugin->handle, plugin->stream, size); if (plugin->buf_frames < frames) {
if (ptr == NULL) if (plugin->buf)
vfree(plugin->buf);
plugin->buf = vmalloc(size);
plugin->buf_frames = frames;
}
if (!plugin->buf)
return -ENOMEM; return -ENOMEM;
assert(size % format->channels == 0); c = plugin->buf_channels;
size /= format->channels; if (format->interleave) {
for (channel = 0; channel < format->channels; channel++, v++) { for (channel = 0; channel < format->channels; channel++, c++) {
v->enabled = 1; c->enabled = 1;
v->wanted = 0; c->wanted = 0;
v->aptr = ptr; c->area.addr = plugin->buf;
if (format->interleave) { c->area.first = channel * width;
v->area.addr = ptr; c->area.step = format->channels * width;
v->area.first = channel * width; }
v->area.step = format->channels * width; } else {
} else { assert(size % format->channels == 0);
v->area.addr = ptr + (channel * size); size /= format->channels;
v->area.first = 0; for (channel = 0; channel < format->channels; channel++, c++) {
v->area.step = width; c->enabled = 1;
c->wanted = 0;
c->area.addr = plugin->buf + (channel * size);
c->area.first = 0;
c->area.step = width;
} }
} }
return 0;
}
int snd_pcm_plug_alloc(snd_pcm_plug_t *plug, size_t frames)
{
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_client_channels(snd_pcm_plugin_t *plugin,
size_t frames,
snd_pcm_plugin_channel_t **channels)
{
assert(frames <= plugin->buf_frames);
*channels = plugin->buf_channels;
return frames; return frames;
} }
ssize_t snd_pcm_plugin_client_channels(snd_pcm_plugin_t *plugin, int snd_pcm_plugin_build(snd_pcm_plug_t *plug,
size_t frames,
snd_pcm_plugin_channel_t **channels)
{
return snd_pcm_plugin_side_channels(plugin, 1, frames, channels);
}
ssize_t snd_pcm_plugin_slave_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);
}
int snd_pcm_plugin_build(snd_pcm_plugin_handle_t *handle,
int stream,
const char *name, const char *name,
snd_pcm_format_t *src_format, snd_pcm_format_t *src_format,
snd_pcm_format_t *dst_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 **ret)
{ {
snd_pcm_plugin_t *plugin; snd_pcm_plugin_t *plugin;
size_t channels;
assert(handle); assert(plug);
assert(stream >= 0 && stream <= 1);
assert(src_format && dst_format); assert(src_format && dst_format);
plugin = (snd_pcm_plugin_t *)calloc(1, sizeof(*plugin) + extra); plugin = (snd_pcm_plugin_t *)calloc(1, sizeof(*plugin) + extra);
if (plugin == NULL) if (plugin == NULL)
return -ENOMEM; return -ENOMEM;
plugin->name = name ? strdup(name) : NULL; plugin->name = name ? strdup(name) : NULL;
plugin->handle = handle; plugin->plug = plug;
plugin->stream = stream; plugin->stream = snd_pcm_plug_stream(plug);
plugin->src_format = *src_format; plugin->src_format = *src_format;
plugin->src_width = snd_pcm_format_physical_width(src_format->format); plugin->src_width = snd_pcm_format_physical_width(src_format->format);
assert(plugin->src_width > 0); assert(plugin->src_width > 0);
plugin->dst_format = *dst_format; plugin->dst_format = *dst_format;
plugin->dst_width = snd_pcm_format_physical_width(dst_format->format); plugin->dst_width = snd_pcm_format_physical_width(dst_format->format);
assert(plugin->dst_width > 0); assert(plugin->dst_width > 0);
plugin->src_channels = calloc(src_format->channels, sizeof(snd_pcm_plugin_channel_t)); if (plugin->stream == SND_PCM_STREAM_PLAYBACK)
if (plugin->src_channels == NULL) { channels = src_format->channels;
free(plugin); else
return -ENOMEM; channels = dst_format->channels;
} plugin->buf_channels = calloc(channels, sizeof(*plugin->buf_channels));
plugin->dst_channels = calloc(dst_format->channels, sizeof(snd_pcm_plugin_channel_t)); if (plugin->buf_channels == NULL) {
if (plugin->dst_channels == NULL) {
free(plugin->src_channels);
free(plugin); free(plugin);
return -ENOMEM; return -ENOMEM;
} }
plugin->src_vmask = bitset_alloc(src_format->channels); plugin->src_vmask = bitset_alloc(src_format->channels);
if (plugin->src_vmask == NULL) { if (plugin->src_vmask == NULL) {
free(plugin->src_channels); free(plugin->buf_channels);
free(plugin->dst_channels);
free(plugin); free(plugin);
return -ENOMEM; return -ENOMEM;
} }
plugin->dst_vmask = bitset_alloc(dst_format->channels); plugin->dst_vmask = bitset_alloc(dst_format->channels);
if (plugin->dst_vmask == NULL) { if (plugin->dst_vmask == NULL) {
free(plugin->src_channels); free(plugin->buf_channels);
free(plugin->dst_channels);
free(plugin->src_vmask); free(plugin->src_vmask);
free(plugin); free(plugin);
return -ENOMEM; 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) int snd_pcm_plugin_free(snd_pcm_plugin_t *plugin)
{ {
if (plugin) { assert(plugin);
if (plugin->private_free) if (plugin->private_free)
plugin->private_free(plugin, plugin->private_data); plugin->private_free(plugin, plugin->private_data);
if (plugin->name) if (plugin->name)
free(plugin->name); free(plugin->name);
free(plugin->src_channels); free(plugin->buf_channels);
free(plugin->dst_channels); if (plugin->buf)
free(plugin->src_vmask); vfree(plugin->buf);
free(plugin->dst_vmask); free(plugin->src_vmask);
free(plugin); free(plugin->dst_vmask);
} free(plugin);
return 0; 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; snd_pcm_plugin_t *plugin, *plugin_prev, *plugin_next;
int stream = snd_pcm_plug_stream(plug);
assert(handle);
assert(plug);
if (drv_frames == 0) if (drv_frames == 0)
return 0; return 0;
if (stream == SND_PCM_STREAM_PLAYBACK) { 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) { while (plugin && drv_frames > 0) {
plugin_prev = plugin->prev; plugin_prev = plugin->prev;
if (plugin->src_frames) 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; plugin = plugin_prev;
} }
} else if (stream == SND_PCM_STREAM_CAPTURE) { } 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) { while (plugin && drv_frames > 0) {
plugin_next = plugin->next; plugin_next = plugin->next;
if (plugin->dst_frames) 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; 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; snd_pcm_plugin_t *plugin, *plugin_prev, *plugin_next;
ssize_t frames; ssize_t frames;
int stream = snd_pcm_plug_stream(plug);
assert(handle); assert(plug);
if (clt_frames == 0) if (clt_frames == 0)
return 0; return 0;
frames = clt_frames; frames = clt_frames;
if (stream == SND_PCM_STREAM_PLAYBACK) { 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) { while (plugin && frames > 0) {
plugin_next = plugin->next; plugin_next = plugin->next;
if (plugin->dst_frames) { 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; plugin = plugin_next;
} }
} else if (stream == SND_PCM_STREAM_CAPTURE) { } 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) { while (plugin) {
plugin_prev = plugin->prev; plugin_prev = plugin->prev;
if (plugin->src_frames) { if (plugin->src_frames) {
@ -294,9 +324,9 @@ static int preferred_formats[] = {
SND_PCM_SFMT_U8 SND_PCM_SFMT_U8
}; };
int snd_pcm_plug_slave_params(snd_pcm_stream_params_t *params, int snd_pcm_plug_slave_params(snd_pcm_params_t *params,
snd_pcm_stream_info_t *slave_info, snd_pcm_info_t *slave_info,
snd_pcm_stream_params_t *slave_params) snd_pcm_params_t *slave_params)
{ {
*slave_params = *params; *slave_params = *params;
if ((slave_info->formats & (1 << params->format.format)) == 0) { 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 */ /* interleave */
if (!(slave_info->flags & SND_PCM_STREAM_INFO_INTERLEAVE)) if (!(slave_info->flags & SND_PCM_INFO_INTERLEAVE))
slave_params->format.interleave = 0; 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; slave_params->format.interleave = 1;
return 0; return 0;
} }
int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle, int snd_pcm_plug_format(snd_pcm_plug_t *plug,
snd_pcm_stream_params_t *params, snd_pcm_params_t *params,
snd_pcm_stream_params_t *slave_params) snd_pcm_params_t *slave_params)
{ {
snd_pcm_stream_params_t tmpparams; snd_pcm_params_t tmpparams;
snd_pcm_stream_params_t dstparams; snd_pcm_params_t dstparams;
snd_pcm_stream_params_t *srcparams; snd_pcm_params_t *srcparams;
snd_pcm_plugin_t *plugin; snd_pcm_plugin_t *plugin;
int err; int err;
switch (params->stream) { switch (snd_pcm_plug_stream(plug)) {
case SND_PCM_STREAM_PLAYBACK: case SND_PCM_STREAM_PLAYBACK:
dstparams = *slave_params; dstparams = *slave_params;
srcparams = 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; tmpparams.format.interleave = dstparams.format.interleave;
switch (srcparams->format.format) { switch (srcparams->format.format) {
case SND_PCM_SFMT_MU_LAW: case SND_PCM_SFMT_MU_LAW:
err = snd_pcm_plugin_build_mulaw(handle, err = snd_pcm_plugin_build_mulaw(plug,
params->stream,
&srcparams->format, &srcparams->format,
&tmpparams.format, &tmpparams.format,
&plugin); &plugin);
break; break;
#ifndef __KERNEL__ #ifndef __KERNEL__
case SND_PCM_SFMT_A_LAW: case SND_PCM_SFMT_A_LAW:
err = snd_pcm_plugin_build_alaw(handle, err = snd_pcm_plugin_build_alaw(plug,
params->stream,
&srcparams->format, &srcparams->format,
&tmpparams.format, &tmpparams.format,
&plugin); &plugin);
break; break;
case SND_PCM_SFMT_IMA_ADPCM: case SND_PCM_SFMT_IMA_ADPCM:
err = snd_pcm_plugin_build_adpcm(handle, err = snd_pcm_plugin_build_adpcm(plug,
params->stream,
&srcparams->format, &srcparams->format,
&tmpparams.format, &tmpparams.format,
&plugin); &plugin);
@ -490,8 +517,7 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle,
if (srcparams->format.rate == dstparams.format.rate && if (srcparams->format.rate == dstparams.format.rate &&
snd_pcm_format_linear(dstparams.format.format)) snd_pcm_format_linear(dstparams.format.format))
tmpparams.format.format = dstparams.format.format; tmpparams.format.format = dstparams.format.format;
err = snd_pcm_plugin_build_route(handle, err = snd_pcm_plugin_build_route(plug,
params->stream,
&srcparams->format, &srcparams->format,
&tmpparams.format, &tmpparams.format,
ttable, ttable,
@ -517,8 +543,7 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle,
if (srcparams->format.channels == dstparams.format.channels && if (srcparams->format.channels == dstparams.format.channels &&
snd_pcm_format_linear(dstparams.format.format)) snd_pcm_format_linear(dstparams.format.format))
tmpparams.format.format = dstparams.format.format; tmpparams.format.format = dstparams.format.format;
err = snd_pcm_plugin_build_rate(handle, err = snd_pcm_plugin_build_rate(plug,
params->stream,
&srcparams->format, &srcparams->format,
&tmpparams.format, &tmpparams.format,
&plugin); &plugin);
@ -562,8 +587,7 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle,
tmpparams.format.interleave = dstparams.format.interleave; tmpparams.format.interleave = dstparams.format.interleave;
if (snd_pcm_format_linear(dstparams.format.format)) if (snd_pcm_format_linear(dstparams.format.format))
tmpparams.format.format = dstparams.format.format; tmpparams.format.format = dstparams.format.format;
err = snd_pcm_plugin_build_route(handle, err = snd_pcm_plugin_build_route(plug,
params->stream,
&srcparams->format, &srcparams->format,
&tmpparams.format, &tmpparams.format,
ttable, ttable,
@ -587,23 +611,20 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle,
tmpparams.format.format = dstparams.format.format; tmpparams.format.format = dstparams.format.format;
tmpparams.format.interleave = dstparams.format.interleave; tmpparams.format.interleave = dstparams.format.interleave;
if (tmpparams.format.format == SND_PCM_SFMT_MU_LAW) { if (tmpparams.format.format == SND_PCM_SFMT_MU_LAW) {
err = snd_pcm_plugin_build_mulaw(handle, err = snd_pcm_plugin_build_mulaw(plug,
params->stream,
&srcparams->format, &srcparams->format,
&tmpparams.format, &tmpparams.format,
&plugin); &plugin);
} }
#ifndef __KERNEL__ #ifndef __KERNEL__
else if (tmpparams.format.format == SND_PCM_SFMT_A_LAW) { else if (tmpparams.format.format == SND_PCM_SFMT_A_LAW) {
err = snd_pcm_plugin_build_alaw(handle, err = snd_pcm_plugin_build_alaw(plug,
params->stream,
&srcparams->format, &srcparams->format,
&tmpparams.format, &tmpparams.format,
&plugin); &plugin);
} }
else if (tmpparams.format.format == SND_PCM_SFMT_IMA_ADPCM) { else if (tmpparams.format.format == SND_PCM_SFMT_IMA_ADPCM) {
err = snd_pcm_plugin_build_adpcm(handle, err = snd_pcm_plugin_build_adpcm(plug,
params->stream,
&srcparams->format, &srcparams->format,
&tmpparams.format, &tmpparams.format,
&plugin); &plugin);
@ -611,8 +632,7 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle,
#endif #endif
else if (snd_pcm_format_linear(srcparams->format.format) && else if (snd_pcm_format_linear(srcparams->format.format) &&
snd_pcm_format_linear(tmpparams.format.format)) { snd_pcm_format_linear(tmpparams.format.format)) {
err = snd_pcm_plugin_build_linear(handle, err = snd_pcm_plugin_build_linear(plug,
params->stream,
&srcparams->format, &srcparams->format,
&tmpparams.format, &tmpparams.format,
&plugin); &plugin);
@ -633,8 +653,7 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle,
/* interleave */ /* interleave */
if (srcparams->format.interleave != dstparams.format.interleave) { if (srcparams->format.interleave != dstparams.format.interleave) {
tmpparams.format.interleave = dstparams.format.interleave; tmpparams.format.interleave = dstparams.format.interleave;
err = snd_pcm_plugin_build_copy(handle, err = snd_pcm_plugin_build_copy(plug,
params->stream,
&srcparams->format, &srcparams->format,
&tmpparams.format, &tmpparams.format,
&plugin); &plugin);
@ -652,8 +671,7 @@ int snd_pcm_plug_format(snd_pcm_plugin_handle_t *handle,
return 0; return 0;
} }
ssize_t snd_pcm_plug_client_channels_buf(snd_pcm_plugin_handle_t *handle, ssize_t snd_pcm_plug_client_channels_buf(snd_pcm_plug_t *plug,
int stream,
char *buf, char *buf,
size_t count, size_t count,
snd_pcm_plugin_channel_t **channels) 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_plugin_channel_t *v;
snd_pcm_format_t *format; snd_pcm_format_t *format;
int width, nchannels, channel; int width, nchannels, channel;
int stream = snd_pcm_plug_stream(plug);
assert(buf); assert(buf);
if (stream == SND_PCM_STREAM_PLAYBACK) { if (stream == SND_PCM_STREAM_PLAYBACK) {
plugin = snd_pcm_plug_first(handle, stream); plugin = snd_pcm_plug_first(plug);
format = &plugin->src_format; format = &plugin->src_format;
v = plugin->src_channels;
} }
else { else {
plugin = snd_pcm_plug_last(handle, stream); plugin = snd_pcm_plug_last(plug);
format = &plugin->dst_format; format = &plugin->dst_format;
v = plugin->dst_channels;
} }
v = plugin->buf_channels;
*channels = v; *channels = v;
if ((width = snd_pcm_format_physical_width(format->format)) < 0) if ((width = snd_pcm_format_physical_width(format->format)) < 0)
return width; 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++) { for (channel = 0; channel < nchannels; channel++, v++) {
v->enabled = 1; v->enabled = 1;
v->wanted = (stream == SND_PCM_STREAM_CAPTURE); v->wanted = (stream == SND_PCM_STREAM_CAPTURE);
v->aptr = NULL;
v->area.addr = buf; v->area.addr = buf;
v->area.first = channel * width; v->area.first = channel * width;
v->area.step = nchannels * 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; return count;
} }
ssize_t snd_pcm_plug_client_channels_iovec(snd_pcm_plugin_handle_t *handle, ssize_t snd_pcm_plug_client_channels_iovec(snd_pcm_plug_t *plug,
int stream,
const struct iovec *vector, const struct iovec *vector,
unsigned long count, unsigned long count,
snd_pcm_plugin_channel_t **channels) 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; snd_pcm_format_t *format;
int width; int width;
unsigned int nchannels, channel; unsigned int nchannels, channel;
int stream = snd_pcm_plug_stream(plug);
if (stream == SND_PCM_STREAM_PLAYBACK) { if (stream == SND_PCM_STREAM_PLAYBACK) {
plugin = snd_pcm_plug_first(handle, stream); plugin = snd_pcm_plug_first(plug);
format = &plugin->src_format; format = &plugin->src_format;
v = plugin->src_channels;
} }
else { else {
plugin = snd_pcm_plug_last(handle, stream); plugin = snd_pcm_plug_last(plug);
format = &plugin->dst_format; format = &plugin->dst_format;
v = plugin->dst_channels;
} }
v = plugin->buf_channels;
*channels = v; *channels = v;
if ((width = snd_pcm_format_physical_width(format->format)) < 0) if ((width = snd_pcm_format_physical_width(format->format)) < 0)
return width; 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++) { for (channel = 0; channel < nchannels; channel++, v++) {
v->enabled = 1; v->enabled = 1;
v->wanted = (stream == SND_PCM_STREAM_CAPTURE); v->wanted = (stream == SND_PCM_STREAM_CAPTURE);
v->aptr = NULL;
v->area.addr = vector->iov_base; v->area.addr = vector->iov_base;
v->area.first = channel * width; v->area.first = channel * width;
v->area.step = nchannels * 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); assert(vector->iov_len == len);
v->enabled = (vector->iov_base != NULL); v->enabled = (vector->iov_base != NULL);
v->wanted = (v->enabled && (stream == SND_PCM_STREAM_CAPTURE)); v->wanted = (v->enabled && (stream == SND_PCM_STREAM_CAPTURE));
v->aptr = NULL;
v->area.addr = vector->iov_base; v->area.addr = vector->iov_base;
v->area.first = 0; v->area.first = 0;
v->area.step = width; 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) bitset_t *client_vmask)
{ {
#ifndef __KERNEL__ snd_pcm_plugin_t *plugin = snd_pcm_plug_last(plug);
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);
if (plugin == NULL) { if (plugin == NULL) {
#ifndef __KERNEL__ #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 #else
return 0; return 0;
#endif #endif
@ -766,7 +777,7 @@ int snd_pcm_plug_playback_channels_mask(snd_pcm_plugin_handle_t *handle,
int err; int err;
bitset_one(dstmask, schannels); bitset_one(dstmask, schannels);
#ifndef __KERNEL__ #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) if (err < 0)
return err; return err;
#endif #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) bitset_t *client_vmask)
{ {
#ifndef __KERNEL__ snd_pcm_plugin_t *plugin = snd_pcm_plug_first(plug);
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);
if (plugin == NULL) { if (plugin == NULL) {
#ifndef __KERNEL__ #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 #else
return 0; return 0;
#endif #endif
@ -809,7 +817,7 @@ int snd_pcm_plug_capture_channels_mask(snd_pcm_plugin_handle_t *handle,
int err; int err;
bitset_one(srcmask, schannels); bitset_one(srcmask, schannels);
#ifndef __KERNEL__ #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) if (err < 0)
return err; return err;
#endif #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_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; unsigned int nchannels = plugin->src_format.channels;
bitset_t bs[bitset_size(nchannels)]; bitset_t bs[bitset_size(nchannels)];
bitset_t *srcmask = bs; bitset_t *srcmask = bs;
@ -842,7 +850,7 @@ static int snd_pcm_plug_playback_disable_useless_channels(snd_pcm_plugin_handle_
else else
bitset_reset(srcmask, channel); 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) if (err < 0)
return err; return err;
for (channel = 0; channel < nchannels; channel++) { 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; 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 *src_channels,
snd_pcm_plugin_channel_t *client_channels) snd_pcm_plugin_channel_t *client_channels)
{ {
#ifndef __KERNEL__ snd_pcm_plugin_t *plugin = snd_pcm_plug_last(plug);
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);
unsigned int nchannels = plugin->dst_format.channels; unsigned int nchannels = plugin->dst_format.channels;
bitset_t bs[bitset_size(nchannels)]; bitset_t bs[bitset_size(nchannels)];
bitset_t *dstmask = bs; 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; plugin = plugin->prev;
} }
#ifndef __KERNEL__ #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) if (err < 0)
return err; return err;
#endif #endif
plugin = snd_pcm_plug_first(handle, SND_PCM_STREAM_CAPTURE); plugin = snd_pcm_plug_first(plug);
nchannels = plugin->src_format.channels; nchannels = plugin->src_format.channels;
for (channel = 0; channel < nchannels; channel++) { for (channel = 0; channel < nchannels; channel++) {
if (!bitset_get(dstmask, 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; 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_t *plugin, *next;
snd_pcm_plugin_channel_t *dst_channels; snd_pcm_plugin_channel_t *dst_channels;
int err; int err;
ssize_t frames = size; 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; return err;
plugin = snd_pcm_plug_first(handle, SND_PCM_STREAM_PLAYBACK); plugin = snd_pcm_plug_first(plug);
while (plugin && frames > 0) { while (plugin && frames > 0) {
if ((next = plugin->next) != NULL) { if ((next = plugin->next) != NULL) {
ssize_t frames1 = frames; ssize_t frames1 = frames;
if (plugin->dst_frames) if (plugin->dst_frames)
frames1 = plugin->dst_frames(plugin, frames); frames1 = plugin->dst_frames(plugin, frames);
if ((err = next->client_channels(next, frames1, &dst_channels)) < 0) { 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; return err;
} }
if (err != frames1) { 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) if (plugin->src_frames)
frames = plugin->src_frames(plugin, frames1); frames = plugin->src_frames(plugin, frames1);
} }
} else { } else
if ((err = snd_pcm_plugin_slave_channels(plugin, frames, &dst_channels)) < 0) dst_channels = 0;
return err;
}
pdprintf("write plugin: %s, %i\n", plugin->name, frames); pdprintf("write plugin: %s, %i\n", plugin->name, frames);
if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0) { 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);
return frames; return frames;
}
snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_PLAYBACK, src_channels->aptr);
src_channels = dst_channels; src_channels = dst_channels;
plugin = next; plugin = next;
} }
snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_PLAYBACK, src_channels->aptr); return snd_pcm_plug_client_size(plug, frames);
return snd_pcm_plug_client_size(handle, SND_PCM_STREAM_PLAYBACK, 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_t *plugin, *next;
snd_pcm_plugin_channel_t *src_channels, *dst_channels; snd_pcm_plugin_channel_t *src_channels, *dst_channels;
ssize_t frames = size; ssize_t frames = size;
int err; int err;
plugin = snd_pcm_plug_last(handle, SND_PCM_STREAM_CAPTURE); frames = snd_pcm_plug_slave_size(plug, frames);
frames = snd_pcm_plug_slave_size(handle, SND_PCM_STREAM_CAPTURE, frames);
if (frames < 0) if (frames < 0)
return frames; return frames;
plugin = snd_pcm_plug_first(handle, SND_PCM_STREAM_CAPTURE); src_channels = 0;
if ((err = snd_pcm_plugin_slave_channels(plugin, frames, &src_channels)) < 0) plugin = snd_pcm_plug_first(plug);
return err;
if ((err = snd_pcm_plug_capture_disable_useless_channels(handle, src_channels, dst_channels_final) < 0))
return err;
while (plugin && frames > 0) { while (plugin && frames > 0) {
if ((next = plugin->next) != NULL) { if ((next = plugin->next) != NULL) {
if ((err = plugin->client_channels(plugin, frames, &dst_channels)) < 0) { 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; return err;
} }
frames = 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 { } else {
dst_channels = dst_channels_final; dst_channels = dst_channels_final;
} }
pdprintf("read plugin: %s, %i\n", plugin->name, frames); pdprintf("read plugin: %s, %i\n", plugin->name, frames);
if ((frames = plugin->transfer(plugin, src_channels, dst_channels, frames)) < 0) { 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);
return frames; 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; plugin = next;
src_channels = dst_channels; src_channels = dst_channels;
} }
snd_pcm_plug_buf_unlock(handle, SND_PCM_STREAM_CAPTURE, src_channels->aptr);
return frames; return frames;
} }

File diff suppressed because it is too large Load diff

View file

@ -372,8 +372,7 @@ static int adpcm_action(snd_pcm_plugin_t * plugin,
return 0; /* silenty ignore other actions */ return 0; /* silenty ignore other actions */
} }
int snd_pcm_plugin_build_adpcm(snd_pcm_plugin_handle_t *handle, int snd_pcm_plugin_build_adpcm(snd_pcm_plug_t *plug,
int stream,
snd_pcm_format_t *src_format, snd_pcm_format_t *src_format,
snd_pcm_format_t *dst_format, snd_pcm_format_t *dst_format,
snd_pcm_plugin_t **r_plugin) 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(0);
assert(snd_pcm_format_linear(format->format)); assert(snd_pcm_format_linear(format->format));
err = snd_pcm_plugin_build(handle, stream, err = snd_pcm_plugin_build(plug, "Ima-ADPCM<->linear conversion",
"Ima-ADPCM<->linear conversion", src_format, dst_format,
src_format,
dst_format,
sizeof(adpcm_t) + src_format->channels * sizeof(adpcm_channel_t), sizeof(adpcm_t) + src_format->channels * sizeof(adpcm_channel_t),
&plugin); &plugin);
if (err < 0) if (err < 0)

View file

@ -248,8 +248,7 @@ static ssize_t alaw_transfer(snd_pcm_plugin_t *plugin,
return frames; return frames;
} }
int snd_pcm_plugin_build_alaw(snd_pcm_plugin_handle_t *handle, int snd_pcm_plugin_build_alaw(snd_pcm_plug_t *plug,
int stream,
snd_pcm_format_t *src_format, snd_pcm_format_t *src_format,
snd_pcm_format_t *dst_format, snd_pcm_format_t *dst_format,
snd_pcm_plugin_t **r_plugin) 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(0);
assert(snd_pcm_format_linear(format->format)); assert(snd_pcm_format_linear(format->format));
err = snd_pcm_plugin_build(handle, stream, err = snd_pcm_plugin_build(plug, "A-Law<->linear conversion",
"A-Law<->linear conversion", src_format, dst_format,
src_format, sizeof(alaw_t), &plugin);
dst_format,
sizeof(alaw_t),
&plugin);
if (err < 0) if (err < 0)
return err; return err;
data = (alaw_t*)plugin->extra_data; data = (alaw_t*)plugin->extra_data;

View file

@ -65,8 +65,7 @@ static ssize_t copy_transfer(snd_pcm_plugin_t *plugin,
return frames; return frames;
} }
int snd_pcm_plugin_build_copy(snd_pcm_plugin_handle_t *handle, int snd_pcm_plugin_build_copy(snd_pcm_plug_t *plug,
int stream,
snd_pcm_format_t *src_format, snd_pcm_format_t *src_format,
snd_pcm_format_t *dst_format, snd_pcm_format_t *dst_format,
snd_pcm_plugin_t **r_plugin) 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); width = snd_pcm_format_physical_width(src_format->format);
assert(width > 0); assert(width > 0);
err = snd_pcm_plugin_build(handle, stream, err = snd_pcm_plugin_build(plug, "copy", src_format, dst_format,
"copy", 0, &plugin);
src_format,
dst_format,
0,
&plugin);
if (err < 0) if (err < 0)
return err; return err;
plugin->transfer = copy_transfer; plugin->transfer = copy_transfer;

View file

@ -23,10 +23,10 @@
#include "../../include/driver.h" #include "../../include/driver.h"
#include "../../include/pcm.h" #include "../../include/pcm.h"
#include "../../include/pcm_plugin.h" #include "../../include/pcm_plugin.h"
#define snd_pcm_write(handle,buf,count) snd_pcm_oss_write3(handle,buf,count,1) #define pcm_write(plug,buf,count) snd_pcm_oss_write3(plug,buf,count,1)
#define snd_pcm_writev(handle,vec,count) snd_pcm_oss_writev3(handle,vec,count,1) #define pcm_writev(plug,vec,count) snd_pcm_oss_writev3(plug,vec,count,1)
#define snd_pcm_read(handle,buf,count) snd_pcm_oss_read3(handle,buf,count,1) #define pcm_read(plug,buf,count) snd_pcm_oss_read3(plug,buf,count,1)
#define snd_pcm_readv(handle,vec,count) snd_pcm_oss_readv3(handle,vec,count,1) #define pcm_readv(plug,vec,count) snd_pcm_oss_readv3(plug,vec,count,1)
#else #else
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -35,65 +35,67 @@
#include <errno.h> #include <errno.h>
#include <sys/uio.h> #include <sys/uio.h>
#include "../pcm_local.h" #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 #endif
/* /*
* Basic io plugin * Basic io plugin
*/ */
typedef struct io_private_data { static ssize_t io_playback_transfer(snd_pcm_plugin_t *plugin,
snd_pcm_plugin_handle_t *slave; const snd_pcm_plugin_channel_t *src_channels,
} io_t; snd_pcm_plugin_channel_t *dst_channels UNUSED,
size_t frames)
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)
{ {
io_t *data;
struct iovec *vec; struct iovec *vec;
int count, channel; int count, channel;
assert(plugin); assert(plugin);
data = (io_t *)plugin->extra_data; vec = (struct iovec *)plugin->extra_data;
assert(data); assert(vec);
vec = (struct iovec *)((char *)data + sizeof(*data)); assert(src_channels);
if (plugin->stream == SND_PCM_STREAM_PLAYBACK) { count = plugin->src_format.channels;
assert(src_channels); if (plugin->src_format.interleave) {
count = plugin->src_format.channels; return pcm_write(plugin->plug, src_channels->area.addr, frames);
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);
}
} else { } else {
assert(0); 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 {
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; return 0;
} }
@ -109,36 +111,37 @@ static ssize_t io_src_channels(snd_pcm_plugin_t *plugin,
if (err < 0) if (err < 0)
return err; return err;
*channels = v; *channels = v;
for (channel = 0; channel < plugin->src_format.channels; ++channel, ++v) if (plugin->src_format.interleave) {
v->wanted = 1; for (channel = 0; channel < plugin->src_format.channels; ++channel, ++v)
v->wanted = 1;
}
return frames; return frames;
} }
int snd_pcm_plugin_build_io(snd_pcm_plugin_handle_t *pcm, int snd_pcm_plugin_build_io(snd_pcm_plug_t *plug,
int stream, snd_pcm_format_t *format,
snd_pcm_plugin_handle_t *slave, snd_pcm_plugin_t **r_plugin)
snd_pcm_format_t *format,
snd_pcm_plugin_t **r_plugin)
{ {
int err; int err;
io_t *data;
snd_pcm_plugin_t *plugin; snd_pcm_plugin_t *plugin;
assert(r_plugin); assert(r_plugin);
*r_plugin = NULL; *r_plugin = NULL;
assert(pcm && format); assert(plug && format);
err = snd_pcm_plugin_build(pcm, stream, err = snd_pcm_plugin_build(plug, "I/O io",
"I/O io",
format, format, format, format,
sizeof(io_t) + sizeof(struct iovec) * format->channels, sizeof(struct iovec) * format->channels,
&plugin); &plugin);
if (err < 0) if (err < 0)
return err; return err;
data = (io_t *)plugin->extra_data; if (snd_pcm_plug_stream(plug) == SND_PCM_STREAM_PLAYBACK) {
data->slave = slave; plugin->transfer = io_playback_transfer;
plugin->transfer = io_transfer; if (format->interleave)
if (format->interleave && stream == SND_PCM_STREAM_PLAYBACK) plugin->client_channels = io_src_channels;
plugin->client_channels = io_src_channels; } else {
plugin->transfer = io_capture_transfer;
}
*r_plugin = plugin; *r_plugin = plugin;
return 0; return 0;
} }

View file

@ -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; 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 snd_pcm_plugin_build_linear(snd_pcm_plug_t *plug,
int stream,
snd_pcm_format_t *src_format, snd_pcm_format_t *src_format,
snd_pcm_format_t *dst_format, snd_pcm_format_t *dst_format,
snd_pcm_plugin_t **r_plugin) 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) && assert(snd_pcm_format_linear(src_format->format) &&
snd_pcm_format_linear(dst_format->format)); snd_pcm_format_linear(dst_format->format));
err = snd_pcm_plugin_build(handle, stream, err = snd_pcm_plugin_build(plug, "linear format conversion",
"linear format conversion", src_format, dst_format,
src_format, sizeof(linear_t), &plugin);
dst_format,
sizeof(linear_t),
&plugin);
if (err < 0) if (err < 0)
return err; return err;
data = (linear_t *)plugin->extra_data; data = (linear_t *)plugin->extra_data;

View file

@ -34,7 +34,6 @@
*/ */
typedef struct mmap_private_data { typedef struct mmap_private_data {
snd_pcm_t *slave;
void *buffer; void *buffer;
#if 0 #if 0
char *silence; char *silence;
@ -49,42 +48,42 @@ static ssize_t mmap_src_channels(snd_pcm_plugin_t *plugin,
mmap_t *data; mmap_t *data;
snd_pcm_plugin_channel_t *sv; snd_pcm_plugin_channel_t *sv;
snd_pcm_channel_area_t *dv; snd_pcm_channel_area_t *dv;
snd_pcm_stream_t *stream; snd_pcm_t *stream;
snd_pcm_stream_setup_t *setup; snd_pcm_setup_t *setup;
size_t pos; size_t pos;
int ready; int ready;
unsigned int channel; unsigned int channel;
assert(plugin && channels); assert(plugin && channels);
data = (mmap_t *)plugin->extra_data; data = (mmap_t *)plugin->extra_data;
stream = &data->slave->stream[plugin->stream]; stream = plugin->plug->slave;
setup = &stream->setup; 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; return -EBADFD;
ready = snd_pcm_mmap_ready(data->slave, plugin->stream); ready = snd_pcm_mmap_ready(stream);
if (ready < 0) if (ready < 0)
return ready; return ready;
if (!ready) { if (!ready) {
struct pollfd pfd; 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; return -EPIPE;
if (stream->mode & SND_PCM_NONBLOCK) if (stream->mode & SND_PCM_NONBLOCK)
return -EAGAIN; return -EAGAIN;
pfd.fd = snd_pcm_file_descriptor(data->slave, plugin->stream); pfd.fd = snd_pcm_file_descriptor(stream);
pfd.events = POLLOUT | POLLERR; pfd.events = POLLOUT | POLLERR;
ready = poll(&pfd, 1, 10000); ready = poll(&pfd, 1, 10000);
if (ready < 0) if (ready < 0)
return ready; return ready;
if (ready && pfd.revents & POLLERR) if (ready && pfd.revents & POLLERR)
return -EPIPE; 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); assert(pos % setup->frames_align == 0);
sv = plugin->src_channels; sv = plugin->buf_channels;
dv = stream->channels; dv = stream->channels;
*channels = sv; *channels = sv;
for (channel = 0; channel < plugin->src_format.channels; ++channel) { 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 #else
sv->wanted = 1; sv->wanted = 1;
#endif #endif
sv->aptr = 0;
sv->area.addr = dv->addr + dv->step * pos / 8; sv->area.addr = dv->addr + dv->step * pos / 8;
sv->area.first = dv->first; sv->area.first = dv->first;
sv->area.step = dv->step; sv->area.step = dv->step;
++sv; ++sv;
++dv; ++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, static ssize_t mmap_dst_channels(snd_pcm_plugin_t *plugin,
size_t frames, size_t frames,
snd_pcm_plugin_channel_t **channels) snd_pcm_plugin_channel_t **channels)
{ {
mmap_t *data; mmap_t *data;
int err; int err;
unsigned int channel; unsigned int channel;
snd_pcm_plugin_channel_t *dv; snd_pcm_plugin_channel_t *dv;
snd_pcm_channel_area_t *sv; snd_pcm_channel_area_t *sv;
snd_pcm_stream_t *stream; snd_pcm_t *stream;
snd_pcm_stream_setup_t *setup; snd_pcm_setup_t *setup;
size_t pos; size_t pos;
int ready; int ready;
assert(plugin && channels); assert(plugin && channels);
data = (mmap_t *)plugin->extra_data; data = (mmap_t *)plugin->extra_data;
stream = &data->slave->stream[plugin->stream]; stream = plugin->plug->slave;
setup = &stream->setup; 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; 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) { 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) if (err < 0)
return err; return err;
} }
ready = snd_pcm_mmap_ready(data->slave, plugin->stream); ready = snd_pcm_mmap_ready(stream);
if (ready < 0) if (ready < 0)
return ready; return ready;
if (!ready) { if (!ready) {
struct pollfd pfd; 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; return -EPIPE;
if (stream->mode & SND_PCM_NONBLOCK) if (stream->mode & SND_PCM_NONBLOCK)
return -EAGAIN; return -EAGAIN;
pfd.fd = snd_pcm_file_descriptor(data->slave, plugin->stream); pfd.fd = snd_pcm_file_descriptor(stream);
pfd.events = POLLIN | POLLERR; pfd.events = POLLIN | POLLERR;
ready = poll(&pfd, 1, 10000); ready = poll(&pfd, 1, 10000);
if (ready < 0) if (ready < 0)
return ready; return ready;
if (ready && pfd.revents & POLLERR) if (ready && pfd.revents & POLLERR)
return -EPIPE; 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); assert(pos % setup->frames_align == 0);
sv = stream->channels; sv = stream->channels;
dv = plugin->dst_channels; dv = plugin->buf_channels;
*channels = dv; *channels = dv;
for (channel = 0; channel < plugin->dst_format.channels; ++channel) { for (channel = 0; channel < plugin->dst_format.channels; ++channel) {
dv->enabled = 1; dv->enabled = 1;
dv->wanted = 0; dv->wanted = 0;
dv->aptr = 0;
dv->area.addr = sv->addr + sv->step * pos / 8; dv->area.addr = sv->addr + sv->step * pos / 8;
dv->area.first = sv->first; dv->area.first = sv->first;
dv->area.step = sv->step; dv->area.step = sv->step;
++sv; ++sv;
++dv; ++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, 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) size_t frames)
{ {
mmap_t *data; mmap_t *data;
snd_pcm_stream_setup_t *setup; snd_pcm_setup_t *setup;
snd_pcm_stream_t *str; snd_pcm_t *stream;
int err; int err;
assert(plugin && plugin->prev); assert(plugin && plugin->prev);
assert(src_channels); assert(src_channels);
data = (mmap_t *)plugin->extra_data; data = (mmap_t *)plugin->extra_data;
str = &data->slave->stream[SND_PCM_STREAM_PLAYBACK]; stream = plugin->plug->slave;
setup = &str->setup; setup = &stream->setup;
#if 0 #if 0
for (channel = 0; channel < plugin->src_format.channels; channel++) { 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 #endif
snd_pcm_mmap_stream_frame_data(data->slave, SND_PCM_STREAM_PLAYBACK, frames); snd_pcm_frame_data(stream, frames);
if (snd_pcm_mmap_stream_state(data->slave, plugin->stream) == SND_PCM_STATE_PREPARED && if (snd_pcm_mmap_state(stream) == SND_PCM_STATE_PREPARED &&
(str->setup.start_mode == SND_PCM_START_DATA || (setup->start_mode == SND_PCM_START_DATA ||
(str->setup.start_mode == SND_PCM_START_FULL && (setup->start_mode == SND_PCM_START_FULL &&
!snd_pcm_mmap_ready(data->slave, plugin->stream)))) { !snd_pcm_mmap_ready(stream)))) {
err = snd_pcm_stream_go(data->slave, plugin->stream); err = snd_pcm_go(stream);
if (err < 0) if (err < 0)
return err; return err;
} }
@ -209,14 +206,14 @@ static ssize_t mmap_capture_transfer(snd_pcm_plugin_t *plugin,
size_t frames) size_t frames)
{ {
mmap_t *data; mmap_t *data;
snd_pcm_stream_t *str; snd_pcm_t *stream;
assert(plugin && plugin->next); assert(plugin && plugin->next);
data = (mmap_t *)plugin->extra_data; data = (mmap_t *)plugin->extra_data;
str = &data->slave->stream[SND_PCM_STREAM_CAPTURE]; stream = plugin->plug->slave;
/* FIXME: not here the increment */ /* 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; return frames;
} }
@ -226,21 +223,23 @@ static int mmap_action(snd_pcm_plugin_t *plugin,
unsigned long udata UNUSED) unsigned long udata UNUSED)
{ {
struct mmap_private_data *data; struct mmap_private_data *data;
snd_pcm_t *stream;
assert(plugin); assert(plugin);
stream = plugin->plug->slave;
data = (mmap_t *)plugin->extra_data; data = (mmap_t *)plugin->extra_data;
if (action == INIT) { if (action == INIT) {
snd_pcm_stream_setup_t *setup; snd_pcm_setup_t *setup;
int result; int result;
if (data->buffer) { if (data->buffer) {
snd_pcm_munmap(data->slave, plugin->stream); snd_pcm_munmap(stream);
data->buffer = 0; 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) if (result < 0)
return result; return result;
setup = &data->slave->stream[plugin->stream].setup; setup = &stream->setup;
#if 0 #if 0
if (plugin->stream == SND_PCM_STREAM_PLAYBACK) { 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); free(data->silence);
#endif #endif
if (data->buffer) 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 snd_pcm_plugin_build_mmap(snd_pcm_plug_t *plug,
int stream,
snd_pcm_t *slave,
snd_pcm_format_t *format, snd_pcm_format_t *format,
snd_pcm_plugin_t **r_plugin) 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); assert(r_plugin);
*r_plugin = NULL; *r_plugin = NULL;
assert(pcm); assert(plug);
err = snd_pcm_plugin_build(pcm, stream, err = snd_pcm_plugin_build(plug, "I/O mmap",
"I/O mmap",
format, format, format, format,
sizeof(mmap_t) + sizeof(snd_pcm_plugin_channel_t) * format->channels, sizeof(mmap_t) + sizeof(snd_pcm_plugin_channel_t) * format->channels,
&plugin); &plugin);
if (err < 0) if (err < 0)
return err; return err;
data = (mmap_t *)plugin->extra_data; data = (mmap_t *)plugin->extra_data;
data->slave = slave; if (plug->handle->stream == SND_PCM_STREAM_PLAYBACK) {
if (stream == SND_PCM_STREAM_PLAYBACK) {
plugin->client_channels = mmap_src_channels; plugin->client_channels = mmap_src_channels;
plugin->transfer = mmap_playback_transfer; plugin->transfer = mmap_playback_transfer;
} else { } else {

View file

@ -264,8 +264,7 @@ static ssize_t mulaw_transfer(snd_pcm_plugin_t *plugin,
return frames; return frames;
} }
int snd_pcm_plugin_build_mulaw(snd_pcm_plugin_handle_t *handle, int snd_pcm_plugin_build_mulaw(snd_pcm_plug_t *plug,
int stream,
snd_pcm_format_t *src_format, snd_pcm_format_t *src_format,
snd_pcm_format_t *dst_format, snd_pcm_format_t *dst_format,
snd_pcm_plugin_t **r_plugin) 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)); assert(snd_pcm_format_linear(format->format));
err = snd_pcm_plugin_build(handle, stream, err = snd_pcm_plugin_build(plug, "Mu-Law<->linear conversion",
"Mu-Law<->linear conversion", src_format, dst_format,
src_format, sizeof(mulaw_t), &plugin);
dst_format,
sizeof(mulaw_t),
&plugin);
if (err < 0) if (err < 0)
return err; return err;
data = (mulaw_t*)plugin->extra_data; data = (mulaw_t*)plugin->extra_data;

View file

@ -343,8 +343,7 @@ static int rate_action(snd_pcm_plugin_t *plugin,
return 0; /* silenty ignore other actions */ return 0; /* silenty ignore other actions */
} }
int snd_pcm_plugin_build_rate(snd_pcm_plugin_handle_t *handle, int snd_pcm_plugin_build_rate(snd_pcm_plug_t *plug,
int stream,
snd_pcm_format_t *src_format, snd_pcm_format_t *src_format,
snd_pcm_format_t *dst_format, snd_pcm_format_t *dst_format,
snd_pcm_plugin_t **r_plugin) 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(snd_pcm_format_linear(dst_format->format) > 0);
assert(src_format->rate != dst_format->rate); assert(src_format->rate != dst_format->rate);
err = snd_pcm_plugin_build(handle, stream, err = snd_pcm_plugin_build(plug, "rate conversion",
"rate conversion", src_format, dst_format,
src_format,
dst_format,
sizeof(rate_t) + src_format->channels * sizeof(rate_channel_t), sizeof(rate_t) + src_format->channels * sizeof(rate_channel_t),
&plugin); &plugin);
if (err < 0) if (err < 0)

View file

@ -534,8 +534,7 @@ int getput_index(int format)
return width * 4 + endian * 2 + sign; return width * 4 + endian * 2 + sign;
} }
int snd_pcm_plugin_build_route(snd_pcm_plugin_handle_t *handle, int snd_pcm_plugin_build_route(snd_pcm_plug_t *plug,
int stream,
snd_pcm_format_t *src_format, snd_pcm_format_t *src_format,
snd_pcm_format_t *dst_format, snd_pcm_format_t *dst_format,
route_ttable_entry_t *ttable, 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) && assert(snd_pcm_format_linear(src_format->format) &&
snd_pcm_format_linear(dst_format->format)); snd_pcm_format_linear(dst_format->format));
err = snd_pcm_plugin_build(handle, stream, err = snd_pcm_plugin_build(plug, "attenuated route conversion",
"attenuated route conversion", src_format, dst_format,
src_format,
dst_format,
sizeof(route_t) + sizeof(data->ttable[0]) * dst_format->channels, sizeof(route_t) + sizeof(data->ttable[0]) * dst_format->channels,
&plugin); &plugin);
if (err < 0) if (err < 0)