
At Fri, 21 Feb 2014 16:24:21 +0100, David Henningsson wrote:
It means we need to initialize this order:
- Read the ttable to figure out which channels are present
- Open slave pcm and find a matching chmap
- Determine size of ttable (this can now depend on the chmap)
- Read ttable coefficients
- At prepare time, select the matching chmap
Signed-off-by: David Henningsson david.henningsson@canonical.com
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