]> git.alsa-project.org Git - alsa-lib.git/commitdiff
ucm: find-card,find-device - add UCM variable support for arguments (Syntax 9)
authorJaroslav Kysela <perex@perex.cz>
Wed, 18 Feb 2026 11:13:15 +0000 (12:13 +0100)
committerJaroslav Kysela <perex@perex.cz>
Wed, 18 Feb 2026 12:29:33 +0000 (13:29 +0100)
Add variable support for all lookup arguments in find-card and find-device
substitutions. Variables are identified by $ prefix and only enabled for
Syntax 9+ to maintain backward compatibility.

Modified arguments with variable support:
- find-card: field, regex
- find-device: type, field, stream, regex

Example usage:
  ${find-card:field=$FieldName,regex=$Pattern,return=number}
  ${find-device:type=$DevType,stream=$StreamType,field=$FieldName,regex=$Pattern}

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
src/ucm/ucm_confdoc.h
src/ucm/ucm_subs.c

index 052f8e20d5d5ac7dec009ed826310af3e5f2eda6..e5d8b82d97464b585fba471aa70bb1f639cc9914 100644 (file)
@@ -663,6 +663,7 @@ Usage example:
 
 ~~~{.html}
 ${find-card:field=name,regex='^acp$',return=number}
+${find-card:field=$FieldName,regex=$Pattern,return=number}
 ~~~
 
 Arguments:
@@ -670,8 +671,8 @@ Arguments:
 Argument             | Description
 ---------------------|-----------------------
 return               | return value type (id, number), id is the default
-field                | field for the lookup (id, driver, name, longname, mixername, components)
-regex                | regex string for the field match
+field                | field for the lookup (id, driver, name, longname, mixername, components) or variable name ($var) [**Syntax 9**]
+regex                | regex string for the field match or variable name ($var) [**Syntax 9**]
 
 #### Find device substitution
 
@@ -679,16 +680,17 @@ Usage example:
 
 ~~~{.html}
 ${find-device:type=pcm,field=name,regex='DMIC'}
+${find-device:type=$DevType,stream=$StreamType,field=$FieldName,regex=$Pattern}
 ~~~
 
 Arguments:
 
 Argument             | Description
 ---------------------|-----------------------
-type                 | device type (pcm)
-stream               | stream type (playback, capture), playback is default
-field                | field for the lookup (id, name, subname)
-regex                | regex string for the field match
+type                 | device type (pcm) or variable name ($var) [**Syntax 9**]
+stream               | stream type (playback, capture), playback is default; variable name ($var) supported in **Syntax 9**
+field                | field for the lookup (id, name, subname) or variable name ($var) [**Syntax 9**]
+regex                | regex string for the field match or variable name ($var) [**Syntax 9**]
 
 #### Card info substitution
 
index 34782795a461c0196bb7d9e6178878737ae69550..5ee386ac850b02e3aaa39ebddf4fa0fb3b252124 100644 (file)
@@ -325,7 +325,7 @@ static char *rval_lookup_main(snd_use_case_mgr_t *uc_mgr,
        snd_config_t *config, *d;
        struct lookup_fcn *fcn;
        struct lookup_iterate *curr;
-       const char *s;
+       const char *s, *tmp;
        char *result;
        regmatch_t match[1];
        regex_t re;
@@ -349,6 +349,12 @@ static char *rval_lookup_main(snd_use_case_mgr_t *uc_mgr,
        }
        if (snd_config_get_string(d, &s))
                goto null;
+       if (s[0] == '$' && uc_mgr->conf_format >= 9) {
+               tmp = s + 1;
+               s = uc_mgr_get_variable(uc_mgr, tmp);
+               if (s == NULL)
+                       goto var_not_found;
+       }
        for (fcn = iter->fcns ; fcn; fcn++) {
                if (strcasecmp(fcn->name, s) == 0) {
                        iter->fcn = fcn->fcn;
@@ -365,6 +371,12 @@ static char *rval_lookup_main(snd_use_case_mgr_t *uc_mgr,
        }
        if (snd_config_get_string(d, &s))
                goto null;
+       if (s[0] == '$' && uc_mgr->conf_format >= 9) {
+               tmp = s + 1;
+               s = uc_mgr_get_variable(uc_mgr, tmp);
+               if (s == NULL)
+                       goto var_not_found;
+       }
        err = regcomp(&re, s, REG_EXTENDED | REG_ICASE);
        if (err) {
                snd_error(UCM, "Regex '%s' compilation failed (code %d)", s, err);
@@ -387,6 +399,8 @@ fin:
        if (iter->done)
                iter->done(iter);
        return result;
+var_not_found:
+       snd_error(UCM, "lookup: variable '%s' not found", tmp);
 null:
        result = NULL;
        goto fin;
@@ -500,7 +514,8 @@ static char *rval_pcm_lookup_return(struct lookup_iterate *iter,
        return strdup(num);
 }
 
-static int rval_pcm_lookup_init(struct lookup_iterate *iter,
+static int rval_pcm_lookup_init(snd_use_case_mgr_t *uc_mgr,
+                               struct lookup_iterate *iter,
                                snd_config_t *config)
 {
        static struct lookup_fcn pcm_fcns[] = {
@@ -510,12 +525,20 @@ static int rval_pcm_lookup_init(struct lookup_iterate *iter,
                { 0 },
        };
        snd_config_t *d;
-       const char *s;
+       const char *s, *tmp;
        snd_pcm_info_t *pcminfo;
        snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
 
        if (snd_config_search(config, "stream", &d) == 0 &&
            snd_config_get_string(d, &s) == 0) {
+               if (s[0] == '$' && uc_mgr->conf_format >= 9) {
+                       tmp = s + 1;
+                       s = uc_mgr_get_variable(uc_mgr, tmp);
+                       if (s == NULL) {
+                               snd_error(UCM, "pcm lookup: variable '%s' not found", tmp);
+                               return -EINVAL;
+                       }
+               }
                if (strcasecmp(s, "playback") == 0)
                        stream = SND_PCM_STREAM_PLAYBACK;
                else if (strcasecmp(s, "capture") == 0)
@@ -544,13 +567,14 @@ static int rval_device_lookup_init(snd_use_case_mgr_t *uc_mgr,
 {
        static struct {
                const char *name;
-               int (*init)(struct lookup_iterate *iter, snd_config_t *config);
+               int (*init)(snd_use_case_mgr_t *uc_mgr, struct lookup_iterate *iter,
+                           snd_config_t *config);
        } *t, types[] = {
                { .name = "pcm", .init = rval_pcm_lookup_init },
                { 0 }
        };
        snd_config_t *d;
-       const char *s;
+       const char *s, *tmp;
        int err;
 
        if (snd_config_search(config, "ctl", &d) || snd_config_get_string(d, &s)) {
@@ -570,9 +594,17 @@ static int rval_device_lookup_init(snd_use_case_mgr_t *uc_mgr,
                snd_error(UCM, "Missing device type!");
                return -EINVAL;
        }
+       if (s[0] == '$' && uc_mgr->conf_format >= 9) {
+               tmp = s + 1;
+               s = uc_mgr_get_variable(uc_mgr, tmp);
+               if (s == NULL) {
+                       snd_error(UCM, "device lookup: variable '%s' not found", tmp);
+                       return -EINVAL;
+               }
+       }
        for (t = types; t->name; t++)
                if (strcasecmp(t->name, s) == 0)
-                       return t->init(iter, config);
+                       return t->init(uc_mgr, iter, config);
        snd_error(UCM, "Device type '%s' is invalid", s);
        return -EINVAL;
 }