From mboxrd@z Thu Jan 1 00:00:00 1970 From: Takashi Iwai Subject: Re: [PATCH 2/3] route: Select slave chmap based on ttable information Date: Fri, 21 Feb 2014 16:49:21 +0100 Message-ID: References: <1392996262-27970-1-git-send-email-david.henningsson@canonical.com> <1392996262-27970-3-git-send-email-david.henningsson@canonical.com> Mime-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: Received: from mx2.suse.de (cantor2.suse.de [195.135.220.15]) by alsa0.perex.cz (Postfix) with ESMTP id E158D2658DE for ; Fri, 21 Feb 2014 16:49:21 +0100 (CET) In-Reply-To: <1392996262-27970-3-git-send-email-david.henningsson@canonical.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org To: David Henningsson Cc: alsa-devel@alsa-project.org List-Id: alsa-devel@alsa-project.org At Fri, 21 Feb 2014 16:24:21 +0100, David Henningsson wrote: > > It means we need to initialize this order: > > 1) Read the ttable to figure out which channels are present > 2) Open slave pcm and find a matching chmap > 3) Determine size of ttable (this can now depend on the chmap) > 4) Read ttable coefficients > 5) At prepare time, select the matching chmap > > Signed-off-by: David Henningsson > --- > src/pcm/pcm_route.c | 300 ++++++++++++++++++++++++++++++++++++++++++++-------- > 1 file changed, 257 insertions(+), 43 deletions(-) > > diff --git a/src/pcm/pcm_route.c b/src/pcm/pcm_route.c > index ffc283f..355da1e 100644 > --- a/src/pcm/pcm_route.c > +++ b/src/pcm/pcm_route.c > @@ -103,6 +103,7 @@ typedef struct { > snd_pcm_format_t sformat; > int schannels; > snd_pcm_route_params_t params; > + snd_pcm_chmap_t *chmap; > } snd_pcm_route_t; > > #endif /* DOC_HIDDEN */ > @@ -518,6 +519,7 @@ static int snd_pcm_route_close(snd_pcm_t *pcm) > } > free(params->dsts); > } > + free(route->chmap); > return snd_pcm_generic_close(pcm); > } > > @@ -789,21 +791,168 @@ static void snd_pcm_route_dump(snd_pcm_t *pcm, snd_output_t *out) > snd_pcm_dump(route->plug.gen.slave, out); > } > > -static int safe_chmapchannel(const char *id, long *channel) > +static int safe_chmapchannel(const char *id, snd_pcm_chmap_t *chmap, > + long *channel, int channel_size) A brief description of the function would be helpful, as the code becomes no longer trivial by this patch. > { > - int err; > int ch; > - err = safe_strtol(id, channel); > - if (err >= 0) > - return err; > + if (safe_strtol(id, channel) >= 0) > + return 1; > > ch = (int) snd_pcm_chmap_from_string(id); > if (ch == -1) > return -EINVAL; > > - /* For now, assume standard channel mapping */ > - *channel = ch - SND_CHMAP_FL; > + if (chmap) { > + int i, r = 0; > + /* Start with highest channel to simplify implementation of > + determine ttable size */ > + for (i = chmap->channels - 1; i >= 0; i--) { > + if ((int) chmap->pos[i] != ch) > + continue; > + if (r >= channel_size) > + continue; > + channel[r++] = i; > + } > + return r; > + } > + else { > + /* Assume ALSA standard channel mapping */ > + *channel = ch - SND_CHMAP_FL; > + return 1; > + } > +} > + > +#define MAX_CHMAP_CHANNELS 256 > + > +static int determine_chmap(snd_config_t *tt, snd_pcm_chmap_t **tt_chmap) > +{ > + snd_config_iterator_t i, inext; > + snd_pcm_chmap_t *chmap; > + > + assert(tt && tt_chmap); > + chmap = malloc(sizeof(snd_pcm_chmap_t) + > + MAX_CHMAP_CHANNELS * sizeof(unsigned int)); > + > + chmap->channels = 0; > + snd_config_for_each(i, inext, tt) { > + const char *id; > + snd_config_iterator_t j, jnext; > + snd_config_t *in = snd_config_iterator_entry(i); > + > + if (!snd_config_get_id(in, &id) < 0) > + continue; > + if (snd_config_get_type(in) != SND_CONFIG_TYPE_COMPOUND) > + goto err; > + snd_config_for_each(j, jnext, in) { > + int ch, k, found; > + long schannel; > + snd_config_t *jnode = snd_config_iterator_entry(j); > + if (snd_config_get_id(jnode, &id) < 0) > + continue; > + if (safe_strtol(id, &schannel) >= 0) > + continue; > + ch = (int) snd_pcm_chmap_from_string(id); > + if (ch == -1) > + goto err; > + > + found = 0; > + for (k = 0; k < (int) chmap->channels; k++) > + if (ch == (int) chmap->pos[k]) { > + found = 1; > + break; > + } > + if (found) > + continue; > + > + if (chmap->channels >= MAX_CHMAP_CHANNELS) { > + SNDERR("Too many channels in ttable chmap"); > + goto err; > + } > + chmap->pos[chmap->channels++] = ch; > + } > + } > + > + > + *tt_chmap = chmap; > return 0; > + > +err: > + *tt_chmap = NULL; > + free(chmap); > + return -EINVAL; > +} > + > +static int find_matching_chmap(snd_pcm_t *spcm, snd_pcm_chmap_t *tt_chmap, > + snd_pcm_chmap_t **found_chmap, int *schannels) > +{ > + snd_pcm_chmap_query_t** chmaps = snd_pcm_query_chmaps(spcm); > + int i; > + > + *found_chmap = NULL; > + > + if (chmaps == NULL) > + return 0; /* chmap API not supported for this slave */ > + > + for (i = 0; chmaps[i]; i++) { > + unsigned int j, k; > + int match = 1; > + snd_pcm_chmap_t *c = &chmaps[i]->map; > + if (*schannels >= 0 && (int) c->channels != *schannels) > + continue; > + > + for (j = 0; j < tt_chmap->channels; j++) { > + int found = 0; > + unsigned int ch = tt_chmap->pos[j]; > + for (k = 0; k < c->channels; k++) > + if (c->pos[k] == ch) { > + found = 1; > + break; > + } > + if (!found) { > + match = 0; > + break; > + } > + } > + > + if (match) { > + int size = sizeof(snd_pcm_chmap_t) + c->channels * sizeof(unsigned int); > + *found_chmap = malloc(size); NULL check is missing here. > + memcpy(*found_chmap, c, size); > + *schannels = c->channels; > + break; > + } > + } > + > + snd_pcm_free_chmaps(chmaps); > + > + if (*found_chmap == NULL) { > + SNDERR("Found no matching channel map"); > + return -EINVAL; > + } > + return 0; > +} > + > +static int route_chmap_init(snd_pcm_t *pcm) > +{ > + int set_map = 0; > + snd_pcm_chmap_t *current; > + snd_pcm_route_t *route = pcm->private_data; > + if (!route->chmap) > + return 0; > + if (snd_pcm_state(pcm) != SND_PCM_STATE_PREPARED) > + return 0; > + > + current = snd_pcm_get_chmap(route->plug.gen.slave); > + if (!current) > + return -ENOSYS; > + if (current->channels != route->chmap->channels) > + set_map = 1; > + else set_map = memcmp(current->pos, route->chmap->pos, current->channels); Please fix the indentation. Takashi