[alsa-devel] [PATCH v4 0/3] topology: Support widgets' stream name and file inclusion for text conf file
From: Mengdong Lin mengdong.lin@linux.intel.com
This series doesn't require or cause any ABI updates. It doesn't need the kernel patches that trying to udpate ABI from v4 or v5.
Patch 1 fixes a missing topology feature for text conf file to configure stream name of a widget.
Patch 2 allows alsaconf to search included files under global configuration directories. This will benefit topology and UCM.
Patch 3 adds document about how to include files for topology configuration. There is no c code change but actually it depends on patch 2.
History: v2: No longer use topology-specific code to support searching included files, but extend alsaconf to support this and user can just use alsaconf syntax <xxx> and confdir:xxx.
v3: Not use confdir:xxx, but define new syntax searchdir:xxx to define directories for searching included file.
v4: Not use doxygen comments for static functins. Fix memory leak, Use snprintf to avoid overflow, use auto variable to cook file path, and list_for_each for non-deletion cases.
Mengdong Lin (3): topology: Fix missing stream name of widgets in text conf file alsaconf: Search included files under user specified configuration directories topology: Add doc for including other files in the text conf file
include/topology.h | 31 ++++++++++ src/conf.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/topology/dapm.c | 10 ++++ 3 files changed, 199 insertions(+), 1 deletion(-)
From: Mengdong Lin mengdong.lin@linux.intel.com
User can define the stream name of an input/output widget in the text conf file, by setting "stream_name" of a SectionWidget.
Topology C API and kernel already have support for configuring a widget's stream name. This patch just adds the missing part of the text conf file.
Signed-off-by: Mengdong Lin mengdong.lin@linux.intel.com
diff --git a/include/topology.h b/include/topology.h index 0675b52..a0d018e 100644 --- a/include/topology.h +++ b/include/topology.h @@ -483,6 +483,7 @@ extern "C" { * index "1" # Index number * * type "aif_in" # Widget type - detailed above + * stream_name "name" # Stream name * * no_pm "true" # No PM control bit. * reg "20" # PM bit register offset diff --git a/src/topology/dapm.c b/src/topology/dapm.c index e3c90d8..9fa0aac 100644 --- a/src/topology/dapm.c +++ b/src/topology/dapm.c @@ -507,6 +507,16 @@ int tplg_parse_dapm_widget(snd_tplg_t *tplg, continue; }
+ if (strcmp(id, "stream_name") == 0) { + if (snd_config_get_string(n, &val) < 0) + return -EINVAL; + + elem_copy_text(widget->sname, val, + SNDRV_CTL_ELEM_ID_NAME_MAXLEN); + tplg_dbg("\t%s: %s\n", id, val); + continue; + } + if (strcmp(id, "no_pm") == 0) { if (snd_config_get_string(n, &val) < 0) return -EINVAL;
From: Mengdong Lin mengdong.lin@linux.intel.com
Users can include file by giving a relative path or just a file name via alsaconf syntax <xxx>. ALSA conf will search the file in top configuration directory and additional configuration directories defined by users via alsaconf syntax searchdir:xxx.
ALSA conf will search and open an included file in the following order of priority:
1. directly open the file by its name; 2. search for the file name in top config direcotry "/usr/share/alsa/"; 3. search for the file name in additional configuration directories specified by users, via alsaconf syntax searchdir:relative-path/to/user/share/alsa; These directories will be searched in the same order as their definition.
The configuration directories defined by a file will only be used to search the files included by this file.
Signed-off-by: Mengdong Lin mengdong.lin@linux.intel.com
diff --git a/src/conf.c b/src/conf.c index a516611..c0999bc 100644 --- a/src/conf.c +++ b/src/conf.c @@ -456,6 +456,18 @@ struct filedesc { snd_input_t *in; unsigned int line, column; struct filedesc *next; + + /* list of the include paths (configuration directories), + * defined by searchdir:relative-path/to/top-alsa-conf-dir, + * for searching its included files. + */ + struct list_head include_paths; +}; + +/* path to search included files */ +struct include_path { + char *dir; + struct list_head list; };
#define LOCAL_ERROR (-0x68000000) @@ -501,6 +513,108 @@ static inline void snd_config_unlock(void) { }
#endif
+/** + * Add a diretory to the paths to search included files. + * param fd - File object that owns these paths to search files included by it. + * param dir - Path of the directory to add. Allocated externally and need to +* be freed manually later. + * return - Zero if successful, otherwise a negative error code. + * + * The direcotry should be a subdiretory of top configuration directory + * "/usr/share/alsa/". + */ +static int add_include_path(struct filedesc *fd, char *dir) +{ + struct include_path *path; + + path = calloc(1, sizeof(*path)); + if (!path) + return -ENOMEM; + + path->dir = dir; + list_add_tail(&path->list, &fd->include_paths); + return 0; +} + +/** + * Free all include paths of a file descriptor. + * param fd - File object that owns these paths to search files included by it. + */ +static void free_include_paths(struct filedesc *fd) +{ + struct list_head *pos, *npos, *base; + struct include_path *path; + + base = &fd->include_paths; + list_for_each_safe(pos, npos, base) { + path = list_entry(pos, struct include_path, list); + list_del(&path->list); + if (path->dir) + free(path->dir); + free(path); + } +} + +/** + * Search and open a file, and creates a new input object reading from the file. + * param inputp - The functions puts the pointer to the new input object + * at the address specified by \p inputp. + * param file - Name of the configuration file. + * param include_paths - Optional, addtional directories to search the file. + * return - Zero if successful, otherwise a negative error code. + * + * This function will search and open the file in the following order + * of priority: + * 1. directly open the file by its name; + * 2. search for the file name in top configuration directory + * "/usr/share/alsa/"; + * 3. search for the file name in in additional configuration directories + * specified by users, via alsaconf syntax + * searchdir:relative-path/to/user/share/alsa; + * These directories should be subdirectories of /usr/share/alsa. + */ +static int input_stdio_open(snd_input_t **inputp, const char *file, + struct list_head *include_paths) +{ + struct list_head *pos, *base; + struct include_path *path; + char full_path[PATH_MAX + 1]; + int err = 0; + + err = snd_input_stdio_open(inputp, file, "r"); + if (err == 0) + goto out; + + if (file[0] == '/') /* not search file with absolute path */ + return err; + + /* search file in top configuration directory /usr/share/alsa */ + snprintf(full_path, PATH_MAX, "%s/%s", ALSA_CONFIG_DIR, file); + err = snd_input_stdio_open(inputp, full_path, "r"); + if (err == 0) + goto out; + + /* search file in user specified include paths. These directories + * are subdirectories of /usr/share/alsa. + */ + if (include_paths) { + base = include_paths; + list_for_each(pos, base) { + path = list_entry(pos, struct include_path, list); + if (!path->dir) + continue; + + snprintf(full_path, PATH_MAX, "%s/%s", path->dir, file); + err = snd_input_stdio_open(inputp, full_path, "r"); + if (err == 0) + goto out; + } + } + +out: + return err; +} + static int safe_strtoll(const char *str, long long *val) { long long v; @@ -629,10 +743,44 @@ static int get_char_skip_comments(input_t *input) char *str; snd_input_t *in; struct filedesc *fd; + DIR *dirp; int err = get_delimstring(&str, '>', input); if (err < 0) return err; + + if (!strncmp(str, "searchdir:", 10)) { + /* directory to search included files */ + char *tmp; + + tmp = malloc(strlen(ALSA_CONFIG_DIR) + 1 + + strlen(str + 10) + 1); + if (tmp == NULL) { + free(str); + return -ENOMEM; + } + sprintf(tmp, ALSA_CONFIG_DIR "/%s", str + 10); + free(str); + str = tmp; + + dirp = opendir(str); + if (!dirp) { + SNDERR("Invalid search dir %s", str); + free(str); + return -EINVAL; + } + closedir(dirp); + + err = add_include_path(input->current, str); + if (err < 0) { + SNDERR("Cannot add search dir %s", str); + free(str); + return err; + } + continue; + } + if (!strncmp(str, "confdir:", 8)) { + /* file in the specified directory */ char *tmp = malloc(strlen(ALSA_CONFIG_DIR) + 1 + strlen(str + 8) + 1); if (tmp == NULL) { free(str); @@ -641,8 +789,12 @@ static int get_char_skip_comments(input_t *input) sprintf(tmp, ALSA_CONFIG_DIR "/%s", str + 8); free(str); str = tmp; + err = snd_input_stdio_open(&in, str, "r"); + } else { /* absolute or relative file path */ + err = input_stdio_open(&in, str, + &input->current->include_paths); } - err = snd_input_stdio_open(&in, str, "r"); + if (err < 0) { SNDERR("Cannot access file %s", str); free(str); @@ -658,6 +810,7 @@ static int get_char_skip_comments(input_t *input) fd->next = input->current; fd->line = 1; fd->column = 0; + INIT_LIST_HEAD(&fd->include_paths); input->current = fd; continue; } @@ -1668,6 +1821,7 @@ static int snd_config_load1(snd_config_t *config, snd_input_t *in, int override) fd->line = 1; fd->column = 0; fd->next = NULL; + INIT_LIST_HEAD(&fd->include_paths); input.current = fd; input.unget = 0; err = parse_defs(config, &input, 0, override); @@ -1708,9 +1862,12 @@ static int snd_config_load1(snd_config_t *config, snd_input_t *in, int override) fd_next = fd->next; snd_input_close(fd->in); free(fd->name); + free_include_paths(fd); free(fd); fd = fd_next; } + + free_include_paths(fd); free(fd); return err; }
From: Mengdong Lin mengdong.lin@linux.intel.com
This patch adds document about how to include other files in the text configuration files, by alsaconf syntax <xxx> and searchdir:xxx.
Users may define common info in separate files (e.g. vendor tokens, tuples) and share them for different platforms, by including them via syntax <path/to/configuration-file>. This can save the total size of files. Users can also specifiy additional configuraiton directories relative to "/usr/share/alsa/" to search the included files, via syntax searchdir:relative-path/to/usr/share/alsa.
The alsaconf will search and open an included file in the following order of priority: 1. directly open the file by its name; 2. search for the file name in "/usr/share/alsa"; 3. search for the file name in user specified subdirectories under "/usr/share/alsa".
The order of the included files need not to be same as their dependencies, because the toplogy library will load all of them before parsing their dependencies.
Signed-off-by: Mengdong Lin mengdong.lin@linux.intel.com
diff --git a/include/topology.h b/include/topology.h index a0d018e..4f606c7 100644 --- a/include/topology.h +++ b/include/topology.h @@ -624,6 +624,36 @@ extern "C" { * data "name" # optional private data * } * </pre> + * + * <h4>Include other files</h4> + * Users may include other files in a text conf file via alsaconf syntax + * <path/to/configuration-file>. This allows users to define common info + * in separate files (e.g. vendor tokens, tuples) and share them for + * different platforms, thus save the total size of config files. <br> + * Users can also specifiy additional configuraiton directories relative + * to "/usr/share/alsa/" to search the included files, via alsaconf syntax + * searchfdir:/relative-path/to/usr/share/alsa. <br><br> + * + * For example, file A and file B are two text conf files for platform X, + * they will be installed to /usr/share/alsa/topology/platformx. If we + * need file A to include file B, in file A we can add: <br> + * + * searchdir:topology/platformx <br> + * <name-of-file-B> <br><br> + * + * ALSA conf will search and open an included file in the following order + * of priority: + * 1. directly open the file by its name; + * 2. search for the file name in "/usr/share/alsa"; + * 3. search for the file name in user specified subdirectories under + * "/usr/share/alsa". + * + * The order of the included files need not to be same as their + * dependencies, since the topology library will load them all before + * parsing their dependencies. <br> + * + * The configuration directories defined by a file will only be used to search + * the files included by this file. */
/** Maximum number of channels supported in one control */
participants (1)
-
mengdong.lin@linux.intel.com