]> git.alsa-project.org Git - alsa-utils.git/commitdiff
topology: pre-process-object: construct object name from its constructor attributes
authorRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Mon, 26 Apr 2021 17:10:03 +0000 (10:10 -0700)
committerJaroslav Kysela <perex@perex.cz>
Tue, 25 May 2021 16:26:51 +0000 (18:26 +0200)
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 <ranjani.sridharan@linux.intel.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
topology/pre-process-object.c

index f738f72fa3a9e95d63a85e1445fa7f03d9195055..3793ab5e90a54e83ebe53c6f5c5dc1f7bcb71379 100644 (file)
@@ -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;
 }