3 * \ingroup Configuration
4 * \brief Configuration helper functions
5 * \author Abramo Bagnara <abramo@alsa-project.org>
6 * \author Jaroslav Kysela <perex@perex.cz>
9 * Tree based, full nesting configuration functions.
11 * See the \ref conf page for more details.
14 * Configuration helper functions
15 * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>,
16 * Jaroslav Kysela <perex@perex.cz>
19 * This library is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU Lesser General Public License as
21 * published by the Free Software Foundation; either version 2.1 of
22 * the License, or (at your option) any later version.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU Lesser General Public License for more details.
29 * You should have received a copy of the GNU Lesser General Public
30 * License along with this library; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
35 /*! \page conf Configuration files
37 <P>Configuration files use a simple format allowing modern
38 data description like nesting and array assignments.</P>
40 \section conf_whitespace Whitespace
42 Whitespace is the collective name given to spaces (blanks), horizontal and
43 vertical tabs, newline characters, and comments. Whitespace can
44 indicate where configuration tokens start and end, but beyond this function,
45 any surplus whitespace is discarded. For example, the two sequences
58 are lexically equivalent and parse identically to give the four tokens:
67 The ASCII characters representing whitespace can occur within literal
68 strings, in which case they are protected from the normal parsing process
69 (they remain as part of the string). For example:
75 parses to two tokens, including the single literal-string token "John
78 \section conf_linesplicing Line continuation with \
80 A special case occurs if a newline character in a string is preceded
81 by a backslash (\). The backslash and the new line are both discarded,
82 allowing two physical lines of text to be treated as one unit.
89 is parsed as "John Smith".
91 \section conf_comments Comments
93 A single-line comment begins with the character #. The comment can start
94 at any position, and extends to the end of the line.
97 a 1 # this is a comment
100 \section conf_include Including configuration files
102 To include another configuration file, write the file name in angle brackets.
103 The prefix \c confdir: will reference the global configuration directory.
107 <confdir:pcm/surround.conf>
110 \section conf_punctuators Punctuators
112 The configuration punctuators (also known as separators) are:
115 {} [] , ; = . ' " new-line form-feed carriage-return whitespace
118 \subsection conf_braces Braces
120 Opening and closing braces { } indicate the start and end of a compound
129 \subsection conf_brackets Brackets
131 Opening and closing brackets indicate a single array definition. The
132 identifiers are automatically generated starting with zero.
141 The above code is equal to
148 \subsection conf_comma_semicolon Comma and semicolon
150 The comma (,) or semicolon (;) can separate value assignments. It is not
151 strictly required to use these separators because whitespace suffices to
159 \subsection conf_equal Equal sign
161 The equal sign (=) can separate variable declarations from
162 initialization lists:
169 Using equal signs is not required because whitespace suffices to separate
172 \section conf_assigns Assignments
174 The configuration file defines id (key) and value pairs. The id (key) can be
175 composed from ASCII digits, characters from a to z and A to Z, and the
176 underscore (_). The value can be either a string, an integer, a real number,
177 or a compound statement.
179 \subsection conf_single Single assignments
188 \subsection conf_compound Compound assignments (definitions using braces)
199 \section conf_compound1 Compound assignments (one key definitions)
206 \subsection conf_array Array assignments (definitions using brackets)
215 \subsection conf_array1 Array assignments (one key definitions)
222 \section conf_mode Operation modes for parsing nodes
224 By default, the node operation mode is 'merge+create', i.e., if
225 a configuration node is not present a new one is created, otherwise
226 the latest assignment is merged (if possible - type checking). The
227 'merge+create' operation mode is specified with the prefix character plus (+).
229 The operation mode 'merge' merges the node with the old one (which must
230 exist). Type checking is done, so strings cannot be assigned to integers
231 and so on. This mode is specified with the prefix character minus (-).
233 The operation mode 'do not override' ignores a new configuration node
234 if a configuration node with the same name exists. This mode is specified with
235 the prefix character question mark (?).
237 The operation mode 'override' always overrides the old configuration node
238 with new contents. This mode is specified with the prefix character
239 exclamation mark (!).
242 defaults.pcm.!device 1
245 \section conf_syntax_summary Syntax summary
248 # Configuration file syntax
250 # Include a new configuration file
256 # Compound assignment (first style)
258 name1 [=] value [,|;]
262 # Compound assignment (second style)
263 name.name1 [=] value [,|;]
265 # Array assignment (first style)
272 # Array assignment (second style)
273 name.0 [=] value0 [,|;]
274 name.1 [=] value1 [,|;]
277 \section conf_syntax_ref References
285 /*! \page confarg Runtime arguments in configuration files
287 <P>The ALSA library can accept runtime arguments for some configuration
288 blocks. This extension is built on top of the basic configuration file
291 \section confarg_define Defining arguments
293 Arguments are defined using the id (key) \c \@args and array values containing
294 the string names of the arguments:
301 \section confarg_type Defining argument types and default values
303 An argument's type is specified with the id (key) \c \@args and the argument
304 name. The type and the default value are specified in the compound block:
313 \section confarg_refer Referring to arguments
315 Arguments are referred to with a dollar-sign ($) and the name of the argument:
321 \section confarg_usage Usage
323 To use a block with arguments, write the argument values after the key,
324 separated with a colon (:). For example, all these names for PCM interfaces
325 give the same result:
332 plug:{SLAVE="hw:{CARD 0 DEV 1}"}
335 As you see, arguments can be specified in their proper order or by name.
336 Note that arguments enclosed in braces are parsed in the same way as in
337 configuration files, but using the override method by default.
339 \section confarg_example Example
343 @args [ CARD DEVICE ]
360 /*! \page conffunc Runtime functions in configuration files
362 <P>The ALSA library can modify the configuration at runtime.
363 Several built-in functions are available.</P>
365 <P>A function is defined with the id \c \@func and the function name. All other
366 values in the current compound are used as configuration for the function.
367 If the compound func.\<function_name\> is defined in the root node, then the
368 library and function from this compound configuration are used, otherwise
369 'snd_func_' is prefixed to the string and code from the ALSA library is used.
370 The definition of a function looks like:</P>
373 func.remove_first_char {
374 lib "/usr/lib/libasoundextend.so"
375 func "extend_remove_first_char"
381 /*! \page confhooks Hooks in configuration files
383 <P>The hook extension in the ALSA library allows expansion of configuration
384 nodes at run-time. The existence of a hook is determined by the
385 presence of a \@hooks compound node.</P>
387 <P>This example defines a hook which loads two configuration files at the
403 \section confhooks_ref Function reference
406 <LI>The function load - \c snd_config_hook_load() - loads and parses the
407 given configuration files.
408 <LI>The function load_for_all_cards - \c snd_config_hook_load_for_all_cards() -
409 loads and parses the given configuration files for each installed sound
410 card. The driver name (the type of the sound card) is passed in the
411 private configuration node.
420 #include <sys/stat.h>
423 #ifdef HAVE_LIBPTHREAD
429 #ifdef HAVE_LIBPTHREAD
430 static pthread_mutex_t snd_config_update_mutex;
431 static pthread_once_t snd_config_update_mutex_once = PTHREAD_ONCE_INIT;
436 snd_config_type_t type;
437 int refcount; /* default = 0 */
445 struct list_head fields;
449 struct list_head list;
450 snd_config_t *parent;
457 unsigned int line, column;
458 struct filedesc *next;
460 /* list of the include paths (configuration directories),
461 * defined by <searchdir:relative-path/to/top-alsa-conf-dir>,
462 * for searching its included files.
464 struct list_head include_paths;
467 /* path to search included files */
468 struct include_path {
470 struct list_head list;
473 #define LOCAL_ERROR (-0x68000000)
475 #define LOCAL_UNTERMINATED_STRING (LOCAL_ERROR - 0)
476 #define LOCAL_UNTERMINATED_QUOTE (LOCAL_ERROR - 1)
477 #define LOCAL_UNEXPECTED_CHAR (LOCAL_ERROR - 2)
478 #define LOCAL_UNEXPECTED_EOF (LOCAL_ERROR - 3)
481 struct filedesc *current;
486 #ifdef HAVE_LIBPTHREAD
488 static void snd_config_init_mutex(void)
490 pthread_mutexattr_t attr;
492 pthread_mutexattr_init(&attr);
493 #ifdef HAVE_PTHREAD_MUTEX_RECURSIVE
494 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
496 pthread_mutex_init(&snd_config_update_mutex, &attr);
497 pthread_mutexattr_destroy(&attr);
500 static inline void snd_config_lock(void)
502 pthread_once(&snd_config_update_mutex_once, snd_config_init_mutex);
503 pthread_mutex_lock(&snd_config_update_mutex);
506 static inline void snd_config_unlock(void)
508 pthread_mutex_unlock(&snd_config_update_mutex);
513 static inline void snd_config_lock(void) { }
514 static inline void snd_config_unlock(void) { }
519 * Add a diretory to the paths to search included files.
520 * param fd - File object that owns these paths to search files included by it.
521 * param dir - Path of the directory to add. Allocated externally and need to
522 * be freed manually later.
523 * return - Zero if successful, otherwise a negative error code.
525 * The direcotry should be a subdiretory of top configuration directory
526 * "/usr/share/alsa/".
528 static int add_include_path(struct filedesc *fd, char *dir)
530 struct include_path *path;
532 path = calloc(1, sizeof(*path));
537 list_add_tail(&path->list, &fd->include_paths);
542 * Free all include paths of a file descriptor.
543 * param fd - File object that owns these paths to search files included by it.
545 static void free_include_paths(struct filedesc *fd)
547 struct list_head *pos, *npos, *base;
548 struct include_path *path;
550 base = &fd->include_paths;
551 list_for_each_safe(pos, npos, base) {
552 path = list_entry(pos, struct include_path, list);
553 list_del(&path->list);
561 * \brief Returns the default top-level config directory
562 * \return The top-level config directory path string
564 * This function returns the string of the top-level config directory path.
565 * If the path is specified via the environment variable \c ALSA_CONFIG_DIR
566 * and the value is a valid path, it returns this value. If unspecified, it
567 * returns the default value, "/usr/share/alsa".
569 const char *snd_config_topdir(void)
574 topdir = getenv("ALSA_CONFIG_DIR");
575 if (!topdir || *topdir != '/' || strlen(topdir) >= PATH_MAX)
576 topdir = ALSA_CONFIG_DIR;
581 static char *_snd_config_path(const char *name)
583 const char *root = snd_config_topdir();
584 char *path = malloc(strlen(root) + strlen(name) + 2);
587 sprintf(path, "%s/%s", root, name);
592 * Search and open a file, and creates a new input object reading from the file.
593 * param inputp - The functions puts the pointer to the new input object
594 * at the address specified by \p inputp.
595 * param file - Name of the configuration file.
596 * param include_paths - Optional, addtional directories to search the file.
597 * return - Zero if successful, otherwise a negative error code.
599 * This function will search and open the file in the following order
601 * 1. directly open the file by its name;
602 * 2. search for the file name in top configuration directory
603 * "/usr/share/alsa/";
604 * 3. search for the file name in in additional configuration directories
605 * specified by users, via alsaconf syntax
606 * <searchdir:relative-path/to/user/share/alsa>;
607 * These directories should be subdirectories of /usr/share/alsa.
609 static int input_stdio_open(snd_input_t **inputp, const char *file,
610 struct list_head *include_paths)
612 struct list_head *pos, *base;
613 struct include_path *path;
614 char full_path[PATH_MAX + 1];
617 err = snd_input_stdio_open(inputp, file, "r");
621 if (file[0] == '/') /* not search file with absolute path */
624 /* search file in top configuration directory /usr/share/alsa */
625 snprintf(full_path, PATH_MAX, "%s/%s", snd_config_topdir(), file);
626 err = snd_input_stdio_open(inputp, full_path, "r");
630 /* search file in user specified include paths. These directories
631 * are subdirectories of /usr/share/alsa.
634 base = include_paths;
635 list_for_each(pos, base) {
636 path = list_entry(pos, struct include_path, list);
640 snprintf(full_path, PATH_MAX, "%s/%s", path->dir, file);
641 err = snd_input_stdio_open(inputp, full_path, "r");
651 static int safe_strtoll(const char *str, long long *val)
658 if (sscanf(str, "%lli%n", &v, &endidx) < 1)
666 int safe_strtol(const char *str, long *val)
673 v = strtol(str, &end, 0);
682 static int safe_strtod(const char *str, double *val)
686 #ifdef HAVE_USELOCALE
687 locale_t saved_locale, c_locale;
690 char locstr[64]; /* enough? */
696 #ifdef HAVE_USELOCALE
697 c_locale = newlocale(LC_NUMERIC_MASK, "C", 0);
698 saved_locale = uselocale(c_locale);
700 saved_locale = setlocale(LC_NUMERIC, NULL);
702 snprintf(locstr, sizeof(locstr), "%s", saved_locale);
703 setlocale(LC_NUMERIC, "C");
707 v = strtod(str, &end);
709 #ifdef HAVE_USELOCALE
710 if (c_locale != (locale_t)0) {
711 uselocale(saved_locale);
712 freelocale(c_locale);
716 setlocale(LC_NUMERIC, locstr);
726 static int get_char(input_t *input)
736 c = snd_input_getc(fd->in);
743 fd->column += 8 - fd->column % 8;
747 snd_input_close(fd->in);
749 input->current = fd->next;
753 return LOCAL_UNEXPECTED_EOF;
758 return (unsigned char)c;
761 static void unget_char(int c, input_t *input)
763 assert(!input->unget);
768 static int get_delimstring(char **string, int delim, input_t *input);
770 static int get_char_skip_comments(input_t *input)
780 int err = get_delimstring(&str, '>', input);
784 if (!strncmp(str, "searchdir:", 10)) {
785 /* directory to search included files */
786 char *tmp = _snd_config_path(str + 10);
794 SNDERR("Invalid search dir %s", str);
800 err = add_include_path(input->current, str);
802 SNDERR("Cannot add search dir %s", str);
809 if (!strncmp(str, "confdir:", 8)) {
810 /* file in the specified directory */
811 char *tmp = _snd_config_path(str + 8);
816 err = snd_input_stdio_open(&in, str, "r");
817 } else { /* absolute or relative file path */
818 err = input_stdio_open(&in, str,
819 &input->current->include_paths);
823 SNDERR("Cannot access file %s", str);
827 fd = malloc(sizeof(*fd));
834 fd->next = input->current;
837 INIT_LIST_HEAD(&fd->include_paths);
856 static int get_nonwhite(input_t *input)
860 c = get_char_skip_comments(input);
874 static int get_quotedchar(input_t *input)
897 if (c < '0' || c > '7') {
898 unget_char(c, input);
901 num = num * 8 + c - '0';
911 #define LOCAL_STR_BUFSIZE 64
912 struct local_string {
916 char tmpbuf[LOCAL_STR_BUFSIZE];
919 static void init_local_string(struct local_string *s)
921 memset(s, 0, sizeof(*s));
923 s->alloc = LOCAL_STR_BUFSIZE;
926 static void free_local_string(struct local_string *s)
928 if (s->buf != s->tmpbuf)
932 static int add_char_local_string(struct local_string *s, int c)
934 if (s->idx >= s->alloc) {
935 size_t nalloc = s->alloc * 2;
936 if (s->buf == s->tmpbuf) {
937 s->buf = malloc(nalloc);
940 memcpy(s->buf, s->tmpbuf, s->alloc);
942 char *ptr = realloc(s->buf, nalloc);
949 s->buf[s->idx++] = c;
953 static char *copy_local_string(struct local_string *s)
955 char *dst = malloc(s->idx + 1);
957 memcpy(dst, s->buf, s->idx);
963 static int get_freestring(char **string, int id, input_t *input)
965 struct local_string str;
968 init_local_string(&str);
972 if (c == LOCAL_UNEXPECTED_EOF) {
973 *string = copy_local_string(&str);
1001 *string = copy_local_string(&str);
1005 unget_char(c, input);
1012 if (add_char_local_string(&str, c) < 0) {
1018 free_local_string(&str);
1022 static int get_delimstring(char **string, int delim, input_t *input)
1024 struct local_string str;
1027 init_local_string(&str);
1029 c = get_char(input);
1033 c = get_quotedchar(input);
1038 } else if (c == delim) {
1039 *string = copy_local_string(&str);
1046 if (add_char_local_string(&str, c) < 0) {
1051 free_local_string(&str);
1055 /* Return 0 for free string, 1 for delimited string */
1056 static int get_string(char **string, int id, input_t *input)
1058 int c = get_nonwhite(input), err;
1071 return LOCAL_UNEXPECTED_CHAR;
1074 err = get_delimstring(string, c, input);
1079 unget_char(c, input);
1080 err = get_freestring(string, id, input);
1087 static int _snd_config_make(snd_config_t **config, char **id, snd_config_type_t type)
1091 n = calloc(1, sizeof(*n));
1104 if (type == SND_CONFIG_TYPE_COMPOUND)
1105 INIT_LIST_HEAD(&n->u.compound.fields);
1111 static int _snd_config_make_add(snd_config_t **config, char **id,
1112 snd_config_type_t type, snd_config_t *parent)
1116 assert(parent->type == SND_CONFIG_TYPE_COMPOUND);
1117 err = _snd_config_make(&n, id, type);
1121 list_add_tail(&n->list, &parent->u.compound.fields);
1126 static int _snd_config_search(snd_config_t *config,
1127 const char *id, int len, snd_config_t **result)
1129 snd_config_iterator_t i, next;
1130 snd_config_for_each(i, next, config) {
1131 snd_config_t *n = snd_config_iterator_entry(i);
1133 if (strcmp(n->id, id) != 0)
1135 } else if (strlen(n->id) != (size_t) len ||
1136 memcmp(n->id, id, (size_t) len) != 0)
1145 static int parse_value(snd_config_t **_n, snd_config_t *parent, input_t *input, char **id, int skip)
1147 snd_config_t *n = *_n;
1151 err = get_string(&s, 0, input);
1158 if (err == 0 && ((s[0] >= '0' && s[0] <= '9') || s[0] == '-')) {
1161 err = safe_strtoll(s, &i);
1164 err = safe_strtod(s, &r);
1168 if (n->type != SND_CONFIG_TYPE_REAL) {
1169 SNDERR("%s is not a real", *id);
1173 err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_REAL, parent);
1184 if (n->type != SND_CONFIG_TYPE_INTEGER && n->type != SND_CONFIG_TYPE_INTEGER64) {
1185 SNDERR("%s is not an integer", *id);
1190 err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_INTEGER, parent);
1192 err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_INTEGER64, parent);
1196 if (n->type == SND_CONFIG_TYPE_INTEGER)
1197 n->u.integer = (long) i;
1205 if (n->type != SND_CONFIG_TYPE_STRING) {
1206 SNDERR("%s is not a string", *id);
1211 err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_STRING, parent);
1221 static int parse_defs(snd_config_t *parent, input_t *input, int skip, int override);
1222 static int parse_array_defs(snd_config_t *farther, input_t *input, int skip, int override);
1224 static int parse_array_def(snd_config_t *parent, input_t *input, int idx, int skip, int override)
1229 snd_config_t *n = NULL;
1233 snprintf(static_id, sizeof(static_id), "%i", idx);
1234 id = strdup(static_id);
1238 c = get_nonwhite(input);
1250 if (n->type != SND_CONFIG_TYPE_COMPOUND) {
1251 SNDERR("%s is not a compound", id);
1256 err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, parent);
1262 err = parse_defs(n, input, skip, override);
1265 err = parse_array_defs(n, input, skip, override);
1268 c = get_nonwhite(input);
1275 snd_config_delete(n);
1276 err = LOCAL_UNEXPECTED_CHAR;
1282 unget_char(c, input);
1283 err = parse_value(&n, parent, input, &id, skip);
1294 static int parse_array_defs(snd_config_t *parent, input_t *input, int skip, int override)
1298 int c = get_nonwhite(input), err;
1301 unget_char(c, input);
1304 err = parse_array_def(parent, input, idx++, skip, override);
1311 static int parse_def(snd_config_t *parent, input_t *input, int skip, int override)
1317 enum {MERGE_CREATE, MERGE, OVERRIDE, DONT_OVERRIDE} mode;
1319 c = get_nonwhite(input);
1324 mode = MERGE_CREATE;
1330 mode = DONT_OVERRIDE;
1336 mode = !override ? MERGE_CREATE : OVERRIDE;
1337 unget_char(c, input);
1339 err = get_string(&id, 1, input);
1342 c = get_nonwhite(input);
1349 if (_snd_config_search(parent, id, -1, &n) == 0) {
1350 if (mode == DONT_OVERRIDE) {
1355 if (mode != OVERRIDE) {
1356 if (n->type != SND_CONFIG_TYPE_COMPOUND) {
1357 SNDERR("%s is not a compound", id);
1360 n->u.compound.join = 1;
1365 snd_config_delete(n);
1367 if (mode == MERGE) {
1368 SNDERR("%s does not exists", id);
1372 err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, parent);
1375 n->u.compound.join = 1;
1379 c = get_nonwhite(input);
1384 if (_snd_config_search(parent, id, -1, &n) == 0) {
1385 if (mode == DONT_OVERRIDE) {
1388 } else if (mode == OVERRIDE) {
1389 snd_config_delete(n);
1394 if (mode == MERGE) {
1395 SNDERR("%s does not exists", id);
1408 if (n->type != SND_CONFIG_TYPE_COMPOUND) {
1409 SNDERR("%s is not a compound", id);
1414 err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, parent);
1420 err = parse_defs(n, input, skip, override);
1423 err = parse_array_defs(n, input, skip, override);
1426 c = get_nonwhite(input);
1429 snd_config_delete(n);
1430 err = LOCAL_UNEXPECTED_CHAR;
1436 unget_char(c, input);
1437 err = parse_value(&n, parent, input, &id, skip);
1442 c = get_nonwhite(input);
1448 unget_char(c, input);
1455 static int parse_defs(snd_config_t *parent, input_t *input, int skip, int override)
1459 c = get_nonwhite(input);
1461 return c == LOCAL_UNEXPECTED_EOF ? 0 : c;
1462 unget_char(c, input);
1465 err = parse_def(parent, input, skip, override);
1472 static void string_print(char *str, int id, snd_output_t *out)
1474 unsigned char *p = (unsigned char *)str;
1476 snd_output_puts(out, "''");
1507 snd_output_puts(out, str);
1510 snd_output_putc(out, '\'');
1511 p = (unsigned char *)str;
1517 snd_output_putc(out, '\\');
1518 snd_output_putc(out, 'n');
1521 snd_output_putc(out, '\\');
1522 snd_output_putc(out, 't');
1525 snd_output_putc(out, '\\');
1526 snd_output_putc(out, 'v');
1529 snd_output_putc(out, '\\');
1530 snd_output_putc(out, 'b');
1533 snd_output_putc(out, '\\');
1534 snd_output_putc(out, 'r');
1537 snd_output_putc(out, '\\');
1538 snd_output_putc(out, 'f');
1541 snd_output_putc(out, '\\');
1542 snd_output_putc(out, c);
1544 case 32 ... '\'' - 1:
1545 case '\'' + 1 ... 126:
1546 snd_output_putc(out, c);
1549 snd_output_printf(out, "\\%04o", c);
1554 snd_output_putc(out, '\'');
1557 static int _snd_config_save_children(snd_config_t *config, snd_output_t *out,
1558 unsigned int level, unsigned int joins);
1560 static int _snd_config_save_node_value(snd_config_t *n, snd_output_t *out,
1566 case SND_CONFIG_TYPE_INTEGER:
1567 snd_output_printf(out, "%ld", n->u.integer);
1569 case SND_CONFIG_TYPE_INTEGER64:
1570 snd_output_printf(out, "%lld", n->u.integer64);
1572 case SND_CONFIG_TYPE_REAL:
1573 snd_output_printf(out, "%-16g", n->u.real);
1575 case SND_CONFIG_TYPE_STRING:
1576 string_print(n->u.string, 0, out);
1578 case SND_CONFIG_TYPE_POINTER:
1579 SNDERR("cannot save runtime pointer type");
1581 case SND_CONFIG_TYPE_COMPOUND:
1582 snd_output_putc(out, '{');
1583 snd_output_putc(out, '\n');
1584 err = _snd_config_save_children(n, out, level + 1, 0);
1587 for (k = 0; k < level; ++k) {
1588 snd_output_putc(out, '\t');
1590 snd_output_putc(out, '}');
1596 static void id_print(snd_config_t *n, snd_output_t *out, unsigned int joins)
1600 id_print(n->parent, out, joins - 1);
1601 snd_output_putc(out, '.');
1603 string_print(n->id, 1, out);
1606 static int _snd_config_save_children(snd_config_t *config, snd_output_t *out,
1607 unsigned int level, unsigned int joins)
1611 snd_config_iterator_t i, next;
1612 assert(config && out);
1613 snd_config_for_each(i, next, config) {
1614 snd_config_t *n = snd_config_iterator_entry(i);
1615 if (n->type == SND_CONFIG_TYPE_COMPOUND &&
1616 n->u.compound.join) {
1617 err = _snd_config_save_children(n, out, level, joins + 1);
1622 for (k = 0; k < level; ++k) {
1623 snd_output_putc(out, '\t');
1625 id_print(n, out, joins);
1627 snd_output_putc(out, ' ');
1628 snd_output_putc(out, '=');
1630 snd_output_putc(out, ' ');
1631 err = _snd_config_save_node_value(n, out, level);
1635 snd_output_putc(out, ';');
1637 snd_output_putc(out, '\n');
1645 * \brief Substitutes one configuration node to another.
1646 * \param dst Handle to the destination node.
1647 * \param src Handle to the source node. Must not be the same as \a dst.
1648 * \return Zero if successful, otherwise a negative error code.
1650 * If both nodes are compounds, the source compound node members are
1651 * appended to the destination compound node.
1653 * If the destination node is a compound and the source node is
1654 * an ordinary type, the compound members are deleted (including
1657 * Otherwise, the source node's value replaces the destination node's
1660 * In any case, a successful call to this function frees the source
1663 int snd_config_substitute(snd_config_t *dst, snd_config_t *src)
1666 if (dst->type == SND_CONFIG_TYPE_COMPOUND &&
1667 src->type == SND_CONFIG_TYPE_COMPOUND) { /* append */
1668 snd_config_iterator_t i, next;
1669 snd_config_for_each(i, next, src) {
1670 snd_config_t *n = snd_config_iterator_entry(i);
1673 src->u.compound.fields.next->prev = &dst->u.compound.fields;
1674 src->u.compound.fields.prev->next = &dst->u.compound.fields;
1675 } else if (dst->type == SND_CONFIG_TYPE_COMPOUND) {
1677 err = snd_config_delete_compound_members(dst);
1683 dst->type = src->type;
1690 * \brief Converts an ASCII string to a configuration node type.
1691 * \param[in] ascii A string containing a configuration node type.
1692 * \param[out] type The node type corresponding to \a ascii.
1693 * \return Zero if successful, otherwise a negative error code.
1695 * This function recognizes at least the following node types:
1697 * <dt>integer<dt>#SND_CONFIG_TYPE_INTEGER
1698 * <dt>integer64<dt>#SND_CONFIG_TYPE_INTEGER64
1699 * <dt>real<dt>#SND_CONFIG_TYPE_REAL
1700 * <dt>string<dt>#SND_CONFIG_TYPE_STRING
1701 * <dt>compound<dt>#SND_CONFIG_TYPE_COMPOUND
1706 * <dt>-EINVAL<dd>Unknown note type in \a type.
1709 int snd_config_get_type_ascii(const char *ascii, snd_config_type_t *type)
1711 assert(ascii && type);
1712 if (!strcmp(ascii, "integer")) {
1713 *type = SND_CONFIG_TYPE_INTEGER;
1716 if (!strcmp(ascii, "integer64")) {
1717 *type = SND_CONFIG_TYPE_INTEGER64;
1720 if (!strcmp(ascii, "real")) {
1721 *type = SND_CONFIG_TYPE_REAL;
1724 if (!strcmp(ascii, "string")) {
1725 *type = SND_CONFIG_TYPE_STRING;
1728 if (!strcmp(ascii, "compound")) {
1729 *type = SND_CONFIG_TYPE_COMPOUND;
1736 * \brief Returns the type of a configuration node.
1737 * \param config Handle to the configuration node.
1738 * \return The node's type.
1740 * \par Conforming to:
1743 snd_config_type_t snd_config_get_type(const snd_config_t *config)
1745 return config->type;
1749 * \brief Returns the id of a configuration node.
1750 * \param[in] config Handle to the configuration node.
1751 * \param[out] id The function puts the pointer to the id string at the
1752 * address specified by \a id.
1753 * \return Zero if successful, otherwise a negative error code.
1755 * The returned string is owned by the configuration node; the application
1756 * must not modify or delete it, and the string becomes invalid when the
1757 * node's id changes or when the node is freed.
1759 * If the node does not have an id, \a *id is set to \c NULL.
1761 * \par Conforming to:
1764 int snd_config_get_id(const snd_config_t *config, const char **id)
1766 assert(config && id);
1772 * \brief Sets the id of a configuration node.
1773 * \param config Handle to the configuration node.
1774 * \param id The new node id, must not be \c NULL.
1775 * \return Zero if successful, otherwise a negative error code.
1777 * This function stores a copy of \a id in the node.
1781 * <dt>-EEXIST<dd>One of \a config's siblings already has the id \a id.
1782 * <dt>-EINVAL<dd>The id of a node with a parent cannot be set to \c NULL.
1783 * <dt>-ENOMEM<dd>Out of memory.
1786 int snd_config_set_id(snd_config_t *config, const char *id)
1788 snd_config_iterator_t i, next;
1792 if (config->parent) {
1793 snd_config_for_each(i, next, config->parent) {
1794 snd_config_t *n = snd_config_iterator_entry(i);
1795 if (n != config && strcmp(id, n->id) == 0)
1799 new_id = strdup(id);
1808 config->id = new_id;
1813 * \brief Creates a top level configuration node.
1814 * \param[out] config Handle to the new node.
1815 * \return Zero if successful, otherwise a negative error code.
1817 * The returned node is an empty compound node without a parent and
1822 * <dt>-ENOMEM<dd>Out of memory.
1825 * \par Conforming to:
1828 int snd_config_top(snd_config_t **config)
1831 return _snd_config_make(config, 0, SND_CONFIG_TYPE_COMPOUND);
1834 static int snd_config_load1(snd_config_t *config, snd_input_t *in, int override)
1838 struct filedesc *fd, *fd_next;
1839 assert(config && in);
1840 fd = malloc(sizeof(*fd));
1848 INIT_LIST_HEAD(&fd->include_paths);
1851 err = parse_defs(config, &input, 0, override);
1856 case LOCAL_UNTERMINATED_STRING:
1857 str = "Unterminated string";
1860 case LOCAL_UNTERMINATED_QUOTE:
1861 str = "Unterminated quote";
1864 case LOCAL_UNEXPECTED_CHAR:
1865 str = "Unexpected char";
1868 case LOCAL_UNEXPECTED_EOF:
1869 str = "Unexpected end of file";
1873 str = strerror(-err);
1876 SNDERR("%s:%d:%d:%s", fd->name ? fd->name : "_toplevel_", fd->line, fd->column, str);
1879 if (get_char(&input) != LOCAL_UNEXPECTED_EOF) {
1880 SNDERR("%s:%d:%d:Unexpected }", fd->name ? fd->name : "", fd->line, fd->column);
1887 snd_input_close(fd->in);
1889 free_include_paths(fd);
1894 free_include_paths(fd);
1900 * \brief Loads a configuration tree.
1901 * \param config Handle to a top level configuration node.
1902 * \param in Input handle to read the configuration from.
1903 * \return Zero if successful, otherwise a negative error code.
1905 * The definitions loaded from the input are added to \a config, which
1906 * must be a compound node.
1909 * Any errors encountered when parsing the input or returned by hooks or
1912 * \par Conforming to:
1915 int snd_config_load(snd_config_t *config, snd_input_t *in)
1917 return snd_config_load1(config, in, 0);
1921 * \brief Loads a configuration tree and overrides existing configuration nodes.
1922 * \param config Handle to a top level configuration node.
1923 * \param in Input handle to read the configuration from.
1924 * \return Zero if successful, otherwise a negative error code.
1926 * This function loads definitions from \a in into \a config like
1927 * #snd_config_load, but the default mode for input nodes is 'override'
1928 * (!) instead of 'merge+create' (+).
1930 int snd_config_load_override(snd_config_t *config, snd_input_t *in)
1932 return snd_config_load1(config, in, 1);
1936 * \brief Adds a child to a compound configuration node.
1937 * \param parent Handle to a compound configuration node.
1938 * \param child Handle to the configuration node to be added.
1939 * \return Zero if successful, otherwise a negative error code.
1941 * This function makes the node \a child a child of the node \a parent.
1943 * The parent node then owns the child node, i.e., the child node gets
1944 * deleted together with its parent.
1946 * \a child must have an id.
1950 * <dt>-EINVAL<dd>\a child does not have an id.
1951 * <dt>-EINVAL<dd>\a child already has a parent.
1952 * <dt>-EEXIST<dd>\a parent already contains a child node with the same
1956 * \par Conforming to:
1959 int snd_config_add(snd_config_t *parent, snd_config_t *child)
1961 snd_config_iterator_t i, next;
1962 assert(parent && child);
1963 if (!child->id || child->parent)
1965 snd_config_for_each(i, next, parent) {
1966 snd_config_t *n = snd_config_iterator_entry(i);
1967 if (strcmp(child->id, n->id) == 0)
1970 child->parent = parent;
1971 list_add_tail(&child->list, &parent->u.compound.fields);
1976 * \brief Removes a configuration node from its tree.
1977 * \param config Handle to the configuration node to be removed.
1978 * \return Zero if successful, otherwise a negative error code.
1980 * This function makes \a config a top-level node, i.e., if \a config
1981 * has a parent, then \a config is removed from the list of the parent's
1984 * This functions does \e not free the removed node.
1986 * \sa snd_config_delete
1988 int snd_config_remove(snd_config_t *config)
1992 list_del(&config->list);
1993 config->parent = NULL;
1998 * \brief Frees a configuration node.
1999 * \param config Handle to the configuration node to be deleted.
2000 * \return Zero if successful, otherwise a negative error code.
2002 * This function frees a configuration node and all its resources.
2004 * If the node is a child node, it is removed from the tree before being
2007 * If the node is a compound node, its descendants (the whole subtree)
2008 * are deleted recursively.
2010 * The function is supposed to be called only for locally copied config
2011 * trees. For the global tree, take the reference via #snd_config_update_ref
2012 * and free it via #snd_config_unref.
2014 * \par Conforming to:
2017 * \sa snd_config_remove
2019 int snd_config_delete(snd_config_t *config)
2022 if (config->refcount > 0) {
2026 switch (config->type) {
2027 case SND_CONFIG_TYPE_COMPOUND:
2030 struct list_head *i;
2031 i = config->u.compound.fields.next;
2032 while (i != &config->u.compound.fields) {
2033 struct list_head *nexti = i->next;
2034 snd_config_t *child = snd_config_iterator_entry(i);
2035 err = snd_config_delete(child);
2042 case SND_CONFIG_TYPE_STRING:
2043 free(config->u.string);
2049 list_del(&config->list);
2056 * \brief Deletes the children of a node.
2057 * \param config Handle to the compound configuration node.
2058 * \return Zero if successful, otherwise a negative error code.
2060 * This function removes and frees all children of a configuration node.
2062 * Any compound nodes among the children of \a config are deleted
2065 * After a successful call to this function, \a config is an empty
2070 * <dt>-EINVAL<dd>\a config is not a compound node.
2073 int snd_config_delete_compound_members(const snd_config_t *config)
2076 struct list_head *i;
2079 if (config->type != SND_CONFIG_TYPE_COMPOUND)
2081 i = config->u.compound.fields.next;
2082 while (i != &config->u.compound.fields) {
2083 struct list_head *nexti = i->next;
2084 snd_config_t *child = snd_config_iterator_entry(i);
2085 err = snd_config_delete(child);
2094 * \brief Creates a configuration node.
2095 * \param[out] config The function puts the handle to the new node at
2096 * the address specified by \a config.
2097 * \param[in] id The id of the new node.
2098 * \param[in] type The type of the new node.
2099 * \return Zero if successful, otherwise a negative error code.
2101 * This functions creates a new node of the specified type.
2102 * The new node has id \a id, which may be \c NULL.
2104 * The value of the new node is zero (for numbers), or \c NULL (for
2105 * strings and pointers), or empty (for compound nodes).
2109 * <dt>-ENOMEM<dd>Out of memory.
2112 int snd_config_make(snd_config_t **config, const char *id,
2113 snd_config_type_t type)
2123 return _snd_config_make(config, &id1, type);
2127 * \brief Creates an integer configuration node.
2128 * \param[out] config The function puts the handle to the new node at
2129 * the address specified by \a config.
2130 * \param[in] id The id of the new node.
2131 * \return Zero if successful, otherwise a negative error code.
2133 * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER and
2138 * <dt>-ENOMEM<dd>Out of memory.
2141 * \par Conforming to:
2144 * \sa snd_config_imake_integer
2146 int snd_config_make_integer(snd_config_t **config, const char *id)
2148 return snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER);
2152 * \brief Creates a 64-bit-integer configuration node.
2153 * \param[out] config The function puts the handle to the new node at
2154 * the address specified by \a config.
2155 * \param[in] id The id of the new node.
2156 * \return Zero if successful, otherwise a negative error code.
2158 * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER64
2159 * and with value \c 0.
2163 * <dt>-ENOMEM<dd>Out of memory.
2166 * \par Conforming to:
2169 * \sa snd_config_imake_integer64
2171 int snd_config_make_integer64(snd_config_t **config, const char *id)
2173 return snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER64);
2177 * \brief Creates a real number configuration node.
2178 * \param[out] config The function puts the handle to the new node at
2179 * the address specified by \a config.
2180 * \param[in] id The id of the new node.
2181 * \return Zero if successful, otherwise a negative error code.
2183 * This function creates a new node of type #SND_CONFIG_TYPE_REAL and
2184 * with value \c 0.0.
2188 * <dt>-ENOMEM<dd>Out of memory.
2191 * \sa snd_config_imake_real
2193 int snd_config_make_real(snd_config_t **config, const char *id)
2195 return snd_config_make(config, id, SND_CONFIG_TYPE_REAL);
2199 * \brief Creates a string configuration node.
2200 * \param[out] config The function puts the handle to the new node at
2201 * the address specified by \a config.
2202 * \param[in] id The id of the new node.
2203 * \return Zero if successful, otherwise a negative error code.
2205 * This function creates a new node of type #SND_CONFIG_TYPE_STRING and
2206 * with value \c NULL.
2210 * <dt>-ENOMEM<dd>Out of memory.
2213 * \par Conforming to:
2216 * \sa snd_config_imake_string
2218 int snd_config_make_string(snd_config_t **config, const char *id)
2220 return snd_config_make(config, id, SND_CONFIG_TYPE_STRING);
2224 * \brief Creates a pointer configuration node.
2225 * \param[out] config The function puts the handle to the new node at
2226 * the address specified by \a config.
2227 * \param[in] id The id of the new node.
2228 * \return Zero if successful, otherwise a negative error code.
2230 * This function creates a new node of type #SND_CONFIG_TYPE_POINTER and
2231 * with value \c NULL.
2235 * <dt>-ENOMEM<dd>Out of memory.
2238 * \sa snd_config_imake_pointer
2240 int snd_config_make_pointer(snd_config_t **config, const char *id)
2242 return snd_config_make(config, id, SND_CONFIG_TYPE_POINTER);
2246 * \brief Creates an empty compound configuration node.
2247 * \param[out] config The function puts the handle to the new node at
2248 * the address specified by \a config.
2249 * \param[in] id The id of the new node.
2250 * \param[in] join Join flag.
2251 * \return Zero if successful, otherwise a negative error code.
2253 * This function creates a new empty node of type
2254 * #SND_CONFIG_TYPE_COMPOUND.
2256 * \a join determines how the compound node's id is printed when the
2257 * configuration is saved to a text file. For example, if the join flag
2258 * of compound node \c a is zero, the output will look as follows:
2265 * If, however, the join flag of \c a is nonzero, its id will be joined
2266 * with its children's ids, like this:
2271 * An \e empty compound node with its join flag set would result in no
2272 * output, i.e., after saving and reloading the configuration file, that
2273 * compound node would be lost.
2277 * <dt>-ENOMEM<dd>Out of memory.
2280 * \par Conforming to:
2283 int snd_config_make_compound(snd_config_t **config, const char *id,
2287 err = snd_config_make(config, id, SND_CONFIG_TYPE_COMPOUND);
2290 (*config)->u.compound.join = join;
2295 * \brief Creates an integer configuration node with the given initial value.
2296 * \param[out] config The function puts the handle to the new node at
2297 * the address specified by \a config.
2298 * \param[in] id The id of the new node.
2299 * \param[in] value The initial value of the new node.
2300 * \return Zero if successful, otherwise a negative error code.
2302 * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER and
2303 * with value \a value.
2307 * <dt>-ENOMEM<dd>Out of memory.
2310 * \par Conforming to:
2313 int snd_config_imake_integer(snd_config_t **config, const char *id, const long value)
2317 err = snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER);
2320 (*config)->u.integer = value;
2325 * \brief Creates a 64-bit-integer configuration node with the given initial value.
2326 * \param[out] config The function puts the handle to the new node at
2327 * the address specified by \a config.
2328 * \param[in] id The id of the new node.
2329 * \param[in] value The initial value of the new node.
2330 * \return Zero if successful, otherwise a negative error code.
2332 * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER64
2333 * and with value \a value.
2337 * <dt>-ENOMEM<dd>Out of memory.
2340 * \par Conforming to:
2343 int snd_config_imake_integer64(snd_config_t **config, const char *id, const long long value)
2347 err = snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER64);
2350 (*config)->u.integer64 = value;
2355 * \brief Creates a real number configuration node with the given initial value.
2356 * \param[out] config The function puts the handle to the new node at
2357 * the address specified by \a config.
2358 * \param[in] id The id of the new node.
2359 * \param[in] value The initial value of the new node.
2360 * \return Zero if successful, otherwise a negative error code.
2362 * This function creates a new node of type #SND_CONFIG_TYPE_REAL and
2363 * with value \a value.
2367 * <dt>-ENOMEM<dd>Out of memory.
2370 int snd_config_imake_real(snd_config_t **config, const char *id, const double value)
2374 err = snd_config_make(config, id, SND_CONFIG_TYPE_REAL);
2377 (*config)->u.real = value;
2382 * \brief Creates a string configuration node with the given initial value.
2383 * \param[out] config The function puts the handle to the new node at
2384 * the address specified by \a config.
2385 * \param[in] id The id of the new node.
2386 * \param[in] value The initial value of the new node. May be \c NULL.
2387 * \return Zero if successful, otherwise a negative error code.
2389 * This function creates a new node of type #SND_CONFIG_TYPE_STRING and
2390 * with a copy of the string \c value.
2394 * <dt>-ENOMEM<dd>Out of memory.
2397 * \par Conforming to:
2400 int snd_config_imake_string(snd_config_t **config, const char *id, const char *value)
2405 err = snd_config_make(&tmp, id, SND_CONFIG_TYPE_STRING);
2409 tmp->u.string = strdup(value);
2410 if (!tmp->u.string) {
2411 snd_config_delete(tmp);
2415 tmp->u.string = NULL;
2421 int snd_config_imake_safe_string(snd_config_t **config, const char *id, const char *value)
2427 err = snd_config_make(&tmp, id, SND_CONFIG_TYPE_STRING);
2431 tmp->u.string = strdup(value);
2432 if (!tmp->u.string) {
2433 snd_config_delete(tmp);
2437 for (c = tmp->u.string; *c; c++) {
2438 if (*c == ' ' || *c == '-' || *c == '_' ||
2439 (*c >= '0' && *c <= '9') ||
2440 (*c >= 'a' && *c <= 'z') ||
2441 (*c >= 'A' && *c <= 'Z'))
2446 tmp->u.string = NULL;
2454 * \brief Creates a pointer configuration node with the given initial value.
2455 * \param[out] config The function puts the handle to the new node at
2456 * the address specified by \a config.
2457 * \param[in] id The id of the new node.
2458 * \param[in] value The initial value of the new node.
2459 * \return Zero if successful, otherwise a negative error code.
2461 * This function creates a new node of type #SND_CONFIG_TYPE_POINTER and
2462 * with value \c value.
2466 * <dt>-ENOMEM<dd>Out of memory.
2469 int snd_config_imake_pointer(snd_config_t **config, const char *id, const void *value)
2473 err = snd_config_make(config, id, SND_CONFIG_TYPE_POINTER);
2476 (*config)->u.ptr = value;
2481 * \brief Changes the value of an integer configuration node.
2482 * \param config Handle to the configuration node.
2483 * \param value The new value for the node.
2484 * \return Zero if successful, otherwise a negative error code.
2488 * <dt>-EINVAL<dd>\a config is not an integer node.
2491 * \par Conforming to:
2494 int snd_config_set_integer(snd_config_t *config, long value)
2497 if (config->type != SND_CONFIG_TYPE_INTEGER)
2499 config->u.integer = value;
2504 * \brief Changes the value of a 64-bit-integer configuration node.
2505 * \param config Handle to the configuration node.
2506 * \param value The new value for the node.
2507 * \return Zero if successful, otherwise a negative error code.
2511 * <dt>-EINVAL<dd>\a config is not a 64-bit-integer node.
2514 * \par Conforming to:
2517 int snd_config_set_integer64(snd_config_t *config, long long value)
2520 if (config->type != SND_CONFIG_TYPE_INTEGER64)
2522 config->u.integer64 = value;
2527 * \brief Changes the value of a real-number configuration node.
2528 * \param config Handle to the configuration node.
2529 * \param value The new value for the node.
2530 * \return Zero if successful, otherwise a negative error code.
2534 * <dt>-EINVAL<dd>\a config is not a real-number node.
2537 int snd_config_set_real(snd_config_t *config, double value)
2540 if (config->type != SND_CONFIG_TYPE_REAL)
2542 config->u.real = value;
2547 * \brief Changes the value of a string configuration node.
2548 * \param config Handle to the configuration node.
2549 * \param value The new value for the node. May be \c NULL.
2550 * \return Zero if successful, otherwise a negative error code.
2552 * This function deletes the old string in the node and stores a copy of
2553 * \a value string in the node.
2557 * <dt>-EINVAL<dd>\a config is not a string node.
2560 * \par Conforming to:
2563 int snd_config_set_string(snd_config_t *config, const char *value)
2567 if (config->type != SND_CONFIG_TYPE_STRING)
2570 new_string = strdup(value);
2576 free(config->u.string);
2577 config->u.string = new_string;
2582 * \brief Changes the value of a pointer configuration node.
2583 * \param config Handle to the configuration node.
2584 * \param value The new value for the node. May be \c NULL.
2585 * \return Zero if successful, otherwise a negative error code.
2587 * This function does not free the old pointer in the node.
2591 * <dt>-EINVAL<dd>\a config is not a pointer node.
2594 int snd_config_set_pointer(snd_config_t *config, const void *value)
2597 if (config->type != SND_CONFIG_TYPE_POINTER)
2599 config->u.ptr = value;
2604 * \brief Changes the value of a configuration node.
2605 * \param config Handle to the configuration node.
2606 * \param ascii The new value for the node, as an ASCII string.
2607 * \return Zero if successful, otherwise a negative error code.
2609 * This function changes the node's value to a new value that is parsed
2610 * from the string \a ascii. \a ascii must not be \c NULL, not even for
2613 * The node's type does not change, i.e., the string must contain a
2614 * valid value with the same type as the node's type. For a string
2615 * node, the node's new value is a copy of \a ascii.
2619 * <dt>-EINVAL<dd>\a config is not a number or string node.
2620 * <dt>-EINVAL<dd>The value in \a ascii cannot be parsed.
2621 * <dt>-ERANGE<dd>The value in \a ascii is too big for the node's type.
2622 * <dt>-ENOMEM<dd>Out of memory.
2625 * \par Conforming to:
2628 int snd_config_set_ascii(snd_config_t *config, const char *ascii)
2630 assert(config && ascii);
2631 switch (config->type) {
2632 case SND_CONFIG_TYPE_INTEGER:
2635 int err = safe_strtol(ascii, &i);
2638 config->u.integer = i;
2641 case SND_CONFIG_TYPE_INTEGER64:
2644 int err = safe_strtoll(ascii, &i);
2647 config->u.integer64 = i;
2650 case SND_CONFIG_TYPE_REAL:
2653 int err = safe_strtod(ascii, &d);
2659 case SND_CONFIG_TYPE_STRING:
2661 char *ptr = strdup(ascii);
2664 free(config->u.string);
2665 config->u.string = ptr;
2675 * \brief Returns the value of an integer configuration node.
2676 * \param[in] config Handle to the configuration node.
2677 * \param[out] ptr The node's value.
2678 * \return Zero if successful, otherwise a negative error code.
2682 * <dt>-EINVAL<dd>\a config is not an integer node.
2685 * \par Conforming to:
2688 int snd_config_get_integer(const snd_config_t *config, long *ptr)
2690 assert(config && ptr);
2691 if (config->type != SND_CONFIG_TYPE_INTEGER)
2693 *ptr = config->u.integer;
2698 * \brief Returns the value of a 64-bit-integer configuration node.
2699 * \param[in] config Handle to the configuration node.
2700 * \param[out] ptr The node's value.
2701 * \return Zero if successful, otherwise a negative error code.
2705 * <dt>-EINVAL<dd>\a config is not a 64-bit-integer node.
2708 * \par Conforming to:
2711 int snd_config_get_integer64(const snd_config_t *config, long long *ptr)
2713 assert(config && ptr);
2714 if (config->type != SND_CONFIG_TYPE_INTEGER64)
2716 *ptr = config->u.integer64;
2721 * \brief Returns the value of a real-number configuration node.
2722 * \param[in] config Handle to the configuration node.
2723 * \param[out] ptr The node's value.
2724 * \return Zero if successful, otherwise a negative error code.
2728 * <dt>-EINVAL<dd>\a config is not a real-number node.
2731 int snd_config_get_real(const snd_config_t *config, double *ptr)
2733 assert(config && ptr);
2734 if (config->type != SND_CONFIG_TYPE_REAL)
2736 *ptr = config->u.real;
2741 * \brief Returns the value of a real or integer configuration node.
2742 * \param[in] config Handle to the configuration node.
2743 * \param[out] ptr The node's value.
2744 * \return Zero if successful, otherwise a negative error code.
2746 * If the node's type is integer or integer64, the value is converted
2747 * to the \c double type on the fly.
2751 * <dt>-EINVAL<dd>\a config is not a number node.
2754 int snd_config_get_ireal(const snd_config_t *config, double *ptr)
2756 assert(config && ptr);
2757 if (config->type == SND_CONFIG_TYPE_REAL)
2758 *ptr = config->u.real;
2759 else if (config->type == SND_CONFIG_TYPE_INTEGER)
2760 *ptr = config->u.integer;
2761 else if (config->type == SND_CONFIG_TYPE_INTEGER64)
2762 *ptr = config->u.integer64;
2769 * \brief Returns the value of a string configuration node.
2770 * \param[in] config Handle to the configuration node.
2771 * \param[out] ptr The function puts the node's value at the address
2772 * specified by \a ptr.
2773 * \return Zero if successful, otherwise a negative error code.
2775 * The returned string is owned by the configuration node; the
2776 * application must not modify or delete it, and the string becomes
2777 * invalid when the node's value changes or when the node is freed.
2779 * The string may be \c NULL.
2783 * <dt>-EINVAL<dd>\a config is not a string node.
2786 * \par Conforming to:
2789 int snd_config_get_string(const snd_config_t *config, const char **ptr)
2791 assert(config && ptr);
2792 if (config->type != SND_CONFIG_TYPE_STRING)
2794 *ptr = config->u.string;
2799 * \brief Returns the value of a pointer configuration node.
2800 * \param[in] config Handle to the configuration node.
2801 * \param[out] ptr The function puts the node's value at the address
2802 * specified by \a ptr.
2803 * \return Zero if successful, otherwise a negative error code.
2807 * <dt>-EINVAL<dd>\a config is not a string node.
2810 int snd_config_get_pointer(const snd_config_t *config, const void **ptr)
2812 assert(config && ptr);
2813 if (config->type != SND_CONFIG_TYPE_POINTER)
2815 *ptr = config->u.ptr;
2820 * \brief Returns the value of a configuration node as a string.
2821 * \param[in] config Handle to the configuration node.
2822 * \param[out] ascii The function puts the pointer to the returned
2823 * string at the address specified by \a ascii.
2824 * \return Zero if successful, otherwise a negative error code.
2826 * This function dynamically allocates the returned string. The
2827 * application is responsible for deleting it with \c free() when it is
2830 * For a string node with \c NULL value, the returned string is \c NULL.
2832 * Supported node types are #SND_CONFIG_TYPE_INTEGER,
2833 * #SND_CONFIG_TYPE_INTEGER64, #SND_CONFIG_TYPE_REAL, and
2834 * #SND_CONFIG_TYPE_STRING.
2838 * <dt>-EINVAL<dd>\a config is not a (64-bit) integer or real number or
2840 * <dt>-ENOMEM<dd>Out of memory.
2843 * \par Conforming to:
2846 int snd_config_get_ascii(const snd_config_t *config, char **ascii)
2848 assert(config && ascii);
2849 switch (config->type) {
2850 case SND_CONFIG_TYPE_INTEGER:
2854 err = snprintf(res, sizeof(res), "%li", config->u.integer);
2855 if (err < 0 || err == sizeof(res)) {
2859 *ascii = strdup(res);
2862 case SND_CONFIG_TYPE_INTEGER64:
2866 err = snprintf(res, sizeof(res), "%lli", config->u.integer64);
2867 if (err < 0 || err == sizeof(res)) {
2871 *ascii = strdup(res);
2874 case SND_CONFIG_TYPE_REAL:
2878 err = snprintf(res, sizeof(res), "%-16g", config->u.real);
2879 if (err < 0 || err == sizeof(res)) {
2883 if (res[0]) { /* trim the string */
2885 ptr = res + strlen(res) - 1;
2886 while (ptr != res && *ptr == ' ')
2892 *ascii = strdup(res);
2895 case SND_CONFIG_TYPE_STRING:
2896 if (config->u.string)
2897 *ascii = strdup(config->u.string);
2912 * \brief Compares the id of a configuration node to a given string.
2913 * \param config Handle to the configuration node.
2914 * \param id ASCII id.
2915 * \return The same value as the result of the \c strcmp function, i.e.,
2916 * less than zero if \a config's id is lexicographically less
2917 * than \a id, zero if \a config's id is equal to id, greater
2918 * than zero otherwise.
2920 int snd_config_test_id(const snd_config_t *config, const char *id)
2922 assert(config && id);
2924 return strcmp(config->id, id);
2930 * \brief Dumps the contents of a configuration node or tree.
2931 * \param config Handle to the (root) configuration node.
2932 * \param out Output handle.
2933 * \return Zero if successful, otherwise a negative error code.
2935 * This function writes a textual representation of \a config's value to
2936 * the output \a out.
2940 * <dt>-EINVAL<dd>A node in the tree has a type that cannot be printed,
2941 * i.e., #SND_CONFIG_TYPE_POINTER.
2944 * \par Conforming to:
2947 int snd_config_save(snd_config_t *config, snd_output_t *out)
2949 assert(config && out);
2950 if (config->type == SND_CONFIG_TYPE_COMPOUND)
2951 return _snd_config_save_children(config, out, 0, 0);
2953 return _snd_config_save_node_value(config, out, 0);
2957 * *** search macros ***
2962 #define SND_CONFIG_SEARCH(config, key, result, extra_code) \
2967 assert(config && key); \
2969 if (config->type != SND_CONFIG_TYPE_COMPOUND) \
2972 p = strchr(key, '.'); \
2974 err = _snd_config_search(config, key, p - key, &n); \
2980 return _snd_config_search(config, key, -1, result); \
2984 #define SND_CONFIG_SEARCHA(root, config, key, result, fcn, extra_code) \
2989 assert(config && key); \
2991 if (config->type != SND_CONFIG_TYPE_COMPOUND) { \
2992 if (snd_config_get_string(config, &p) < 0) \
2994 err = fcn(root, root, p, &config); \
2999 p = strchr(key, '.'); \
3001 err = _snd_config_search(config, key, p - key, &n); \
3007 return _snd_config_search(config, key, -1, result); \
3011 #define SND_CONFIG_SEARCHV(config, result, fcn) \
3016 va_start(arg, result); \
3018 const char *k = va_arg(arg, const char *); \
3022 err = fcn(config, k, &n); \
3033 #define SND_CONFIG_SEARCHVA(root, config, result, fcn) \
3038 va_start(arg, result); \
3040 const char *k = va_arg(arg, const char *); \
3044 err = fcn(root, config, k, &n); \
3055 #define SND_CONFIG_SEARCH_ALIAS(config, base, key, result, fcn1, fcn2) \
3057 snd_config_t *res = NULL; \
3059 int err, first = 1, maxloop = 1000; \
3060 assert(config && key); \
3062 old_key = strdup(key); \
3063 if (old_key == NULL) { \
3068 err = first && base ? -EIO : fcn1(config, config, key, &res); \
3072 err = fcn2(config, config, &res, base, key, NULL); \
3076 if (snd_config_get_string(res, &key) < 0) \
3079 if (!first && (strcmp(key, old_key) == 0 || maxloop <= 0)) { \
3081 SNDERR("maximum loop count reached (circular configuration?)"); \
3083 SNDERR("key %s refers to itself", key); \
3100 #endif /* DOC_HIDDEN */
3103 * \brief Searches for a node in a configuration tree.
3104 * \param[in] config Handle to the root of the configuration (sub)tree to search.
3105 * \param[in] key Search key: one or more node ids, separated with dots.
3106 * \param[out] result When \a result != \c NULL, the function puts the
3107 * handle to the node found at the address specified
3109 * \return Zero if successful, otherwise a negative error code.
3111 * This function searches for a child node of \a config that is
3112 * identified by \a key, which contains either the id of a direct child
3113 * node of \a config, or a series of ids, separated with dots, where
3114 * each id specifies a node that is contained in the previous compound
3117 * In the following example, the comment after each node shows the
3118 * search key to find that node, assuming that \a config is a handle to
3119 * the compound node with id \c config:
3126 * e 2.71828 # "b.d.e"
3134 * <dt>-ENOENT<dd>An id in \a key does not exist.
3135 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3136 * not a compound node.
3139 * \par Conforming to:
3142 int snd_config_search(snd_config_t *config, const char *key, snd_config_t **result)
3144 SND_CONFIG_SEARCH(config, key, result, );
3148 * \brief Searches for a node in a configuration tree, expanding aliases.
3149 * \param[in] root Handle to the root configuration node containing
3150 * alias definitions.
3151 * \param[in] config Handle to the root of the configuration (sub)tree to search.
3152 * \param[in] key Search key: one or more node keys, separated with dots.
3153 * \param[out] result When \a result != \c NULL, the function puts the
3154 * handle to the node found at the address specified
3156 * \return Zero if successful, otherwise a negative error code.
3158 * This functions searches for a child node of \a config like
3159 * #snd_config_search. However, any compound node can also be
3160 * identified by an alias, which is a string node whose value is taken
3161 * as the id of a compound node below \a root.
3163 * \a root must be a compound node.
3164 * \a root and \a config may be the same node.
3166 * For example, with the following configuration, the call
3168 * snd_config_searcha(root, config, "a.b.c.d", &result);
3170 * would return the node with id \c d:
3192 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist.
3193 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3194 * not a compound or string node.
3197 int snd_config_searcha(snd_config_t *root, snd_config_t *config, const char *key, snd_config_t **result)
3199 SND_CONFIG_SEARCHA(root, config, key, result, snd_config_searcha, );
3203 * \brief Searches for a node in a configuration tree.
3204 * \param[in] config Handle to the root of the configuration (sub)tree to search.
3205 * \param[out] result When \a result != \c NULL, the function puts the
3206 * handle to the node found at the address specified
3208 * \param[in] ... One or more concatenated dot-separated search keys,
3209 * terminated with \c NULL.
3210 * \return Zero if successful, otherwise a negative error code.
3212 * This functions searches for a child node of \a config like
3213 * #snd_config_search, but the search key is the concatenation of all
3214 * passed search key strings. For example, the call
3216 * snd_config_searchv(cfg, &res, "a", "b.c", "d.e", NULL);
3218 * is equivalent to the call
3220 * snd_config_search(cfg, "a.b.c.d.e", &res);
3225 * <dt>-ENOENT<dd>An id in a search key does not exist.
3226 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3227 * not a compound node.
3230 * \par Conforming to:
3233 int snd_config_searchv(snd_config_t *config, snd_config_t **result, ...)
3235 SND_CONFIG_SEARCHV(config, result, snd_config_search);
3239 * \brief Searches for a node in a configuration tree, expanding aliases.
3240 * \param[in] root Handle to the root configuration node containing
3241 * alias definitions.
3242 * \param[in] config Handle to the root of the configuration (sub)tree to search.
3243 * \param[out] result When \a result != \c NULL, the function puts the
3244 * handle to the node found at the address specified
3246 * \param[in] ... One or more concatenated dot separated search keys,
3247 * terminated with \c NULL.
3248 * \return Zero if successful, otherwise a negative error code.
3250 * This function searches for a child node of \a config, allowing
3251 * aliases, like #snd_config_searcha, but the search key is the
3252 * concatenation of all passed seach key strings, like with
3253 * #snd_config_searchv.
3257 * <dt>-ENOENT<dd>An id in a search key does not exist.
3258 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3259 * not a compound or string node.
3262 int snd_config_searchva(snd_config_t *root, snd_config_t *config, snd_config_t **result, ...)
3264 SND_CONFIG_SEARCHVA(root, config, result, snd_config_searcha);
3268 * \brief Searches for a node in a configuration tree, expanding aliases.
3269 * \param[in] config Handle to the root of the configuration (sub)tree to search.
3270 * \param[in] base Search key base, or \c NULL.
3271 * \param[in] key Search key suffix.
3272 * \param[out] result When \a result != \c NULL, the function puts the
3273 * handle to the node found at the address specified
3275 * \return Zero if successful, otherwise a negative error code.
3277 * This functions searches for a child node of \a config, allowing
3278 * aliases, like #snd_config_searcha. However, alias definitions are
3279 * searched below \a config (there is no separate \a root parameter),
3280 * and \a base specifies a seach key that identifies a compound node
3281 * that is used to search for an alias definitions that is not found
3282 * directly below \a config and that does not contain a period. In
3283 * other words, when \c "id" is not found in \a config, this function
3284 * also tries \c "base.id".
3288 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist.
3289 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3290 * not a compound or string node.
3293 int snd_config_search_alias(snd_config_t *config,
3294 const char *base, const char *key,
3295 snd_config_t **result)
3297 SND_CONFIG_SEARCH_ALIAS(config, base, key, result,
3298 snd_config_searcha, snd_config_searchva);
3301 static int snd_config_hooks(snd_config_t *config, snd_config_t *private_data);
3304 * \brief Searches for a node in a configuration tree and expands hooks.
3305 * \param[in,out] config Handle to the root of the configuration
3306 * (sub)tree to search.
3307 * \param[in] key Search key: one or more node keys, separated with dots.
3308 * \param[out] result The function puts the handle to the node found at
3309 * the address specified by \a result.
3310 * \return Zero if successful, otherwise a negative error code.
3312 * This functions searches for a child node of \a config like
3313 * #snd_config_search, but any compound nodes to be searched that
3314 * contain hooks are modified by the respective hook functions.
3318 * <dt>-ENOENT<dd>An id in \a key does not exist.
3319 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3320 * not a compound node.
3322 * Additionally, any errors encountered when parsing the hook
3323 * definitions or returned by the hook functions.
3325 int snd_config_search_hooks(snd_config_t *config, const char *key, snd_config_t **result)
3327 SND_CONFIG_SEARCH(config, key, result, \
3328 err = snd_config_hooks(config, NULL); \
3335 * \brief Searches for a node in a configuration tree, expanding aliases and hooks.
3336 * \param[in] root Handle to the root configuration node containing
3337 * alias definitions.
3338 * \param[in,out] config Handle to the root of the configuration
3339 * (sub)tree to search.
3340 * \param[in] key Search key: one or more node keys, separated with dots.
3341 * \param[out] result The function puts the handle to the node found at
3342 * the address specified by \a result.
3343 * \return Zero if successful, otherwise a negative error code.
3345 * This function searches for a child node of \a config, allowing
3346 * aliases, like #snd_config_searcha, and expanding hooks, like
3347 * #snd_config_search_hooks.
3351 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist.
3352 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3353 * not a compound node.
3355 * Additionally, any errors encountered when parsing the hook
3356 * definitions or returned by the hook functions.
3358 int snd_config_searcha_hooks(snd_config_t *root, snd_config_t *config, const char *key, snd_config_t **result)
3360 SND_CONFIG_SEARCHA(root, config, key, result,
3361 snd_config_searcha_hooks,
3362 err = snd_config_hooks(config, NULL); \
3369 * \brief Searches for a node in a configuration tree, expanding aliases and hooks.
3370 * \param[in] root Handle to the root configuration node containing
3371 * alias definitions.
3372 * \param[in,out] config Handle to the root of the configuration
3373 * (sub)tree to search.
3374 * \param[out] result The function puts the handle to the node found at
3375 * the address specified by \a result.
3376 * \param[in] ... One or more concatenated dot separated search keys,
3377 * terminated with \c NULL.
3378 * \return Zero if successful, otherwise a negative error code.
3380 * This function searches for a child node of \a config, allowing
3381 * aliases and expanding hooks like #snd_config_searcha_hooks, but the
3382 * search key is the concatenation of all passed seach key strings, like
3383 * with #snd_config_searchv.
3387 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist.
3388 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3389 * not a compound node.
3391 * Additionally, any errors encountered when parsing the hook
3392 * definitions or returned by the hook functions.
3394 int snd_config_searchva_hooks(snd_config_t *root, snd_config_t *config,
3395 snd_config_t **result, ...)
3397 SND_CONFIG_SEARCHVA(root, config, result, snd_config_searcha_hooks);
3401 * \brief Searches for a node in a configuration tree, using an alias and expanding hooks.
3402 * \param[in] config Handle to the root of the configuration (sub)tree
3404 * \param[in] base Search key base, or \c NULL.
3405 * \param[in] key Search key suffix.
3406 * \param[out] result The function puts the handle to the node found at
3407 * the address specified by \a result.
3408 * \return Zero if successful, otherwise a negative error code.
3410 * This functions searches for a child node of \a config, allowing
3411 * aliases, like #snd_config_search_alias, and expanding hooks, like
3412 * #snd_config_search_hooks.
3416 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist.
3417 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3418 * not a compound node.
3420 * Additionally, any errors encountered when parsing the hook
3421 * definitions or returned by the hook functions.
3423 int snd_config_search_alias_hooks(snd_config_t *config,
3424 const char *base, const char *key,
3425 snd_config_t **result)
3427 SND_CONFIG_SEARCH_ALIAS(config, base, key, result,
3428 snd_config_searcha_hooks,
3429 snd_config_searchva_hooks);
3432 /** The name of the environment variable containing the files list for #snd_config_update. */
3433 #define ALSA_CONFIG_PATH_VAR "ALSA_CONFIG_PATH"
3437 * \brief Configuration top-level node (the global configuration).
3439 * This variable contains a handle to the top-level configuration node,
3440 * as loaded from global configuration file.
3442 * This variable is initialized or updated by #snd_config_update.
3443 * Functions like #snd_pcm_open (that use a device name from the global
3444 * configuration) automatically call #snd_config_update. Before the
3445 * first call to #snd_config_update, this variable is \c NULL.
3447 * The global configuration files are specified in the environment
3448 * variable \c ALSA_CONFIG_PATH. If this is not set, the default value
3449 * is "/usr/share/alsa/alsa.conf".
3451 * \warning Whenever the configuration tree is updated, all string
3452 * pointers and configuration node handles previously obtained from this
3453 * variable may become invalid.
3455 * \par Conforming to:
3458 snd_config_t *snd_config = NULL;
3468 struct _snd_config_update {
3470 struct finfo *finfo;
3472 #endif /* DOC_HIDDEN */
3474 static snd_config_update_t *snd_config_global_update = NULL;
3476 static int snd_config_hooks_call(snd_config_t *root, snd_config_t *config, snd_config_t *private_data)
3479 snd_config_t *c, *func_conf = NULL;
3481 const char *lib = NULL, *func_name = NULL;
3483 int (*func)(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data) = NULL;
3486 err = snd_config_search(config, "func", &c);
3488 SNDERR("Field func is missing");
3491 err = snd_config_get_string(c, &str);
3493 SNDERR("Invalid type for field func");
3497 err = snd_config_search_definition(root, "hook_func", str, &func_conf);
3499 snd_config_iterator_t i, next;
3500 if (snd_config_get_type(func_conf) != SND_CONFIG_TYPE_COMPOUND) {
3501 SNDERR("Invalid type for func %s definition", str);
3505 snd_config_for_each(i, next, func_conf) {
3506 snd_config_t *n = snd_config_iterator_entry(i);
3507 const char *id = n->id;
3508 if (strcmp(id, "comment") == 0)
3510 if (strcmp(id, "lib") == 0) {
3511 err = snd_config_get_string(n, &lib);
3513 SNDERR("Invalid type for %s", id);
3518 if (strcmp(id, "func") == 0) {
3519 err = snd_config_get_string(n, &func_name);
3521 SNDERR("Invalid type for %s", id);
3526 SNDERR("Unknown field %s", id);
3530 int len = 16 + strlen(str) + 1;
3536 snprintf(buf, len, "snd_config_hook_%s", str);
3540 h = snd_dlopen(lib, RTLD_NOW);
3541 func = h ? snd_dlsym(h, func_name, SND_DLSYM_VERSION(SND_CONFIG_DLSYM_VERSION_HOOK)) : NULL;
3544 SNDERR("Cannot open shared library %s", lib);
3547 SNDERR("symbol %s is not defined inside %s", func_name, lib);
3553 snd_config_delete(func_conf);
3555 snd_config_t *nroot;
3556 err = func(root, config, &nroot, private_data);
3558 SNDERR("function %s returned error: %s", func_name, snd_strerror(err));
3560 if (err >= 0 && nroot)
3561 err = snd_config_substitute(root, nroot);
3569 static int snd_config_hooks(snd_config_t *config, snd_config_t *private_data)
3572 snd_config_iterator_t i, next;
3573 int err, hit, idx = 0;
3575 if ((err = snd_config_search(config, "@hooks", &n)) < 0)
3578 snd_config_remove(n);
3581 snd_config_for_each(i, next, n) {
3582 snd_config_t *n = snd_config_iterator_entry(i);
3583 const char *id = n->id;
3585 err = safe_strtol(id, &i);
3587 SNDERR("id of field %s is not and integer", id);
3592 err = snd_config_hooks_call(config, n, private_data);
3602 snd_config_delete(n);
3603 snd_config_unlock();
3607 static int config_filename_filter(const struct dirent *dirent)
3613 if (dirent->d_type == DT_DIR)
3616 flen = strlen(dirent->d_name);
3620 if (strncmp(&dirent->d_name[flen-5], ".conf", 5) == 0)
3626 static int config_file_open(snd_config_t *root, const char *filename)
3631 err = snd_input_stdio_open(&in, filename, "r");
3633 err = snd_config_load(root, in);
3634 snd_input_close(in);
3636 SNDERR("%s may be old or corrupted: consider to remove or fix it", filename);
3638 SNDERR("cannot access file %s", filename);
3644 * \brief Loads and parses the given configurations files.
3645 * \param[in] root Handle to the root configuration node.
3646 * \param[in] config Handle to the configuration node for this hook.
3647 * \param[out] dst The function puts the handle to the configuration
3648 * node loaded from the file(s) at the address specified
3650 * \param[in] private_data Handle to the private data configuration node.
3651 * \return Zero if successful, otherwise a negative error code.
3653 * See \ref confhooks for an example.
3655 int snd_config_hook_load(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data)
3658 snd_config_iterator_t i, next;
3659 struct finfo *fi = NULL;
3660 int err, idx = 0, fi_count = 0, errors = 1, hit;
3662 assert(root && dst);
3663 if ((err = snd_config_search(config, "errors", &n)) >= 0) {
3665 err = snd_config_get_ascii(n, &tmp);
3668 errors = snd_config_get_bool_ascii(tmp);
3671 SNDERR("Invalid bool value in field errors");
3675 if ((err = snd_config_search(config, "files", &n)) < 0) {
3676 SNDERR("Unable to find field files in the pre-load section");
3679 if ((err = snd_config_expand(n, root, NULL, private_data, &n)) < 0) {
3680 SNDERR("Unable to expand filenames in the pre-load section");
3683 if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
3684 SNDERR("Invalid type for field filenames");
3687 snd_config_for_each(i, next, n) {
3688 snd_config_t *c = snd_config_iterator_entry(i);
3690 if ((err = snd_config_get_string(c, &str)) < 0) {
3691 SNDERR("Field %s is not a string", c->id);
3696 fi = calloc(fi_count, sizeof(*fi));
3703 snd_config_for_each(i, next, n) {
3704 snd_config_t *n = snd_config_iterator_entry(i);
3705 const char *id = n->id;
3707 err = safe_strtol(id, &i);
3709 SNDERR("id of field %s is not and integer", id);
3715 if ((err = snd_config_get_ascii(n, &name)) < 0)
3717 if ((err = snd_user_file(name, &fi[idx].name)) < 0)
3718 fi[idx].name = name;
3726 for (idx = 0; idx < fi_count; idx++) {
3728 if (!errors && access(fi[idx].name, R_OK) < 0)
3730 if (stat(fi[idx].name, &st) < 0) {
3731 SNDERR("cannot stat file/directory %s", fi[idx].name);
3734 if (S_ISDIR(st.st_mode)) {
3735 struct dirent **namelist;
3739 #if defined(_GNU_SOURCE) && !defined(__NetBSD__) && !defined(__FreeBSD__) && !defined(__sun)
3740 #define SORTFUNC versionsort
3742 #define SORTFUNC alphasort
3745 n = scandir(fi[idx].name, &namelist, config_filename_filter, SORTFUNC);
3749 for (j = 0; j < n; ++j) {
3751 int sl = strlen(fi[idx].name) + strlen(namelist[j]->d_name) + 2;
3752 char *filename = malloc(sl);
3753 snprintf(filename, sl, "%s/%s", fi[idx].name, namelist[j]->d_name);
3754 filename[sl-1] = '\0';
3756 err = config_file_open(root, filename);
3765 } else if ((err = config_file_open(root, fi[idx].name)) < 0)
3772 for (idx = 0; idx < fi_count; idx++)
3775 snd_config_delete(n);
3779 SND_DLSYM_BUILD_VERSION(snd_config_hook_load, SND_CONFIG_DLSYM_VERSION_HOOK);
3783 int snd_determine_driver(int card, char **driver);
3787 * \brief Loads and parses the given configurations files for each
3788 * installed sound card.
3789 * \param[in] root Handle to the root configuration node.
3790 * \param[in] config Handle to the configuration node for this hook.
3791 * \param[out] dst The function puts the handle to the configuration
3792 * node loaded from the file(s) at the address specified
3794 * \param[in] private_data Handle to the private data configuration node.
3795 * \return Zero if successful, otherwise a negative error code.
3797 * This function works like #snd_config_hook_load, but the files are
3798 * loaded once for each sound card. The driver name is available with
3799 * the \c private_string function to customize the file name.
3801 int snd_config_hook_load_for_all_cards(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data ATTRIBUTE_UNUSED)
3806 err = snd_card_next(&card);
3810 snd_config_t *n, *private_data = NULL;
3812 char *fdriver = NULL;
3813 err = snd_determine_driver(card, &fdriver);
3816 if (snd_config_search(root, fdriver, &n) >= 0) {
3817 if (snd_config_get_string(n, &driver) < 0)
3821 char *s = strchr(driver, '.');
3826 if (snd_config_search(root, driver, &n) >= 0)
3831 err = snd_config_imake_string(&private_data, "string", driver);
3834 err = snd_config_hook_load(root, config, &n, private_data);
3837 snd_config_delete(private_data);
3842 } while (card >= 0);
3847 SND_DLSYM_BUILD_VERSION(snd_config_hook_load_for_all_cards, SND_CONFIG_DLSYM_VERSION_HOOK);
3851 * \brief Updates a configuration tree by rereading the configuration files (if needed).
3852 * \param[in,out] _top Address of the handle to the top-level node.
3853 * \param[in,out] _update Address of a pointer to private update information.
3854 * \param[in] cfgs A list of configuration file names, delimited with ':'.
3855 * If \p cfgs is \c NULL, the default global
3856 * configuration file is used.
3857 * \return 0 if \a _top was up to date, 1 if the configuration files
3858 * have been reread, otherwise a negative error code.
3860 * The variables pointed to by \a _top and \a _update can be initialized
3861 * to \c NULL before the first call to this function. The private
3862 * update information holds information about all used configuration
3863 * files that allows this function to detects changes to them; this data
3864 * can be freed with #snd_config_update_free.
3866 * The global configuration files are specified in the environment variable
3867 * \c ALSA_CONFIG_PATH.
3869 * \warning If the configuration tree is reread, all string pointers and
3870 * configuration node handles previously obtained from this tree become
3874 * Any errors encountered when parsing the input or returned by hooks or
3877 int snd_config_update_r(snd_config_t **_top, snd_config_update_t **_update, const char *cfgs)
3880 const char *configs, *c;
3883 snd_config_update_t *local;
3884 snd_config_update_t *update;
3887 assert(_top && _update);
3892 configs = getenv(ALSA_CONFIG_PATH_VAR);
3893 if (!configs || !*configs) {
3894 const char *topdir = snd_config_topdir();
3895 char *s = alloca(strlen(topdir) +
3896 strlen("alsa.conf") + 2);
3897 sprintf(s, "%s/alsa.conf", topdir);
3901 for (k = 0, c = configs; (l = strcspn(c, ": ")) > 0; ) {
3912 local = (snd_config_update_t *)calloc(1, sizeof(snd_config_update_t));
3916 local->finfo = calloc(local->count, sizeof(struct finfo));
3917 if (!local->finfo) {
3921 for (k = 0, c = configs; (l = strcspn(c, ": ")) > 0; ) {
3925 err = snd_user_file(name, &local->finfo[k].name);
3934 for (k = 0; k < local->count; ++k) {
3936 struct finfo *lf = &local->finfo[k];
3937 if (stat(lf->name, &st) >= 0) {
3938 lf->dev = st.st_dev;
3939 lf->ino = st.st_ino;
3940 lf->mtime = st.st_mtime;
3942 SNDERR("Cannot access file %s", lf->name);
3944 memmove(&local->finfo[k], &local->finfo[k+1], sizeof(struct finfo) * (local->count - k - 1));
3951 if (local->count != update->count)
3953 for (k = 0; k < local->count; ++k) {
3954 struct finfo *lf = &local->finfo[k];
3955 struct finfo *uf = &update->finfo[k];
3956 if (strcmp(lf->name, uf->name) != 0 ||
3957 lf->dev != uf->dev ||
3958 lf->ino != uf->ino ||
3959 lf->mtime != uf->mtime)
3967 snd_config_delete(top);
3971 snd_config_update_free(update);
3976 snd_config_update_free(local);
3983 snd_config_update_free(update);
3987 snd_config_delete(top);
3990 err = snd_config_top(&top);
3995 for (k = 0; k < local->count; ++k) {
3997 err = snd_input_stdio_open(&in, local->finfo[k].name, "r");
3999 err = snd_config_load(top, in);
4000 snd_input_close(in);
4002 SNDERR("%s may be old or corrupted: consider to remove or fix it", local->finfo[k].name);
4006 SNDERR("cannot access file %s", local->finfo[k].name);
4010 err = snd_config_hooks(top, NULL);
4012 SNDERR("hooks failed, removing configuration");
4021 * \brief Updates #snd_config by rereading the global configuration files (if needed).
4022 * \return 0 if #snd_config was up to date, 1 if #snd_config was
4023 * updated, otherwise a negative error code.
4025 * \warning Whenever #snd_config is updated, all string pointers and
4026 * configuration node handles previously obtained from it may become
4028 * For safer operations, use #snd_config_update_ref and release the config
4029 * via #snd_config_unref.
4032 * Any errors encountered when parsing the input or returned by hooks or
4035 * \par Conforming to:
4038 int snd_config_update(void)
4043 err = snd_config_update_r(&snd_config, &snd_config_global_update, NULL);
4044 snd_config_unlock();
4049 * \brief Updates #snd_config and takes its reference.
4050 * \return 0 if #snd_config was up to date, 1 if #snd_config was
4051 * updated, otherwise a negative error code.
4053 * Unlike #snd_config_update, this function increases a reference counter
4054 * so that the obtained tree won't be deleted until unreferenced by
4055 * #snd_config_unref.
4057 * This function is supposed to be thread-safe.
4059 int snd_config_update_ref(snd_config_t **top)
4066 err = snd_config_update_r(&snd_config, &snd_config_global_update, NULL);
4070 snd_config->refcount++;
4077 snd_config_unlock();
4082 * \brief Take the reference of the config tree.
4084 * Increases a reference counter of the given config tree.
4086 * This function is supposed to be thread-safe.
4088 void snd_config_ref(snd_config_t *cfg)
4093 snd_config_unlock();
4097 * \brief Unreference the config tree.
4099 * Decreases a reference counter of the given config tree, and eventually
4100 * deletes the tree if all references are gone. This is the counterpart of
4101 * #snd_config_unref.
4103 * Also, the config taken via #snd_config_update_ref must be unreferenced
4104 * by this function, too.
4106 * This function is supposed to be thread-safe.
4108 void snd_config_unref(snd_config_t *cfg)
4112 snd_config_delete(cfg);
4113 snd_config_unlock();
4117 * \brief Frees a private update structure.
4118 * \param[in] update The private update structure to free.
4119 * \return Zero if successful, otherwise a negative error code.
4121 int snd_config_update_free(snd_config_update_t *update)
4126 for (k = 0; k < update->count; k++)
4127 free(update->finfo[k].name);
4128 free(update->finfo);
4134 * \brief Frees the global configuration tree in #snd_config.
4135 * \return Zero if successful, otherwise a negative error code.
4137 * This functions releases all resources of the global configuration
4138 * tree, and sets #snd_config to \c NULL.
4140 * \par Conforming to:
4143 int snd_config_update_free_global(void)
4147 snd_config_delete(snd_config);
4149 if (snd_config_global_update)
4150 snd_config_update_free(snd_config_global_update);
4151 snd_config_global_update = NULL;
4152 snd_config_unlock();
4153 /* FIXME: better to place this in another place... */
4154 snd_dlobj_cache_cleanup();
4160 * \brief Returns an iterator pointing to a node's first child.
4161 * \param[in] config Handle to a configuration node.
4162 * \return An iterator pointing to \a config's first child.
4164 * \a config must be a compound node.
4166 * The returned iterator is valid if it is not equal to the return value
4167 * of #snd_config_iterator_end on \a config.
4169 * Use #snd_config_iterator_entry to get the handle of the node pointed
4172 * \par Conforming to:
4175 snd_config_iterator_t snd_config_iterator_first(const snd_config_t *config)
4177 assert(config->type == SND_CONFIG_TYPE_COMPOUND);
4178 return config->u.compound.fields.next;
4182 * \brief Returns an iterator pointing to the next sibling.
4183 * \param[in] iterator An iterator pointing to a child configuration node.
4184 * \return An iterator pointing to the next sibling of \a iterator.
4186 * The returned iterator is valid if it is not equal to the return value
4187 * of #snd_config_iterator_end on the node's parent.
4189 * Use #snd_config_iterator_entry to get the handle of the node pointed
4192 * \par Conforming to:
4195 snd_config_iterator_t snd_config_iterator_next(const snd_config_iterator_t iterator)
4197 return iterator->next;
4201 * \brief Returns an iterator that ends a node's children list.
4202 * \param[in] config Handle to a configuration node.
4203 * \return An iterator that indicates the end of \a config's children list.
4205 * \a config must be a compound node.
4207 * The return value can be understood as pointing past the last child of
4210 * \par Conforming to:
4213 snd_config_iterator_t snd_config_iterator_end(const snd_config_t *config)
4215 assert(config->type == SND_CONFIG_TYPE_COMPOUND);
4216 return (const snd_config_iterator_t)&config->u.compound.fields;
4220 * \brief Returns the configuration node handle pointed to by an iterator.
4221 * \param[in] iterator A configuration node iterator.
4222 * \return The configuration node handle pointed to by \a iterator.
4224 * \par Conforming to:
4227 snd_config_t *snd_config_iterator_entry(const snd_config_iterator_t iterator)
4229 return list_entry(iterator, snd_config_t, list);
4233 typedef enum _snd_config_walk_pass {
4234 SND_CONFIG_WALK_PASS_PRE,
4235 SND_CONFIG_WALK_PASS_POST,
4236 SND_CONFIG_WALK_PASS_LEAF,
4237 } snd_config_walk_pass_t;
4240 /* Return 1 if node needs to be attached to parent */
4241 /* Return 2 if compound is replaced with standard node */
4243 typedef int (*snd_config_walk_callback_t)(snd_config_t *src,
4246 snd_config_walk_pass_t pass,
4247 snd_config_t *private_data);
4250 static int snd_config_walk(snd_config_t *src,
4253 snd_config_walk_callback_t callback,
4254 snd_config_t *private_data)
4257 snd_config_iterator_t i, next;
4259 switch (snd_config_get_type(src)) {
4260 case SND_CONFIG_TYPE_COMPOUND:
4261 err = callback(src, root, dst, SND_CONFIG_WALK_PASS_PRE, private_data);
4264 snd_config_for_each(i, next, src) {
4265 snd_config_t *s = snd_config_iterator_entry(i);
4266 snd_config_t *d = NULL;
4268 err = snd_config_walk(s, root, (dst && *dst) ? &d : NULL,
4269 callback, private_data);
4273 err = snd_config_add(*dst, d);
4278 err = callback(src, root, dst, SND_CONFIG_WALK_PASS_POST, private_data);
4282 snd_config_delete(*dst);
4286 err = callback(src, root, dst, SND_CONFIG_WALK_PASS_LEAF, private_data);
4292 static int _snd_config_copy(snd_config_t *src,
4293 snd_config_t *root ATTRIBUTE_UNUSED,
4295 snd_config_walk_pass_t pass,
4296 snd_config_t *private_data ATTRIBUTE_UNUSED)
4299 const char *id = src->id;
4300 snd_config_type_t type = snd_config_get_type(src);
4302 case SND_CONFIG_WALK_PASS_PRE:
4303 err = snd_config_make_compound(dst, id, src->u.compound.join);
4307 case SND_CONFIG_WALK_PASS_LEAF:
4308 err = snd_config_make(dst, id, type);
4312 case SND_CONFIG_TYPE_INTEGER:
4315 err = snd_config_get_integer(src, &v);
4317 snd_config_set_integer(*dst, v);
4320 case SND_CONFIG_TYPE_INTEGER64:
4323 err = snd_config_get_integer64(src, &v);
4325 snd_config_set_integer64(*dst, v);
4328 case SND_CONFIG_TYPE_REAL:
4331 err = snd_config_get_real(src, &v);
4333 snd_config_set_real(*dst, v);
4336 case SND_CONFIG_TYPE_STRING:
4339 err = snd_config_get_string(src, &s);
4341 err = snd_config_set_string(*dst, s);
4357 * \brief Creates a copy of a configuration node.
4358 * \param[out] dst The function puts the handle to the new configuration
4359 * node at the address specified by \a dst.
4360 * \param[in] src Handle to the source configuration node.
4361 * \return A non-negative value if successful, otherwise a negative error code.
4363 * This function creates a deep copy, i.e., if \a src is a compound
4364 * node, all children are copied recursively.
4368 * <dt>-ENOMEM<dd>Out of memory.
4371 * \par Conforming to:
4374 int snd_config_copy(snd_config_t **dst,
4377 return snd_config_walk(src, NULL, dst, _snd_config_copy, NULL);
4380 static int _snd_config_expand(snd_config_t *src,
4381 snd_config_t *root ATTRIBUTE_UNUSED,
4383 snd_config_walk_pass_t pass,
4384 snd_config_t *private_data)
4387 const char *id = src->id;
4388 snd_config_type_t type = snd_config_get_type(src);
4390 case SND_CONFIG_WALK_PASS_PRE:
4392 if (id && strcmp(id, "@args") == 0)
4394 err = snd_config_make_compound(dst, id, src->u.compound.join);
4399 case SND_CONFIG_WALK_PASS_LEAF:
4401 case SND_CONFIG_TYPE_INTEGER:
4404 err = snd_config_get_integer(src, &v);
4406 err = snd_config_imake_integer(dst, id, v);
4411 case SND_CONFIG_TYPE_INTEGER64:
4414 err = snd_config_get_integer64(src, &v);
4416 err = snd_config_imake_integer64(dst, id, v);
4421 case SND_CONFIG_TYPE_REAL:
4424 err = snd_config_get_real(src, &v);
4426 err = snd_config_imake_real(dst, id, v);
4431 case SND_CONFIG_TYPE_STRING:
4435 snd_config_t *vars = private_data;
4436 snd_config_get_string(src, &s);
4437 if (s && *s == '$') {
4439 if (snd_config_search(vars, s, &val) < 0)
4441 err = snd_config_copy(dst, val);
4444 err = snd_config_set_id(*dst, id);
4446 snd_config_delete(*dst);
4450 err = snd_config_imake_string(dst, id, s);
4466 static int _snd_config_evaluate(snd_config_t *src,
4468 snd_config_t **dst ATTRIBUTE_UNUSED,
4469 snd_config_walk_pass_t pass,
4470 snd_config_t *private_data)
4473 if (pass == SND_CONFIG_WALK_PASS_PRE) {
4475 const char *lib = NULL, *func_name = NULL;
4477 int (*func)(snd_config_t **dst, snd_config_t *root,
4478 snd_config_t *src, snd_config_t *private_data) = NULL;
4480 snd_config_t *c, *func_conf = NULL;
4481 err = snd_config_search(src, "@func", &c);
4484 err = snd_config_get_string(c, &str);
4486 SNDERR("Invalid type for @func");
4490 err = snd_config_search_definition(root, "func", str, &func_conf);
4492 snd_config_iterator_t i, next;
4493 if (snd_config_get_type(func_conf) != SND_CONFIG_TYPE_COMPOUND) {
4494 SNDERR("Invalid type for func %s definition", str);
4498 snd_config_for_each(i, next, func_conf) {
4499 snd_config_t *n = snd_config_iterator_entry(i);
4500 const char *id = n->id;
4501 if (strcmp(id, "comment") == 0)
4503 if (strcmp(id, "lib") == 0) {
4504 err = snd_config_get_string(n, &lib);
4506 SNDERR("Invalid type for %s", id);
4511 if (strcmp(id, "func") == 0) {
4512 err = snd_config_get_string(n, &func_name);
4514 SNDERR("Invalid type for %s", id);
4519 SNDERR("Unknown field %s", id);
4523 int len = 9 + strlen(str) + 1;
4529 snprintf(buf, len, "snd_func_%s", str);
4533 h = snd_dlopen(lib, RTLD_NOW);
4535 func = snd_dlsym(h, func_name, SND_DLSYM_VERSION(SND_CONFIG_DLSYM_VERSION_EVALUATE));
4538 SNDERR("Cannot open shared library %s", lib);
4542 SNDERR("symbol %s is not defined inside %s", func_name, lib);
4549 snd_config_delete(func_conf);
4552 err = func(&eval, root, src, private_data);
4554 SNDERR("function %s returned error: %s", func_name, snd_strerror(err));
4556 if (err >= 0 && eval) {
4557 /* substitute merges compound members */
4558 /* we don't want merging at all */
4559 err = snd_config_delete_compound_members(src);
4561 err = snd_config_substitute(src, eval);
4574 * \brief Evaluates a configuration node at runtime.
4575 * \param[in,out] config Handle to the source configuration node.
4576 * \param[in] root Handle to the root of the source configuration.
4577 * \param[in] private_data Handle to the private data node for runtime evaluation.
4578 * \param result Must be \c NULL.
4579 * \return A non-negative value if successful, otherwise a negative error code.
4581 * This function evaluates any functions (\c \@func) in \a config and
4582 * replaces those nodes with the respective function results.
4584 int snd_config_evaluate(snd_config_t *config, snd_config_t *root,
4585 snd_config_t *private_data, snd_config_t **result)
4587 /* FIXME: Only in place evaluation is currently implemented */
4588 assert(result == NULL);
4589 return snd_config_walk(config, root, result, _snd_config_evaluate, private_data);
4592 static int load_defaults(snd_config_t *subs, snd_config_t *defs)
4594 snd_config_iterator_t d, dnext;
4595 snd_config_for_each(d, dnext, defs) {
4596 snd_config_t *def = snd_config_iterator_entry(d);
4597 snd_config_iterator_t f, fnext;
4598 if (snd_config_get_type(def) != SND_CONFIG_TYPE_COMPOUND)
4600 snd_config_for_each(f, fnext, def) {
4601 snd_config_t *fld = snd_config_iterator_entry(f);
4602 const char *id = fld->id;
4603 if (strcmp(id, "type") == 0)
4605 if (strcmp(id, "default") == 0) {
4606 snd_config_t *deflt;
4608 err = snd_config_copy(&deflt, fld);
4611 err = snd_config_set_id(deflt, def->id);
4613 snd_config_delete(deflt);
4616 err = snd_config_add(subs, deflt);
4618 snd_config_delete(deflt);
4623 SNDERR("Unknown field %s", id);
4630 static void skip_blank(const char **ptr)
4647 static int parse_char(const char **ptr)
4650 assert(**ptr == '\\');
4679 if (c < '0' || c > '7')
4681 num = num * 8 + c - '0';
4694 static int parse_id(const char **ptr)
4715 static int parse_string(const char **ptr, char **val)
4717 const size_t bufsize = 256;
4720 size_t alloc = bufsize;
4728 SNDERR("Unterminated string");
4731 c = parse_char(ptr);
4738 *val = malloc(idx + 1);
4741 memcpy(*val, buf, idx);
4743 if (alloc > bufsize)
4749 size_t old_alloc = alloc;
4751 if (old_alloc == bufsize) {
4752 buf = malloc(alloc);
4753 memcpy(buf, _buf, old_alloc);
4755 buf = realloc(buf, alloc);
4765 /* Parse var=val or val */
4766 static int parse_arg(const char **ptr, unsigned int *varlen, char **val)
4772 if (*str == '"' || *str == '\'') {
4773 err = parse_string(ptr, val);
4779 err = parse_id(ptr);
4782 vallen = *ptr - str;
4792 if (*str == '"' || *str == '\'') {
4793 err = parse_string(ptr, val);
4798 err = parse_id(ptr);
4801 vallen = *ptr - str;
4803 *val = malloc(vallen + 1);
4806 memcpy(*val, str, vallen);
4813 * var1=val1,var2=val2,...
4816 static int parse_args(snd_config_t *subs, const char *str, snd_config_t *defs)
4826 int len = strlen(str);
4828 snd_config_iterator_t i, next;
4830 switch (str[--len]) {
4842 if (str[len] != '}')
4844 err = snd_input_buffer_open(&input, str + 1, len - 1);
4847 err = snd_config_load_override(subs, input);
4848 snd_input_close(input);
4851 snd_config_for_each(i, next, subs) {
4852 snd_config_t *n = snd_config_iterator_entry(i);
4854 const char *id = n->id;
4855 err = snd_config_search(defs, id, &d);
4857 SNDERR("Unknown parameter %s", id);
4866 const char *var = buf;
4867 unsigned int varlen;
4868 snd_config_t *def, *sub, *typ;
4869 const char *new = str;
4872 err = parse_arg(&new, &varlen, &val);
4876 assert(varlen < sizeof(buf));
4877 memcpy(buf, str, varlen);
4880 sprintf(buf, "%d", arg);
4882 err = snd_config_search_alias(defs, NULL, var, &def);
4884 SNDERR("Unknown parameter %s", var);
4887 if (snd_config_get_type(def) != SND_CONFIG_TYPE_COMPOUND) {
4888 SNDERR("Parameter %s definition is not correct", var);
4893 err = snd_config_search(subs, var, &sub);
4895 snd_config_delete(sub);
4896 err = snd_config_search(def, "type", &typ);
4899 SNDERR("Parameter %s definition is missing a valid type info", var);
4902 err = snd_config_get_string(typ, &tmp);
4903 if (err < 0 || !tmp)
4905 if (strcmp(tmp, "integer") == 0) {
4907 err = snd_config_make(&sub, var, SND_CONFIG_TYPE_INTEGER);
4910 err = safe_strtol(val, &v);
4912 SNDERR("Parameter %s must be an integer", var);
4915 err = snd_config_set_integer(sub, v);
4918 } else if (strcmp(tmp, "integer64") == 0) {
4920 err = snd_config_make(&sub, var, SND_CONFIG_TYPE_INTEGER64);
4923 err = safe_strtoll(val, &v);
4925 SNDERR("Parameter %s must be an integer", var);
4928 err = snd_config_set_integer64(sub, v);
4931 } else if (strcmp(tmp, "real") == 0) {
4933 err = snd_config_make(&sub, var, SND_CONFIG_TYPE_REAL);
4936 err = safe_strtod(val, &v);
4938 SNDERR("Parameter %s must be a real", var);
4941 err = snd_config_set_real(sub, v);
4944 } else if (strcmp(tmp, "string") == 0) {
4945 err = snd_config_make(&sub, var, SND_CONFIG_TYPE_STRING);
4948 err = snd_config_set_string(sub, val);
4955 err = snd_config_set_id(sub, var);
4958 err = snd_config_add(subs, sub);
4976 * \brief Expands a configuration node, applying arguments and functions.
4977 * \param[in] config Handle to the configuration node.
4978 * \param[in] root Handle to the root configuration node.
4979 * \param[in] args Arguments string, can be \c NULL.
4980 * \param[in] private_data Handle to the private data node for functions.
4981 * \param[out] result The function puts the handle to the result
4982 * configuration node at the address specified by
4984 * \return A non-negative value if successful, otherwise a negative error code.
4986 * If \a config has arguments (defined by a child with id \c \@args),
4987 * this function replaces any string node beginning with $ with the
4988 * respective argument value, or the default argument value, or nothing.
4989 * Furthermore, any functions are evaluated (see #snd_config_evaluate).
4990 * The resulting copy of \a config is returned in \a result.
4992 int snd_config_expand(snd_config_t *config, snd_config_t *root, const char *args,
4993 snd_config_t *private_data, snd_config_t **result)
4996 snd_config_t *defs, *subs = NULL, *res;
4997 err = snd_config_search(config, "@args", &defs);
5000 SNDERR("Unknown parameters %s", args);
5003 err = snd_config_copy(&res, config);
5007 err = snd_config_top(&subs);
5010 err = load_defaults(subs, defs);
5012 SNDERR("Load defaults error: %s", snd_strerror(err));
5015 err = parse_args(subs, args, defs);
5017 SNDERR("Parse arguments error: %s", snd_strerror(err));
5020 err = snd_config_evaluate(subs, root, private_data, NULL);
5022 SNDERR("Args evaluate error: %s", snd_strerror(err));
5025 err = snd_config_walk(config, root, &res, _snd_config_expand, subs);
5027 SNDERR("Expand error (walk): %s", snd_strerror(err));
5031 err = snd_config_evaluate(res, root, private_data, NULL);
5033 SNDERR("Evaluate error: %s", snd_strerror(err));
5034 snd_config_delete(res);
5041 snd_config_delete(subs);
5046 * \brief Searches for a definition in a configuration tree, using
5047 * aliases and expanding hooks and arguments.
5048 * \param[in] config Handle to the configuration (sub)tree to search.
5049 * \param[in] base Implicit key base, or \c NULL for none.
5050 * \param[in] name Key suffix, optionally with arguments.
5051 * \param[out] result The function puts the handle to the expanded found
5052 * node at the address specified by \a result.
5053 * \return A non-negative value if successful, otherwise a negative error code.
5055 * This functions searches for a child node of \a config, allowing
5056 * aliases and expanding hooks, like #snd_config_search_alias_hooks.
5058 * If \a name contains a colon (:), the rest of the string after the
5059 * colon contains arguments that are expanded as with
5060 * #snd_config_expand.
5062 * In any case, \a result is a new node that must be freed by the
5067 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist.
5068 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
5069 * not a compound node.
5071 * Additionally, any errors encountered when parsing the hook
5072 * definitions or arguments, or returned by (hook) functions.
5074 int snd_config_search_definition(snd_config_t *config,
5075 const char *base, const char *name,
5076 snd_config_t **result)
5080 const char *args = strchr(name, ':');
5084 key = alloca(args - name);
5085 memcpy(key, name, args - name - 1);
5086 key[args - name - 1] = '\0';
5088 key = (char *) name;
5091 * if key contains dot (.), the implicit base is ignored
5092 * and the key starts from root given by the 'config' parameter
5095 err = snd_config_search_alias_hooks(config, strchr(key, '.') ? NULL : base, key, &conf);
5097 snd_config_unlock();
5100 err = snd_config_expand(conf, config, args, NULL, result);
5101 snd_config_unlock();
5106 void snd_config_set_hop(snd_config_t *conf, int hop)
5111 int snd_config_check_hop(snd_config_t *conf)
5114 if (conf->hop >= SND_CONF_MAX_HOPS) {
5115 SYSERR("Too many definition levels (looped?)\n");
5125 /* Not strictly needed, but useful to check for memory leaks */
5126 void _snd_config_end(void) __attribute__ ((destructor));
5128 static void _snd_config_end(void)
5132 snd_config_delete(snd_config);
5134 for (k = 0; k < files_info_count; ++k)
5135 free(files_info[k].name);
5138 files_info_count = 0;
5142 size_t page_size(void)
5144 long s = sysconf(_SC_PAGE_SIZE);
5149 size_t page_align(size_t size)
5152 long psz = page_size();
5155 return size + psz - r;
5159 size_t page_ptr(size_t object_offset, size_t object_size, size_t *offset, size_t *mmap_offset)
5162 long psz = page_size();
5164 assert(mmap_offset);
5165 *mmap_offset = object_offset;
5166 object_offset %= psz;
5167 *mmap_offset -= object_offset;
5168 object_size += object_offset;
5169 r = object_size % psz;
5171 r = object_size + psz - r;
5174 *offset = object_offset;