mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2026-02-05 04:06:34 -05:00
ucm: add possibility to inline Verb configurations to the main configuration file
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
parent
a8620e814b
commit
9e933a08ed
2 changed files with 107 additions and 42 deletions
122
src/ucm/parser.c
122
src/ucm/parser.c
|
|
@ -1945,9 +1945,9 @@ static int parse_verb(snd_use_case_mgr_t *uc_mgr,
|
|||
}
|
||||
|
||||
/*
|
||||
* Parse a Use case verb file.
|
||||
* Parse a Use case verb configuration.
|
||||
*
|
||||
* This file contains the following :-
|
||||
* This configuration contains the following :-
|
||||
* o Verb enable and disable sequences.
|
||||
* o Supported Device enable and disable sequences for verb.
|
||||
* o Supported Modifier enable and disable sequences for verb
|
||||
|
|
@ -1955,15 +1955,15 @@ static int parse_verb(snd_use_case_mgr_t *uc_mgr,
|
|||
* o Optional PCM device ID for verb and modifiers
|
||||
* o Alias kcontrols IDs for master and volumes and mutes.
|
||||
*/
|
||||
static int parse_verb_file(snd_use_case_mgr_t *uc_mgr,
|
||||
const char *use_case_name,
|
||||
const char *comment,
|
||||
const char *file)
|
||||
static int parse_verb_config(snd_use_case_mgr_t *uc_mgr,
|
||||
const char *use_case_name,
|
||||
const char *comment,
|
||||
snd_config_t *cfg,
|
||||
const char *what)
|
||||
{
|
||||
snd_config_iterator_t i, next;
|
||||
snd_config_t *n;
|
||||
struct use_case_verb *verb;
|
||||
snd_config_t *cfg;
|
||||
int err;
|
||||
|
||||
/* allocate verb */
|
||||
|
|
@ -1992,15 +1992,10 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* open Verb file for reading */
|
||||
err = uc_mgr_config_load_file(uc_mgr, file, &cfg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* in-place evaluation */
|
||||
err = uc_mgr_evaluate_inplace(uc_mgr, cfg);
|
||||
if (err < 0)
|
||||
goto _err;
|
||||
return err;
|
||||
|
||||
/* parse master config sections */
|
||||
snd_config_for_each(i, next, cfg) {
|
||||
|
|
@ -2013,8 +2008,8 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr,
|
|||
if (strcmp(id, "SectionVerb") == 0) {
|
||||
err = parse_verb(uc_mgr, verb, n);
|
||||
if (err < 0) {
|
||||
snd_error(UCM, "%s failed to parse verb", file);
|
||||
goto _err;
|
||||
snd_error(UCM, "%s failed to parse verb", what);
|
||||
return err;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
|
@ -2024,8 +2019,8 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr,
|
|||
err = parse_compound(uc_mgr, n,
|
||||
parse_device_name, verb, NULL);
|
||||
if (err < 0) {
|
||||
snd_error(UCM, "%s failed to parse device", file);
|
||||
goto _err;
|
||||
snd_error(UCM, "%s failed to parse device", what);
|
||||
return err;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
|
@ -2035,8 +2030,8 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr,
|
|||
err = parse_compound(uc_mgr, n,
|
||||
parse_modifier_name, verb, NULL);
|
||||
if (err < 0) {
|
||||
snd_error(UCM, "%s failed to parse modifier", file);
|
||||
goto _err;
|
||||
snd_error(UCM, "%s failed to parse modifier", what);
|
||||
return err;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
|
@ -2045,8 +2040,8 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr,
|
|||
if (strcmp(id, "RenameDevice") == 0) {
|
||||
err = parse_dev_name_list(uc_mgr, n, &verb->rename_list);
|
||||
if (err < 0) {
|
||||
snd_error(UCM, " %s failed to parse device rename", file);
|
||||
goto _err;
|
||||
snd_error(UCM, "%s failed to parse device rename", what);
|
||||
return err;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
|
@ -2055,8 +2050,8 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr,
|
|||
if (strcmp(id, "RemoveDevice") == 0) {
|
||||
err = parse_dev_name_list(uc_mgr, n, &verb->remove_list);
|
||||
if (err < 0) {
|
||||
snd_error(UCM, "%s failed to parse device remove", file);
|
||||
goto _err;
|
||||
snd_error(UCM, "%s failed to parse device remove", what);
|
||||
return err;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
|
@ -2065,18 +2060,16 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr,
|
|||
if (uc_mgr->conf_format > 3 && strcmp(id, "LibraryConfig") == 0) {
|
||||
err = parse_libconfig(uc_mgr, n);
|
||||
if (err < 0) {
|
||||
snd_error(UCM, "failed to parse LibConfig");
|
||||
goto _err;
|
||||
snd_error(UCM, "%s failed to parse LibConfig", what);
|
||||
return err;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
snd_config_delete(cfg);
|
||||
|
||||
/* use case verb must have at least 1 device */
|
||||
if (list_empty(&verb->device_list)) {
|
||||
snd_error(UCM, "no use case device defined", file);
|
||||
snd_error(UCM, "no use case device defined");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
@ -2088,10 +2081,6 @@ static int parse_verb_file(snd_use_case_mgr_t *uc_mgr,
|
|||
}
|
||||
|
||||
return 0;
|
||||
|
||||
_err:
|
||||
snd_config_delete(cfg);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -2161,7 +2150,7 @@ static int parse_master_section(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg,
|
|||
void *data2 ATTRIBUTE_UNUSED)
|
||||
{
|
||||
snd_config_iterator_t i, next;
|
||||
snd_config_t *n, *variant = NULL;
|
||||
snd_config_t *n, *variant = NULL, *config = NULL;
|
||||
char *use_case_name, *file = NULL, *comment = NULL;
|
||||
bool variant_ok = false;
|
||||
int err;
|
||||
|
|
@ -2201,6 +2190,22 @@ static int parse_master_section(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg,
|
|||
continue;
|
||||
}
|
||||
|
||||
/* get use case verb configuration block (syntax version 8+) */
|
||||
if (strcmp(id, "Config") == 0) {
|
||||
if (uc_mgr->conf_format < 8) {
|
||||
snd_error(UCM, "Config is supported in v8+ syntax");
|
||||
err = -EINVAL;
|
||||
goto __error;
|
||||
}
|
||||
if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
|
||||
snd_error(UCM, "compound type expected for Config");
|
||||
err = -EINVAL;
|
||||
goto __error;
|
||||
}
|
||||
config = n;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* get optional use case comment */
|
||||
if (strncmp(id, "Comment", 7) == 0) {
|
||||
err = parse_string_substitute3(uc_mgr, n, &comment);
|
||||
|
|
@ -2238,18 +2243,38 @@ static int parse_master_section(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg,
|
|||
goto __error;
|
||||
}
|
||||
|
||||
/* check mutual exclusivity of File and Config */
|
||||
if (file && config) {
|
||||
snd_error(UCM, "both File and Config specified in SectionUseCase");
|
||||
err = -EINVAL;
|
||||
goto __error;
|
||||
}
|
||||
|
||||
if (!variant) {
|
||||
snd_debug(UCM, "use_case_name %s file '%s'", use_case_name, file);
|
||||
|
||||
/* do we have both use case name and file ? */
|
||||
if (!file) {
|
||||
snd_error(UCM, "use case missing file");
|
||||
/* do we have both use case name and (file or config) ? */
|
||||
if (!file && !config) {
|
||||
snd_error(UCM, "use case missing file or config");
|
||||
err = -EINVAL;
|
||||
goto __error;
|
||||
}
|
||||
|
||||
/* parse verb file */
|
||||
err = parse_verb_file(uc_mgr, use_case_name, comment, file);
|
||||
/* parse verb from file or config */
|
||||
if (file) {
|
||||
snd_config_t *cfg;
|
||||
/* load config from file */
|
||||
err = uc_mgr_config_load_file(uc_mgr, file, &cfg);
|
||||
if (err < 0)
|
||||
goto __error;
|
||||
/* parse the config */
|
||||
err = parse_verb_config(uc_mgr, use_case_name, comment, cfg, file);
|
||||
snd_config_delete(cfg);
|
||||
} else {
|
||||
/* inline config - parse directly */
|
||||
err = parse_verb_config(uc_mgr, use_case_name, comment, config,
|
||||
comment ? comment : use_case_name);
|
||||
}
|
||||
} else {
|
||||
/* parse variants */
|
||||
struct list_head orig_variable_list;
|
||||
|
|
@ -2303,9 +2328,24 @@ static int parse_master_section(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg,
|
|||
if (err < 0)
|
||||
break;
|
||||
uc_mgr->parse_variant = id;
|
||||
err = parse_verb_file(uc_mgr, id,
|
||||
vcomment ? vcomment : comment,
|
||||
vfile ? vfile : file);
|
||||
if (vfile || file) {
|
||||
snd_config_t *cfg;
|
||||
const char *fname = vfile ? vfile : file;
|
||||
/* load config from file */
|
||||
err = uc_mgr_config_load_file(uc_mgr, fname, &cfg);
|
||||
if (err >= 0) {
|
||||
err = parse_verb_config(uc_mgr, id,
|
||||
vcomment ? vcomment : comment,
|
||||
cfg, fname);
|
||||
snd_config_delete(cfg);
|
||||
}
|
||||
} else {
|
||||
/* inline config from variant */
|
||||
err = parse_verb_config(uc_mgr, id,
|
||||
vcomment ? vcomment : comment,
|
||||
config,
|
||||
vcomment ? vcomment : (comment ? comment : id));
|
||||
}
|
||||
uc_mgr->parse_variant = NULL;
|
||||
free(vfile);
|
||||
free(vcomment);
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ use case verbs for that sound card. i.e.:
|
|||
# Example master file for blah sound card
|
||||
# By Joe Blogs <joe@bloggs.org>
|
||||
|
||||
Syntax 7
|
||||
Syntax 8
|
||||
|
||||
# Use Case name for user interface
|
||||
Comment "Nice Abstracted Soundcard"
|
||||
|
|
@ -80,6 +80,31 @@ SectionUseCase."HiFi" {
|
|||
Comment "Play and record HiFi quality Music."
|
||||
}
|
||||
|
||||
# Since Syntax 8, you can also use Config to specify configuration inline
|
||||
# instead of referencing an external file. Only one of File or Config can be used.
|
||||
|
||||
SectionUseCase."Inline Example" {
|
||||
Comment "Example with inline configuration"
|
||||
Config {
|
||||
SectionVerb {
|
||||
EnableSequence [
|
||||
cset "name='Power Save' off"
|
||||
]
|
||||
DisableSequence [
|
||||
cset "name='Power Save' on"
|
||||
]
|
||||
}
|
||||
SectionDevice."Speaker" {
|
||||
EnableSequence [
|
||||
cset "name='Speaker Switch' on"
|
||||
]
|
||||
DisableSequence [
|
||||
cset "name='Speaker Switch' off"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Define Value defaults
|
||||
|
||||
ValueDefaults {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue