topology: Add option to pass pre-processor definitions

Add a -D switch to be able to pass pre-processor definitions that will
be used to expand arguments in the input config file. This will be
useful to generate multiple topology binaries from the same input config
file with different argument values.

For example: if we had a pipeline config as follows:

Object.Pipeline {
	volume-playback.1 {
		dynamic_pipeline $DYNAMIC_PIPELINE
	}
}

We can define the variable for DYNAMIC_PIPELINE as:

Define {
	DYNAMIC_PIPELINE 0
}

And when pre-processing the conf file pass "-D DYNAMIC_PIPELINE=1" to
override the default value for dynamic_pipeline attribute in the input
conf file.

Signed-off-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
Ranjani Sridharan 2021-11-04 12:17:24 -07:00 committed by Jaroslav Kysela
parent c4e43384fc
commit da8f90c424
3 changed files with 118 additions and 10 deletions

View file

@ -222,7 +222,93 @@ err:
return ret; return ret;
} }
int pre_process(struct tplg_pre_processor *tplg_pp, char *config, size_t config_size) static int pre_process_defines(struct tplg_pre_processor *tplg_pp, const char *pre_processor_defs,
snd_config_t *top)
{
snd_config_t *conf_defines, *defines;
int ret;
ret = snd_config_search(tplg_pp->input_cfg, "Define", &conf_defines);
if (ret < 0)
return 0;
if (snd_config_get_type(conf_defines) != SND_CONFIG_TYPE_COMPOUND)
return 0;
/*
* load and merge the command line defines with the variables in the conf file to override
* default values
*/
if (pre_processor_defs != NULL) {
ret = snd_config_load_string(&defines, pre_processor_defs, strlen(pre_processor_defs));
if (ret < 0) {
fprintf(stderr, "Failed to load pre-processor command line definitions\n");
return ret;
}
ret = snd_config_merge(conf_defines, defines, true);
if (ret < 0) {
fprintf(stderr, "Failed to override variable definitions\n");
return ret;
}
}
return 0;
}
static int pre_process_variables_expand_fcn(snd_config_t **dst, const char *str,
void *private_data)
{
struct tplg_pre_processor *tplg_pp = private_data;
snd_config_iterator_t i, next;
snd_config_t *conf_defines;
int ret;
ret = snd_config_search(tplg_pp->input_cfg, "Define", &conf_defines);
if (ret < 0)
return 0;
/* find variable definition */
snd_config_for_each(i, next, conf_defines) {
snd_config_t *n;
const char *id;
n = snd_config_iterator_entry(i);
if (snd_config_get_id(n, &id) < 0)
continue;
if (strcmp(id, str))
continue;
/* found definition. Match type and return appropriate config */
if (snd_config_get_type(n) == SND_CONFIG_TYPE_STRING) {
const char *s;
if (snd_config_get_string(n, &s) < 0)
continue;
return snd_config_imake_string(dst, NULL, s);
}
if (snd_config_get_type(n) == SND_CONFIG_TYPE_INTEGER) {
long v;
if (snd_config_get_integer(n, &v) < 0)
continue;
ret = snd_config_imake_integer(dst, NULL, v);
return ret;
}
}
fprintf(stderr, "No definition for variable %s\n", str);
return -EINVAL;
}
int pre_process(struct tplg_pre_processor *tplg_pp, char *config, size_t config_size,
const char *pre_processor_defs)
{ {
snd_input_t *in; snd_input_t *in;
snd_config_t *top; snd_config_t *top;
@ -249,7 +335,22 @@ int pre_process(struct tplg_pre_processor *tplg_pp, char *config, size_t config_
tplg_pp->input_cfg = top; tplg_pp->input_cfg = top;
err = pre_process_config(tplg_pp, top); /* parse command line definitions */
err = pre_process_defines(tplg_pp, pre_processor_defs, tplg_pp->input_cfg);
if (err < 0) {
fprintf(stderr, "Failed to parse arguments in input config\n");
goto err;
}
/* expand pre-processor variables */
err = snd_config_expand_custom(tplg_pp->input_cfg, tplg_pp->input_cfg, pre_process_variables_expand_fcn,
tplg_pp, &tplg_pp->input_cfg);
if (err < 0) {
fprintf(stderr, "Failed to expand pre-processor definitions in input config\n");
goto err;
}
err = pre_process_config(tplg_pp, tplg_pp->input_cfg);
if (err < 0) { if (err < 0) {
fprintf(stderr, "Unable to pre-process configuration\n"); fprintf(stderr, "Unable to pre-process configuration\n");
goto err; goto err;

View file

@ -234,7 +234,8 @@ static int dump(const char *source_file, const char *output_file, int cflags, in
} }
/* Convert Topology2.0 conf to the existing conf syntax */ /* Convert Topology2.0 conf to the existing conf syntax */
static int pre_process_conf(const char *source_file, const char *output_file) static int pre_process_conf(const char *source_file, const char *output_file,
const char *pre_processor_defs)
{ {
struct tplg_pre_processor *tplg_pp; struct tplg_pre_processor *tplg_pp;
size_t config_size; size_t config_size;
@ -254,7 +255,7 @@ static int pre_process_conf(const char *source_file, const char *output_file)
} }
/* pre-process conf file */ /* pre-process conf file */
err = pre_process(tplg_pp, config, config_size); err = pre_process(tplg_pp, config, config_size, pre_processor_defs);
/* free pre-processor */ /* free pre-processor */
free_pre_preprocessor(tplg_pp); free_pre_preprocessor(tplg_pp);
@ -262,7 +263,8 @@ static int pre_process_conf(const char *source_file, const char *output_file)
return err; return err;
} }
static int compile(const char *source_file, const char *output_file, int cflags) static int compile(const char *source_file, const char *output_file, int cflags,
const char *pre_processor_defs)
{ {
struct tplg_pre_processor *tplg_pp = NULL; struct tplg_pre_processor *tplg_pp = NULL;
snd_tplg_t *tplg; snd_tplg_t *tplg;
@ -284,7 +286,7 @@ static int compile(const char *source_file, const char *output_file, int cflags)
init_pre_precessor(&tplg_pp, SND_OUTPUT_BUFFER, NULL); init_pre_precessor(&tplg_pp, SND_OUTPUT_BUFFER, NULL);
/* pre-process conf file */ /* pre-process conf file */
err = pre_process(tplg_pp, config, config_size); err = pre_process(tplg_pp, config, config_size, pre_processor_defs);
if (err) { if (err) {
free_pre_preprocessor(tplg_pp); free_pre_preprocessor(tplg_pp);
free(config); free(config);
@ -353,7 +355,7 @@ static int decode(const char *source_file, const char *output_file,
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
static const char short_options[] = "hc:d:n:u:v:o:pP:sgxzV"; static const char short_options[] = "hc:d:n:u:v:o:pP:sgxzVD:";
static const struct option long_options[] = { static const struct option long_options[] = {
{"help", 0, NULL, 'h'}, {"help", 0, NULL, 'h'},
{"verbose", 1, NULL, 'v'}, {"verbose", 1, NULL, 'v'},
@ -372,6 +374,7 @@ int main(int argc, char *argv[])
}; };
char *source_file = NULL; char *source_file = NULL;
char *output_file = NULL; char *output_file = NULL;
const char *pre_processor_defs = NULL;
int c, err, op = 'c', cflags = 0, dflags = 0, sflags = 0, option_index; int c, err, op = 'c', cflags = 0, dflags = 0, sflags = 0, option_index;
#ifdef ENABLE_NLS #ifdef ENABLE_NLS
@ -423,6 +426,9 @@ int main(int argc, char *argv[])
case 'x': case 'x':
sflags |= SND_TPLG_SAVE_NOCHECK; sflags |= SND_TPLG_SAVE_NOCHECK;
break; break;
case 'D':
pre_processor_defs = optarg;
break;
case 'V': case 'V':
version(argv[0]); version(argv[0]);
return 0; return 0;
@ -448,13 +454,13 @@ int main(int argc, char *argv[])
switch (op) { switch (op) {
case 'c': case 'c':
err = compile(source_file, output_file, cflags); err = compile(source_file, output_file, cflags, pre_processor_defs);
break; break;
case 'd': case 'd':
err = decode(source_file, output_file, cflags, dflags, sflags); err = decode(source_file, output_file, cflags, dflags, sflags);
break; break;
case 'P': case 'P':
err = pre_process_conf(source_file, output_file); err = pre_process_conf(source_file, output_file, pre_processor_defs);
break; break;
default: default:
err = dump(source_file, output_file, cflags, sflags); err = dump(source_file, output_file, cflags, sflags);

View file

@ -27,7 +27,8 @@ struct tplg_pre_processor {
snd_output_t *dbg_output; snd_output_t *dbg_output;
}; };
int pre_process(struct tplg_pre_processor *tplg_pp, char *config, size_t config_size); int pre_process(struct tplg_pre_processor *tplg_pp, char *config, size_t config_size,
const char *pre_processor_defs);
int init_pre_precessor(struct tplg_pre_processor **tplg_pp, snd_output_type_t type, int init_pre_precessor(struct tplg_pre_processor **tplg_pp, snd_output_type_t type,
const char *output_file); const char *output_file);
void free_pre_preprocessor(struct tplg_pre_processor *tplg_pp); void free_pre_preprocessor(struct tplg_pre_processor *tplg_pp);