From: Ranjani Sridharan Date: Mon, 26 Apr 2021 18:30:07 +0000 (-0700) Subject: topology: pre-process-object: add data section for attributes with token reference X-Git-Tag: v1.2.5~17 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=571d1fe8718b4b08273d452ccca22415207b2879;p=alsa-utils.git topology: pre-process-object: add data section for attributes with token reference Objects that have attributes with token_ref need to have separate SectionData and SectionVendorTuples for each unique token_ref based on the attribute_sets in the object's attribute_set_list. Add the tplg_pp_add_object_data() function to add the data[] refs in the object and also the respective SectionData and SectionVendorTuples. For example for the pga object: Object.Widget.pga."0" { pipeline_id 2 format s24le type pga no_pm 1 uuid "7e:67:7e:b7:f4:5f:88:41:af:14:fb:a8:bd:bf:8" period_sink_count 2 period_source_count 2 ramp_step_ms 250 ramp_step_type "linear" mixer.0 { .... } mixer.0.name "2 Master Playback Volume" } The following sections will be added: SectionWidget.'pga.2.0' { index 2 type pga no_pm 1 mixer [ "2 Master Playback Volume" ] bytes [ ] data [ "pga.2.0.sof_tkn_comp.word" "pga.2.0.sof_tkn_comp.string" "pga.2.0.sof_tkn_comp.uuid" "pga.2.0.sof_tkn_volume.word" ] } SectionData."pga.2.0.sof_tkn_comp.word" { tuples "pga.2.0.sof_tkn_comp.word" } SectionData."pga.2.0.sof_tkn_comp.string" { tuples "pga.2.0.sof_tkn_comp.string" } SectionData."pga.2.0.sof_tkn_comp.uuid" { tuples "pga.2.0.sof_tkn_comp.uuid" } SectionData."pga.2.0.sof_tkn_volume.word" { tuples "pga.2.0.sof_tkn_volume.word" } SectionVendorTuples."pga.2.0.sof_tkn_comp.word" { tokens "sof_tkn_comp" tuples."word" { period_source_count "2" period_sink_count "2" } } SectionVendorTuples."pga.2.0.sof_tkn_comp.string" { tokens "sof_tkn_comp" tuples."string" { format "s24le" } } SectionVendorTuples."pga.2.0.sof_tkn_comp.uuid" { tokens "sof_tkn_comp" tuples."uuid" { uuid "7e:67:7e:b7:f4:5f:88:41:af:14:fb:a8:bd:bf:8" } } SectionVendorTuples."pga.2.0.sof_tkn_volume.word" { tokens "sof_tkn_volume" tuples."word" { ramp_step_ms "250" ramp_step_type "0" } } Note that the ramp_step_type of "linear" is converted to the tuple value 0. Signed-off-by: Ranjani Sridharan Signed-off-by: Jaroslav Kysela --- diff --git a/topology/pre-process-object.c b/topology/pre-process-object.c index 609e1ec..249bd7d 100644 --- a/topology/pre-process-object.c +++ b/topology/pre-process-object.c @@ -309,6 +309,247 @@ static snd_config_t *tplg_object_lookup_in_config(struct tplg_pre_processor *tpl return obj_cfg; } +static int tplg_pp_add_object_tuple_section(struct tplg_pre_processor *tplg_pp, + snd_config_t *class_cfg, + snd_config_t *attr, char *data_name, + const char *token_ref) +{ + snd_config_t *top, *tuple_cfg, *child, *cfg, *new; + const char *id; + char *token, *type; + long tuple_value; + int ret; + + tplg_pp_debug("Building vendor tuples section: '%s' ...", data_name); + + ret = snd_config_search(tplg_pp->output_cfg, "SectionVendorTuples", &top); + if (ret < 0) { + ret = tplg_config_make_add(&top, "SectionVendorTuples", + SND_CONFIG_TYPE_COMPOUND, tplg_pp->output_cfg); + if (ret < 0) { + SNDERR("Error creating SectionVendorTuples config\n"); + return ret; + } + } + + type = strchr(token_ref, '.'); + token = calloc(1, strlen(token_ref) - strlen(type) + 1); + if (!token) + return -ENOMEM; + snprintf(token, strlen(token_ref) - strlen(type) + 1, "%s", token_ref); + + tuple_cfg = tplg_find_config(top, data_name); + if (!tuple_cfg) { + /* add new SectionVendorTuples */ + ret = tplg_config_make_add(&tuple_cfg, data_name, SND_CONFIG_TYPE_COMPOUND, top); + if (ret < 0) { + SNDERR("Error creating new vendor tuples config %s\n", data_name); + goto err; + } + + ret = tplg_config_make_add(&child, "tokens", SND_CONFIG_TYPE_STRING, + tuple_cfg); + if (ret < 0) { + SNDERR("Error creating tokens config for '%s'\n", data_name); + goto err; + } + + ret = snd_config_set_string(child, token); + if (ret < 0) { + SNDERR("Error setting tokens config for '%s'\n", data_name); + goto err; + } + + ret = tplg_config_make_add(&child, "tuples", SND_CONFIG_TYPE_COMPOUND, + tuple_cfg); + if (ret < 0) { + SNDERR("Error creating tuples config for '%s'\n", data_name); + goto err; + } + + ret = tplg_config_make_add(&cfg, type + 1, SND_CONFIG_TYPE_COMPOUND, + child); + if (ret < 0) { + SNDERR("Error creating tuples type config for '%s'\n", data_name); + goto err; + } + } else { + char *id; + + id = tplg_snprintf("tuples.%s", type + 1); + if (!id) { + ret = -ENOMEM; + goto err; + } + + ret = snd_config_search(tuple_cfg, id , &cfg); + free(id); + if (ret < 0) { + SNDERR("can't find type config %s\n", type + 1); + goto err; + } + } + + ret = snd_config_get_id(attr, &id); + if (ret < 0) + goto err; + + /* tuple exists already? */ + ret = snd_config_search(cfg, id, &child); + if (ret >=0) + goto err; + + /* add attribute to tuples */ + tuple_value = tplg_class_attribute_valid_tuple_value(tplg_pp, class_cfg, attr); + if (tuple_value < 0) { + /* just copy attribute cfg as is */ + ret = snd_config_copy(&new, attr); + if (ret < 0) { + SNDERR("can't copy attribute for %s\n", data_name); + goto err; + } + } else { + ret = snd_config_make(&new, id, SND_CONFIG_TYPE_INTEGER); + if (ret < 0) + goto err; + + ret = snd_config_set_integer(new, tuple_value); + if (ret < 0) + goto err; + } + + ret = snd_config_add(cfg, new); + if (ret < 0) + goto err; + +err: + free(token); + return ret; +} + +static int tplg_pp_add_object_data_section(struct tplg_pre_processor *tplg_pp, + snd_config_t *obj_data, char *data_name) +{ + snd_config_iterator_t i, next; + snd_config_t *top, *data_cfg, *child; + char *data_id; + int ret, id = 0; + + ret = snd_config_search(tplg_pp->output_cfg, "SectionData", &top); + if (ret < 0) { + ret = tplg_config_make_add(&top, "SectionData", SND_CONFIG_TYPE_COMPOUND, + tplg_pp->output_cfg); + if (ret < 0) { + SNDERR("Failed to add SectionData\n"); + return ret; + } + } + + /* nothing to do if data section already exists */ + data_cfg = tplg_find_config(top, data_name); + if (data_cfg) + return 0; + + tplg_pp_debug("Building data section %s ...", data_name); + + /* add new SectionData */ + ret = tplg_config_make_add(&data_cfg, data_name, SND_CONFIG_TYPE_COMPOUND, top); + if (ret < 0) + return ret; + + ret = tplg_config_make_add(&child, "tuples", SND_CONFIG_TYPE_STRING, data_cfg); + if (ret < 0) { + SNDERR("error adding data ref for %s\n", data_name); + return ret; + } + + ret = snd_config_set_string(child, data_name); + if (ret < 0) { + SNDERR("error setting tuples ref for %s\n", data_name); + return ret; + } + + /* add data item to object */ + snd_config_for_each(i, next, obj_data) + id++; + + data_id = tplg_snprintf("%d", id); + if (!data_id) + return -ENOMEM; + + ret = tplg_config_make_add(&child, data_id, SND_CONFIG_TYPE_STRING, obj_data); + free(data_id); + if (ret < 0) { + SNDERR("error adding data ref %s\n", data_name); + return ret; + } + + return snd_config_set_string(child, data_name); +} + +static int tplg_add_object_data(struct tplg_pre_processor *tplg_pp, snd_config_t *obj_cfg, + snd_config_t *top) +{ + snd_config_iterator_t i, next; + snd_config_t *data_cfg, *class_cfg, *n, *obj; + const char *object_id; + int ret; + + if (snd_config_get_id(top, &object_id) < 0) + return 0; + + obj = tplg_object_get_instance_config(tplg_pp, obj_cfg); + + class_cfg = tplg_class_lookup(tplg_pp, obj_cfg); + if (!class_cfg) + return -EINVAL; + + /* add data config to top */ + ret = snd_config_search(top, "data", &data_cfg); + if (ret < 0) { + ret = tplg_config_make_add(&data_cfg, "data", SND_CONFIG_TYPE_COMPOUND, top); + if (ret < 0) { + SNDERR("error creating data config for %s\n", object_id); + return ret; + } + } + + /* add data items to object's data section */ + snd_config_for_each(i, next, obj) { + const char *id, *token; + char *data_cfg_name; + + n = snd_config_iterator_entry(i); + if (snd_config_get_id(n, &id) < 0) + continue; + + token = tplg_class_get_attribute_token_ref(tplg_pp, class_cfg, id); + if (!token) + continue; + + data_cfg_name = tplg_snprintf("%s.%s", object_id, token); + if (!data_cfg_name) + return -ENOMEM; + + ret = tplg_pp_add_object_data_section(tplg_pp, data_cfg, data_cfg_name); + if (ret < 0) { + SNDERR("Failed to add data section %s\n", data_cfg_name); + free(data_cfg_name); + return ret; + } + + ret = tplg_pp_add_object_tuple_section(tplg_pp, class_cfg, n, data_cfg_name, + token); + free(data_cfg_name); + if (ret < 0) { + SNDERR("Failed to add data section %s\n", data_cfg_name); + return ret; + } + } + + return 0; +} + /* search for all template configs in the source config and copy them to the destination */ static int tplg_object_add_attributes(snd_config_t *dst, snd_config_t *template, snd_config_t *src) @@ -440,8 +681,22 @@ static int tplg_build_generic_object(struct tplg_pre_processor *tplg_pp, snd_con snd_config_t *parent) { snd_config_t *wtop; + const char *name; + int ret; + + ret = tplg_build_object_from_template(tplg_pp, obj_cfg, &wtop, NULL, false); + if (ret < 0) + return ret; + + ret = snd_config_get_id(wtop, &name); + if (ret < 0) + return ret; - return tplg_build_object_from_template(tplg_pp, obj_cfg, &wtop, NULL, false); + ret = tplg_add_object_data(tplg_pp, obj_cfg, wtop); + if (ret < 0) + SNDERR("Failed to add data section for %s\n", name); + + return ret; } const struct build_function_map object_build_map[] = { @@ -904,8 +1159,6 @@ static int tplg_build_object(struct tplg_pre_processor *tplg_pp, snd_config_t *n return ret; } - tplg_pp_config_debug(tplg_pp, obj_local); - /* nothing to do if object is not supported */ map = tplg_object_get_map(tplg_pp, new_obj); if (!map)