]> git.alsa-project.org Git - alsa-utils.git/commitdiff
topology: Add option to pass pre-processor definitions
authorRanjani Sridharan <ranjani.sridharan@linux.intel.com>
Thu, 4 Nov 2021 19:17:24 +0000 (12:17 -0700)
committerJaroslav Kysela <perex@perex.cz>
Mon, 6 Dec 2021 08:19:20 +0000 (09:19 +0100)
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>
topology/pre-processor.c
topology/topology.c
topology/topology.h

index e6f9af69117191af2dcb84ed7ea10f3fb6a2bb03..b0353bb60b88afda4df15677e66e683b369dc309 100644 (file)
@@ -222,7 +222,93 @@ err:
        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_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;
 
-       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) {
                fprintf(stderr, "Unable to pre-process configuration\n");
                goto err;
index e0c7e7c88bff93db164781ebb1769bfe3465dc85..4a0750fdc1a507bdec7372f3a9290c335487ce86 100644 (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 */
-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;
        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 */
-       err = pre_process(tplg_pp, config, config_size);
+       err = pre_process(tplg_pp, config, config_size, pre_processor_defs);
 
        /* free pre-processor */
        free_pre_preprocessor(tplg_pp);
@@ -262,7 +263,8 @@ static int pre_process_conf(const char *source_file, const char *output_file)
        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;
        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);
 
                /* 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) {
                        free_pre_preprocessor(tplg_pp);
                        free(config);
@@ -353,7 +355,7 @@ static int decode(const char *source_file, const char *output_file,
 
 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[] = {
                {"help", 0, NULL, 'h'},
                {"verbose", 1, NULL, 'v'},
@@ -372,6 +374,7 @@ int main(int argc, char *argv[])
        };
        char *source_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;
 
 #ifdef ENABLE_NLS
@@ -423,6 +426,9 @@ int main(int argc, char *argv[])
                case 'x':
                        sflags |= SND_TPLG_SAVE_NOCHECK;
                        break;
+               case 'D':
+                       pre_processor_defs = optarg;
+                       break;
                case 'V':
                        version(argv[0]);
                        return 0;
@@ -448,13 +454,13 @@ int main(int argc, char *argv[])
 
        switch (op) {
        case 'c':
-               err = compile(source_file, output_file, cflags);
+               err = compile(source_file, output_file, cflags, pre_processor_defs);
                break;
        case 'd':
                err = decode(source_file, output_file, cflags, dflags, sflags);
                break;
        case 'P':
-               err = pre_process_conf(source_file, output_file);
+               err = pre_process_conf(source_file, output_file, pre_processor_defs);
                break;
        default:
                err = dump(source_file, output_file, cflags, sflags);
index 494612b2d8e7306d0991feaeb27488015e033808..5dd9b1ff088fd31f1ea7843eef356bd72ee1de79 100644 (file)
@@ -27,7 +27,8 @@ struct tplg_pre_processor {
        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,
                       const char *output_file);
 void free_pre_preprocessor(struct tplg_pre_processor *tplg_pp);