]> git.alsa-project.org Git - alsa-lib.git/commitdiff
ucm: allow passing variables through ucm open string
authorJaroslav Kysela <perex@perex.cz>
Mon, 16 May 2022 11:16:01 +0000 (13:16 +0200)
committerJaroslav Kysela <perex@perex.cz>
Mon, 16 May 2022 12:17:31 +0000 (14:17 +0200)
It is useful to pass information like application capabilities
to the UCM configuration parser. Those variables are prefixed
with '@' for the configuration files.

An example:

   "<<<v1='a b c',x=12>>>hw:1"

Variables can substituted in the configuration:

   "${var:@v1}" -> "a b c"
   "${var:@x}" -> 12

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
src/ucm/main.c
src/ucm/parser.c

index 8ca766309cc8602732c2b3c2537aefdf7ff9008c..ccae43f63d2d5458c6a2a4ac1d9e9d561c935671 100644 (file)
@@ -1356,6 +1356,57 @@ static int set_device(snd_use_case_mgr_t *uc_mgr,
        return err;
 }
 
+/**
+ * \brief Parse open arguments
+ * \param uc_mgr Use case manager
+ * \param name name of card to open
+ * \return the rest of the card name to open
+ */
+const char *parse_open_variables(snd_use_case_mgr_t *uc_mgr, const char *name)
+{
+       const char *end, *id;
+       char *args, *var;
+       snd_config_t *cfg, *n;
+       snd_config_iterator_t i, next;
+       char vname[128];
+       size_t l;
+       int err;
+
+       end = strstr(name, ">>>");
+       if (end == NULL)
+               return name;
+       l = end - name - 3;
+       args = alloca(l + 1);
+       strncpy(args, name + 3, l);
+       args[l] = '\0';
+
+       err = snd_config_load_string(&cfg, args, 0);
+       if (err < 0) {
+               uc_error("error: open arguments are not valid (%s)", args);
+               goto skip;
+       }
+
+       /* set arguments */
+       snd_config_for_each(i, next, cfg) {
+               n = snd_config_iterator_entry(i);
+               err = snd_config_get_id(n, &id);
+               if (err < 0)
+                       goto skip;
+               err = snd_config_get_ascii(n, &var);
+               if (err < 0)
+                       goto skip;
+               snprintf(vname, sizeof(vname), "@%s", id);
+               err = uc_mgr_set_variable(uc_mgr, vname, var);
+               free(var);
+               if (err < 0)
+                       goto skip;
+       }
+
+       snd_config_delete(cfg);
+skip:
+       return end + 3;
+}
+
 /**
  * \brief Init sound card use case manager.
  * \param uc_mgr Returned use case manager pointer
@@ -1388,6 +1439,9 @@ int snd_use_case_mgr_open(snd_use_case_mgr_t **uc_mgr,
                mgr->suppress_nodev_errors = 1;
        }
 
+       if (card_name[0] == '<' && card_name[1] == '<' && card_name[2] == '<')
+               card_name = parse_open_variables(mgr, card_name);
+
        err = uc_mgr_card_open(mgr);
        if (err < 0) {
                uc_mgr_free(mgr);
index 830c37d2a360c7289c7d73312a165205cf2804cd..65ebc179ffee385060b6766f3a713223c2476ff6 100644 (file)
@@ -278,6 +278,10 @@ static int evaluate_regex(snd_use_case_mgr_t *uc_mgr,
                err = snd_config_get_id(n, &id);
                if (err < 0)
                        return err;
+               if (id[0] == '@') {
+                       uc_error("error: value names starting with '@' are reserved for application variables");
+                       return -EINVAL;
+               }
                err = uc_mgr_define_regex(uc_mgr, id, n);
                if (err < 0)
                        return err;
@@ -327,6 +331,11 @@ static int evaluate_define(snd_use_case_mgr_t *uc_mgr,
                free(var);
                if (err < 0)
                        return err;
+               if (id[0] == '@') {
+                       free(s);
+                       uc_error("error: value names starting with '@' are reserved for application variables");
+                       return -EINVAL;
+               }
                err = uc_mgr_set_variable(uc_mgr, id, s);
                free(s);
                if (err < 0)