summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaroslav Kysela <perex@perex.cz>2022-05-16 13:16:01 +0200
committerJaroslav Kysela <perex@perex.cz>2022-05-16 14:17:31 +0200
commit11ec9e497ee542dc987ab191abee16440336bfe4 (patch)
treec5a1be88fd9da53f7738a2b5d417ab14c7c79146
parent46e991c9ce629d5541db22c660c3e92a2f66c0d3 (diff)
downloadalsa-lib-11ec9e497ee542dc987ab191abee16440336bfe4.tar.gz
ucm: allow passing variables through ucm open string
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>
-rw-r--r--src/ucm/main.c54
-rw-r--r--src/ucm/parser.c9
2 files changed, 63 insertions, 0 deletions
diff --git a/src/ucm/main.c b/src/ucm/main.c
index 8ca76630..ccae43f6 100644
--- a/src/ucm/main.c
+++ b/src/ucm/main.c
@@ -1357,6 +1357,57 @@ static int set_device(snd_use_case_mgr_t *uc_mgr,
}
/**
+ * \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
* \param card_name name of card to open
@@ -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);
diff --git a/src/ucm/parser.c b/src/ucm/parser.c
index 830c37d2..65ebc179 100644
--- a/src/ucm/parser.c
+++ b/src/ucm/parser.c
@@ -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)