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.
419 #include <sys/stat.h>
423 #ifdef HAVE_LIBPTHREAD
429 #ifdef HAVE_LIBPTHREAD
430 static pthread_mutex_t snd_config_update_mutex =
431 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
436 snd_config_type_t type;
444 struct list_head fields;
448 struct list_head list;
449 snd_config_t *parent;
456 unsigned int line, column;
457 struct filedesc *next;
460 #define LOCAL_ERROR (-0x68000000)
462 #define LOCAL_UNTERMINATED_STRING (LOCAL_ERROR - 0)
463 #define LOCAL_UNTERMINATED_QUOTE (LOCAL_ERROR - 1)
464 #define LOCAL_UNEXPECTED_CHAR (LOCAL_ERROR - 2)
465 #define LOCAL_UNEXPECTED_EOF (LOCAL_ERROR - 3)
468 struct filedesc *current;
473 #ifdef HAVE_LIBPTHREAD
475 static inline void snd_config_lock(void)
477 pthread_mutex_lock(&snd_config_update_mutex);
480 static inline void snd_config_unlock(void)
482 pthread_mutex_unlock(&snd_config_update_mutex);
487 static inline void snd_config_lock(void) { }
488 static inline void snd_config_unlock(void) { }
492 static int safe_strtoll(const char *str, long long *val)
499 if (sscanf(str, "%Li%n", &v, &endidx) < 1)
507 int safe_strtol(const char *str, long *val)
514 v = strtol(str, &end, 0);
523 static int safe_strtod(const char *str, double *val)
527 #ifdef HAVE_USELOCALE
528 locale_t saved_locale, c_locale;
531 char locstr[64]; /* enough? */
537 #ifdef HAVE_USELOCALE
538 c_locale = newlocale(LC_NUMERIC_MASK, "C", 0);
539 saved_locale = uselocale(c_locale);
541 saved_locale = setlocale(LC_NUMERIC, NULL);
543 snprintf(locstr, sizeof(locstr), "%s", saved_locale);
544 setlocale(LC_NUMERIC, "C");
548 v = strtod(str, &end);
550 #ifdef HAVE_USELOCALE
551 if (c_locale != (locale_t)0) {
552 uselocale(saved_locale);
553 freelocale(c_locale);
557 setlocale(LC_NUMERIC, locstr);
567 static int get_char(input_t *input)
577 c = snd_input_getc(fd->in);
584 fd->column += 8 - fd->column % 8;
588 snd_input_close(fd->in);
590 input->current = fd->next;
594 return LOCAL_UNEXPECTED_EOF;
599 return (unsigned char)c;
602 static void unget_char(int c, input_t *input)
604 assert(!input->unget);
609 static int get_delimstring(char **string, int delim, input_t *input);
611 static int get_char_skip_comments(input_t *input)
620 int err = get_delimstring(&str, '>', input);
623 if (!strncmp(str, "confdir:", 8)) {
624 char *tmp = malloc(strlen(ALSA_CONFIG_DIR) + 1 + strlen(str + 8) + 1);
629 sprintf(tmp, ALSA_CONFIG_DIR "/%s", str + 8);
633 err = snd_input_stdio_open(&in, str, "r");
635 SNDERR("Cannot access file %s", str);
639 fd = malloc(sizeof(*fd));
646 fd->next = input->current;
667 static int get_nonwhite(input_t *input)
671 c = get_char_skip_comments(input);
685 static int get_quotedchar(input_t *input)
708 if (c < '0' || c > '7') {
709 unget_char(c, input);
712 num = num * 8 + c - '0';
722 #define LOCAL_STR_BUFSIZE 64
723 struct local_string {
727 char tmpbuf[LOCAL_STR_BUFSIZE];
730 static void init_local_string(struct local_string *s)
732 memset(s, 0, sizeof(*s));
734 s->alloc = LOCAL_STR_BUFSIZE;
737 static void free_local_string(struct local_string *s)
739 if (s->buf != s->tmpbuf)
743 static int add_char_local_string(struct local_string *s, int c)
745 if (s->idx >= s->alloc) {
746 size_t nalloc = s->alloc * 2;
747 if (s->buf == s->tmpbuf) {
748 s->buf = malloc(nalloc);
751 memcpy(s->buf, s->tmpbuf, s->alloc);
753 char *ptr = realloc(s->buf, nalloc);
760 s->buf[s->idx++] = c;
764 static char *copy_local_string(struct local_string *s)
766 char *dst = malloc(s->idx + 1);
768 memcpy(dst, s->buf, s->idx);
774 static int get_freestring(char **string, int id, input_t *input)
776 struct local_string str;
779 init_local_string(&str);
783 if (c == LOCAL_UNEXPECTED_EOF) {
784 *string = copy_local_string(&str);
812 *string = copy_local_string(&str);
816 unget_char(c, input);
823 if (add_char_local_string(&str, c) < 0) {
829 free_local_string(&str);
833 static int get_delimstring(char **string, int delim, input_t *input)
835 struct local_string str;
838 init_local_string(&str);
844 c = get_quotedchar(input);
849 } else if (c == delim) {
850 *string = copy_local_string(&str);
857 if (add_char_local_string(&str, c) < 0) {
862 free_local_string(&str);
866 /* Return 0 for free string, 1 for delimited string */
867 static int get_string(char **string, int id, input_t *input)
869 int c = get_nonwhite(input), err;
882 return LOCAL_UNEXPECTED_CHAR;
885 err = get_delimstring(string, c, input);
890 unget_char(c, input);
891 err = get_freestring(string, id, input);
898 static int _snd_config_make(snd_config_t **config, char **id, snd_config_type_t type)
902 n = calloc(1, sizeof(*n));
915 if (type == SND_CONFIG_TYPE_COMPOUND)
916 INIT_LIST_HEAD(&n->u.compound.fields);
922 static int _snd_config_make_add(snd_config_t **config, char **id,
923 snd_config_type_t type, snd_config_t *parent)
927 assert(parent->type == SND_CONFIG_TYPE_COMPOUND);
928 err = _snd_config_make(&n, id, type);
932 list_add_tail(&n->list, &parent->u.compound.fields);
937 static int _snd_config_search(snd_config_t *config,
938 const char *id, int len, snd_config_t **result)
940 snd_config_iterator_t i, next;
941 snd_config_for_each(i, next, config) {
942 snd_config_t *n = snd_config_iterator_entry(i);
944 if (strcmp(n->id, id) != 0)
946 } else if (strlen(n->id) != (size_t) len ||
947 memcmp(n->id, id, (size_t) len) != 0)
956 static int parse_value(snd_config_t **_n, snd_config_t *parent, input_t *input, char **id, int skip)
958 snd_config_t *n = *_n;
962 err = get_string(&s, 0, input);
969 if (err == 0 && ((s[0] >= '0' && s[0] <= '9') || s[0] == '-')) {
972 err = safe_strtoll(s, &i);
975 err = safe_strtod(s, &r);
979 if (n->type != SND_CONFIG_TYPE_REAL) {
980 SNDERR("%s is not a real", *id);
984 err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_REAL, parent);
995 if (n->type != SND_CONFIG_TYPE_INTEGER && n->type != SND_CONFIG_TYPE_INTEGER64) {
996 SNDERR("%s is not an integer", *id);
1001 err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_INTEGER, parent);
1003 err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_INTEGER64, parent);
1007 if (n->type == SND_CONFIG_TYPE_INTEGER)
1008 n->u.integer = (long) i;
1016 if (n->type != SND_CONFIG_TYPE_STRING) {
1017 SNDERR("%s is not a string", *id);
1022 err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_STRING, parent);
1032 static int parse_defs(snd_config_t *parent, input_t *input, int skip, int override);
1033 static int parse_array_defs(snd_config_t *farther, input_t *input, int skip, int override);
1035 static int parse_array_def(snd_config_t *parent, input_t *input, int idx, int skip, int override)
1040 snd_config_t *n = NULL;
1044 snprintf(static_id, sizeof(static_id), "%i", idx);
1045 id = strdup(static_id);
1049 c = get_nonwhite(input);
1061 if (n->type != SND_CONFIG_TYPE_COMPOUND) {
1062 SNDERR("%s is not a compound", id);
1067 err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, parent);
1073 err = parse_defs(n, input, skip, override);
1076 err = parse_array_defs(n, input, skip, override);
1079 c = get_nonwhite(input);
1086 snd_config_delete(n);
1087 err = LOCAL_UNEXPECTED_CHAR;
1093 unget_char(c, input);
1094 err = parse_value(&n, parent, input, &id, skip);
1105 static int parse_array_defs(snd_config_t *parent, input_t *input, int skip, int override)
1109 int c = get_nonwhite(input), err;
1112 unget_char(c, input);
1115 err = parse_array_def(parent, input, idx++, skip, override);
1122 static int parse_def(snd_config_t *parent, input_t *input, int skip, int override)
1128 enum {MERGE_CREATE, MERGE, OVERRIDE, DONT_OVERRIDE} mode;
1130 c = get_nonwhite(input);
1135 mode = MERGE_CREATE;
1141 mode = DONT_OVERRIDE;
1147 mode = !override ? MERGE_CREATE : OVERRIDE;
1148 unget_char(c, input);
1150 err = get_string(&id, 1, input);
1153 c = get_nonwhite(input);
1160 if (_snd_config_search(parent, id, -1, &n) == 0) {
1161 if (mode == DONT_OVERRIDE) {
1166 if (mode != OVERRIDE) {
1167 if (n->type != SND_CONFIG_TYPE_COMPOUND) {
1168 SNDERR("%s is not a compound", id);
1171 n->u.compound.join = 1;
1176 snd_config_delete(n);
1178 if (mode == MERGE) {
1179 SNDERR("%s does not exists", id);
1183 err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, parent);
1186 n->u.compound.join = 1;
1190 c = get_nonwhite(input);
1195 if (_snd_config_search(parent, id, -1, &n) == 0) {
1196 if (mode == DONT_OVERRIDE) {
1199 } else if (mode == OVERRIDE) {
1200 snd_config_delete(n);
1205 if (mode == MERGE) {
1206 SNDERR("%s does not exists", id);
1219 if (n->type != SND_CONFIG_TYPE_COMPOUND) {
1220 SNDERR("%s is not a compound", id);
1225 err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, parent);
1231 err = parse_defs(n, input, skip, override);
1234 err = parse_array_defs(n, input, skip, override);
1237 c = get_nonwhite(input);
1240 snd_config_delete(n);
1241 err = LOCAL_UNEXPECTED_CHAR;
1247 unget_char(c, input);
1248 err = parse_value(&n, parent, input, &id, skip);
1253 c = get_nonwhite(input);
1259 unget_char(c, input);
1266 static int parse_defs(snd_config_t *parent, input_t *input, int skip, int override)
1270 c = get_nonwhite(input);
1272 return c == LOCAL_UNEXPECTED_EOF ? 0 : c;
1273 unget_char(c, input);
1276 err = parse_def(parent, input, skip, override);
1283 static void string_print(char *str, int id, snd_output_t *out)
1285 unsigned char *p = (unsigned char *)str;
1287 snd_output_puts(out, "''");
1318 snd_output_puts(out, str);
1321 snd_output_putc(out, '\'');
1322 p = (unsigned char *)str;
1328 snd_output_putc(out, '\\');
1329 snd_output_putc(out, 'n');
1332 snd_output_putc(out, '\\');
1333 snd_output_putc(out, 't');
1336 snd_output_putc(out, '\\');
1337 snd_output_putc(out, 'v');
1340 snd_output_putc(out, '\\');
1341 snd_output_putc(out, 'b');
1344 snd_output_putc(out, '\\');
1345 snd_output_putc(out, 'r');
1348 snd_output_putc(out, '\\');
1349 snd_output_putc(out, 'f');
1352 snd_output_putc(out, '\\');
1353 snd_output_putc(out, c);
1355 case 32 ... '\'' - 1:
1356 case '\'' + 1 ... 126:
1357 snd_output_putc(out, c);
1360 snd_output_printf(out, "\\%04o", c);
1365 snd_output_putc(out, '\'');
1368 static int _snd_config_save_children(snd_config_t *config, snd_output_t *out,
1369 unsigned int level, unsigned int joins);
1371 static int _snd_config_save_node_value(snd_config_t *n, snd_output_t *out,
1377 case SND_CONFIG_TYPE_INTEGER:
1378 snd_output_printf(out, "%ld", n->u.integer);
1380 case SND_CONFIG_TYPE_INTEGER64:
1381 snd_output_printf(out, "%Ld", n->u.integer64);
1383 case SND_CONFIG_TYPE_REAL:
1384 snd_output_printf(out, "%-16g", n->u.real);
1386 case SND_CONFIG_TYPE_STRING:
1387 string_print(n->u.string, 0, out);
1389 case SND_CONFIG_TYPE_POINTER:
1390 SNDERR("cannot save runtime pointer type");
1392 case SND_CONFIG_TYPE_COMPOUND:
1393 snd_output_putc(out, '{');
1394 snd_output_putc(out, '\n');
1395 err = _snd_config_save_children(n, out, level + 1, 0);
1398 for (k = 0; k < level; ++k) {
1399 snd_output_putc(out, '\t');
1401 snd_output_putc(out, '}');
1407 static void id_print(snd_config_t *n, snd_output_t *out, unsigned int joins)
1411 id_print(n->parent, out, joins - 1);
1412 snd_output_putc(out, '.');
1414 string_print(n->id, 1, out);
1417 static int _snd_config_save_children(snd_config_t *config, snd_output_t *out,
1418 unsigned int level, unsigned int joins)
1422 snd_config_iterator_t i, next;
1423 assert(config && out);
1424 snd_config_for_each(i, next, config) {
1425 snd_config_t *n = snd_config_iterator_entry(i);
1426 if (n->type == SND_CONFIG_TYPE_COMPOUND &&
1427 n->u.compound.join) {
1428 err = _snd_config_save_children(n, out, level, joins + 1);
1433 for (k = 0; k < level; ++k) {
1434 snd_output_putc(out, '\t');
1436 id_print(n, out, joins);
1438 snd_output_putc(out, ' ');
1439 snd_output_putc(out, '=');
1441 snd_output_putc(out, ' ');
1442 err = _snd_config_save_node_value(n, out, level);
1446 snd_output_putc(out, ';');
1448 snd_output_putc(out, '\n');
1456 * \brief Substitutes one configuration node to another.
1457 * \param dst Handle to the destination node.
1458 * \param src Handle to the source node. Must not be the same as \a dst.
1459 * \return Zero if successful, otherwise a negative error code.
1461 * If both nodes are compounds, the source compound node members are
1462 * appended to the destination compound node.
1464 * If the destination node is a compound and the source node is
1465 * an ordinary type, the compound members are deleted (including
1468 * Otherwise, the source node's value replaces the destination node's
1471 * In any case, a successful call to this function frees the source
1474 int snd_config_substitute(snd_config_t *dst, snd_config_t *src)
1477 if (dst->type == SND_CONFIG_TYPE_COMPOUND &&
1478 src->type == SND_CONFIG_TYPE_COMPOUND) { /* append */
1479 snd_config_iterator_t i, next;
1480 snd_config_for_each(i, next, src) {
1481 snd_config_t *n = snd_config_iterator_entry(i);
1484 src->u.compound.fields.next->prev = &dst->u.compound.fields;
1485 src->u.compound.fields.prev->next = &dst->u.compound.fields;
1486 } else if (dst->type == SND_CONFIG_TYPE_COMPOUND) {
1488 err = snd_config_delete_compound_members(dst);
1494 dst->type = src->type;
1501 * \brief Converts an ASCII string to a configuration node type.
1502 * \param[in] ascii A string containing a configuration node type.
1503 * \param[out] type The node type corresponding to \a ascii.
1504 * \return Zero if successful, otherwise a negative error code.
1506 * This function recognizes at least the following node types:
1508 * <dt>integer<dt>#SND_CONFIG_TYPE_INTEGER
1509 * <dt>integer64<dt>#SND_CONFIG_TYPE_INTEGER64
1510 * <dt>real<dt>#SND_CONFIG_TYPE_REAL
1511 * <dt>string<dt>#SND_CONFIG_TYPE_STRING
1512 * <dt>compound<dt>#SND_CONFIG_TYPE_COMPOUND
1517 * <dt>-EINVAL<dd>Unknown note type in \a type.
1520 int snd_config_get_type_ascii(const char *ascii, snd_config_type_t *type)
1522 assert(ascii && type);
1523 if (!strcmp(ascii, "integer")) {
1524 *type = SND_CONFIG_TYPE_INTEGER;
1527 if (!strcmp(ascii, "integer64")) {
1528 *type = SND_CONFIG_TYPE_INTEGER64;
1531 if (!strcmp(ascii, "real")) {
1532 *type = SND_CONFIG_TYPE_REAL;
1535 if (!strcmp(ascii, "string")) {
1536 *type = SND_CONFIG_TYPE_STRING;
1539 if (!strcmp(ascii, "compound")) {
1540 *type = SND_CONFIG_TYPE_COMPOUND;
1547 * \brief Returns the type of a configuration node.
1548 * \param config Handle to the configuration node.
1549 * \return The node's type.
1551 * \par Conforming to:
1554 snd_config_type_t snd_config_get_type(const snd_config_t *config)
1556 return config->type;
1560 * \brief Returns the id of a configuration node.
1561 * \param[in] config Handle to the configuration node.
1562 * \param[out] id The function puts the pointer to the id string at the
1563 * address specified by \a id.
1564 * \return Zero if successful, otherwise a negative error code.
1566 * The returned string is owned by the configuration node; the application
1567 * must not modify or delete it, and the string becomes invalid when the
1568 * node's id changes or when the node is freed.
1570 * If the node does not have an id, \a *id is set to \c NULL.
1572 * \par Conforming to:
1575 int snd_config_get_id(const snd_config_t *config, const char **id)
1577 assert(config && id);
1583 * \brief Sets the id of a configuration node.
1584 * \param config Handle to the configuration node.
1585 * \param id The new node id, must not be \c NULL.
1586 * \return Zero if successful, otherwise a negative error code.
1588 * This function stores a copy of \a id in the node.
1592 * <dt>-EEXIST<dd>One of \a config's siblings already has the id \a id.
1593 * <dt>-EINVAL<dd>The id of a node with a parent cannot be set to \c NULL.
1594 * <dt>-ENOMEM<dd>Out of memory.
1597 int snd_config_set_id(snd_config_t *config, const char *id)
1599 snd_config_iterator_t i, next;
1603 if (config->parent) {
1604 snd_config_for_each(i, next, config->parent) {
1605 snd_config_t *n = snd_config_iterator_entry(i);
1606 if (n != config && strcmp(id, n->id) == 0)
1610 new_id = strdup(id);
1619 config->id = new_id;
1624 * \brief Creates a top level configuration node.
1625 * \param[out] config Handle to the new node.
1626 * \return Zero if successful, otherwise a negative error code.
1628 * The returned node is an empty compound node without a parent and
1633 * <dt>-ENOMEM<dd>Out of memory.
1636 * \par Conforming to:
1639 int snd_config_top(snd_config_t **config)
1642 return _snd_config_make(config, 0, SND_CONFIG_TYPE_COMPOUND);
1645 static int snd_config_load1(snd_config_t *config, snd_input_t *in, int override)
1649 struct filedesc *fd, *fd_next;
1650 assert(config && in);
1651 fd = malloc(sizeof(*fd));
1661 err = parse_defs(config, &input, 0, override);
1666 case LOCAL_UNTERMINATED_STRING:
1667 str = "Unterminated string";
1670 case LOCAL_UNTERMINATED_QUOTE:
1671 str = "Unterminated quote";
1674 case LOCAL_UNEXPECTED_CHAR:
1675 str = "Unexpected char";
1678 case LOCAL_UNEXPECTED_EOF:
1679 str = "Unexpected end of file";
1683 str = strerror(-err);
1686 SNDERR("%s:%d:%d:%s", fd->name ? fd->name : "_toplevel_", fd->line, fd->column, str);
1689 if (get_char(&input) != LOCAL_UNEXPECTED_EOF) {
1690 SNDERR("%s:%d:%d:Unexpected }", fd->name ? fd->name : "", fd->line, fd->column);
1697 snd_input_close(fd->in);
1707 * \brief Loads a configuration tree.
1708 * \param config Handle to a top level configuration node.
1709 * \param in Input handle to read the configuration from.
1710 * \return Zero if successful, otherwise a negative error code.
1712 * The definitions loaded from the input are added to \a config, which
1713 * must be a compound node.
1716 * Any errors encountered when parsing the input or returned by hooks or
1719 * \par Conforming to:
1722 int snd_config_load(snd_config_t *config, snd_input_t *in)
1724 return snd_config_load1(config, in, 0);
1728 * \brief Loads a configuration tree and overrides existing configuration nodes.
1729 * \param config Handle to a top level configuration node.
1730 * \param in Input handle to read the configuration from.
1731 * \return Zero if successful, otherwise a negative error code.
1733 * This function loads definitions from \a in into \a config like
1734 * #snd_config_load, but the default mode for input nodes is 'override'
1735 * (!) instead of 'merge+create' (+).
1737 int snd_config_load_override(snd_config_t *config, snd_input_t *in)
1739 return snd_config_load1(config, in, 1);
1743 * \brief Adds a child to a compound configuration node.
1744 * \param parent Handle to a compound configuration node.
1745 * \param child Handle to the configuration node to be added.
1746 * \return Zero if successful, otherwise a negative error code.
1748 * This function makes the node \a child a child of the node \a parent.
1750 * The parent node then owns the child node, i.e., the child node gets
1751 * deleted together with its parent.
1753 * \a child must have an id.
1757 * <dt>-EINVAL<dd>\a child does not have an id.
1758 * <dt>-EINVAL<dd>\a child already has a parent.
1759 * <dt>-EEXIST<dd>\a parent already contains a child node with the same
1763 * \par Conforming to:
1766 int snd_config_add(snd_config_t *parent, snd_config_t *child)
1768 snd_config_iterator_t i, next;
1769 assert(parent && child);
1770 if (!child->id || child->parent)
1772 snd_config_for_each(i, next, parent) {
1773 snd_config_t *n = snd_config_iterator_entry(i);
1774 if (strcmp(child->id, n->id) == 0)
1777 child->parent = parent;
1778 list_add_tail(&child->list, &parent->u.compound.fields);
1783 * \brief Removes a configuration node from its tree.
1784 * \param config Handle to the configuration node to be removed.
1785 * \return Zero if successful, otherwise a negative error code.
1787 * This function makes \a config a top-level node, i.e., if \a config
1788 * has a parent, then \a config is removed from the list of the parent's
1791 * This functions does \e not free the removed node.
1793 * \sa snd_config_delete
1795 int snd_config_remove(snd_config_t *config)
1799 list_del(&config->list);
1800 config->parent = NULL;
1805 * \brief Frees a configuration node.
1806 * \param config Handle to the configuration node to be deleted.
1807 * \return Zero if successful, otherwise a negative error code.
1809 * This function frees a configuration node and all its resources.
1811 * If the node is a child node, it is removed from the tree before being
1814 * If the node is a compound node, its descendants (the whole subtree)
1815 * are deleted recursively.
1817 * \par Conforming to:
1820 * \sa snd_config_remove
1822 int snd_config_delete(snd_config_t *config)
1825 switch (config->type) {
1826 case SND_CONFIG_TYPE_COMPOUND:
1829 struct list_head *i;
1830 i = config->u.compound.fields.next;
1831 while (i != &config->u.compound.fields) {
1832 struct list_head *nexti = i->next;
1833 snd_config_t *child = snd_config_iterator_entry(i);
1834 err = snd_config_delete(child);
1841 case SND_CONFIG_TYPE_STRING:
1842 free(config->u.string);
1848 list_del(&config->list);
1855 * \brief Deletes the children of a node.
1856 * \param config Handle to the compound configuration node.
1857 * \return Zero if successful, otherwise a negative error code.
1859 * This function removes and frees all children of a configuration node.
1861 * Any compound nodes among the children of \a config are deleted
1864 * After a successful call to this function, \a config is an empty
1869 * <dt>-EINVAL<dd>\a config is not a compound node.
1872 int snd_config_delete_compound_members(const snd_config_t *config)
1875 struct list_head *i;
1878 if (config->type != SND_CONFIG_TYPE_COMPOUND)
1880 i = config->u.compound.fields.next;
1881 while (i != &config->u.compound.fields) {
1882 struct list_head *nexti = i->next;
1883 snd_config_t *child = snd_config_iterator_entry(i);
1884 err = snd_config_delete(child);
1893 * \brief Creates a configuration node.
1894 * \param[out] config The function puts the handle to the new node at
1895 * the address specified by \a config.
1896 * \param[in] id The id of the new node.
1897 * \param[in] type The type of the new node.
1898 * \return Zero if successful, otherwise a negative error code.
1900 * This functions creates a new node of the specified type.
1901 * The new node has id \a id, which may be \c NULL.
1903 * The value of the new node is zero (for numbers), or \c NULL (for
1904 * strings and pointers), or empty (for compound nodes).
1908 * <dt>-ENOMEM<dd>Out of memory.
1911 int snd_config_make(snd_config_t **config, const char *id,
1912 snd_config_type_t type)
1922 return _snd_config_make(config, &id1, type);
1926 * \brief Creates an integer configuration node.
1927 * \param[out] config The function puts the handle to the new node at
1928 * the address specified by \a config.
1929 * \param[in] id The id of the new node.
1930 * \return Zero if successful, otherwise a negative error code.
1932 * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER and
1937 * <dt>-ENOMEM<dd>Out of memory.
1940 * \par Conforming to:
1943 * \sa snd_config_imake_integer
1945 int snd_config_make_integer(snd_config_t **config, const char *id)
1947 return snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER);
1951 * \brief Creates a 64-bit-integer configuration node.
1952 * \param[out] config The function puts the handle to the new node at
1953 * the address specified by \a config.
1954 * \param[in] id The id of the new node.
1955 * \return Zero if successful, otherwise a negative error code.
1957 * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER64
1958 * and with value \c 0.
1962 * <dt>-ENOMEM<dd>Out of memory.
1965 * \par Conforming to:
1968 * \sa snd_config_imake_integer64
1970 int snd_config_make_integer64(snd_config_t **config, const char *id)
1972 return snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER64);
1976 * \brief Creates a real number configuration node.
1977 * \param[out] config The function puts the handle to the new node at
1978 * the address specified by \a config.
1979 * \param[in] id The id of the new node.
1980 * \return Zero if successful, otherwise a negative error code.
1982 * This function creates a new node of type #SND_CONFIG_TYPE_REAL and
1983 * with value \c 0.0.
1987 * <dt>-ENOMEM<dd>Out of memory.
1990 * \sa snd_config_imake_real
1992 int snd_config_make_real(snd_config_t **config, const char *id)
1994 return snd_config_make(config, id, SND_CONFIG_TYPE_REAL);
1998 * \brief Creates a string configuration node.
1999 * \param[out] config The function puts the handle to the new node at
2000 * the address specified by \a config.
2001 * \param[in] id The id of the new node.
2002 * \return Zero if successful, otherwise a negative error code.
2004 * This function creates a new node of type #SND_CONFIG_TYPE_STRING and
2005 * with value \c NULL.
2009 * <dt>-ENOMEM<dd>Out of memory.
2012 * \par Conforming to:
2015 * \sa snd_config_imake_string
2017 int snd_config_make_string(snd_config_t **config, const char *id)
2019 return snd_config_make(config, id, SND_CONFIG_TYPE_STRING);
2023 * \brief Creates a pointer configuration node.
2024 * \param[out] config The function puts the handle to the new node at
2025 * the address specified by \a config.
2026 * \param[in] id The id of the new node.
2027 * \return Zero if successful, otherwise a negative error code.
2029 * This function creates a new node of type #SND_CONFIG_TYPE_POINTER and
2030 * with value \c NULL.
2034 * <dt>-ENOMEM<dd>Out of memory.
2037 * \sa snd_config_imake_pointer
2039 int snd_config_make_pointer(snd_config_t **config, const char *id)
2041 return snd_config_make(config, id, SND_CONFIG_TYPE_POINTER);
2045 * \brief Creates an empty compound configuration node.
2046 * \param[out] config The function puts the handle to the new node at
2047 * the address specified by \a config.
2048 * \param[in] id The id of the new node.
2049 * \param[in] join Join flag.
2050 * \return Zero if successful, otherwise a negative error code.
2052 * This function creates a new empty node of type
2053 * #SND_CONFIG_TYPE_COMPOUND.
2055 * \a join determines how the compound node's id is printed when the
2056 * configuration is saved to a text file. For example, if the join flag
2057 * of compound node \c a is zero, the output will look as follows:
2064 * If, however, the join flag of \c a is nonzero, its id will be joined
2065 * with its children's ids, like this:
2070 * An \e empty compound node with its join flag set would result in no
2071 * output, i.e., after saving and reloading the configuration file, that
2072 * compound node would be lost.
2076 * <dt>-ENOMEM<dd>Out of memory.
2079 * \par Conforming to:
2082 int snd_config_make_compound(snd_config_t **config, const char *id,
2086 err = snd_config_make(config, id, SND_CONFIG_TYPE_COMPOUND);
2089 (*config)->u.compound.join = join;
2094 * \brief Creates an integer configuration node with the given initial value.
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] value The initial value of the new node.
2099 * \return Zero if successful, otherwise a negative error code.
2101 * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER and
2102 * with value \a value.
2106 * <dt>-ENOMEM<dd>Out of memory.
2109 * \par Conforming to:
2112 int snd_config_imake_integer(snd_config_t **config, const char *id, const long value)
2116 err = snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER);
2119 (*config)->u.integer = value;
2124 * \brief Creates a 64-bit-integer configuration node with the given initial value.
2125 * \param[out] config The function puts the handle to the new node at
2126 * the address specified by \a config.
2127 * \param[in] id The id of the new node.
2128 * \param[in] value The initial value of the new node.
2129 * \return Zero if successful, otherwise a negative error code.
2131 * This function creates a new node of type #SND_CONFIG_TYPE_INTEGER64
2132 * and with value \a value.
2136 * <dt>-ENOMEM<dd>Out of memory.
2139 * \par Conforming to:
2142 int snd_config_imake_integer64(snd_config_t **config, const char *id, const long long value)
2146 err = snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER64);
2149 (*config)->u.integer64 = value;
2154 * \brief Creates a real number configuration node with the given initial value.
2155 * \param[out] config The function puts the handle to the new node at
2156 * the address specified by \a config.
2157 * \param[in] id The id of the new node.
2158 * \param[in] value The initial value of the new node.
2159 * \return Zero if successful, otherwise a negative error code.
2161 * This function creates a new node of type #SND_CONFIG_TYPE_REAL and
2162 * with value \a value.
2166 * <dt>-ENOMEM<dd>Out of memory.
2169 int snd_config_imake_real(snd_config_t **config, const char *id, const double value)
2173 err = snd_config_make(config, id, SND_CONFIG_TYPE_REAL);
2176 (*config)->u.real = value;
2181 * \brief Creates a string configuration node with the given initial value.
2182 * \param[out] config The function puts the handle to the new node at
2183 * the address specified by \a config.
2184 * \param[in] id The id of the new node.
2185 * \param[in] value The initial value of the new node. May be \c NULL.
2186 * \return Zero if successful, otherwise a negative error code.
2188 * This function creates a new node of type #SND_CONFIG_TYPE_STRING and
2189 * with a copy of the string \c value.
2193 * <dt>-ENOMEM<dd>Out of memory.
2196 * \par Conforming to:
2199 int snd_config_imake_string(snd_config_t **config, const char *id, const char *value)
2204 err = snd_config_make(&tmp, id, SND_CONFIG_TYPE_STRING);
2208 tmp->u.string = strdup(value);
2209 if (!tmp->u.string) {
2210 snd_config_delete(tmp);
2214 tmp->u.string = NULL;
2221 * \brief Creates a pointer configuration node with the given initial value.
2222 * \param[out] config The function puts the handle to the new node at
2223 * the address specified by \a config.
2224 * \param[in] id The id of the new node.
2225 * \param[in] value The initial value of the new node.
2226 * \return Zero if successful, otherwise a negative error code.
2228 * This function creates a new node of type #SND_CONFIG_TYPE_POINTER and
2229 * with value \c value.
2233 * <dt>-ENOMEM<dd>Out of memory.
2236 int snd_config_imake_pointer(snd_config_t **config, const char *id, const void *value)
2240 err = snd_config_make(config, id, SND_CONFIG_TYPE_POINTER);
2243 (*config)->u.ptr = value;
2248 * \brief Changes the value of an integer configuration node.
2249 * \param config Handle to the configuration node.
2250 * \param value The new value for the node.
2251 * \return Zero if successful, otherwise a negative error code.
2255 * <dt>-EINVAL<dd>\a config is not an integer node.
2258 * \par Conforming to:
2261 int snd_config_set_integer(snd_config_t *config, long value)
2264 if (config->type != SND_CONFIG_TYPE_INTEGER)
2266 config->u.integer = value;
2271 * \brief Changes the value of a 64-bit-integer configuration node.
2272 * \param config Handle to the configuration node.
2273 * \param value The new value for the node.
2274 * \return Zero if successful, otherwise a negative error code.
2278 * <dt>-EINVAL<dd>\a config is not a 64-bit-integer node.
2281 * \par Conforming to:
2284 int snd_config_set_integer64(snd_config_t *config, long long value)
2287 if (config->type != SND_CONFIG_TYPE_INTEGER64)
2289 config->u.integer64 = value;
2294 * \brief Changes the value of a real-number configuration node.
2295 * \param config Handle to the configuration node.
2296 * \param value The new value for the node.
2297 * \return Zero if successful, otherwise a negative error code.
2301 * <dt>-EINVAL<dd>\a config is not a real-number node.
2304 int snd_config_set_real(snd_config_t *config, double value)
2307 if (config->type != SND_CONFIG_TYPE_REAL)
2309 config->u.real = value;
2314 * \brief Changes the value of a string configuration node.
2315 * \param config Handle to the configuration node.
2316 * \param value The new value for the node. May be \c NULL.
2317 * \return Zero if successful, otherwise a negative error code.
2319 * This function deletes the old string in the node and stores a copy of
2320 * \a value string in the node.
2324 * <dt>-EINVAL<dd>\a config is not a string node.
2327 * \par Conforming to:
2330 int snd_config_set_string(snd_config_t *config, const char *value)
2334 if (config->type != SND_CONFIG_TYPE_STRING)
2337 new_string = strdup(value);
2343 free(config->u.string);
2344 config->u.string = new_string;
2349 * \brief Changes the value of a pointer configuration node.
2350 * \param config Handle to the configuration node.
2351 * \param value The new value for the node. May be \c NULL.
2352 * \return Zero if successful, otherwise a negative error code.
2354 * This function does not free the old pointer in the node.
2358 * <dt>-EINVAL<dd>\a config is not a pointer node.
2361 int snd_config_set_pointer(snd_config_t *config, const void *value)
2364 if (config->type != SND_CONFIG_TYPE_POINTER)
2366 config->u.ptr = value;
2371 * \brief Changes the value of a configuration node.
2372 * \param config Handle to the configuration node.
2373 * \param ascii The new value for the node, as an ASCII string.
2374 * \return Zero if successful, otherwise a negative error code.
2376 * This function changes the node's value to a new value that is parsed
2377 * from the string \a ascii. \a ascii must not be \c NULL, not even for
2380 * The node's type does not change, i.e., the string must contain a
2381 * valid value with the same type as the node's type. For a string
2382 * node, the node's new value is a copy of \a ascii.
2386 * <dt>-EINVAL<dd>\a config is not a number or string node.
2387 * <dt>-EINVAL<dd>The value in \a ascii cannot be parsed.
2388 * <dt>-ERANGE<dd>The value in \a ascii is too big for the node's type.
2389 * <dt>-ENOMEM<dd>Out of memory.
2392 * \par Conforming to:
2395 int snd_config_set_ascii(snd_config_t *config, const char *ascii)
2397 assert(config && ascii);
2398 switch (config->type) {
2399 case SND_CONFIG_TYPE_INTEGER:
2402 int err = safe_strtol(ascii, &i);
2405 config->u.integer = i;
2408 case SND_CONFIG_TYPE_INTEGER64:
2411 int err = safe_strtoll(ascii, &i);
2414 config->u.integer64 = i;
2417 case SND_CONFIG_TYPE_REAL:
2420 int err = safe_strtod(ascii, &d);
2426 case SND_CONFIG_TYPE_STRING:
2428 char *ptr = strdup(ascii);
2431 free(config->u.string);
2432 config->u.string = ptr;
2442 * \brief Returns the value of an integer configuration node.
2443 * \param[in] config Handle to the configuration node.
2444 * \param[out] ptr The node's value.
2445 * \return Zero if successful, otherwise a negative error code.
2449 * <dt>-EINVAL<dd>\a config is not an integer node.
2452 * \par Conforming to:
2455 int snd_config_get_integer(const snd_config_t *config, long *ptr)
2457 assert(config && ptr);
2458 if (config->type != SND_CONFIG_TYPE_INTEGER)
2460 *ptr = config->u.integer;
2465 * \brief Returns the value of a 64-bit-integer configuration node.
2466 * \param[in] config Handle to the configuration node.
2467 * \param[out] ptr The node's value.
2468 * \return Zero if successful, otherwise a negative error code.
2472 * <dt>-EINVAL<dd>\a config is not a 64-bit-integer node.
2475 * \par Conforming to:
2478 int snd_config_get_integer64(const snd_config_t *config, long long *ptr)
2480 assert(config && ptr);
2481 if (config->type != SND_CONFIG_TYPE_INTEGER64)
2483 *ptr = config->u.integer64;
2488 * \brief Returns the value of a real-number configuration node.
2489 * \param[in] config Handle to the configuration node.
2490 * \param[out] ptr The node's value.
2491 * \return Zero if successful, otherwise a negative error code.
2495 * <dt>-EINVAL<dd>\a config is not a real-number node.
2498 int snd_config_get_real(const snd_config_t *config, double *ptr)
2500 assert(config && ptr);
2501 if (config->type != SND_CONFIG_TYPE_REAL)
2503 *ptr = config->u.real;
2508 * \brief Returns the value of a real or integer configuration node.
2509 * \param[in] config Handle to the configuration node.
2510 * \param[out] ptr The node's value.
2511 * \return Zero if successful, otherwise a negative error code.
2513 * If the node's type is integer or integer64, the value is converted
2514 * to the \c double type on the fly.
2518 * <dt>-EINVAL<dd>\a config is not a number node.
2521 int snd_config_get_ireal(const snd_config_t *config, double *ptr)
2523 assert(config && ptr);
2524 if (config->type == SND_CONFIG_TYPE_REAL)
2525 *ptr = config->u.real;
2526 else if (config->type == SND_CONFIG_TYPE_INTEGER)
2527 *ptr = config->u.integer;
2528 else if (config->type == SND_CONFIG_TYPE_INTEGER64)
2529 *ptr = config->u.integer64;
2536 * \brief Returns the value of a string configuration node.
2537 * \param[in] config Handle to the configuration node.
2538 * \param[out] ptr The function puts the node's value at the address
2539 * specified by \a ptr.
2540 * \return Zero if successful, otherwise a negative error code.
2542 * The returned string is owned by the configuration node; the
2543 * application must not modify or delete it, and the string becomes
2544 * invalid when the node's value changes or when the node is freed.
2546 * The string may be \c NULL.
2550 * <dt>-EINVAL<dd>\a config is not a string node.
2553 * \par Conforming to:
2556 int snd_config_get_string(const snd_config_t *config, const char **ptr)
2558 assert(config && ptr);
2559 if (config->type != SND_CONFIG_TYPE_STRING)
2561 *ptr = config->u.string;
2566 * \brief Returns the value of a pointer configuration node.
2567 * \param[in] config Handle to the configuration node.
2568 * \param[out] ptr The function puts the node's value at the address
2569 * specified by \a ptr.
2570 * \return Zero if successful, otherwise a negative error code.
2574 * <dt>-EINVAL<dd>\a config is not a string node.
2577 int snd_config_get_pointer(const snd_config_t *config, const void **ptr)
2579 assert(config && ptr);
2580 if (config->type != SND_CONFIG_TYPE_POINTER)
2582 *ptr = config->u.ptr;
2587 * \brief Returns the value of a configuration node as a string.
2588 * \param[in] config Handle to the configuration node.
2589 * \param[out] ascii The function puts the pointer to the returned
2590 * string at the address specified by \a ascii.
2591 * \return Zero if successful, otherwise a negative error code.
2593 * This function dynamically allocates the returned string. The
2594 * application is responsible for deleting it with \c free() when it is
2597 * For a string node with \c NULL value, the returned string is \c NULL.
2599 * Supported node types are #SND_CONFIG_TYPE_INTEGER,
2600 * #SND_CONFIG_TYPE_INTEGER64, #SND_CONFIG_TYPE_REAL, and
2601 * #SND_CONFIG_TYPE_STRING.
2605 * <dt>-EINVAL<dd>\a config is not a (64-bit) integer or real number or
2607 * <dt>-ENOMEM<dd>Out of memory.
2610 * \par Conforming to:
2613 int snd_config_get_ascii(const snd_config_t *config, char **ascii)
2615 assert(config && ascii);
2616 switch (config->type) {
2617 case SND_CONFIG_TYPE_INTEGER:
2621 err = snprintf(res, sizeof(res), "%li", config->u.integer);
2622 if (err < 0 || err == sizeof(res)) {
2626 *ascii = strdup(res);
2629 case SND_CONFIG_TYPE_INTEGER64:
2633 err = snprintf(res, sizeof(res), "%Li", config->u.integer64);
2634 if (err < 0 || err == sizeof(res)) {
2638 *ascii = strdup(res);
2641 case SND_CONFIG_TYPE_REAL:
2645 err = snprintf(res, sizeof(res), "%-16g", config->u.real);
2646 if (err < 0 || err == sizeof(res)) {
2650 if (res[0]) { /* trim the string */
2652 ptr = res + strlen(res) - 1;
2653 while (ptr != res && *ptr == ' ')
2659 *ascii = strdup(res);
2662 case SND_CONFIG_TYPE_STRING:
2663 if (config->u.string)
2664 *ascii = strdup(config->u.string);
2679 * \brief Compares the id of a configuration node to a given string.
2680 * \param config Handle to the configuration node.
2681 * \param id ASCII id.
2682 * \return The same value as the result of the \c strcmp function, i.e.,
2683 * less than zero if \a config's id is lexicographically less
2684 * than \a id, zero if \a config's id is equal to id, greater
2685 * than zero otherwise.
2687 int snd_config_test_id(const snd_config_t *config, const char *id)
2689 assert(config && id);
2691 return strcmp(config->id, id);
2697 * \brief Dumps the contents of a configuration node or tree.
2698 * \param config Handle to the (root) configuration node.
2699 * \param out Output handle.
2700 * \return Zero if successful, otherwise a negative error code.
2702 * This function writes a textual representation of \a config's value to
2703 * the output \a out.
2707 * <dt>-EINVAL<dd>A node in the tree has a type that cannot be printed,
2708 * i.e., #SND_CONFIG_TYPE_POINTER.
2711 * \par Conforming to:
2714 int snd_config_save(snd_config_t *config, snd_output_t *out)
2716 assert(config && out);
2717 if (config->type == SND_CONFIG_TYPE_COMPOUND)
2718 return _snd_config_save_children(config, out, 0, 0);
2720 return _snd_config_save_node_value(config, out, 0);
2724 * *** search macros ***
2729 #define SND_CONFIG_SEARCH(config, key, result, extra_code) \
2734 assert(config && key); \
2736 if (config->type != SND_CONFIG_TYPE_COMPOUND) \
2739 p = strchr(key, '.'); \
2741 err = _snd_config_search(config, key, p - key, &n); \
2747 return _snd_config_search(config, key, -1, result); \
2751 #define SND_CONFIG_SEARCHA(root, config, key, result, fcn, extra_code) \
2756 assert(config && key); \
2758 if (config->type != SND_CONFIG_TYPE_COMPOUND) { \
2759 if (snd_config_get_string(config, &p) < 0) \
2761 err = fcn(root, root, p, &config); \
2766 p = strchr(key, '.'); \
2768 err = _snd_config_search(config, key, p - key, &n); \
2774 return _snd_config_search(config, key, -1, result); \
2778 #define SND_CONFIG_SEARCHV(config, result, fcn) \
2783 va_start(arg, result); \
2785 const char *k = va_arg(arg, const char *); \
2789 err = fcn(config, k, &n); \
2800 #define SND_CONFIG_SEARCHVA(root, config, result, fcn) \
2805 va_start(arg, result); \
2807 const char *k = va_arg(arg, const char *); \
2811 err = fcn(root, config, k, &n); \
2822 #define SND_CONFIG_SEARCH_ALIAS(config, base, key, result, fcn1, fcn2) \
2824 snd_config_t *res = NULL; \
2826 int err, first = 1, maxloop = 1000; \
2827 assert(config && key); \
2829 old_key = strdup(key); \
2830 if (old_key == NULL) { \
2835 err = first && base ? -EIO : fcn1(config, config, key, &res); \
2839 err = fcn2(config, config, &res, base, key, NULL); \
2843 if (snd_config_get_string(res, &key) < 0) \
2846 if (!first && (strcmp(key, old_key) == 0 || maxloop <= 0)) { \
2848 SNDERR("maximum loop count reached (circular configuration?)"); \
2850 SNDERR("key %s refers to itself", key); \
2867 #endif /* DOC_HIDDEN */
2870 * \brief Searches for a node in a configuration tree.
2871 * \param[in] config Handle to the root of the configuration (sub)tree to search.
2872 * \param[in] key Search key: one or more node ids, separated with dots.
2873 * \param[out] result When \a result != \c NULL, the function puts the
2874 * handle to the node found at the address specified
2876 * \return Zero if successful, otherwise a negative error code.
2878 * This function searches for a child node of \a config that is
2879 * identified by \a key, which contains either the id of a direct child
2880 * node of \a config, or a series of ids, separated with dots, where
2881 * each id specifies a node that is contained in the previous compound
2884 * In the following example, the comment after each node shows the
2885 * search key to find that node, assuming that \a config is a handle to
2886 * the compound node with id \c config:
2893 * e 2.71828 # "b.d.e"
2901 * <dt>-ENOENT<dd>An id in \a key does not exist.
2902 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
2903 * not a compound node.
2906 * \par Conforming to:
2909 int snd_config_search(snd_config_t *config, const char *key, snd_config_t **result)
2911 SND_CONFIG_SEARCH(config, key, result, );
2915 * \brief Searches for a node in a configuration tree, expanding aliases.
2916 * \param[in] root Handle to the root configuration node containing
2917 * alias definitions.
2918 * \param[in] config Handle to the root of the configuration (sub)tree to search.
2919 * \param[in] key Search key: one or more node keys, separated with dots.
2920 * \param[out] result When \a result != \c NULL, the function puts the
2921 * handle to the node found at the address specified
2923 * \return Zero if successful, otherwise a negative error code.
2925 * This functions searches for a child node of \a config like
2926 * #snd_config_search. However, any compound node can also be
2927 * identified by an alias, which is a string node whose value is taken
2928 * as the id of a compound node below \a root.
2930 * \a root must be a compound node.
2931 * \a root and \a config may be the same node.
2933 * For example, with the following configuration, the call
2935 * snd_config_searcha(root, config, "a.b.c.d", &result);
2937 * would return the node with id \c d:
2959 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist.
2960 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
2961 * not a compound or string node.
2964 int snd_config_searcha(snd_config_t *root, snd_config_t *config, const char *key, snd_config_t **result)
2966 SND_CONFIG_SEARCHA(root, config, key, result, snd_config_searcha, );
2970 * \brief Searches for a node in a configuration tree.
2971 * \param[in] config Handle to the root of the configuration (sub)tree to search.
2972 * \param[out] result When \a result != \c NULL, the function puts the
2973 * handle to the node found at the address specified
2975 * \param[in] ... One or more concatenated dot-separated search keys,
2976 * terminated with \c NULL.
2977 * \return Zero if successful, otherwise a negative error code.
2979 * This functions searches for a child node of \a config like
2980 * #snd_config_search, but the search key is the concatenation of all
2981 * passed search key strings. For example, the call
2983 * snd_config_searchv(cfg, &res, "a", "b.c", "d.e", NULL);
2985 * is equivalent to the call
2987 * snd_config_search(cfg, "a.b.c.d.e", &res);
2992 * <dt>-ENOENT<dd>An id in a search key does not exist.
2993 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
2994 * not a compound node.
2997 * \par Conforming to:
3000 int snd_config_searchv(snd_config_t *config, snd_config_t **result, ...)
3002 SND_CONFIG_SEARCHV(config, result, snd_config_search);
3006 * \brief Searches for a node in a configuration tree, expanding aliases.
3007 * \param[in] root Handle to the root configuration node containing
3008 * alias definitions.
3009 * \param[in] config Handle to the root of the configuration (sub)tree to search.
3010 * \param[out] result When \a result != \c NULL, the function puts the
3011 * handle to the node found at the address specified
3013 * \param[in] ... One or more concatenated dot separated search keys,
3014 * terminated with \c NULL.
3015 * \return Zero if successful, otherwise a negative error code.
3017 * This function searches for a child node of \a config, allowing
3018 * aliases, like #snd_config_searcha, but the search key is the
3019 * concatenation of all passed seach key strings, like with
3020 * #snd_config_searchv.
3024 * <dt>-ENOENT<dd>An id in a search key does not exist.
3025 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3026 * not a compound or string node.
3029 int snd_config_searchva(snd_config_t *root, snd_config_t *config, snd_config_t **result, ...)
3031 SND_CONFIG_SEARCHVA(root, config, result, snd_config_searcha);
3035 * \brief Searches for a node in a configuration tree, expanding aliases.
3036 * \param[in] config Handle to the root of the configuration (sub)tree to search.
3037 * \param[in] base Search key base, or \c NULL.
3038 * \param[in] key Search key suffix.
3039 * \param[out] result When \a result != \c NULL, the function puts the
3040 * handle to the node found at the address specified
3042 * \return Zero if successful, otherwise a negative error code.
3044 * This functions searches for a child node of \a config, allowing
3045 * aliases, like #snd_config_searcha. However, alias definitions are
3046 * searched below \a config (there is no separate \a root parameter),
3047 * and \a base specifies a seach key that identifies a compound node
3048 * that is used to search for an alias definitions that is not found
3049 * directly below \a config and that does not contain a period. In
3050 * other words, when \c "id" is not found in \a config, this function
3051 * also tries \c "base.id".
3055 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist.
3056 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3057 * not a compound or string node.
3060 int snd_config_search_alias(snd_config_t *config,
3061 const char *base, const char *key,
3062 snd_config_t **result)
3064 SND_CONFIG_SEARCH_ALIAS(config, base, key, result,
3065 snd_config_searcha, snd_config_searchva);
3068 static int snd_config_hooks(snd_config_t *config, snd_config_t *private_data);
3071 * \brief Searches for a node in a configuration tree and expands hooks.
3072 * \param[in,out] config Handle to the root of the configuration
3073 * (sub)tree to search.
3074 * \param[in] key Search key: one or more node keys, separated with dots.
3075 * \param[out] result The function puts the handle to the node found at
3076 * the address specified by \a result.
3077 * \return Zero if successful, otherwise a negative error code.
3079 * This functions searches for a child node of \a config like
3080 * #snd_config_search, but any compound nodes to be searched that
3081 * contain hooks are modified by the respective hook functions.
3085 * <dt>-ENOENT<dd>An id in \a key does not exist.
3086 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3087 * not a compound node.
3089 * Additionally, any errors encountered when parsing the hook
3090 * definitions or returned by the hook functions.
3092 int snd_config_search_hooks(snd_config_t *config, const char *key, snd_config_t **result)
3094 SND_CONFIG_SEARCH(config, key, result, \
3095 err = snd_config_hooks(config, NULL); \
3102 * \brief Searches for a node in a configuration tree, expanding aliases and hooks.
3103 * \param[in] root Handle to the root configuration node containing
3104 * alias definitions.
3105 * \param[in,out] config Handle to the root of the configuration
3106 * (sub)tree to search.
3107 * \param[in] key Search key: one or more node keys, separated with dots.
3108 * \param[out] result The function puts the handle to the node found at
3109 * the address specified by \a result.
3110 * \return Zero if successful, otherwise a negative error code.
3112 * This function searches for a child node of \a config, allowing
3113 * aliases, like #snd_config_searcha, and expanding hooks, like
3114 * #snd_config_search_hooks.
3118 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist.
3119 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3120 * not a compound node.
3122 * Additionally, any errors encountered when parsing the hook
3123 * definitions or returned by the hook functions.
3125 int snd_config_searcha_hooks(snd_config_t *root, snd_config_t *config, const char *key, snd_config_t **result)
3127 SND_CONFIG_SEARCHA(root, config, key, result,
3128 snd_config_searcha_hooks,
3129 err = snd_config_hooks(config, NULL); \
3136 * \brief Searches for a node in a configuration tree, expanding aliases and hooks.
3137 * \param[in] root Handle to the root configuration node containing
3138 * alias definitions.
3139 * \param[in,out] config Handle to the root of the configuration
3140 * (sub)tree to search.
3141 * \param[out] result The function puts the handle to the node found at
3142 * the address specified by \a result.
3143 * \param[in] ... One or more concatenated dot separated search keys,
3144 * terminated with \c NULL.
3145 * \return Zero if successful, otherwise a negative error code.
3147 * This function searches for a child node of \a config, allowing
3148 * aliases and expanding hooks like #snd_config_searcha_hooks, but the
3149 * search key is the concatenation of all passed seach key strings, like
3150 * with #snd_config_searchv.
3154 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist.
3155 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3156 * not a compound node.
3158 * Additionally, any errors encountered when parsing the hook
3159 * definitions or returned by the hook functions.
3161 int snd_config_searchva_hooks(snd_config_t *root, snd_config_t *config,
3162 snd_config_t **result, ...)
3164 SND_CONFIG_SEARCHVA(root, config, result, snd_config_searcha_hooks);
3168 * \brief Searches for a node in a configuration tree, using an alias and expanding hooks.
3169 * \param[in] config Handle to the root of the configuration (sub)tree
3171 * \param[in] base Search key base, or \c NULL.
3172 * \param[in] key Search key suffix.
3173 * \param[out] result The function puts the handle to the node found at
3174 * the address specified by \a result.
3175 * \return Zero if successful, otherwise a negative error code.
3177 * This functions searches for a child node of \a config, allowing
3178 * aliases, like #snd_config_search_alias, and expanding hooks, like
3179 * #snd_config_search_hooks.
3183 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist.
3184 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
3185 * not a compound node.
3187 * Additionally, any errors encountered when parsing the hook
3188 * definitions or returned by the hook functions.
3190 int snd_config_search_alias_hooks(snd_config_t *config,
3191 const char *base, const char *key,
3192 snd_config_t **result)
3194 SND_CONFIG_SEARCH_ALIAS(config, base, key, result,
3195 snd_config_searcha_hooks,
3196 snd_config_searchva_hooks);
3199 /** The name of the environment variable containing the files list for #snd_config_update. */
3200 #define ALSA_CONFIG_PATH_VAR "ALSA_CONFIG_PATH"
3202 /** The name of the default files used by #snd_config_update. */
3203 #define ALSA_CONFIG_PATH_DEFAULT ALSA_CONFIG_DIR "/alsa.conf"
3207 * \brief Configuration top-level node (the global configuration).
3209 * This variable contains a handle to the top-level configuration node,
3210 * as loaded from global configuration file.
3212 * This variable is initialized or updated by #snd_config_update.
3213 * Functions like #snd_pcm_open (that use a device name from the global
3214 * configuration) automatically call #snd_config_update. Before the
3215 * first call to #snd_config_update, this variable is \c NULL.
3217 * The global configuration files are specified in the environment
3218 * variable \c ALSA_CONFIG_PATH. If this is not set, the default value
3219 * is "/usr/share/alsa/alsa.conf".
3221 * \warning Whenever the configuration tree is updated, all string
3222 * pointers and configuration node handles previously obtained from this
3223 * variable may become invalid.
3225 * \par Conforming to:
3228 snd_config_t *snd_config = NULL;
3238 struct _snd_config_update {
3240 struct finfo *finfo;
3242 #endif /* DOC_HIDDEN */
3244 static snd_config_update_t *snd_config_global_update = NULL;
3246 static int snd_config_hooks_call(snd_config_t *root, snd_config_t *config, snd_config_t *private_data)
3249 snd_config_t *c, *func_conf = NULL;
3251 const char *lib = NULL, *func_name = NULL;
3253 int (*func)(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data) = NULL;
3256 err = snd_config_search(config, "func", &c);
3258 SNDERR("Field func is missing");
3261 err = snd_config_get_string(c, &str);
3263 SNDERR("Invalid type for field func");
3267 err = snd_config_search_definition(root, "hook_func", str, &func_conf);
3269 snd_config_iterator_t i, next;
3270 if (snd_config_get_type(func_conf) != SND_CONFIG_TYPE_COMPOUND) {
3271 SNDERR("Invalid type for func %s definition", str);
3275 snd_config_for_each(i, next, func_conf) {
3276 snd_config_t *n = snd_config_iterator_entry(i);
3277 const char *id = n->id;
3278 if (strcmp(id, "comment") == 0)
3280 if (strcmp(id, "lib") == 0) {
3281 err = snd_config_get_string(n, &lib);
3283 SNDERR("Invalid type for %s", id);
3288 if (strcmp(id, "func") == 0) {
3289 err = snd_config_get_string(n, &func_name);
3291 SNDERR("Invalid type for %s", id);
3296 SNDERR("Unknown field %s", id);
3300 int len = 16 + strlen(str) + 1;
3306 snprintf(buf, len, "snd_config_hook_%s", str);
3310 h = snd_dlopen(lib, RTLD_NOW);
3311 func = h ? snd_dlsym(h, func_name, SND_DLSYM_VERSION(SND_CONFIG_DLSYM_VERSION_HOOK)) : NULL;
3314 SNDERR("Cannot open shared library %s", lib);
3317 SNDERR("symbol %s is not defined inside %s", func_name, lib);
3323 snd_config_delete(func_conf);
3325 snd_config_t *nroot;
3326 err = func(root, config, &nroot, private_data);
3328 SNDERR("function %s returned error: %s", func_name, snd_strerror(err));
3330 if (err >= 0 && nroot)
3331 err = snd_config_substitute(root, nroot);
3339 static int snd_config_hooks(snd_config_t *config, snd_config_t *private_data)
3342 snd_config_iterator_t i, next;
3343 int err, hit, idx = 0;
3345 if ((err = snd_config_search(config, "@hooks", &n)) < 0)
3348 snd_config_remove(n);
3351 snd_config_for_each(i, next, n) {
3352 snd_config_t *n = snd_config_iterator_entry(i);
3353 const char *id = n->id;
3355 err = safe_strtol(id, &i);
3357 SNDERR("id of field %s is not and integer", id);
3362 err = snd_config_hooks_call(config, n, private_data);
3372 snd_config_delete(n);
3373 snd_config_unlock();
3377 static int config_filename_filter(const struct dirent *dirent)
3383 if (dirent->d_type == DT_DIR)
3386 flen = strlen(dirent->d_name);
3390 if (strncmp(&dirent->d_name[flen-5], ".conf", 5) == 0)
3396 static int config_file_open(snd_config_t *root, const char *filename)
3401 err = snd_input_stdio_open(&in, filename, "r");
3403 err = snd_config_load(root, in);
3404 snd_input_close(in);
3406 SNDERR("%s may be old or corrupted: consider to remove or fix it", filename);
3408 SNDERR("cannot access file %s", filename);
3414 * \brief Loads and parses the given configurations files.
3415 * \param[in] root Handle to the root configuration node.
3416 * \param[in] config Handle to the configuration node for this hook.
3417 * \param[out] dst The function puts the handle to the configuration
3418 * node loaded from the file(s) at the address specified
3420 * \param[in] private_data Handle to the private data configuration node.
3421 * \return Zero if successful, otherwise a negative error code.
3423 * See \ref confhooks for an example.
3425 int snd_config_hook_load(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data)
3428 snd_config_iterator_t i, next;
3429 struct finfo *fi = NULL;
3430 int err, idx = 0, fi_count = 0, errors = 1, hit;
3432 assert(root && dst);
3433 if ((err = snd_config_search(config, "errors", &n)) >= 0) {
3435 err = snd_config_get_ascii(n, &tmp);
3438 errors = snd_config_get_bool_ascii(tmp);
3441 SNDERR("Invalid bool value in field errors");
3445 if ((err = snd_config_search(config, "files", &n)) < 0) {
3446 SNDERR("Unable to find field files in the pre-load section");
3449 if ((err = snd_config_expand(n, root, NULL, private_data, &n)) < 0) {
3450 SNDERR("Unable to expand filenames in the pre-load section");
3453 if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
3454 SNDERR("Invalid type for field filenames");
3457 snd_config_for_each(i, next, n) {
3458 snd_config_t *c = snd_config_iterator_entry(i);
3460 if ((err = snd_config_get_string(c, &str)) < 0) {
3461 SNDERR("Field %s is not a string", c->id);
3466 fi = calloc(fi_count, sizeof(*fi));
3473 snd_config_for_each(i, next, n) {
3474 snd_config_t *n = snd_config_iterator_entry(i);
3475 const char *id = n->id;
3477 err = safe_strtol(id, &i);
3479 SNDERR("id of field %s is not and integer", id);
3485 if ((err = snd_config_get_ascii(n, &name)) < 0)
3487 if ((err = snd_user_file(name, &fi[idx].name)) < 0)
3488 fi[idx].name = name;
3496 for (idx = 0; idx < fi_count; idx++) {
3498 if (!errors && access(fi[idx].name, R_OK) < 0)
3500 if (stat(fi[idx].name, &st) < 0) {
3501 SNDERR("cannot stat file/directory %s", fi[idx].name);
3504 if (S_ISDIR(st.st_mode)) {
3505 struct dirent **namelist;
3508 n = scandir(fi[idx].name, &namelist, config_filename_filter, versionsort);
3512 for (j = 0; j < n; ++j) {
3514 int sl = strlen(fi[idx].name) + strlen(namelist[j]->d_name) + 2;
3515 char *filename = malloc(sl);
3516 snprintf(filename, sl, "%s/%s", fi[idx].name, namelist[j]->d_name);
3517 filename[sl-1] = '\0';
3519 err = config_file_open(root, filename);
3528 } else if (config_file_open(root, fi[idx].name) < 0)
3535 for (idx = 0; idx < fi_count; idx++)
3538 snd_config_delete(n);
3542 SND_DLSYM_BUILD_VERSION(snd_config_hook_load, SND_CONFIG_DLSYM_VERSION_HOOK);
3546 int snd_determine_driver(int card, char **driver);
3550 * \brief Loads and parses the given configurations files for each
3551 * installed sound card.
3552 * \param[in] root Handle to the root configuration node.
3553 * \param[in] config Handle to the configuration node for this hook.
3554 * \param[out] dst The function puts the handle to the configuration
3555 * node loaded from the file(s) at the address specified
3557 * \param[in] private_data Handle to the private data configuration node.
3558 * \return Zero if successful, otherwise a negative error code.
3560 * This function works like #snd_config_hook_load, but the files are
3561 * loaded once for each sound card. The driver name is available with
3562 * the \c private_string function to customize the file name.
3564 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)
3569 err = snd_card_next(&card);
3573 snd_config_t *n, *private_data = NULL;
3575 char *fdriver = NULL;
3576 err = snd_determine_driver(card, &fdriver);
3579 if (snd_config_search(root, fdriver, &n) >= 0) {
3580 if (snd_config_get_string(n, &driver) < 0)
3584 char *s = strchr(driver, '.');
3589 if (snd_config_search(root, driver, &n) >= 0)
3594 err = snd_config_imake_string(&private_data, "string", driver);
3597 err = snd_config_hook_load(root, config, &n, private_data);
3600 snd_config_delete(private_data);
3605 } while (card >= 0);
3610 SND_DLSYM_BUILD_VERSION(snd_config_hook_load_for_all_cards, SND_CONFIG_DLSYM_VERSION_HOOK);
3614 * \brief Updates a configuration tree by rereading the configuration files (if needed).
3615 * \param[in,out] _top Address of the handle to the top-level node.
3616 * \param[in,out] _update Address of a pointer to private update information.
3617 * \param[in] cfgs A list of configuration file names, delimited with ':'.
3618 * If \p cfgs is \c NULL, the default global
3619 * configuration file is used.
3620 * \return 0 if \a _top was up to date, 1 if the configuration files
3621 * have been reread, otherwise a negative error code.
3623 * The variables pointed to by \a _top and \a _update can be initialized
3624 * to \c NULL before the first call to this function. The private
3625 * update information holds information about all used configuration
3626 * files that allows this function to detects changes to them; this data
3627 * can be freed with #snd_config_update_free.
3629 * The global configuration files are specified in the environment variable
3630 * \c ALSA_CONFIG_PATH.
3632 * \warning If the configuration tree is reread, all string pointers and
3633 * configuration node handles previously obtained from this tree become
3637 * Any errors encountered when parsing the input or returned by hooks or
3640 int snd_config_update_r(snd_config_t **_top, snd_config_update_t **_update, const char *cfgs)
3643 const char *configs, *c;
3646 snd_config_update_t *local;
3647 snd_config_update_t *update;
3650 assert(_top && _update);
3655 configs = getenv(ALSA_CONFIG_PATH_VAR);
3656 if (!configs || !*configs)
3657 configs = ALSA_CONFIG_PATH_DEFAULT;
3659 for (k = 0, c = configs; (l = strcspn(c, ": ")) > 0; ) {
3670 local = (snd_config_update_t *)calloc(1, sizeof(snd_config_update_t));
3674 local->finfo = calloc(local->count, sizeof(struct finfo));
3675 if (!local->finfo) {
3679 for (k = 0, c = configs; (l = strcspn(c, ": ")) > 0; ) {
3683 err = snd_user_file(name, &local->finfo[k].name);
3692 for (k = 0; k < local->count; ++k) {
3694 struct finfo *lf = &local->finfo[k];
3695 if (stat(lf->name, &st) >= 0) {
3696 lf->dev = st.st_dev;
3697 lf->ino = st.st_ino;
3698 lf->mtime = st.st_mtime;
3700 SNDERR("Cannot access file %s", lf->name);
3702 memmove(&local->finfo[k], &local->finfo[k+1], sizeof(struct finfo) * (local->count - k - 1));
3709 if (local->count != update->count)
3711 for (k = 0; k < local->count; ++k) {
3712 struct finfo *lf = &local->finfo[k];
3713 struct finfo *uf = &update->finfo[k];
3714 if (strcmp(lf->name, uf->name) != 0 ||
3715 lf->dev != uf->dev ||
3716 lf->ino != uf->ino ||
3717 lf->mtime != uf->mtime)
3725 snd_config_delete(top);
3729 snd_config_update_free(update);
3734 snd_config_update_free(local);
3741 snd_config_update_free(update);
3745 snd_config_delete(top);
3748 err = snd_config_top(&top);
3753 for (k = 0; k < local->count; ++k) {
3755 err = snd_input_stdio_open(&in, local->finfo[k].name, "r");
3757 err = snd_config_load(top, in);
3758 snd_input_close(in);
3760 SNDERR("%s may be old or corrupted: consider to remove or fix it", local->finfo[k].name);
3764 SNDERR("cannot access file %s", local->finfo[k].name);
3768 err = snd_config_hooks(top, NULL);
3770 SNDERR("hooks failed, removing configuration");
3779 * \brief Updates #snd_config by rereading the global configuration files (if needed).
3780 * \return 0 if #snd_config was up to date, 1 if #snd_config was
3781 * updated, otherwise a negative error code.
3783 * \warning Whenever #snd_config is updated, all string pointers and
3784 * configuration node handles previously obtained from it may become
3788 * Any errors encountered when parsing the input or returned by hooks or
3791 * \par Conforming to:
3794 int snd_config_update(void)
3799 err = snd_config_update_r(&snd_config, &snd_config_global_update, NULL);
3800 snd_config_unlock();
3805 * \brief Frees a private update structure.
3806 * \param[in] update The private update structure to free.
3807 * \return Zero if successful, otherwise a negative error code.
3809 int snd_config_update_free(snd_config_update_t *update)
3814 for (k = 0; k < update->count; k++)
3815 free(update->finfo[k].name);
3816 free(update->finfo);
3822 * \brief Frees the global configuration tree in #snd_config.
3823 * \return Zero if successful, otherwise a negative error code.
3825 * This functions releases all resources of the global configuration
3826 * tree, and sets #snd_config to \c NULL.
3828 * \par Conforming to:
3831 int snd_config_update_free_global(void)
3835 snd_config_delete(snd_config);
3837 if (snd_config_global_update)
3838 snd_config_update_free(snd_config_global_update);
3839 snd_config_global_update = NULL;
3840 snd_config_unlock();
3841 /* FIXME: better to place this in another place... */
3842 snd_dlobj_cache_cleanup();
3848 * \brief Returns an iterator pointing to a node's first child.
3849 * \param[in] config Handle to a configuration node.
3850 * \return An iterator pointing to \a config's first child.
3852 * \a config must be a compound node.
3854 * The returned iterator is valid if it is not equal to the return value
3855 * of #snd_config_iterator_end on \a config.
3857 * Use #snd_config_iterator_entry to get the handle of the node pointed
3860 * \par Conforming to:
3863 snd_config_iterator_t snd_config_iterator_first(const snd_config_t *config)
3865 assert(config->type == SND_CONFIG_TYPE_COMPOUND);
3866 return config->u.compound.fields.next;
3870 * \brief Returns an iterator pointing to the next sibling.
3871 * \param[in] iterator An iterator pointing to a child configuration node.
3872 * \return An iterator pointing to the next sibling of \a iterator.
3874 * The returned iterator is valid if it is not equal to the return value
3875 * of #snd_config_iterator_end on the node's parent.
3877 * Use #snd_config_iterator_entry to get the handle of the node pointed
3880 * \par Conforming to:
3883 snd_config_iterator_t snd_config_iterator_next(const snd_config_iterator_t iterator)
3885 return iterator->next;
3889 * \brief Returns an iterator that ends a node's children list.
3890 * \param[in] config Handle to a configuration node.
3891 * \return An iterator that indicates the end of \a config's children list.
3893 * \a config must be a compound node.
3895 * The return value can be understood as pointing past the last child of
3898 * \par Conforming to:
3901 snd_config_iterator_t snd_config_iterator_end(const snd_config_t *config)
3903 assert(config->type == SND_CONFIG_TYPE_COMPOUND);
3904 return (const snd_config_iterator_t)&config->u.compound.fields;
3908 * \brief Returns the configuration node handle pointed to by an iterator.
3909 * \param[in] iterator A configuration node iterator.
3910 * \return The configuration node handle pointed to by \a iterator.
3912 * \par Conforming to:
3915 snd_config_t *snd_config_iterator_entry(const snd_config_iterator_t iterator)
3917 return list_entry(iterator, snd_config_t, list);
3921 typedef enum _snd_config_walk_pass {
3922 SND_CONFIG_WALK_PASS_PRE,
3923 SND_CONFIG_WALK_PASS_POST,
3924 SND_CONFIG_WALK_PASS_LEAF,
3925 } snd_config_walk_pass_t;
3928 /* Return 1 if node needs to be attached to parent */
3929 /* Return 2 if compound is replaced with standard node */
3931 typedef int (*snd_config_walk_callback_t)(snd_config_t *src,
3934 snd_config_walk_pass_t pass,
3935 snd_config_t *private_data);
3938 static int snd_config_walk(snd_config_t *src,
3941 snd_config_walk_callback_t callback,
3942 snd_config_t *private_data)
3945 snd_config_iterator_t i, next;
3947 switch (snd_config_get_type(src)) {
3948 case SND_CONFIG_TYPE_COMPOUND:
3949 err = callback(src, root, dst, SND_CONFIG_WALK_PASS_PRE, private_data);
3952 snd_config_for_each(i, next, src) {
3953 snd_config_t *s = snd_config_iterator_entry(i);
3954 snd_config_t *d = NULL;
3956 err = snd_config_walk(s, root, (dst && *dst) ? &d : NULL,
3957 callback, private_data);
3961 err = snd_config_add(*dst, d);
3966 err = callback(src, root, dst, SND_CONFIG_WALK_PASS_POST, private_data);
3970 snd_config_delete(*dst);
3974 err = callback(src, root, dst, SND_CONFIG_WALK_PASS_LEAF, private_data);
3980 static int _snd_config_copy(snd_config_t *src,
3981 snd_config_t *root ATTRIBUTE_UNUSED,
3983 snd_config_walk_pass_t pass,
3984 snd_config_t *private_data ATTRIBUTE_UNUSED)
3987 const char *id = src->id;
3988 snd_config_type_t type = snd_config_get_type(src);
3990 case SND_CONFIG_WALK_PASS_PRE:
3991 err = snd_config_make_compound(dst, id, src->u.compound.join);
3995 case SND_CONFIG_WALK_PASS_LEAF:
3996 err = snd_config_make(dst, id, type);
4000 case SND_CONFIG_TYPE_INTEGER:
4003 err = snd_config_get_integer(src, &v);
4005 snd_config_set_integer(*dst, v);
4008 case SND_CONFIG_TYPE_INTEGER64:
4011 err = snd_config_get_integer64(src, &v);
4013 snd_config_set_integer64(*dst, v);
4016 case SND_CONFIG_TYPE_REAL:
4019 err = snd_config_get_real(src, &v);
4021 snd_config_set_real(*dst, v);
4024 case SND_CONFIG_TYPE_STRING:
4027 err = snd_config_get_string(src, &s);
4029 err = snd_config_set_string(*dst, s);
4045 * \brief Creates a copy of a configuration node.
4046 * \param[out] dst The function puts the handle to the new configuration
4047 * node at the address specified by \a dst.
4048 * \param[in] src Handle to the source configuration node.
4049 * \return A non-negative value if successful, otherwise a negative error code.
4051 * This function creates a deep copy, i.e., if \a src is a compound
4052 * node, all children are copied recursively.
4056 * <dt>-ENOMEM<dd>Out of memory.
4059 * \par Conforming to:
4062 int snd_config_copy(snd_config_t **dst,
4065 return snd_config_walk(src, NULL, dst, _snd_config_copy, NULL);
4068 static int _snd_config_expand(snd_config_t *src,
4069 snd_config_t *root ATTRIBUTE_UNUSED,
4071 snd_config_walk_pass_t pass,
4072 snd_config_t *private_data)
4075 const char *id = src->id;
4076 snd_config_type_t type = snd_config_get_type(src);
4078 case SND_CONFIG_WALK_PASS_PRE:
4080 if (id && strcmp(id, "@args") == 0)
4082 err = snd_config_make_compound(dst, id, src->u.compound.join);
4087 case SND_CONFIG_WALK_PASS_LEAF:
4089 case SND_CONFIG_TYPE_INTEGER:
4092 err = snd_config_get_integer(src, &v);
4094 err = snd_config_imake_integer(dst, id, v);
4099 case SND_CONFIG_TYPE_INTEGER64:
4102 err = snd_config_get_integer64(src, &v);
4104 err = snd_config_imake_integer64(dst, id, v);
4109 case SND_CONFIG_TYPE_REAL:
4112 err = snd_config_get_real(src, &v);
4114 err = snd_config_imake_real(dst, id, v);
4119 case SND_CONFIG_TYPE_STRING:
4123 snd_config_t *vars = private_data;
4124 snd_config_get_string(src, &s);
4125 if (s && *s == '$') {
4127 if (snd_config_search(vars, s, &val) < 0)
4129 err = snd_config_copy(dst, val);
4132 err = snd_config_set_id(*dst, id);
4134 snd_config_delete(*dst);
4138 err = snd_config_imake_string(dst, id, s);
4154 static int _snd_config_evaluate(snd_config_t *src,
4156 snd_config_t **dst ATTRIBUTE_UNUSED,
4157 snd_config_walk_pass_t pass,
4158 snd_config_t *private_data)
4161 if (pass == SND_CONFIG_WALK_PASS_PRE) {
4163 const char *lib = NULL, *func_name = NULL;
4165 int (*func)(snd_config_t **dst, snd_config_t *root,
4166 snd_config_t *src, snd_config_t *private_data) = NULL;
4168 snd_config_t *c, *func_conf = NULL;
4169 err = snd_config_search(src, "@func", &c);
4172 err = snd_config_get_string(c, &str);
4174 SNDERR("Invalid type for @func");
4178 err = snd_config_search_definition(root, "func", str, &func_conf);
4180 snd_config_iterator_t i, next;
4181 if (snd_config_get_type(func_conf) != SND_CONFIG_TYPE_COMPOUND) {
4182 SNDERR("Invalid type for func %s definition", str);
4185 snd_config_for_each(i, next, func_conf) {
4186 snd_config_t *n = snd_config_iterator_entry(i);
4187 const char *id = n->id;
4188 if (strcmp(id, "comment") == 0)
4190 if (strcmp(id, "lib") == 0) {
4191 err = snd_config_get_string(n, &lib);
4193 SNDERR("Invalid type for %s", id);
4198 if (strcmp(id, "func") == 0) {
4199 err = snd_config_get_string(n, &func_name);
4201 SNDERR("Invalid type for %s", id);
4206 SNDERR("Unknown field %s", id);
4210 int len = 9 + strlen(str) + 1;
4216 snprintf(buf, len, "snd_func_%s", str);
4220 h = snd_dlopen(lib, RTLD_NOW);
4222 func = snd_dlsym(h, func_name, SND_DLSYM_VERSION(SND_CONFIG_DLSYM_VERSION_EVALUATE));
4225 SNDERR("Cannot open shared library %s", lib);
4229 SNDERR("symbol %s is not defined inside %s", func_name, lib);
4236 snd_config_delete(func_conf);
4239 err = func(&eval, root, src, private_data);
4241 SNDERR("function %s returned error: %s", func_name, snd_strerror(err));
4243 if (err >= 0 && eval) {
4244 /* substitute merges compound members */
4245 /* we don't want merging at all */
4246 err = snd_config_delete_compound_members(src);
4248 err = snd_config_substitute(src, eval);
4261 * \brief Evaluates a configuration node at runtime.
4262 * \param[in,out] config Handle to the source configuration node.
4263 * \param[in] root Handle to the root of the source configuration.
4264 * \param[in] private_data Handle to the private data node for runtime evaluation.
4265 * \param result Must be \c NULL.
4266 * \return A non-negative value if successful, otherwise a negative error code.
4268 * This function evaluates any functions (\c \@func) in \a config and
4269 * replaces those nodes with the respective function results.
4271 int snd_config_evaluate(snd_config_t *config, snd_config_t *root,
4272 snd_config_t *private_data, snd_config_t **result)
4274 /* FIXME: Only in place evaluation is currently implemented */
4275 assert(result == NULL);
4276 return snd_config_walk(config, root, result, _snd_config_evaluate, private_data);
4279 static int load_defaults(snd_config_t *subs, snd_config_t *defs)
4281 snd_config_iterator_t d, dnext;
4282 snd_config_for_each(d, dnext, defs) {
4283 snd_config_t *def = snd_config_iterator_entry(d);
4284 snd_config_iterator_t f, fnext;
4285 if (snd_config_get_type(def) != SND_CONFIG_TYPE_COMPOUND)
4287 snd_config_for_each(f, fnext, def) {
4288 snd_config_t *fld = snd_config_iterator_entry(f);
4289 const char *id = fld->id;
4290 if (strcmp(id, "type") == 0)
4292 if (strcmp(id, "default") == 0) {
4293 snd_config_t *deflt;
4295 err = snd_config_copy(&deflt, fld);
4298 err = snd_config_set_id(deflt, def->id);
4300 snd_config_delete(deflt);
4303 err = snd_config_add(subs, deflt);
4305 snd_config_delete(deflt);
4310 SNDERR("Unknown field %s", id);
4317 static void skip_blank(const char **ptr)
4334 static int parse_char(const char **ptr)
4337 assert(**ptr == '\\');
4366 if (c < '0' || c > '7')
4368 num = num * 8 + c - '0';
4381 static int parse_id(const char **ptr)
4402 static int parse_string(const char **ptr, char **val)
4404 const size_t bufsize = 256;
4407 size_t alloc = bufsize;
4415 SNDERR("Unterminated string");
4418 c = parse_char(ptr);
4425 *val = malloc(idx + 1);
4428 memcpy(*val, buf, idx);
4430 if (alloc > bufsize)
4436 size_t old_alloc = alloc;
4438 if (old_alloc == bufsize) {
4439 buf = malloc(alloc);
4440 memcpy(buf, _buf, old_alloc);
4442 buf = realloc(buf, alloc);
4452 /* Parse var=val or val */
4453 static int parse_arg(const char **ptr, unsigned int *varlen, char **val)
4459 if (*str == '"' || *str == '\'') {
4460 err = parse_string(ptr, val);
4466 err = parse_id(ptr);
4469 vallen = *ptr - str;
4479 if (*str == '"' || *str == '\'') {
4480 err = parse_string(ptr, val);
4485 err = parse_id(ptr);
4488 vallen = *ptr - str;
4490 *val = malloc(vallen + 1);
4493 memcpy(*val, str, vallen);
4500 * var1=val1,var2=val2,...
4503 static int parse_args(snd_config_t *subs, const char *str, snd_config_t *defs)
4513 int len = strlen(str);
4515 snd_config_iterator_t i, next;
4517 switch (str[--len]) {
4529 if (str[len] != '}')
4531 err = snd_input_buffer_open(&input, str + 1, len - 1);
4534 err = snd_config_load_override(subs, input);
4535 snd_input_close(input);
4538 snd_config_for_each(i, next, subs) {
4539 snd_config_t *n = snd_config_iterator_entry(i);
4541 const char *id = n->id;
4542 err = snd_config_search(defs, id, &d);
4544 SNDERR("Unknown parameter %s", id);
4553 const char *var = buf;
4554 unsigned int varlen;
4555 snd_config_t *def, *sub, *typ;
4556 const char *new = str;
4559 err = parse_arg(&new, &varlen, &val);
4563 assert(varlen < sizeof(buf));
4564 memcpy(buf, str, varlen);
4567 sprintf(buf, "%d", arg);
4569 err = snd_config_search_alias(defs, NULL, var, &def);
4571 SNDERR("Unknown parameter %s", var);
4574 if (snd_config_get_type(def) != SND_CONFIG_TYPE_COMPOUND) {
4575 SNDERR("Parameter %s definition is not correct", var);
4580 err = snd_config_search(subs, var, &sub);
4582 snd_config_delete(sub);
4583 err = snd_config_search(def, "type", &typ);
4586 SNDERR("Parameter %s definition is missing a valid type info", var);
4589 err = snd_config_get_string(typ, &tmp);
4590 if (err < 0 || !tmp)
4592 if (strcmp(tmp, "integer") == 0) {
4594 err = snd_config_make(&sub, var, SND_CONFIG_TYPE_INTEGER);
4597 err = safe_strtol(val, &v);
4599 SNDERR("Parameter %s must be an integer", var);
4602 err = snd_config_set_integer(sub, v);
4605 } else if (strcmp(tmp, "integer64") == 0) {
4607 err = snd_config_make(&sub, var, SND_CONFIG_TYPE_INTEGER64);
4610 err = safe_strtoll(val, &v);
4612 SNDERR("Parameter %s must be an integer", var);
4615 err = snd_config_set_integer64(sub, v);
4618 } else if (strcmp(tmp, "real") == 0) {
4620 err = snd_config_make(&sub, var, SND_CONFIG_TYPE_REAL);
4623 err = safe_strtod(val, &v);
4625 SNDERR("Parameter %s must be a real", var);
4628 err = snd_config_set_real(sub, v);
4631 } else if (strcmp(tmp, "string") == 0) {
4632 err = snd_config_make(&sub, var, SND_CONFIG_TYPE_STRING);
4635 err = snd_config_set_string(sub, val);
4642 err = snd_config_set_id(sub, var);
4645 err = snd_config_add(subs, sub);
4663 * \brief Expands a configuration node, applying arguments and functions.
4664 * \param[in] config Handle to the configuration node.
4665 * \param[in] root Handle to the root configuration node.
4666 * \param[in] args Arguments string, can be \c NULL.
4667 * \param[in] private_data Handle to the private data node for functions.
4668 * \param[out] result The function puts the handle to the result
4669 * configuration node at the address specified by
4671 * \return A non-negative value if successful, otherwise a negative error code.
4673 * If \a config has arguments (defined by a child with id \c \@args),
4674 * this function replaces any string node beginning with $ with the
4675 * respective argument value, or the default argument value, or nothing.
4676 * Furthermore, any functions are evaluated (see #snd_config_evaluate).
4677 * The resulting copy of \a config is returned in \a result.
4679 int snd_config_expand(snd_config_t *config, snd_config_t *root, const char *args,
4680 snd_config_t *private_data, snd_config_t **result)
4683 snd_config_t *defs, *subs = NULL, *res;
4684 err = snd_config_search(config, "@args", &defs);
4687 SNDERR("Unknown parameters %s", args);
4690 err = snd_config_copy(&res, config);
4694 err = snd_config_top(&subs);
4697 err = load_defaults(subs, defs);
4699 SNDERR("Load defaults error: %s", snd_strerror(err));
4702 err = parse_args(subs, args, defs);
4704 SNDERR("Parse arguments error: %s", snd_strerror(err));
4707 err = snd_config_evaluate(subs, root, private_data, NULL);
4709 SNDERR("Args evaluate error: %s", snd_strerror(err));
4712 err = snd_config_walk(config, root, &res, _snd_config_expand, subs);
4714 SNDERR("Expand error (walk): %s", snd_strerror(err));
4718 err = snd_config_evaluate(res, root, private_data, NULL);
4720 SNDERR("Evaluate error: %s", snd_strerror(err));
4721 snd_config_delete(res);
4728 snd_config_delete(subs);
4733 * \brief Searches for a definition in a configuration tree, using
4734 * aliases and expanding hooks and arguments.
4735 * \param[in] config Handle to the configuration (sub)tree to search.
4736 * \param[in] base Implicit key base, or \c NULL for none.
4737 * \param[in] name Key suffix, optionally with arguments.
4738 * \param[out] result The function puts the handle to the expanded found
4739 * node at the address specified by \a result.
4740 * \return A non-negative value if successful, otherwise a negative error code.
4742 * This functions searches for a child node of \a config, allowing
4743 * aliases and expanding hooks, like #snd_config_search_alias_hooks.
4745 * If \a name contains a colon (:), the rest of the string after the
4746 * colon contains arguments that are expanded as with
4747 * #snd_config_expand.
4749 * In any case, \a result is a new node that must be freed by the
4754 * <dt>-ENOENT<dd>An id in \a key or an alias id does not exist.
4755 * <dt>-ENOENT<dd>\a config or one of its child nodes to be searched is
4756 * not a compound node.
4758 * Additionally, any errors encountered when parsing the hook
4759 * definitions or arguments, or returned by (hook) functions.
4761 int snd_config_search_definition(snd_config_t *config,
4762 const char *base, const char *name,
4763 snd_config_t **result)
4767 const char *args = strchr(name, ':');
4771 key = alloca(args - name);
4772 memcpy(key, name, args - name - 1);
4773 key[args - name - 1] = '\0';
4775 key = (char *) name;
4778 * if key contains dot (.), the implicit base is ignored
4779 * and the key starts from root given by the 'config' parameter
4782 err = snd_config_search_alias_hooks(config, strchr(key, '.') ? NULL : base, key, &conf);
4784 snd_config_unlock();
4787 err = snd_config_expand(conf, config, args, NULL, result);
4788 snd_config_unlock();
4793 void snd_config_set_hop(snd_config_t *conf, int hop)
4798 int snd_config_check_hop(snd_config_t *conf)
4801 if (conf->hop >= SND_CONF_MAX_HOPS) {
4802 SYSERR("Too many definition levels (looped?)\n");
4812 /* Not strictly needed, but useful to check for memory leaks */
4813 void _snd_config_end(void) __attribute__ ((destructor));
4815 static void _snd_config_end(void)
4819 snd_config_delete(snd_config);
4821 for (k = 0; k < files_info_count; ++k)
4822 free(files_info[k].name);
4825 files_info_count = 0;