diff options
author | Jaroslav Kysela <perex@perex.cz> | 2022-05-16 13:16:01 +0200 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2022-05-16 14:17:31 +0200 |
commit | 11ec9e497ee542dc987ab191abee16440336bfe4 (patch) | |
tree | c5a1be88fd9da53f7738a2b5d417ab14c7c79146 | |
parent | 46e991c9ce629d5541db22c660c3e92a2f66c0d3 (diff) | |
download | alsa-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.c | 54 | ||||
-rw-r--r-- | src/ucm/parser.c | 9 |
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) |