ssize_t snd_pcm_writev(snd_pcm_t *handle, const struct iovec *vector, unsigned long count);
ssize_t snd_pcm_readv(snd_pcm_t *handle, const struct iovec *vector, unsigned long count);
int snd_pcm_dump_setup(snd_pcm_t *handle, FILE *fp);
+int snd_pcm_dump(snd_pcm_t *handle, FILE *fp);
int snd_pcm_channels_mask(snd_pcm_t *handle, bitset_t *client_vmask);
int snd_pcm_mmap_get_areas(snd_pcm_t *handle, snd_pcm_channel_area_t *areas);
-const char *snd_pcm_get_format_name(int format);
-const char *snd_pcm_get_format_description(int format);
-int snd_pcm_get_format_value(const char* name);
+const char *snd_pcm_format_name(int format);
+const char *snd_pcm_format_description(int format);
+int snd_pcm_format_value(const char* name);
int snd_pcm_area_silence(const snd_pcm_channel_area_t *dst_channel, size_t dst_offset,
size_t samples, int format);
int (*parameter_get)(snd_pcm_plugin_t *plugin,
const char *name,
unsigned long *value);
+ void (*dump)(snd_pcm_plugin_t *plugin, FILE *fp);
snd_pcm_plugin_t *prev;
snd_pcm_plugin_t *next;
snd_pcm_plug_t *plug;
int snd_pcm_plug_create(snd_pcm_t **handle, snd_pcm_t *slave, int close_slave);
int snd_pcm_plug_open_subdevice(snd_pcm_t **handle, int card, int device, int subdevice, int stream, int mode);
int snd_pcm_plug_open(snd_pcm_t **handle, int card, int device, int stream, int mode);
-int snd_pcm_multi_create(snd_pcm_t **handlep, size_t slaves_count,
- snd_pcm_t **slaves_handle, size_t *slaves_channels_count,
- size_t binds_count, unsigned int *binds_client_channel,
- unsigned int *binds_slave, unsigned int *binds_slave_channel,
- int close_slaves);
int snd_pcm_plugin_free(snd_pcm_plugin_t *plugin);
int snd_pcm_plugin_insert(snd_pcm_plugin_t *plugin);
int snd_pcm_plugin_append(snd_pcm_plugin_t *plugin);
+void snd_pcm_plugin_dump(snd_pcm_plugin_t *plugin, FILE *fp);
int snd_pcm_plug_alloc(snd_pcm_plug_t *plug, size_t frames);
int snd_pcm_plug_clear(snd_pcm_plug_t *plug);
snd_pcm_plugin_t *snd_pcm_plug_first(snd_pcm_plug_t *plug);
snd_pcm_format_t *dst_format,
snd_pcm_plugin_t **r_plugin);
+int snd_pcm_multi_create(snd_pcm_t **handlep, size_t slaves_count,
+ snd_pcm_t **slaves_handle, size_t *slaves_channels_count,
+ size_t binds_count, unsigned int *binds_client_channel,
+ unsigned int *binds_slave, unsigned int *binds_slave_channel,
+ int close_slaves);
+
#ifdef __cplusplus
}
#endif
assert(handle);
assert(count == 0 || vector);
assert(handle->valid_setup);
+ assert(handle->setup.format.interleave ||
+ count % handle->setup.format.channels == 0);
return handle->ops->writev(handle->op_arg, -1, vector, count);
}
{
snd_pcm_setup_t *setup;
assert(handle);
+ assert(fp);
assert(handle->valid_setup);
setup = &handle->setup;
fprintf(fp, "stream: %s\n", assoc(handle->stream, streams));
return 0;
}
-const char *snd_pcm_get_format_name(int format)
+int snd_pcm_dump(snd_pcm_t *handle, FILE *fp)
+{
+ assert(handle);
+ assert(fp);
+ handle->ops->dump(handle->op_arg, fp);
+ return 0;
+}
+
+const char *snd_pcm_format_name(int format)
{
assoc_t *a = assoc_value(format, fmts);
if (a)
return 0;
}
-const char *snd_pcm_get_format_description(int format)
+const char *snd_pcm_format_description(int format)
{
assoc_t *a = assoc_value(format, fmts);
if (a)
return "Unknown";
}
-int snd_pcm_get_format_value(const char* name)
+int snd_pcm_format_value(const char* name)
{
assoc_t *a = assoc_name(name, fmts);
if (a)
typedef struct {
snd_pcm_t *handle;
int fd;
+ int card, device, subdevice;
} snd_pcm_hw_t;
#define SND_FILE_PCM_STREAM_PLAYBACK "/dev/snd/pcmC%iD%ip"
return 0;
}
+static void snd_pcm_hw_dump(void *private, FILE *fp)
+{
+ snd_pcm_hw_t *hw = (snd_pcm_hw_t*) private;
+ snd_pcm_t *handle = hw->handle;
+ char *name = "Unknown";
+ snd_card_get_name(hw->card, &name);
+ fprintf(fp, "Hardware PCM card %d '%s' device %d subdevice %d\n",
+ hw->card, name, hw->device, hw->subdevice);
+ free(name);
+ if (handle->valid_setup) {
+ fprintf(fp, "\nIts setup is:\n");
+ snd_pcm_dump_setup(handle, fp);
+ }
+}
+
struct snd_pcm_ops snd_pcm_hw_ops = {
close: snd_pcm_hw_close,
nonblock: snd_pcm_hw_nonblock,
munmap_data: snd_pcm_hw_munmap_data,
file_descriptor: snd_pcm_hw_file_descriptor,
channels_mask: snd_pcm_hw_channels_mask,
+ dump: snd_pcm_hw_dump,
};
int snd_pcm_hw_open_subdevice(snd_pcm_t **handlep, int card, int device, int subdevice, int stream, int mode)
goto __end;
}
hw->handle = handle;
+ hw->card = card;
+ hw->device = device;
+ hw->subdevice = subdevice;
hw->fd = fd;
handle->type = SND_PCM_TYPE_HW;
handle->stream = stream;
int (*munmap_data)(void *private, void *buffer, size_t bsize);
int (*file_descriptor)(void *private);
int (*channels_mask)(void *private, bitset_t *client_vmask);
+ void (*dump)(void *private, FILE *fp);
};
struct snd_pcm {
size_t binds_count;
snd_pcm_multi_bind_t *binds;
size_t channels_count;
+ size_t frames_alloc;
int interleave;
int one_to_many;
} snd_pcm_multi_t;
for (i = 1; i < multi->slaves_count; ++i) {
snd_pcm_t *handle_i = multi->slaves[i].handle;
snd_pcm_info_t info_i;
+ memset(&info_i, 0, sizeof(info_i));
err = snd_pcm_info(handle_i, &info_i);
if (err < 0)
return err;
unsigned int i;
int err;
snd_pcm_t *handle_0 = multi->slaves[0].handle;
+ unsigned int old_mask = info->req_mask;
+ info->req_mask &= ~SND_PCM_PARAMS_CHANNELS;
err = snd_pcm_params_info(handle_0, info);
if (err < 0)
return err;
+ info->min_channels = multi->channels_count;
+ info->max_channels = multi->channels_count;
for (i = 1; i < multi->slaves_count; ++i) {
snd_pcm_t *handle_i = multi->slaves[i].handle;
snd_pcm_params_info_t info_i;
+ info_i = *info;
err = snd_pcm_params_info(handle_i, &info_i);
if (err < 0)
return err;
if (info_i.max_fragments < info->max_fragments)
info->max_fragments = info_i.max_fragments;
}
+ info->req_mask = old_mask;
return 0;
}
else if (!(info.flags & SND_PCM_INFO_NONINTERLEAVE))
p.format.interleave = 1;
p.format.channels = multi->slaves[i].channels_total;
+#if 1
+ p.frames_xrun_max = ~0;
+#endif
err = snd_pcm_params(handle, &p);
if (err < 0)
return err;
snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
unsigned int i;
int err;
+ size_t frames_alloc;
err = snd_pcm_setup(multi->slaves[0].handle, setup);
if (err < 0)
return err;
+ frames_alloc = multi->slaves[0].handle->setup.frag_size;
+ multi->frames_alloc = 0;
for (i = 1; i < multi->slaves_count; ++i) {
snd_pcm_setup_t s;
snd_pcm_t *sh = multi->slaves[i].handle;
if (!multi->handle->setup.format.interleave)
continue;
}
- s->buf = malloc(sh->setup.frag_size * sh->bits_per_frame / 8);
+ s->buf = malloc(frames_alloc * sh->bits_per_frame / 8);
if (!s->buf)
return -ENOMEM;
snd_pcm_format_set_silence(sh->setup.format.format, s->buf,
a->addr = s->buf + sh->setup.frag_size * sh->bits_per_sample / 8;
a->first = 0;
a->step = sh->bits_per_sample;
+ s->iovec[c].iov_base = a->addr;
}
}
}
+ multi->frames_alloc = frames_alloc;
/* Loaded with a value != 0 if mmap is feasible */
setup->mmap_bytes = !multi->one_to_many;
return 0;
}
return newpos;
}
-
-ssize_t snd_pcm_multi_write(void *private, snd_timestamp_t timestamp UNUSED, const void *buf, size_t count)
+
+static int snd_pcm_multi_write_copy(snd_pcm_multi_t *multi, const void *buf,
+ size_t offset, size_t count)
{
- snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
- snd_pcm_t *handle = multi->handle;
unsigned int i;
snd_pcm_channel_area_t area;
- area.addr = (void *) buf;
+ snd_pcm_t *handle = multi->handle;
+ area.addr = (void *) buf + offset * handle->bits_per_frame;
area.step = handle->bits_per_frame;
for (i = 0; i < multi->binds_count; ++i) {
snd_pcm_multi_bind_t *bind = &multi->binds[i];
err = snd_pcm_area_copy(&area, 0, &slave->areas[bind->slave_channel], 0, count, handle->setup.format.format);
if (err < 0)
return err;
- if (!slave->handle->setup.format.interleave)
- slave->iovec[bind->slave_channel].iov_base = slave->areas[bind->slave_channel].addr;
+ if (!slave->handle->setup.format.interleave) {
+ struct iovec *vec = &slave->iovec[bind->slave_channel];
+ vec->iov_len = count;
+ }
+ }
+ return 0;
+}
+
+static int snd_pcm_multi_writev_copy(snd_pcm_multi_t *multi, const struct iovec *vec,
+ size_t offset, size_t count)
+{
+ unsigned int i;
+ snd_pcm_channel_area_t area;
+ snd_pcm_t *handle = multi->handle;
+ area.first = 0;
+ area.step = handle->bits_per_sample;
+ for (i = 0; i < multi->binds_count; ++i) {
+ snd_pcm_multi_bind_t *bind = &multi->binds[i];
+ snd_pcm_multi_slave_t *slave = &multi->slaves[bind->slave];
+ int err;
+ area.addr = vec[bind->client_channel].iov_base +
+ offset * handle->bits_per_sample;
+ if (slave->handle->setup.format.interleave) {
+ assert(slave->buf);
+ err = snd_pcm_area_copy(&area, 0, &slave->areas[bind->slave_channel], 0, count, handle->setup.format.format);
+ if (err < 0)
+ return err;
+ } else {
+ struct iovec *vec = &slave->iovec[bind->slave_channel];
+ vec->iov_base = area.addr;
+ vec->iov_len = count;
+ }
}
+ return 0;
+}
+
+static ssize_t snd_pcm_multi_write_io(snd_pcm_multi_t *multi, size_t count)
+{
+ unsigned int i;
+ ssize_t frames = count;
for (i = 0; i < multi->slaves_count; ++i) {
snd_pcm_multi_slave_t *slave = &multi->slaves[i];
snd_pcm_t *sh = slave->handle;
if (sh->setup.format.interleave) {
- count = snd_pcm_write(sh, slave->buf, count);
+ frames = snd_pcm_write(sh, slave->buf, frames);
} else {
int channels = sh->setup.format.channels;
- struct iovec vec[channels];
- int c;
- for (c = 0; c < channels; ++c)
- vec[c].iov_len = count;
- count = snd_pcm_writev(sh, vec, channels);
+ frames = snd_pcm_writev(sh, slave->iovec, channels);
}
- if (count <= 0)
+ if (frames <= 0)
break;
}
- return count;
+ return frames;
}
-ssize_t snd_pcm_multi_read(void *private, snd_timestamp_t timestamp UNUSED, void *buf, size_t count)
+static ssize_t snd_pcm_multi_write(void *private, snd_timestamp_t timestamp UNUSED, const void *buf, size_t count)
{
snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
- return -ENOSYS;
+ size_t result = 0;
+ while (count > 0) {
+ int err;
+ ssize_t ret;
+ size_t frames = count;
+ if (frames > multi->frames_alloc)
+ frames = multi->frames_alloc;
+ err = snd_pcm_multi_write_copy(multi, buf, result, frames);
+ if (err < 0)
+ return err;
+ ret = snd_pcm_multi_write_io(multi, frames);
+ if (ret > 0)
+ result += ret;
+ if (ret != (ssize_t)frames) {
+ if (result > 0)
+ return result;
+ return ret;
+ }
+ count -= ret;
+ }
+ return result;
+}
+
+static ssize_t snd_pcm_multi_writev1(snd_pcm_multi_t *multi, const struct iovec *vector, size_t count)
+{
+ size_t result = 0;
+ while (count > 0) {
+ int err;
+ ssize_t ret;
+ size_t frames = count;
+ if (frames > multi->frames_alloc)
+ frames = multi->frames_alloc;
+ err = snd_pcm_multi_writev_copy(multi, vector, result, frames);
+ if (err < 0)
+ return err;
+ ret = snd_pcm_multi_write_io(multi, frames);
+ if (ret > 0)
+ result += ret;
+ if (ret != (ssize_t) frames) {
+ if (result > 0)
+ return result;
+ return ret;
+ }
+ count -= ret;
+ }
+ return result;
+}
+
+static ssize_t snd_pcm_multi_writev(void *private, snd_timestamp_t timestamp UNUSED, const struct iovec *vector, unsigned long count)
+{
+ snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+ snd_pcm_t *handle = multi->handle;
+ unsigned int k, step;
+ size_t result = 0;
+ if (handle->setup.format.interleave)
+ step = 1;
+ else
+ step = handle->setup.format.channels;
+ for (k = 0; k < count; k += step) {
+ ssize_t ret;
+ if (handle->setup.format.interleave)
+ ret = snd_pcm_multi_write(private, timestamp, vector->iov_base, vector->iov_len);
+ else
+ ret = snd_pcm_multi_writev1(multi, vector, vector->iov_len);
+ if (ret > 0)
+ result += ret;
+ if (ret != (ssize_t) vector->iov_len) {
+ if (result > 0)
+ return result;
+ return ret;
+ }
+ vector += step;
+ }
+ return result;
}
-ssize_t snd_pcm_multi_writev(void *private, snd_timestamp_t timestamp UNUSED, const struct iovec *vector, unsigned long count)
+static ssize_t snd_pcm_multi_read(void *private, snd_timestamp_t timestamp UNUSED, void *buf, size_t count)
{
snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
return -ENOSYS;
}
-ssize_t snd_pcm_multi_readv(void *private, snd_timestamp_t timestamp UNUSED, const struct iovec *vector, unsigned long count)
+static ssize_t snd_pcm_multi_readv(void *private, snd_timestamp_t timestamp UNUSED, const struct iovec *vector, unsigned long count)
{
snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
return -ENOSYS;
return snd_pcm_file_descriptor(handle);
}
+static void snd_pcm_multi_dump(void *private, FILE *fp)
+{
+ snd_pcm_multi_t *multi = (snd_pcm_multi_t*) private;
+ snd_pcm_t *handle = multi->handle;
+ unsigned int k;
+ fprintf(fp, "Multi PCM\n");
+ if (handle->valid_setup) {
+ fprintf(fp, "\nIts setup is:\n");
+ snd_pcm_dump_setup(handle, fp);
+ }
+ for (k = 0; k < multi->slaves_count; ++k) {
+ fprintf(fp, "\nSlave #%d: ", k);
+ snd_pcm_dump(multi->slaves[k].handle, fp);
+ }
+ fprintf(fp, "\nBindings:\n");
+ for (k = 0; k < multi->binds_count; ++k) {
+ fprintf(fp, "Channel #%d: slave %d[%d]\n",
+ multi->binds[k].client_channel,
+ multi->binds[k].slave,
+ multi->binds[k].slave_channel);
+ }
+}
+
struct snd_pcm_ops snd_pcm_multi_ops = {
close: snd_pcm_multi_close,
nonblock: snd_pcm_multi_nonblock,
munmap_data: snd_pcm_multi_munmap_data,
file_descriptor: snd_pcm_multi_file_descriptor,
channels_mask: snd_pcm_multi_channels_mask,
+ dump: snd_pcm_multi_dump,
};
int snd_pcm_multi_create(snd_pcm_t **handlep, size_t slaves_count,
return 0;
}
+void snd_pcm_plugin_dump(snd_pcm_plugin_t *plugin, FILE *fp)
+{
+ fprintf(fp, "----------- %s\n", plugin->name);
+ fprintf(fp, "Buffer: %d frames\n", plugin->buf_frames);
+ if (plugin->src_format.interleave != plugin->dst_format.interleave) {
+ if (plugin->src_format.interleave)
+ fprintf(fp, "Interleaved -> Non interleaved\n");
+ else
+ fprintf(fp, "Non interleaved -> Interleaved\n");
+ }
+ if (plugin->src_format.channels != plugin->dst_format.channels) {
+ fprintf(fp, "Channels: %d -> %d\n",
+ plugin->src_format.channels,
+ plugin->dst_format.channels);
+ }
+ if (plugin->src_format.format != plugin->dst_format.format) {
+ fprintf(fp, "Format: %s -> %s\n",
+ snd_pcm_format_name(plugin->src_format.format),
+ snd_pcm_format_name(plugin->dst_format.format));
+ }
+ if (plugin->src_format.rate != plugin->dst_format.rate) {
+ fprintf(fp, "Rate: %d -> %d\n",
+ plugin->src_format.rate,
+ plugin->dst_format.rate);
+ }
+ if (plugin->dump)
+ plugin->dump(plugin, fp);
+}
+
/* snd_pcm_plug externs */
int snd_pcm_plug_clear(snd_pcm_plug_t *plug)
{
snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
snd_pcm_t *handle = plug->handle;
- unsigned int k, step, channels;
- size_t size = 0;
+ unsigned int k, step;
+ size_t result = 0;
assert(plug->frames_alloc);
- channels = handle->setup.format.channels;
if (handle->setup.format.interleave)
step = 1;
- else {
- step = channels;
- assert(count % channels == 0);
- }
+ else
+ step = handle->setup.format.channels;
for (k = 0; k < count; k += step) {
snd_pcm_plugin_channel_t *channels;
ssize_t frames;
- frames = snd_pcm_plug_client_channels_iovec(plug, vector, count, &channels);
- if (frames < 0)
+ frames = snd_pcm_plug_client_channels_iovec(plug, vector, step, &channels);
+ if (frames < 0) {
+ if (result > 0)
+ return result;
return frames;
+ }
while (1) {
unsigned int c;
ssize_t ret;
frames1 = plug->frames_alloc;
ret = snd_pcm_plug_write_transfer(plug, channels, frames1);
if (ret < 0) {
- if (size > 0)
- return size;
+ if (result > 0)
+ return result;
return ret;
}
- size += ret;
+ result += 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;
}
+ vector += step;
}
- return size;
+ return result;
}
ssize_t snd_pcm_plug_readv(void *private, snd_timestamp_t tstamp UNUSED, const struct iovec *vector, unsigned long count)
{
snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
snd_pcm_t *handle = plug->handle;
- unsigned int k, step, channels;
- size_t size = 0;
+ unsigned int k, step;
+ size_t result = 0;
assert(plug->frames_alloc);
- channels = handle->setup.format.channels;
if (handle->setup.format.interleave)
step = 1;
- else {
- step = channels;
- assert(count % channels == 0);
- }
+ else
+ step = handle->setup.format.channels;
for (k = 0; k < count; k += step) {
snd_pcm_plugin_channel_t *channels;
ssize_t frames;
- frames = snd_pcm_plug_client_channels_iovec(plug, vector, count, &channels);
- if (frames < 0)
+ frames = snd_pcm_plug_client_channels_iovec(plug, vector, step, &channels);
+ if (frames < 0) {
+ if (result > 0)
+ return result;
return frames;
+ }
while (1) {
unsigned int c;
ssize_t ret;
frames1 = plug->frames_alloc;
ret = snd_pcm_plug_read_transfer(plug, channels, frames1);
if (ret < 0) {
- if (size > 0)
- return size;
+ if (result > 0)
+ return result;
return ret;
}
- size += ret;
+ result += 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;
}
+ vector += step;
}
- return size;
+ return result;
}
ssize_t snd_pcm_plug_write(void *private, snd_timestamp_t tstamp UNUSED, const void *buf, size_t count)
return snd_pcm_file_descriptor(plug->slave);
}
+static void snd_pcm_plug_dump(void *private, FILE *fp)
+{
+ snd_pcm_plug_t *plug = (snd_pcm_plug_t*) private;
+ snd_pcm_t *handle = plug->handle;
+ snd_pcm_plugin_t *plugin;
+ fprintf(fp, "Plug PCM\n");
+ if (handle->valid_setup) {
+ fprintf(fp, "\nIts setup is:\n");
+ snd_pcm_dump_setup(handle, fp);
+ }
+ fprintf(fp, "\nPlugins:\n");
+ plugin = plug->first;
+ while (plugin) {
+ snd_pcm_plugin_dump(plugin, fp);
+ plugin = plugin->next;
+ }
+ fprintf(fp, "\n");
+}
+
static int snd_pcm_plug_params(void *private, snd_pcm_params_t *params);
struct snd_pcm_ops snd_pcm_plug_ops = {
munmap_data: snd_pcm_plug_munmap_data,
file_descriptor: snd_pcm_plug_file_descriptor,
channels_mask: snd_pcm_plug_channels_mask,
+ dump: snd_pcm_plug_dump,
};
static void snd_pcm_plug_slave_params(snd_pcm_plug_t *plug,
return frames;
}
+#ifndef __KERNEL__
+static void io_dump(snd_pcm_plugin_t *plugin, FILE *fp)
+{
+ snd_pcm_t *slave = plugin->plug->slave;
+ if (slave->valid_setup) {
+ fprintf(fp, "Slave: ");
+ snd_pcm_dump(slave, fp);
+ }
+}
+#endif
+
int snd_pcm_plugin_build_io(snd_pcm_plug_t *plug,
snd_pcm_format_t *format,
snd_pcm_plugin_t **r_plugin)
} else {
plugin->transfer = io_capture_transfer;
}
+#ifndef __KERNEL__
+ plugin->dump = io_dump;
+#endif
*r_plugin = plugin;
return 0;
static ssize_t mmap_src_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;
snd_pcm_plugin_channel_t *sv;
if (data->buffer)
snd_pcm_munmap(plugin->plug->slave);
}
-
+
+static void mmap_dump(snd_pcm_plugin_t *plugin, FILE *fp)
+{
+ snd_pcm_t *slave = plugin->plug->slave;
+ if (slave->valid_setup) {
+ fprintf(fp, "Slave: ");
+ snd_pcm_dump(slave, fp);
+ }
+}
+
int snd_pcm_plugin_build_mmap(snd_pcm_plug_t *plug,
snd_pcm_format_t *format,
snd_pcm_plugin_t **r_plugin)
}
plugin->action = mmap_action;
plugin->private_free = mmap_free;
+ plugin->dump = mmap_dump;
*r_plugin = plugin;
return 0;
}
struct ttable_dst {
int att; /* Attenuated */
- int nsrcs;
+ unsigned int nsrcs;
ttable_src_t* srcs;
route_channel_f func;
};
route_t *data = (route_t *)plugin->extra_data;
void *conv;
const snd_pcm_plugin_channel_t *src_channel = 0;
- int srcidx;
+ unsigned int srcidx;
char *src, *dst;
int src_step, dst_step;
for (srcidx = 0; srcidx < ttable->nsrcs; ++srcidx) {
ttable_dst_t *dp = data->ttable;
bitset_zero(vmask, schannels);
for (channel = 0; channel < dchannels; channel++, dp++) {
- int src;
+ unsigned int src;
ttable_src_t *sp;
if (!bitset_get(dst_vmask, channel))
continue;
ttable_dst_t *dp = data->ttable;
bitset_zero(vmask, dchannels);
for (channel = 0; channel < dchannels; channel++, dp++) {
- int src;
+ unsigned int src;
ttable_src_t *sp;
sp = dp->srcs;
for (src = 0; src < dp->nsrcs; src++, sp++) {
return width * 4 + endian * 2 + sign;
}
+#ifndef __KERNEL__
+static void route_dump(snd_pcm_plugin_t *plugin, FILE *fp)
+{
+ route_t *data;
+ ttable_dst_t *tdp;
+ unsigned int dst_channel, dst_nchannels;
+ data = (route_t *)plugin->extra_data;
+ tdp = data->ttable;
+ dst_nchannels = plugin->dst_format.channels;
+ for (dst_channel = 0; dst_channel < dst_nchannels; ++dst_channel) {
+ unsigned int k;
+ ttable_src_t *tsp = tdp->srcs;
+ fprintf(fp, "Channel %d = ", dst_channel);
+ for (k = 0; k < tdp->nsrcs; ++k) {
+ if (k > 0)
+ fprintf(fp, " + ");
+ fprintf(fp, "[%d]", tsp->channel);
+ if (tdp->att) {
+#if ROUTE_PLUGIN_USE_FLOAT
+ fprintf(fp, "*%g", tsp->as_float);
+#else
+ fprintf(fp, "*%d/%d", tsp->as_int, ROUTE_PLUGIN_RESOLUTION);
+#endif
+ }
+ ++tsp;
+ }
+ fprintf(fp, "\n");
+ ++tdp;
+ }
+}
+#endif
+
int snd_pcm_plugin_build_route(snd_pcm_plug_t *plug,
snd_pcm_format_t *src_format,
snd_pcm_format_t *dst_format,
plugin->transfer = route_transfer;
plugin->src_channels_mask = route_src_channels_mask;
plugin->dst_channels_mask = route_dst_channels_mask;
+#ifndef __KERNEL__
+ plugin->dump = route_dump;
+#endif
*r_plugin = plugin;
return 0;
}