From: Abramo Bagnara Date: Mon, 2 Oct 2000 06:58:38 +0000 (+0000) Subject: Cleaning and fixes X-Git-Tag: v1.0.3~1119 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=ebae7ebeb2cd55e5ed5cd45e68b45614f6599af6;p=alsa-lib.git Cleaning and fixes --- diff --git a/src/pcm/pcm_multi.c b/src/pcm/pcm_multi.c index 9451ad1a..f9c0990d 100644 --- a/src/pcm/pcm_multi.c +++ b/src/pcm/pcm_multi.c @@ -25,28 +25,25 @@ #include #include #include -#include #include "pcm_local.h" typedef struct { - snd_pcm_t *handle; - unsigned int channels_total; + snd_pcm_t *pcm; + unsigned int channels_count; int close_slave; } snd_pcm_multi_slave_t; typedef struct { - unsigned int client_channel; - unsigned int slave; + int slave_idx; unsigned int slave_channel; -} snd_pcm_multi_bind_t; +} snd_pcm_multi_channel_t; typedef struct { size_t slaves_count; snd_pcm_multi_slave_t *slaves; - size_t bindings_count; - snd_pcm_multi_bind_t *bindings; size_t channels_count; - int xfer_mode, mmap_shape; + snd_pcm_multi_channel_t *channels; + int xfer_mode; } snd_pcm_multi_t; static int snd_pcm_multi_close(snd_pcm_t *pcm) @@ -58,32 +55,30 @@ static int snd_pcm_multi_close(snd_pcm_t *pcm) int err; snd_pcm_multi_slave_t *slave = &multi->slaves[i]; if (slave->close_slave) { - err = snd_pcm_close(slave->handle); + err = snd_pcm_close(slave->pcm); if (err < 0) ret = err; } else - snd_pcm_unlink(slave->handle); + snd_pcm_unlink(slave->pcm); } free(multi->slaves); - free(multi->bindings); + free(multi->channels); free(multi); return ret; } -static int snd_pcm_multi_nonblock(snd_pcm_t *pcm, int nonblock) +static int snd_pcm_multi_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED) { - snd_pcm_multi_t *multi = pcm->private; - snd_pcm_t *handle = multi->slaves[0].handle; - return snd_pcm_nonblock(handle, nonblock); + return 0; } static int snd_pcm_multi_info(snd_pcm_t *pcm, snd_pcm_info_t *info) { snd_pcm_multi_t *multi = pcm->private; int err; - snd_pcm_t *handle_0 = multi->slaves[0].handle; + snd_pcm_t *slave_0 = multi->slaves[0].pcm; /* FIXME */ - err = snd_pcm_info(handle_0, info); + err = snd_pcm_info(slave_0, info); if (err < 0) return err; return 0; @@ -94,23 +89,31 @@ static int snd_pcm_multi_params_info(snd_pcm_t *pcm, snd_pcm_params_info_t *info snd_pcm_multi_t *multi = pcm->private; 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 | - SND_PCM_PARAMS_MMAP_SHAPE | - SND_PCM_PARAMS_XFER_MODE); - err = snd_pcm_params_info(handle_0, info); + snd_pcm_t *slave_0 = multi->slaves[0].pcm; + unsigned int req_mask = info->req_mask; + unsigned int channels = info->req.format.channels; + if ((req_mask & SND_PCM_PARAMS_CHANNELS) && + channels != multi->channels_count) { + info->req.fail_mask |= SND_PCM_PARAMS_CHANNELS; + info->req.fail_reason = SND_PCM_PARAMS_FAIL_INVAL; + return -EINVAL; + } + info->req_mask |= SND_PCM_PARAMS_CHANNELS; + info->req.format.channels = multi->slaves[0].channels_count; + err = snd_pcm_params_info(slave_0, info); + info->req_mask = req_mask; + info->req.format.channels = channels; 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_t *slave_i = multi->slaves[i].pcm; snd_pcm_params_info_t info_i; info_i = *info; info_i.req_mask |= SND_PCM_PARAMS_CHANNELS; - info_i.req.format.channels = multi->slaves[i].channels_total; - err = snd_pcm_params_info(handle_i, &info_i); + info_i.req.format.channels = multi->slaves[i].channels_count; + err = snd_pcm_params_info(slave_i, &info_i); if (err < 0) return err; info->formats &= info_i.formats; @@ -131,7 +134,14 @@ static int snd_pcm_multi_params_info(snd_pcm_t *pcm, snd_pcm_params_info_t *info info->max_fragments = info_i.max_fragments; info->flags &= info_i.flags; } - info->req_mask = old_mask; + if (info->flags & SND_PCM_INFO_INTERLEAVED) { + if (multi->slaves_count > 0) { + info->flags &= ~SND_PCM_INFO_INTERLEAVED; + info->flags |= SND_PCM_INFO_COMPLEX; + } + } else if (!(info->flags & SND_PCM_INFO_NONINTERLEAVED)) + info->flags |= SND_PCM_INFO_COMPLEX; + info->req_mask = req_mask; return 0; } @@ -140,42 +150,42 @@ static int snd_pcm_multi_params(snd_pcm_t *pcm, snd_pcm_params_t *params) snd_pcm_multi_t *multi = pcm->private; unsigned int i; snd_pcm_params_t p; - if (params->format.channels != multi->channels_count) + int err = 0; + if (params->format.channels != multi->channels_count) { + params->fail_mask = SND_PCM_PARAMS_CHANNELS; + params->fail_reason = SND_PCM_PARAMS_FAIL_INVAL; return -EINVAL; - multi->xfer_mode = params->xfer_mode; - multi->mmap_shape = params->mmap_shape; + } p = *params; for (i = 0; i < multi->slaves_count; ++i) { - int err; - snd_pcm_t *handle = multi->slaves[i].handle; - if (handle->mmap_data) { - err = snd_pcm_munmap_data(handle); + snd_pcm_t *slave = multi->slaves[i].pcm; + if (slave->mmap_data) { + err = snd_pcm_munmap_data(slave); if (err < 0) return err; } - p.xfer_mode = SND_PCM_XFER_UNSPECIFIED; - p.mmap_shape = SND_PCM_MMAP_UNSPECIFIED; - p.format.channels = multi->slaves[i].channels_total; + p.format.channels = multi->slaves[i].channels_count; #if 1 - p.xrun_max = ~0; + p.xrun_mode = SND_PCM_XRUN_NONE; #endif - err = snd_pcm_params(handle, &p); + err = snd_pcm_params(slave, &p); if (err < 0) { params->fail_mask = p.fail_mask; params->fail_reason = p.fail_reason; - return err; + break; } } for (i = 0; i < multi->slaves_count; ++i) { - snd_pcm_t *handle = multi->slaves[i].handle; - int err = snd_pcm_mmap_data(handle, NULL); - if (err < 0) - return err; - if (pcm->stream == SND_PCM_STREAM_PLAYBACK) - snd_pcm_areas_silence(handle->mmap_areas, 0, handle->setup.format.channels, - handle->setup.buffer_size, handle->setup.format.sfmt); + snd_pcm_t *slave = multi->slaves[i].pcm; + snd_pcm_mmap_data(slave, NULL); + if (pcm->stream == SND_PCM_STREAM_PLAYBACK && + err == 0) + snd_pcm_areas_silence(slave->mmap_areas, 0, slave->setup.format.channels, + slave->setup.buffer_size, slave->setup.format.sfmt); } - return 0; + if (err == 0) + multi->xfer_mode = params->xfer_mode; + return err; } static int snd_pcm_multi_setup(snd_pcm_t *pcm, snd_pcm_setup_t *setup) @@ -183,14 +193,12 @@ static int snd_pcm_multi_setup(snd_pcm_t *pcm, snd_pcm_setup_t *setup) snd_pcm_multi_t *multi = pcm->private; unsigned int i; int err; - size_t frames_alloc; - err = snd_pcm_setup(multi->slaves[0].handle, setup); + err = snd_pcm_setup(multi->slaves[0].pcm, setup); if (err < 0) return err; - frames_alloc = multi->slaves[0].handle->setup.frag_size; for (i = 1; i < multi->slaves_count; ++i) { snd_pcm_setup_t s; - snd_pcm_t *sh = multi->slaves[i].handle; + snd_pcm_t *sh = multi->slaves[i].pcm; err = snd_pcm_setup(sh, &s); if (err < 0) return err; @@ -207,123 +215,107 @@ static int snd_pcm_multi_setup(snd_pcm_t *pcm, snd_pcm_setup_t *setup) setup->xfer_mode = SND_PCM_XFER_NONINTERLEAVED; else setup->xfer_mode = multi->xfer_mode; - if (multi->mmap_shape != SND_PCM_MMAP_UNSPECIFIED && - multi->mmap_shape != setup->mmap_shape) - return -EINVAL; return 0; } static int snd_pcm_multi_status(snd_pcm_t *pcm, snd_pcm_status_t *status) { snd_pcm_multi_t *multi = pcm->private; - snd_pcm_t *handle = multi->slaves[0].handle; - return snd_pcm_status(handle, status); + snd_pcm_t *slave = multi->slaves[0].pcm; + return snd_pcm_status(slave, status); } static int snd_pcm_multi_state(snd_pcm_t *pcm) { snd_pcm_multi_t *multi = pcm->private; - snd_pcm_t *handle = multi->slaves[0].handle; - return snd_pcm_state(handle); + snd_pcm_t *slave = multi->slaves[0].pcm; + return snd_pcm_state(slave); } static int snd_pcm_multi_delay(snd_pcm_t *pcm, ssize_t *delayp) { snd_pcm_multi_t *multi = pcm->private; - snd_pcm_t *handle = multi->slaves[0].handle; - return snd_pcm_delay(handle, delayp); + snd_pcm_t *slave = multi->slaves[0].pcm; + return snd_pcm_delay(slave, delayp); } static ssize_t snd_pcm_multi_avail_update(snd_pcm_t *pcm) { snd_pcm_multi_t *multi = pcm->private; - snd_pcm_t *handle = multi->slaves[0].handle; - return snd_pcm_avail_update(handle); + snd_pcm_t *slave = multi->slaves[0].pcm; + return snd_pcm_avail_update(slave); } static int snd_pcm_multi_prepare(snd_pcm_t *pcm) { snd_pcm_multi_t *multi = pcm->private; - return snd_pcm_prepare(multi->slaves[0].handle); + return snd_pcm_prepare(multi->slaves[0].pcm); } static int snd_pcm_multi_start(snd_pcm_t *pcm) { snd_pcm_multi_t *multi = pcm->private; - return snd_pcm_start(multi->slaves[0].handle); + return snd_pcm_start(multi->slaves[0].pcm); } -static int snd_pcm_multi_stop(snd_pcm_t *pcm) +static int snd_pcm_multi_drop(snd_pcm_t *pcm) { snd_pcm_multi_t *multi = pcm->private; - return snd_pcm_stop(multi->slaves[0].handle); + return snd_pcm_drop(multi->slaves[0].pcm); } static int snd_pcm_multi_drain(snd_pcm_t *pcm) { snd_pcm_multi_t *multi = pcm->private; - return snd_pcm_drain(multi->slaves[0].handle); + return snd_pcm_drain(multi->slaves[0].pcm); } static int snd_pcm_multi_pause(snd_pcm_t *pcm, int enable) { snd_pcm_multi_t *multi = pcm->private; - return snd_pcm_pause(multi->slaves[0].handle, enable); + return snd_pcm_pause(multi->slaves[0].pcm, enable); } static int snd_pcm_multi_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t *info) { - int err; snd_pcm_multi_t *multi = pcm->private; unsigned int channel = info->channel; - unsigned int i; - for (i = 0; i < multi->bindings_count; ++i) { - if (multi->bindings[i].client_channel == channel) { - info->channel = multi->bindings[i].slave_channel; - err = snd_pcm_channel_info(multi->slaves[multi->bindings[i].slave].handle, info); - info->channel = channel; - return err; - } - } + snd_pcm_multi_channel_t *c = &multi->channels[channel]; + int err; + if (c->slave_idx < 0) + return -ENXIO; + info->channel = c->slave_channel; + err = snd_pcm_channel_info(multi->slaves[c->slave_idx].pcm, info); info->channel = channel; - return -EINVAL; + return err; } static int snd_pcm_multi_channel_params(snd_pcm_t *pcm, snd_pcm_channel_params_t *params) { - int err; snd_pcm_multi_t *multi = pcm->private; unsigned int channel = params->channel; - unsigned int i; - for (i = 0; i < multi->bindings_count; ++i) { - if (multi->bindings[i].client_channel == channel) { - params->channel = multi->bindings[i].slave_channel; - err = snd_pcm_channel_params(multi->slaves[multi->bindings[i].slave].handle, params); - params->channel = channel; - return err; - } - } + snd_pcm_multi_channel_t *c = &multi->channels[channel]; + int err; + if (c->slave_idx < 0) + return -ENXIO; + params->channel = c->slave_channel; + err = snd_pcm_channel_params(multi->slaves[c->slave_idx].pcm, params); params->channel = channel; - return -EINVAL; + return err; } static int snd_pcm_multi_channel_setup(snd_pcm_t *pcm, snd_pcm_channel_setup_t *setup) { - int err; snd_pcm_multi_t *multi = pcm->private; unsigned int channel = setup->channel; - unsigned int i; - for (i = 0; i < multi->bindings_count; ++i) { - if (multi->bindings[i].client_channel == channel) { - setup->channel = multi->bindings[i].slave_channel; - err = snd_pcm_channel_setup(multi->slaves[multi->bindings[i].slave].handle, setup); - setup->channel = channel; - return err; - } - } - memset(setup, 0, sizeof(*setup)); + snd_pcm_multi_channel_t *c = &multi->channels[channel]; + int err; + if (c->slave_idx < 0) + return -ENXIO; + setup->channel = c->slave_channel; + err = snd_pcm_channel_setup(multi->slaves[c->slave_idx].pcm, setup); setup->channel = channel; - return 0; + return err; } static ssize_t snd_pcm_multi_rewind(snd_pcm_t *pcm, size_t frames) @@ -333,8 +325,8 @@ static ssize_t snd_pcm_multi_rewind(snd_pcm_t *pcm, size_t frames) size_t pos[multi->slaves_count]; memset(pos, 0, sizeof(pos)); for (i = 0; i < multi->slaves_count; ++i) { - snd_pcm_t *handle_i = multi->slaves[i].handle; - ssize_t f = snd_pcm_rewind(handle_i, frames); + snd_pcm_t *slave_i = multi->slaves[i].pcm; + ssize_t f = snd_pcm_rewind(slave_i, frames); if (f < 0) return f; pos[i] = f; @@ -342,10 +334,10 @@ static ssize_t snd_pcm_multi_rewind(snd_pcm_t *pcm, size_t frames) } /* Realign the pointers */ for (i = 0; i < multi->slaves_count; ++i) { - snd_pcm_t *handle_i = multi->slaves[i].handle; + snd_pcm_t *slave_i = multi->slaves[i].pcm; size_t f = pos[i] - frames; if (f > 0) - snd_pcm_mmap_appl_forward(handle_i, f); + snd_pcm_mmap_appl_forward(slave_i, f); } return frames; } @@ -353,14 +345,14 @@ static ssize_t snd_pcm_multi_rewind(snd_pcm_t *pcm, size_t frames) static int snd_pcm_multi_mmap_status(snd_pcm_t *pcm) { snd_pcm_multi_t *multi = pcm->private; - pcm->mmap_status = multi->slaves[0].handle->mmap_status; + pcm->mmap_status = multi->slaves[0].pcm->mmap_status; return 0; } static int snd_pcm_multi_mmap_control(snd_pcm_t *pcm) { snd_pcm_multi_t *multi = pcm->private; - pcm->mmap_control = multi->slaves[0].handle->mmap_control; + pcm->mmap_control = multi->slaves[0].pcm->mmap_control; return 0; } @@ -369,15 +361,15 @@ static int snd_pcm_multi_mmap_data(snd_pcm_t *pcm) snd_pcm_multi_t *multi = pcm->private; unsigned int i; for (i = 0; i < multi->slaves_count; ++i) { - snd_pcm_t *handle = multi->slaves[i].handle; - int err = snd_pcm_mmap_data(handle, 0); + snd_pcm_t *slave = multi->slaves[i].pcm; + int err = snd_pcm_mmap_data(slave, 0); snd_pcm_setup_t *setup; if (err < 0) return err; - setup = &handle->setup; + setup = &slave->setup; if (pcm->stream == SND_PCM_STREAM_PLAYBACK) { snd_pcm_channel_area_t areas[setup->format.channels]; - err = snd_pcm_mmap_get_areas(handle, areas); + err = snd_pcm_mmap_get_areas(slave, areas); if (err < 0) return err; err = snd_pcm_areas_silence(areas, 0, setup->format.channels, setup->buffer_size, setup->format.sfmt); @@ -385,7 +377,7 @@ static int snd_pcm_multi_mmap_data(snd_pcm_t *pcm) return err; } } - pcm->mmap_data = multi->slaves[0].handle->mmap_data; + pcm->mmap_data = multi->slaves[0].pcm->mmap_data; return 0; } @@ -405,8 +397,8 @@ static int snd_pcm_multi_munmap_data(snd_pcm_t *pcm) unsigned int i; int ret = 0; for (i = 0; i < multi->slaves_count; ++i) { - snd_pcm_t *handle = multi->slaves[i].handle; - int err = snd_pcm_munmap_data(handle); + snd_pcm_t *slave = multi->slaves[i].pcm; + int err = snd_pcm_munmap_data(slave); if (err < 0) ret = err; } @@ -419,8 +411,8 @@ static ssize_t snd_pcm_multi_mmap_forward(snd_pcm_t *pcm, size_t size) unsigned int i; for (i = 0; i < multi->slaves_count; ++i) { - snd_pcm_t *handle = multi->slaves[i].handle; - ssize_t frames = snd_pcm_mmap_forward(handle, size); + snd_pcm_t *slave = multi->slaves[i].pcm; + ssize_t frames = snd_pcm_mmap_forward(slave, size); if (frames < 0) return frames; if (i == 0) { @@ -440,15 +432,17 @@ static int snd_pcm_multi_channels_mask(snd_pcm_t *pcm, bitset_t *cmask) bitset_t *cmasks[multi->slaves_count]; int err; for (i = 0; i < multi->slaves_count; ++i) - cmasks[i] = bitset_alloc(multi->slaves[i].channels_total); - for (i = 0; i < multi->bindings_count; ++i) { - snd_pcm_multi_bind_t *b = &multi->bindings[i]; - if (bitset_get(cmask, b->client_channel)) - bitset_set(cmasks[b->slave], b->slave_channel); + cmasks[i] = bitset_alloc(multi->slaves[i].channels_count); + for (i = 0; i < multi->channels_count; ++i) { + snd_pcm_multi_channel_t *b = &multi->channels[i]; + if (b->slave_idx < 0) + continue; + if (bitset_get(cmask, i)) + bitset_set(cmasks[b->slave_idx], b->slave_channel); } for (i = 0; i < multi->slaves_count; ++i) { - snd_pcm_t *handle = multi->slaves[i].handle; - err = snd_pcm_channels_mask(handle, cmasks[i]); + snd_pcm_t *slave = multi->slaves[i].pcm; + err = snd_pcm_channels_mask(slave, cmasks[i]); if (err < 0) { for (i = 0; i <= multi->slaves_count; ++i) free(cmasks[i]); @@ -456,10 +450,12 @@ static int snd_pcm_multi_channels_mask(snd_pcm_t *pcm, bitset_t *cmask) } } bitset_zero(cmask, pcm->setup.format.channels); - for (i = 0; i < multi->bindings_count; ++i) { - snd_pcm_multi_bind_t *b = &multi->bindings[i]; - if (bitset_get(cmasks[b->slave], b->slave_channel)) - bitset_set(cmask, b->client_channel); + for (i = 0; i < multi->channels_count; ++i) { + snd_pcm_multi_channel_t *b = &multi->channels[i]; + if (b->slave_idx < 0) + continue; + if (bitset_get(cmasks[b->slave_idx], b->slave_channel)) + bitset_set(cmask, i); } for (i = 0; i < multi->slaves_count; ++i) free(cmasks[i]); @@ -469,8 +465,8 @@ static int snd_pcm_multi_channels_mask(snd_pcm_t *pcm, bitset_t *cmask) int snd_pcm_multi_poll_descriptor(snd_pcm_t *pcm) { snd_pcm_multi_t *multi = pcm->private; - snd_pcm_t *handle = multi->slaves[0].handle; - return snd_pcm_poll_descriptor(handle); + snd_pcm_t *slave = multi->slaves[0].pcm; + return snd_pcm_poll_descriptor(slave); } static void snd_pcm_multi_dump(snd_pcm_t *pcm, FILE *fp) @@ -484,14 +480,15 @@ static void snd_pcm_multi_dump(snd_pcm_t *pcm, FILE *fp) } for (k = 0; k < multi->slaves_count; ++k) { fprintf(fp, "\nSlave #%d: ", k); - snd_pcm_dump(multi->slaves[k].handle, fp); + snd_pcm_dump(multi->slaves[k].pcm, fp); } - fprintf(fp, "\nBindings:\n"); - for (k = 0; k < multi->bindings_count; ++k) { + fprintf(fp, "\nChannel bindings:\n"); + for (k = 0; k < multi->channels_count; ++k) { + snd_pcm_multi_channel_t *c = &multi->channels[k]; + if (c->slave_idx < 0) + continue; fprintf(fp, "Channel #%d: slave %d[%d]\n", - multi->bindings[k].client_channel, - multi->bindings[k].slave, - multi->bindings[k].slave_channel); + k, c->slave_idx, c->slave_channel); } } @@ -520,7 +517,7 @@ struct snd_pcm_fast_ops snd_pcm_multi_fast_ops = { delay: snd_pcm_multi_delay, prepare: snd_pcm_multi_prepare, start: snd_pcm_multi_start, - stop: snd_pcm_multi_stop, + drop: snd_pcm_multi_drop, drain: snd_pcm_multi_drain, pause: snd_pcm_multi_pause, writei: snd_pcm_mmap_writei, @@ -536,22 +533,20 @@ struct snd_pcm_fast_ops snd_pcm_multi_fast_ops = { int snd_pcm_multi_create(snd_pcm_t **handlep, size_t slaves_count, snd_pcm_t **slaves_handle, size_t *schannels_count, - size_t bindings_count, unsigned int *bindings_cchannel, - unsigned int *bindings_slave, unsigned int *bindings_schannel, + size_t channels_count, + int *sidxs, unsigned int *schannels, int close_slaves) { snd_pcm_t *handle; snd_pcm_multi_t *multi; - size_t channels = 0; unsigned int i; int err; int stream; - char client_map[32] = { 0 }; char slave_map[32][32] = { { 0 } }; assert(handlep); assert(slaves_count > 0 && slaves_handle && schannels_count); - assert(bindings_count > 0 && bindings_slave && bindings_cchannel && bindings_schannel); + assert(channels_count > 0 && sidxs && schannels); multi = calloc(1, sizeof(snd_pcm_multi_t)); if (!multi) { @@ -562,32 +557,29 @@ int snd_pcm_multi_create(snd_pcm_t **handlep, size_t slaves_count, multi->slaves_count = slaves_count; multi->slaves = calloc(slaves_count, sizeof(*multi->slaves)); - multi->bindings_count = bindings_count; - multi->bindings = calloc(bindings_count, sizeof(*multi->bindings)); + multi->channels_count = channels_count; + multi->channels = calloc(channels_count, sizeof(*multi->channels)); for (i = 0; i < slaves_count; ++i) { snd_pcm_multi_slave_t *slave = &multi->slaves[i]; assert(slaves_handle[i]->stream == stream); - slave->handle = slaves_handle[i]; - slave->channels_total = schannels_count[i]; + slave->pcm = slaves_handle[i]; + slave->channels_count = schannels_count[i]; slave->close_slave = close_slaves; if (i != 0) snd_pcm_link(slaves_handle[i-1], slaves_handle[i]); } - for (i = 0; i < bindings_count; ++i) { - snd_pcm_multi_bind_t *bind = &multi->bindings[i]; - assert(bindings_slave[i] < slaves_count); - assert(bindings_schannel[i] < schannels_count[bindings_slave[i]]); - bind->client_channel = bindings_cchannel[i]; - bind->slave = bindings_slave[i]; - bind->slave_channel = bindings_schannel[i]; - assert(!slave_map[bindings_slave[i]][bindings_schannel[i]]); - slave_map[bindings_slave[i]][bindings_schannel[i]] = 1; - assert(!client_map[bindings_cchannel[i]]); - client_map[bindings_cchannel[i]] = 1; - if (bindings_cchannel[i] >= channels) - channels = bindings_cchannel[i] + 1; + for (i = 0; i < channels_count; ++i) { + snd_pcm_multi_channel_t *bind = &multi->channels[i]; + assert(sidxs[i] < (int)slaves_count); + assert(schannels[i] < schannels_count[sidxs[i]]); + bind->slave_idx = sidxs[i]; + bind->slave_channel = schannels[i]; + if (sidxs[i] < 0) + continue; + assert(!slave_map[sidxs[i]][schannels[i]]); + slave_map[sidxs[i]][schannels[i]] = 1; } - multi->channels_count = channels; + multi->channels_count = channels_count; handle = calloc(1, sizeof(snd_pcm_t)); if (!handle) { @@ -596,7 +588,7 @@ int snd_pcm_multi_create(snd_pcm_t **handlep, size_t slaves_count, } handle->type = SND_PCM_TYPE_MULTI; handle->stream = stream; - handle->mode = multi->slaves[0].handle->mode; + handle->mode = multi->slaves[0].pcm->mode; handle->ops = &snd_pcm_multi_ops; handle->op_arg = handle; handle->fast_ops = &snd_pcm_multi_fast_ops; @@ -623,11 +615,10 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, char *name, snd_config_t *conf, char **slaves_name = NULL; snd_pcm_t **slaves_pcm = NULL; size_t *slaves_channels = NULL; - unsigned int *bindings_cchannel = NULL; - unsigned int *bindings_slave = NULL; - unsigned int *bindings_schannel = NULL; + unsigned int *channels_sidx = NULL; + unsigned int *channels_schannel = NULL; size_t slaves_count = 0; - size_t bindings_count = 0; + size_t channels_count = 0; snd_config_foreach(i, conf) { snd_config_t *n = snd_config_entry(i); if (strcmp(n->id, "comment") == 0) @@ -656,27 +647,38 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, char *name, snd_config_t *conf, ++slaves_count; } snd_config_foreach(i, binding) { - ++bindings_count; + int cchannel = -1; + char *p; + snd_config_t *m = snd_config_entry(i); + errno = 0; + cchannel = strtol(m->id, &p, 10); + if (errno || *p || cchannel < 0) + return -EINVAL; + if ((unsigned)cchannel > channels_count) + channels_count = cchannel + 1; } + if (channels_count == 0) + return -EINVAL; slaves_id = calloc(slaves_count, sizeof(*slaves_id)); slaves_name = calloc(slaves_count, sizeof(*slaves_name)); slaves_pcm = calloc(slaves_count, sizeof(*slaves_pcm)); slaves_channels = calloc(slaves_count, sizeof(*slaves_channels)); - bindings_cchannel = calloc(bindings_count, sizeof(*bindings_cchannel)); - bindings_slave = calloc(bindings_count, sizeof(*bindings_slave)); - bindings_schannel = calloc(bindings_count, sizeof(*bindings_schannel)); + channels_sidx = calloc(channels_count, sizeof(*channels_sidx)); + channels_schannel = calloc(channels_count, sizeof(*channels_schannel)); idx = 0; + for (idx = 0; idx < channels_count; ++idx) + channels_sidx[idx] = -1; snd_config_foreach(i, slave) { snd_config_t *m = snd_config_entry(i); - char *pcm = NULL; + char *name = NULL; long channels = -1; slaves_id[idx] = snd_config_id(m); snd_config_foreach(j, m) { snd_config_t *n = snd_config_entry(j); if (strcmp(n->id, "comment") == 0) continue; - if (strcmp(n->id, "pcm") == 0) { - err = snd_config_string_get(n, &pcm); + if (strcmp(n->id, "name") == 0) { + err = snd_config_string_get(n, &name); if (err < 0) goto _free; continue; @@ -690,33 +692,28 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, char *name, snd_config_t *conf, err = -EINVAL; goto _free; } - if (!pcm || channels < 0) { + if (!name || channels < 0) { err = -EINVAL; goto _free; } - slaves_name[idx] = strdup(pcm); + slaves_name[idx] = strdup(name); slaves_channels[idx] = channels; ++idx; } - idx = 0; snd_config_foreach(i, binding) { snd_config_t *m = snd_config_entry(i); - long cchannel = -1, schannel = -1; + long cchannel = -1; + long schannel = -1; int slave = -1; long val; char *str; + cchannel = strtol(m->id, 0, 10); snd_config_foreach(j, m) { snd_config_t *n = snd_config_entry(j); if (strcmp(n->id, "comment") == 0) continue; - if (strcmp(n->id, "client_channel") == 0) { - err = snd_config_integer_get(n, &cchannel); - if (err < 0) - goto _free; - continue; - } - if (strcmp(n->id, "slave") == 0) { + if (strcmp(n->id, "sidx") == 0) { char buf[32]; unsigned int k; err = snd_config_string_get(n, &str); @@ -733,7 +730,7 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, char *name, snd_config_t *conf, } continue; } - if (strcmp(n->id, "slave_channel") == 0) { + if (strcmp(n->id, "schannel") == 0) { err = snd_config_integer_get(n, &schannel); if (err < 0) goto _free; @@ -754,10 +751,8 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, char *name, snd_config_t *conf, err = -EINVAL; goto _free; } - bindings_cchannel[idx] = cchannel; - bindings_slave[idx] = slave; - bindings_schannel[idx] = schannel; - ++idx; + channels_sidx[cchannel] = slave; + channels_schannel[cchannel] = schannel; } for (idx = 0; idx < slaves_count; ++idx) { @@ -767,8 +762,8 @@ int _snd_pcm_multi_open(snd_pcm_t **pcmp, char *name, snd_config_t *conf, } err = snd_pcm_multi_create(pcmp, slaves_count, slaves_pcm, slaves_channels, - bindings_count, bindings_cchannel, - bindings_slave, bindings_schannel, + channels_count, + channels_sidx, channels_schannel, 1); _free: if (err < 0) { @@ -785,12 +780,10 @@ _free: free(slaves_pcm); if (slaves_channels) free(slaves_channels); - if (bindings_cchannel) - free(bindings_cchannel); - if (bindings_slave) - free(bindings_slave); - if (bindings_schannel) - free(bindings_schannel); + if (channels_sidx) + free(channels_sidx); + if (channels_schannel) + free(channels_schannel); return err; }