From: Abramo Bagnara Date: Mon, 17 Jul 2000 15:33:29 +0000 (+0000) Subject: Added dump facility. Continued pcm_multi implementation X-Git-Tag: v1.0.3~1196 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=84cb338f8320fd98ac7c6233cd250355f2f00ba4;p=alsa-lib.git Added dump facility. Continued pcm_multi implementation --- diff --git a/include/pcm.h b/include/pcm.h index 641c5750..2bbda9aa 100644 --- a/include/pcm.h +++ b/include/pcm.h @@ -146,6 +146,7 @@ ssize_t snd_pcm_read(snd_pcm_t *handle, void *buffer, size_t size); 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); @@ -176,9 +177,9 @@ ssize_t snd_pcm_mmap_read_frames(snd_pcm_t *handle, const void *buffer, size_t f 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); @@ -274,6 +275,7 @@ struct snd_stru_pcm_plugin { 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; @@ -290,15 +292,11 @@ struct snd_stru_pcm_plugin { 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); @@ -371,6 +369,12 @@ int snd_pcm_plugin_build_copy(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 diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c index 7b23a0b5..d63e36ca 100644 --- a/src/pcm/pcm.c +++ b/src/pcm/pcm.c @@ -249,6 +249,8 @@ ssize_t snd_pcm_writev(snd_pcm_t *handle, const struct iovec *vector, unsigned l 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); } @@ -366,6 +368,7 @@ int snd_pcm_dump_setup(snd_pcm_t *handle, FILE *fp) { 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)); @@ -392,7 +395,15 @@ int snd_pcm_dump_setup(snd_pcm_t *handle, FILE *fp) 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) @@ -400,7 +411,7 @@ const char *snd_pcm_get_format_name(int format) 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) @@ -408,7 +419,7 @@ const char *snd_pcm_get_format_description(int format) 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) diff --git a/src/pcm/pcm_hw.c b/src/pcm/pcm_hw.c index f6d8eae0..dcbc01ce 100644 --- a/src/pcm/pcm_hw.c +++ b/src/pcm/pcm_hw.c @@ -32,6 +32,7 @@ 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" @@ -330,6 +331,21 @@ static int snd_pcm_hw_channels_mask(void *private UNUSED, 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, @@ -359,6 +375,7 @@ struct snd_pcm_ops snd_pcm_hw_ops = { 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) @@ -436,6 +453,9 @@ int snd_pcm_hw_open_subdevice(snd_pcm_t **handlep, int card, int device, int sub 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; diff --git a/src/pcm/pcm_local.h b/src/pcm/pcm_local.h index dedaa7b0..c569f27b 100644 --- a/src/pcm/pcm_local.h +++ b/src/pcm/pcm_local.h @@ -51,6 +51,7 @@ struct snd_pcm_ops { 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 { diff --git a/src/pcm/pcm_multi.c b/src/pcm/pcm_multi.c index 6dfb62ab..9f9b5178 100644 --- a/src/pcm/pcm_multi.c +++ b/src/pcm/pcm_multi.c @@ -50,6 +50,7 @@ typedef struct { 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; @@ -99,6 +100,7 @@ static int snd_pcm_multi_info(void *private, snd_pcm_info_t *info) 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; @@ -115,12 +117,17 @@ static int snd_pcm_multi_params_info(void *private, snd_pcm_params_info_t *info) 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; @@ -141,6 +148,7 @@ static int snd_pcm_multi_params_info(void *private, snd_pcm_params_info_t *info) if (info_i.max_fragments < info->max_fragments) info->max_fragments = info_i.max_fragments; } + info->req_mask = old_mask; return 0; } @@ -166,6 +174,9 @@ static int snd_pcm_multi_params(void *private, snd_pcm_params_t *params) 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; @@ -186,9 +197,12 @@ static int snd_pcm_multi_setup(void *private, snd_pcm_setup_t *setup) 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; @@ -219,7 +233,7 @@ static int snd_pcm_multi_setup(void *private, snd_pcm_setup_t *setup) 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, @@ -237,9 +251,11 @@ static int snd_pcm_multi_setup(void *private, snd_pcm_setup_t *setup) 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; @@ -376,14 +392,14 @@ static ssize_t snd_pcm_multi_frame_data(void *private, off_t offset) } 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]; @@ -394,41 +410,147 @@ ssize_t snd_pcm_multi_write(void *private, snd_timestamp_t timestamp UNUSED, con 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; @@ -577,6 +699,29 @@ int snd_pcm_multi_file_descriptor(void *private) 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, @@ -606,6 +751,7 @@ struct snd_pcm_ops snd_pcm_multi_ops = { 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, diff --git a/src/pcm/pcm_plug.c b/src/pcm/pcm_plug.c index 8de2134f..44677119 100644 --- a/src/pcm/pcm_plug.c +++ b/src/pcm/pcm_plug.c @@ -65,6 +65,35 @@ int snd_pcm_plugin_append(snd_pcm_plugin_t *plugin) 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) @@ -378,22 +407,22 @@ ssize_t snd_pcm_plug_writev(void *private, snd_timestamp_t tstamp UNUSED, const { 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; @@ -402,41 +431,42 @@ ssize_t snd_pcm_plug_writev(void *private, snd_timestamp_t tstamp UNUSED, const 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; @@ -445,19 +475,20 @@ ssize_t snd_pcm_plug_readv(void *private, snd_timestamp_t tstamp UNUSED, const s 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) @@ -574,6 +605,25 @@ int snd_pcm_plug_file_descriptor(void *private) 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 = { @@ -605,6 +655,7 @@ 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, diff --git a/src/pcm/plugin/io.c b/src/pcm/plugin/io.c index a449ec67..5848773e 100644 --- a/src/pcm/plugin/io.c +++ b/src/pcm/plugin/io.c @@ -118,6 +118,17 @@ static ssize_t io_src_channels(snd_pcm_plugin_t *plugin, 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) @@ -141,6 +152,9 @@ int snd_pcm_plugin_build_io(snd_pcm_plug_t *plug, } else { plugin->transfer = io_capture_transfer; } +#ifndef __KERNEL__ + plugin->dump = io_dump; +#endif *r_plugin = plugin; return 0; diff --git a/src/pcm/plugin/mmap.c b/src/pcm/plugin/mmap.c index 177e04fb..869cda79 100644 --- a/src/pcm/plugin/mmap.c +++ b/src/pcm/plugin/mmap.c @@ -42,8 +42,8 @@ typedef struct mmap_private_data { 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; @@ -272,7 +272,16 @@ static void mmap_free(snd_pcm_plugin_t *plugin, void *private_data UNUSED) 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) @@ -300,6 +309,7 @@ int snd_pcm_plugin_build_mmap(snd_pcm_plug_t *plug, } plugin->action = mmap_action; plugin->private_free = mmap_free; + plugin->dump = mmap_dump; *r_plugin = plugin; return 0; } diff --git a/src/pcm/plugin/route.c b/src/pcm/plugin/route.c index 6368df9e..cd439f4d 100644 --- a/src/pcm/plugin/route.c +++ b/src/pcm/plugin/route.c @@ -61,7 +61,7 @@ typedef struct { struct ttable_dst { int att; /* Attenuated */ - int nsrcs; + unsigned int nsrcs; ttable_src_t* srcs; route_channel_f func; }; @@ -104,7 +104,7 @@ static void route_to_channel_from_one(snd_pcm_plugin_t *plugin, 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) { @@ -373,7 +373,7 @@ int route_src_channels_mask(snd_pcm_plugin_t *plugin, 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; @@ -396,7 +396,7 @@ int route_dst_channels_mask(snd_pcm_plugin_t *plugin, 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++) { @@ -535,6 +535,38 @@ int getput_index(int format) 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, @@ -581,6 +613,9 @@ int snd_pcm_plugin_build_route(snd_pcm_plug_t *plug, 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; }