]> git.alsa-project.org Git - alsa-lib.git/commitdiff
ucm: add info-card substitution (Syntax 9)
authorJaroslav Kysela <perex@perex.cz>
Mon, 9 Feb 2026 15:02:01 +0000 (16:02 +0100)
committerJaroslav Kysela <perex@perex.cz>
Wed, 18 Feb 2026 11:21:52 +0000 (12:21 +0100)
Implement ${info-card:} substitution to retrieve specific fields from
a card's information structure by card number or ID. Unlike ${find-card:}
which searches through cards using regex, ${info-card:} directly queries
a specific card.

Arguments:
  card=<STR>   card number or card ID (string identifier)
  field=<STR>  number, id, driver, name, longname, mixername, components

Allow card and field parameters to reference UCM variables by prefixing
with $ character. When the first character is $, the value is resolved
using uc_mgr_get_variable().

Example usage:
  ${info-card:card=$MyCard,field=$MyField}

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

index 47a1e182b049affc51529911abc24891efe23974..052f8e20d5d5ac7dec009ed826310af3e5f2eda6 100644 (file)
@@ -616,6 +616,7 @@ ${var:\<str\>}         | UCM parser variable (set using a _Define_ block)
 ${eval:\<str\>}        | Evaluate expression like *($var+2)/3* [**Syntax 5**]
 ${find-card:\<str\>}   | Find a card - see _Find card substitution_ section
 ${find-device:\<str\>} | Find a device - see _Find device substitution_ section
+${info-card:\<str\>}   | Get card information - see _Card info substitution_ section [**Syntax 9**]
 
 General note: If two dollars '$$' instead one dolar '$' are used for the
 substitution identification, the error is ignored (e.g. file does not
@@ -689,6 +690,39 @@ stream               | stream type (playback, capture), playback is default
 field                | field for the lookup (id, name, subname)
 regex                | regex string for the field match
 
+#### Card info substitution
+
+This substitution retrieves information about a specific ALSA card by card number
+or card ID and returns the requested field value.
+
+Usage examples:
+
+~~~{.html}
+${info-card:card=0,field=name}
+${info-card:card=acp,field=driver}
+${info-card:card=PCH,field=longname}
+${info-card:card=$MyCard,field=$MyField}
+~~~
+
+Arguments:
+
+Argument             | Description
+---------------------|--------------------------------------------------
+card                 | card number (integer), card ID (string), or variable name ($var)
+field                | field to retrieve (number, id, driver, name, longname, mixername, components) or variable name ($var)
+
+The **card** parameter can be either a card number (e.g., 0, 1, 2), a card ID string (e.g., "PCH", "acp", "Intel"),
+or a variable name prefixed with $ (e.g., $CardId).
+
+The **field** parameter specifies which card information to return or can be a variable name prefixed with $ (e.g., $FieldName):
+- **number**: Card number (integer as string)
+- **id**: Card identifier
+- **driver**: Card driver name
+- **name**: Card short name
+- **longname**: Card long name
+- **mixername**: Mixer name
+- **components**: Card components
+
 
 ### Variable defines
 
index 73230a2a94fe55903c218c7ff54b59d1ef82cdfa..34782795a461c0196bb7d9e6178878737ae69550 100644 (file)
@@ -204,6 +204,96 @@ static char *rval_card_id_by_name(snd_use_case_mgr_t *uc_mgr, const char *id)
        return strdup(snd_ctl_card_info_get_id(ctl_list->ctl_info));
 }
 
+static char *rval_card_info(snd_use_case_mgr_t *uc_mgr, const char *query)
+{
+       snd_config_t *config, *d;
+       const char *card_str, *field_str, *tmp;
+       struct ctl_list *ctl_list = NULL;
+       snd_ctl_card_info_t *info;
+       char *result = NULL;
+       long card_num;
+       int err;
+
+       if (uc_mgr->conf_format < 9) {
+               snd_error(UCM, "info-card substitution is supported in v9+ syntax");
+               return NULL;
+       }
+
+       err = snd_config_load_string(&config, query, 0);
+       if (err < 0) {
+               snd_error(UCM, "info-card: invalid arguments '%s'", query);
+               return NULL;
+       }
+
+       if (snd_config_search(config, "card", &d)) {
+               snd_error(UCM, "info-card: 'card' parameter is required");
+               goto __error;
+       }
+       if (snd_config_get_string(d, &card_str))
+               goto __error;
+
+       if (card_str[0] == '$') {
+               tmp = card_str + 1;
+               card_str = uc_mgr_get_variable(uc_mgr, tmp);
+               if (card_str == NULL) {
+                       snd_error(UCM, "info-card: variable '%s' not found", tmp);
+                       goto __error;
+               }
+       }
+
+       if (snd_config_search(config, "field", &d)) {
+               snd_error(UCM, "info-card: 'field' parameter is required");
+               goto __error;
+       }
+       if (snd_config_get_string(d, &field_str))
+               goto __error;
+
+       if (field_str[0] == '$') {
+               tmp = field_str + 1;
+               field_str = uc_mgr_get_variable(uc_mgr, tmp);
+               if (field_str == NULL) {
+                       snd_error(UCM, "info-card: variable '%s' not found", tmp);
+                       goto __error;
+               }
+       }
+
+       if (safe_strtol(card_str, &card_num) == 0)
+               ctl_list = uc_mgr_get_ctl_by_card(uc_mgr, (int)card_num);
+       if (ctl_list == NULL)
+               ctl_list = get_ctl_list_by_name(uc_mgr, card_str);
+       if (ctl_list == NULL) {
+               snd_error(UCM, "info-card: card '%s' not found", card_str);
+               goto __error;
+       }
+
+       info = ctl_list->ctl_info;
+
+       if (strcasecmp(field_str, "number") == 0) {
+               char num[16];
+               snprintf(num, sizeof(num), "%d", snd_ctl_card_info_get_card(info));
+               result = strdup(num);
+       } else if (strcasecmp(field_str, "id") == 0) {
+               result = strdup(snd_ctl_card_info_get_id(info));
+       } else if (strcasecmp(field_str, "driver") == 0) {
+               result = strdup(snd_ctl_card_info_get_driver(info));
+       } else if (strcasecmp(field_str, "name") == 0) {
+               result = strdup(snd_ctl_card_info_get_name(info));
+       } else if (strcasecmp(field_str, "longname") == 0) {
+               result = strdup(snd_ctl_card_info_get_longname(info));
+       } else if (strcasecmp(field_str, "mixername") == 0) {
+               result = strdup(snd_ctl_card_info_get_mixername(info));
+       } else if (strcasecmp(field_str, "components") == 0) {
+               result = strdup(snd_ctl_card_info_get_components(info));
+       } else {
+               snd_error(UCM, "info-card: unknown field '%s'", field_str);
+               result = NULL;
+       }
+
+__error:
+       snd_config_delete(config);
+       return result;
+}
+
 #ifndef DOC_HIDDEN
 typedef struct lookup_iterate *(*lookup_iter_fcn_t)
                        (snd_use_case_mgr_t *uc_mgr, struct lookup_iterate *iter);
@@ -913,6 +1003,7 @@ __std:
                MATCH_VARIABLE2(value, "${eval:", rval_eval, false);
                MATCH_VARIABLE2(value, "${find-card:", rval_card_lookup, false);
                MATCH_VARIABLE2(value, "${find-device:", rval_device_lookup, false);
+               MATCH_VARIABLE2(value, "${info-card:", rval_card_info, false);
                MATCH_VARIABLE2(value, "${CardNumberByName:", rval_card_number_by_name, false);
                MATCH_VARIABLE2(value, "${CardIdByName:", rval_card_id_by_name, false);
 __merr: