ucm: add If condition block

The syntax is simple:

If./any-if-identificator/ {
  Condition {
    Type /type_here/
    /optional defines/
  }
  True {
    /block used when condition is evaluated as true/
  }
  False {
    /block used when condition is evaluated as false/
  }
}

The Type "ControlExists" is implemented:

Condition {
  Type ControlExists
  Device "hw:${CardId}"
  Control "iface=CARD,name='Headphone Jack'"
}

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
Jaroslav Kysela 2019-11-05 13:02:41 +01:00
parent b9b2247943
commit 8a36e38dc4
8 changed files with 536 additions and 162 deletions

View file

@ -1352,151 +1352,6 @@ int snd_use_case_get_list(snd_use_case_mgr_t *uc_mgr,
return err;
}
static char *rval_conf_name(snd_use_case_mgr_t *uc_mgr)
{
if (uc_mgr->conf_file_name[0])
return strdup(uc_mgr->conf_file_name);
return NULL;
}
static char *rval_card_id(snd_use_case_mgr_t *uc_mgr)
{
struct ctl_list *ctl_list;
ctl_list = uc_mgr_get_one_ctl(uc_mgr);
if (ctl_list == NULL)
return NULL;
return strdup(snd_ctl_card_info_get_id(ctl_list->ctl_info));
}
static char *rval_card_name(snd_use_case_mgr_t *uc_mgr)
{
struct ctl_list *ctl_list;
ctl_list = uc_mgr_get_one_ctl(uc_mgr);
if (ctl_list == NULL)
return NULL;
return strdup(snd_ctl_card_info_get_name(ctl_list->ctl_info));
}
static char *rval_card_longname(snd_use_case_mgr_t *uc_mgr)
{
struct ctl_list *ctl_list;
ctl_list = uc_mgr_get_one_ctl(uc_mgr);
if (ctl_list == NULL)
return NULL;
return strdup(snd_ctl_card_info_get_longname(ctl_list->ctl_info));
}
static char *rval_env(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED, const char *id)
{
char *e;
e = getenv(id);
if (e)
return strdup(e);
return NULL;
}
#define MATCH_VARIABLE(name, id, fcn) \
if (strncmp((name), (id), sizeof(id) - 1) == 0) { \
rval = fcn(uc_mgr); \
idsize = sizeof(id) - 1; \
goto __rval; \
}
#define MATCH_VARIABLE2(name, id, fcn) \
if (strncmp((name), (id), sizeof(id) - 1) == 0) { \
idsize = sizeof(id) - 1; \
tmp = strchr(value + idsize, '}'); \
if (tmp) { \
rvalsize = tmp - (value + idsize); \
if (rvalsize > sizeof(v2)) { \
err = -ENOMEM; \
goto __error; \
} \
strncpy(v2, value + idsize, rvalsize); \
v2[rvalsize] = '\0'; \
idsize += rvalsize + 1; \
rval = fcn(uc_mgr, v2); \
goto __rval; \
} \
}
static int get_substituted_value(snd_use_case_mgr_t *uc_mgr,
char **_rvalue,
const char *value)
{
size_t size, nsize, idsize, rvalsize, dpos = 0;
const char *tmp;
char *r, *nr, *rval, v2[32];
int err;
if (value == NULL)
return -ENOENT;
size = strlen(value) + 1;
r = malloc(size);
if (r == NULL)
return -ENOMEM;
while (*value) {
if (*value == '$' && *(value+1) == '{') {
MATCH_VARIABLE(value, "${ConfName}", rval_conf_name);
MATCH_VARIABLE(value, "${CardId}", rval_card_id);
MATCH_VARIABLE(value, "${CardName}", rval_card_name);
MATCH_VARIABLE(value, "${CardLongName}", rval_card_longname);
MATCH_VARIABLE2(value, "${env:", rval_env);
err = -EINVAL;
tmp = strchr(value, '}');
if (tmp) {
strncpy(r, value, tmp + 1 - value);
r[tmp + 1 - value] = '\0';
uc_error("variable '%s' is not known!", r);
} else {
uc_error("variable reference '%s' is not complete", value);
}
goto __error;
__rval:
if (rval == NULL || rval[0] == '\0') {
free(rval);
strncpy(r, value, idsize);
r[idsize] = '\0';
uc_error("variable '%s' is not defined in this context!", r);
err = -EINVAL;
goto __error;
}
value += idsize;
rvalsize = strlen(rval);
nsize = size + rvalsize - idsize;
if (nsize > size) {
nr = realloc(r, nsize);
if (nr == NULL) {
err = -ENOMEM;
goto __error;
}
size = nsize;
r = nr;
}
strcpy(r + dpos, rval);
dpos += rvalsize;
free(rval);
} else {
r[dpos++] = *value;
value++;
}
}
r[dpos] = '\0';
*_rvalue = r;
return 0;
__error:
free(r);
return err;
}
static int get_value1(snd_use_case_mgr_t *uc_mgr, char **value,
struct list_head *value_list, const char *identifier)
{
@ -1515,7 +1370,7 @@ static int get_value1(snd_use_case_mgr_t *uc_mgr, char **value,
return -ENOMEM;
return 0;
}
return get_substituted_value(uc_mgr, value, val->data);
return uc_mgr_get_substituted_value(uc_mgr, value, val->data);
}
}
return -ENOENT;