From 1ca07d8dbca3194e9835e547476c0574b583b169 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 26 Apr 2021 10:10:03 -0700 Subject: [PATCH] topology: pre-process-object: construct object name from its constructor attributes An object's name is derived from its constructor attribute values separated by '.'. For example, the name for the host widget objects is derived from its index and direction attribute values as follows: Object.Widget.host."playback" { index 2 } The name for the host widget object would be host.2.playback. Alternatively, if the object has a name attribute, the class definition may skip the constructor attributes and the name attribute value will be used instead. Signed-off-by: Ranjani Sridharan Signed-off-by: Jaroslav Kysela --- topology/pre-process-object.c | 109 +++++++++++++++++++++++++++++++++- 1 file changed, 108 insertions(+), 1 deletion(-) diff --git a/topology/pre-process-object.c b/topology/pre-process-object.c index f738f72..3793ab5 100644 --- a/topology/pre-process-object.c +++ b/topology/pre-process-object.c @@ -410,6 +410,106 @@ validate: return 0; } +static int tplg_construct_object_name(struct tplg_pre_processor *tplg_pp, snd_config_t *obj, + snd_config_t *class_cfg) +{ + snd_config_iterator_t i, next; + snd_config_t *args, *n; + const char *id, *class_id, *obj_id, *s; + char *new_name; + int ret; + + /* find config for class constructor attributes. Nothing to do if not defined */ + ret = snd_config_search(class_cfg, "attributes.constructor", &args); + if (ret < 0) + return 0; + + /* set class name as the name prefix for the object */ + snd_config_get_id(obj, &obj_id); + snd_config_get_id(class_cfg, &class_id); + new_name = strdup(class_id); + if (!new_name) + return -ENOMEM; + + /* iterate through all class arguments and set object name */ + snd_config_for_each(i, next, args) { + snd_config_t *arg; + char *arg_value, *temp; + + n = snd_config_iterator_entry(i); + + if (snd_config_get_id(n, &id) < 0) { + SNDERR("Invalid ID for constructor argument\n"); + ret = -EINVAL; + goto err; + } + + if (snd_config_get_string(n, &s) < 0) { + SNDERR("Invalid value for constructor argument\n"); + ret = -EINVAL; + goto err; + } + + /* find and replace with value set in object */ + ret = snd_config_search(obj, s, &arg); + if (ret < 0) { + SNDERR("Argument %s not set for object '%s.%s'\n", s, class_id, obj_id); + ret = -ENOENT; + goto err; + } + + /* concat arg value to object name. arg types must be either integer or string */ + switch (snd_config_get_type(arg)) { + case SND_CONFIG_TYPE_INTEGER: + { + long v; + ret = snd_config_get_integer(arg, &v); + assert(ret >= 0); + + arg_value = tplg_snprintf("%ld", v); + if (!arg_value) { + ret = -ENOMEM; + goto err; + } + break; + } + case SND_CONFIG_TYPE_STRING: + { + const char *s; + + ret = snd_config_get_string(arg, &s); + assert(ret >= 0); + + arg_value = strdup(s); + if (!arg_value) { + ret = -ENOMEM; + goto err; + } + break; + } + default: + SNDERR("Argument '%s' in object '%s.%s' is not an integer or a string\n", + s, class_id, obj_id); + return -EINVAL; + } + + /* alloc and concat arg value to the name */ + temp = tplg_snprintf("%s.%s", new_name, arg_value); + if (!temp) { + ret = -ENOMEM; + goto err; + } + free(new_name); + new_name = temp; + free(arg_value); + } + + ret = snd_config_set_id(obj, new_name); +err: + free(new_name); + return ret; +} + /* set the attribute value by type */ static int tplg_set_attribute_value(snd_config_t *attr, const char *value) { @@ -545,8 +645,15 @@ static int tplg_build_object(struct tplg_pre_processor *tplg_pp, snd_config_t *n /* update object attributes and validate them */ ret = tplg_object_update(tplg_pp, new_obj, parent); - if (ret < 0) + if (ret < 0) { SNDERR("Failed to update attributes for object '%s.%s'\n", class_id, id); + return ret; + } + + /* construct object name using class constructor */ + ret = tplg_construct_object_name(tplg_pp, obj_local, class_cfg); + if (ret < 0) + SNDERR("Failed to construct object name for %s\n", id); return ret; }