ucm: add Prepend and Append block handling for If conditions (syntax 8+)

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
Jaroslav Kysela 2025-11-17 18:00:59 +01:00
parent ebfc29110c
commit a8620e814b
2 changed files with 125 additions and 26 deletions

View file

@ -373,21 +373,50 @@ static int if_eval_one(snd_use_case_mgr_t *uc_mgr,
snd_config_t *cond,
snd_config_t **result,
snd_config_t **before,
snd_config_t **after)
snd_config_t **after,
snd_config_t **prepend,
snd_config_t **append)
{
snd_config_t *expr, *_true = NULL, *_false = NULL;
int err;
int err, has_condition;
*result = NULL;
*prepend = NULL;
*append = NULL;
if (snd_config_get_type(cond) != SND_CONFIG_TYPE_COMPOUND) {
snd_error(UCM, "compound type expected for If.1");
return -EINVAL;
}
if (snd_config_search(cond, "Condition", &expr) < 0) {
snd_error(UCM, "condition block expected (If)");
return -EINVAL;
/* For syntax v8+, Condition is optional if Prepend or Append is present */
has_condition = snd_config_search(cond, "Condition", &expr) >= 0;
if (uc_mgr->conf_format >= 8) {
/* Check for Prepend block */
err = snd_config_search(cond, "Prepend", prepend);
if (err < 0 && err != -ENOENT) {
snd_error(UCM, "prepend block error (If)");
return -EINVAL;
}
/* Check for Append block */
err = snd_config_search(cond, "Append", append);
if (err < 0 && err != -ENOENT) {
snd_error(UCM, "append block error (If)");
return -EINVAL;
}
/* If Prepend or Append is present, Condition can be omitted */
if (!has_condition && (*prepend == NULL && *append == NULL)) {
snd_error(UCM, "condition block expected (If)");
return -EINVAL;
}
} else {
if (!has_condition) {
snd_error(UCM, "condition block expected (If)");
return -EINVAL;
}
}
err = snd_config_search(cond, "True", &_true);
@ -414,16 +443,22 @@ static int if_eval_one(snd_use_case_mgr_t *uc_mgr,
return -EINVAL;
}
err = if_eval(uc_mgr, expr);
if (err > 0) {
*result = _true;
return 0;
} else if (err == 0) {
*result = _false;
return 0;
} else {
return err;
/* Evaluate condition if present */
if (has_condition) {
err = if_eval(uc_mgr, expr);
if (err > 0) {
*result = _true;
return 0;
} else if (err == 0) {
*result = _false;
return 0;
} else {
return err;
}
}
/* If no condition (v8+ with Prepend/Append only), no result block */
return 0;
}
#if 0
@ -445,7 +480,7 @@ int uc_mgr_evaluate_condition(snd_use_case_mgr_t *uc_mgr,
snd_config_t *cond)
{
snd_config_iterator_t i, next;
snd_config_t *a, *n, *before, *after;
snd_config_t *a, *n, *before, *after, *prepend, *append;
int err;
if (uc_mgr->conf_format < 2) {
@ -460,19 +495,43 @@ int uc_mgr_evaluate_condition(snd_use_case_mgr_t *uc_mgr,
snd_config_for_each(i, next, cond) {
n = snd_config_iterator_entry(i);
before = after = NULL;
err = if_eval_one(uc_mgr, n, &a, &before, &after);
before = after = prepend = append = NULL;
err = if_eval_one(uc_mgr, n, &a, &before, &after, &prepend, &append);
if (err < 0)
return err;
if (a == NULL)
continue;
err = uc_mgr_evaluate_inplace(uc_mgr, a);
if (err < 0)
return err;
err = uc_mgr_config_tree_merge(uc_mgr, parent, a, before, after);
if (err < 0)
return err;
snd_config_delete(a);
/* For v8+: Handle Prepend block - prepend to parent before result */
if (prepend != NULL) {
err = uc_mgr_evaluate_inplace(uc_mgr, prepend);
if (err < 0)
return err;
err = uc_mgr_config_tree_merge(uc_mgr, parent, prepend, before, after);
if (err < 0)
return err;
snd_config_delete(prepend);
}
/* Merge the condition result (True or False block) */
if (a != NULL) {
err = uc_mgr_evaluate_inplace(uc_mgr, a);
if (err < 0)
return err;
err = uc_mgr_config_tree_merge(uc_mgr, parent, a, before, after);
if (err < 0)
return err;
snd_config_delete(a);
}
/* For v8+: Handle Append block - append to parent after result */
if (append != NULL) {
err = uc_mgr_evaluate_inplace(uc_mgr, append);
if (err < 0)
return err;
err = uc_mgr_config_tree_merge(uc_mgr, parent, append, before, after);
if (err < 0)
return err;
snd_config_delete(append);
}
}
return 0;
}

View file

@ -550,6 +550,14 @@ must define a *Condition* block and *True* or *False* blocks or both. The *True*
blocks will be merged to the parent tree (where the *If* block is defined) when
the *Condition* is evaluated.
Starting with *Syntax* version *8*, *If* blocks can also include *Prepend* and *Append*
configuration blocks. These blocks are always merged to the parent tree, independent of the
condition evaluation result:
- *Prepend* block is merged before the condition result (*True* or *False* block)
- *Append* block is merged after the condition result (*True* or *False* block)
- Both *Prepend* and *Append* can be specified simultaneously
- When *Prepend* or *Append* is present, the *Condition* directive can be omitted
Example:
~~~{.html}
@ -566,6 +574,38 @@ If.uniqueid {
}
~~~
Example with Prepend and Append (*Syntax* version *8*+):
~~~{.html}
If.setup {
Prepend {
Define.before "prepended"
}
Condition {
Type AlwaysTrue
}
True {
Define.middle "conditional"
}
Append {
Define.after "appended"
}
}
~~~
Example with Prepend/Append only (no Condition, *Syntax* version *8*+):
~~~{.html}
If.common {
Prepend {
Define.x "always executed"
}
Append {
Define.y "also always executed"
}
}
~~~
#### True (Type AlwaysTrue)
Execute only *True* block. It may be used to change the evaluation order as