From 11ec9e497ee542dc987ab191abee16440336bfe4 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 16 May 2022 13:16:01 +0200 Subject: [PATCH] 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: "<<>>hw:1" Variables can substituted in the configuration: "${var:@v1}" -> "a b c" "${var:@x}" -> 12 Signed-off-by: Jaroslav Kysela --- src/ucm/main.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ src/ucm/parser.c | 9 ++++++++ 2 files changed, 63 insertions(+) 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 @@ -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); 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) -- 2.47.1