3 * \ingroup Configuration
4 * \brief Configuration helper functions
5 * \author Abramo Bagnara <abramo@alsa-project.org>
6 * \author Jaroslav Kysela <perex@suse.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@suse.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.
421 #include <sys/stat.h>
429 snd_config_type_t type;
437 struct list_head fields;
441 struct list_head list;
442 snd_config_t *father;
448 unsigned int line, column;
449 struct filedesc *next;
452 #define LOCAL_ERROR (-0x68000000)
454 #define LOCAL_UNTERMINATED_STRING (LOCAL_ERROR - 0)
455 #define LOCAL_UNTERMINATED_QUOTE (LOCAL_ERROR - 1)
456 #define LOCAL_UNEXPECTED_CHAR (LOCAL_ERROR - 2)
457 #define LOCAL_UNEXPECTED_EOF (LOCAL_ERROR - 3)
460 struct filedesc *current;
465 static int safe_strtoll(const char *str, long long *val)
472 if (sscanf(str, "%Ld%n", &v, &endidx) < 1)
480 int safe_strtol(const char *str, long *val)
487 v = strtol(str, &end, 0);
496 static int safe_strtod(const char *str, double *val)
503 v = strtod(str, &end);
512 static int get_char(input_t *input)
522 c = snd_input_getc(fd->in);
529 fd->column += 8 - fd->column % 8;
533 snd_input_close(fd->in);
535 input->current = fd->next;
539 return LOCAL_UNEXPECTED_EOF;
544 return (unsigned char)c;
547 static void unget_char(int c, input_t *input)
549 assert(!input->unget);
554 static int get_delimstring(char **string, int delim, input_t *input);
556 static int get_char_skip_comments(input_t *input)
565 int err = get_delimstring(&str, '>', input);
568 if (!strncmp(str, "confdir:", 8)) {
569 char *tmp = malloc(strlen(DATADIR "/alsa") + 1 + strlen(str + 8) + 1);
574 sprintf(tmp, DATADIR "/alsa/%s", str + 8);
578 err = snd_input_stdio_open(&in, str, "r");
583 fd = malloc(sizeof(*fd));
590 fd->next = input->current;
611 static int get_nonwhite(input_t *input)
615 c = get_char_skip_comments(input);
629 static int get_quotedchar(input_t *input)
652 if (c < '0' || c > '7') {
653 unget_char(c, input);
656 num = num * 8 + c - '0';
666 static int get_freestring(char **string, int id, input_t *input)
668 const size_t bufsize = 64;
671 size_t alloc = bufsize;
677 if (c == LOCAL_UNEXPECTED_EOF) {
678 char *s = malloc(idx + 1);
711 char *s = malloc(idx + 1);
714 unget_char(c, input);
726 size_t old_alloc = alloc;
728 if (old_alloc == bufsize) {
732 memcpy(buf, _buf, old_alloc);
734 char *ptr = realloc(buf, alloc);
747 static int get_delimstring(char **string, int delim, input_t *input)
749 const size_t bufsize = 64;
752 size_t alloc = bufsize;
761 c = get_quotedchar(input);
769 char *s = malloc(idx + 1);
781 size_t old_alloc = alloc;
783 if (old_alloc == bufsize) {
787 memcpy(buf, _buf, old_alloc);
789 char *ptr = realloc(buf, alloc);
801 /* Return 0 for free string, 1 for delimited string */
802 static int get_string(char **string, int id, input_t *input)
804 int c = get_nonwhite(input), err;
816 return LOCAL_UNEXPECTED_CHAR;
819 err = get_delimstring(string, c, input);
824 unget_char(c, input);
825 err = get_freestring(string, id, input);
832 static int _snd_config_make(snd_config_t **config, char **id, snd_config_type_t type)
836 n = calloc(1, sizeof(*n));
849 if (type == SND_CONFIG_TYPE_COMPOUND)
850 INIT_LIST_HEAD(&n->u.compound.fields);
856 static int _snd_config_make_add(snd_config_t **config, char **id,
857 snd_config_type_t type, snd_config_t *father)
861 assert(father->type == SND_CONFIG_TYPE_COMPOUND);
862 err = _snd_config_make(&n, id, type);
866 list_add_tail(&n->list, &father->u.compound.fields);
871 static int _snd_config_search(snd_config_t *config,
872 const char *id, int len, snd_config_t **result)
874 snd_config_iterator_t i, next;
875 snd_config_for_each(i, next, config) {
876 snd_config_t *n = snd_config_iterator_entry(i);
878 if (strcmp(n->id, id) != 0)
880 } else if (strlen(n->id) != (size_t) len ||
881 memcmp(n->id, id, (size_t) len) != 0)
890 static int parse_value(snd_config_t **_n, snd_config_t *father, input_t *input, char **id, int skip)
892 snd_config_t *n = *_n;
896 err = get_string(&s, 0, input);
903 if (err == 0 && ((s[0] >= '0' && s[0] <= '9') || s[0] == '-')) {
906 err = safe_strtoll(s, &i);
909 err = safe_strtod(s, &r);
913 if (n->type != SND_CONFIG_TYPE_REAL) {
914 SNDERR("%s is not a real", *id);
918 err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_REAL, father);
929 if (n->type != SND_CONFIG_TYPE_INTEGER && n->type != SND_CONFIG_TYPE_INTEGER64) {
930 SNDERR("%s is not an integer", *id);
935 err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_INTEGER, father);
937 err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_INTEGER64, father);
941 if (n->type == SND_CONFIG_TYPE_INTEGER)
942 n->u.integer = (long) i;
950 if (n->type != SND_CONFIG_TYPE_STRING) {
951 SNDERR("%s is not a string", *id);
956 err = _snd_config_make_add(&n, id, SND_CONFIG_TYPE_STRING, father);
967 static int parse_defs(snd_config_t *father, input_t *input, int skip, int override);
968 static int parse_array_defs(snd_config_t *farther, input_t *input, int skip, int override);
970 static int parse_array_def(snd_config_t *father, input_t *input, int idx, int skip, int override)
972 char static_id[12], *id = NULL;
975 snd_config_t *n = NULL;
978 snprintf(static_id, sizeof(static_id), "%i", idx);
979 static_id[sizeof(static_id)-1] = '\0';
980 id = strdup(static_id);
984 c = get_nonwhite(input);
996 if (n->type != SND_CONFIG_TYPE_COMPOUND) {
997 SNDERR("%s is not a compound", id);
1002 err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, father);
1008 err = parse_defs(n, input, skip, override);
1011 err = parse_array_defs(n, input, skip, override);
1014 c = get_nonwhite(input);
1021 snd_config_delete(n);
1022 err = LOCAL_UNEXPECTED_CHAR;
1028 unget_char(c, input);
1029 err = parse_value(&n, father, input, &id, skip);
1041 static int parse_array_defs(snd_config_t *father, input_t *input, int skip, int override)
1045 int c = get_nonwhite(input), err;
1048 unget_char(c, input);
1051 err = parse_array_def(father, input, idx++, skip, override);
1058 static int parse_def(snd_config_t *father, input_t *input, int skip, int override)
1064 enum {MERGE_CREATE, MERGE, OVERRIDE, DONT_OVERRIDE} mode;
1066 c = get_nonwhite(input);
1071 mode = MERGE_CREATE;
1077 mode = DONT_OVERRIDE;
1083 mode = !override ? MERGE_CREATE : OVERRIDE;
1084 unget_char(c, input);
1086 err = get_string(&id, 1, input);
1089 c = get_nonwhite(input);
1096 if (_snd_config_search(father, id, -1, &n) == 0) {
1097 if (mode == DONT_OVERRIDE) {
1102 if (mode != OVERRIDE) {
1103 if (n->type != SND_CONFIG_TYPE_COMPOUND) {
1104 SNDERR("%s is not a compound", id);
1107 n->u.compound.join = 1;
1112 snd_config_delete(n);
1114 if (mode == MERGE) {
1115 SNDERR("%s does not exists", id);
1119 err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, father);
1122 n->u.compound.join = 1;
1126 c = get_nonwhite(input);
1131 if (_snd_config_search(father, id, -1, &n) == 0) {
1132 if (mode == DONT_OVERRIDE) {
1135 } else if (mode == OVERRIDE) {
1136 snd_config_delete(n);
1141 if (mode == MERGE) {
1142 SNDERR("%s does not exists", id);
1155 if (n->type != SND_CONFIG_TYPE_COMPOUND) {
1156 SNDERR("%s is not a compound", id);
1161 err = _snd_config_make_add(&n, &id, SND_CONFIG_TYPE_COMPOUND, father);
1167 err = parse_defs(n, input, skip, override);
1170 err = parse_array_defs(n, input, skip, override);
1173 c = get_nonwhite(input);
1176 snd_config_delete(n);
1177 err = LOCAL_UNEXPECTED_CHAR;
1183 unget_char(c, input);
1184 err = parse_value(&n, father, input, &id, skip);
1189 c = get_nonwhite(input);
1195 unget_char(c, input);
1203 static int parse_defs(snd_config_t *father, input_t *input, int skip, int override)
1207 c = get_nonwhite(input);
1209 return c == LOCAL_UNEXPECTED_EOF ? 0 : c;
1210 unget_char(c, input);
1213 err = parse_def(father, input, skip, override);
1220 static void string_print(char *str, int id, snd_output_t *out)
1222 unsigned char *p = str;
1234 snd_output_puts(out, "''");
1258 snd_output_puts(out, str);
1261 snd_output_putc(out, '\'');
1268 snd_output_putc(out, '\\');
1269 snd_output_putc(out, 'n');
1272 snd_output_putc(out, '\\');
1273 snd_output_putc(out, 't');
1276 snd_output_putc(out, '\\');
1277 snd_output_putc(out, 'v');
1280 snd_output_putc(out, '\\');
1281 snd_output_putc(out, 'b');
1284 snd_output_putc(out, '\\');
1285 snd_output_putc(out, 'r');
1288 snd_output_putc(out, '\\');
1289 snd_output_putc(out, 'f');
1292 snd_output_putc(out, '\\');
1293 snd_output_putc(out, c);
1295 case 32 ... '\'' - 1:
1296 case '\'' + 1 ... 126:
1297 snd_output_putc(out, c);
1300 snd_output_printf(out, "\\%04o", c);
1305 snd_output_putc(out, '\'');
1308 static int _snd_config_save_leaves(snd_config_t *config, snd_output_t *out, unsigned int level, unsigned int joins);
1310 static int _snd_config_save_leaf(snd_config_t *n, snd_output_t *out,
1316 case SND_CONFIG_TYPE_INTEGER:
1317 snd_output_printf(out, "%ld", n->u.integer);
1319 case SND_CONFIG_TYPE_INTEGER64:
1320 snd_output_printf(out, "%Ld", n->u.integer64);
1322 case SND_CONFIG_TYPE_REAL:
1323 snd_output_printf(out, "%-16g", n->u.real);
1325 case SND_CONFIG_TYPE_STRING:
1326 string_print(n->u.string, 0, out);
1328 case SND_CONFIG_TYPE_POINTER:
1329 SNDERR("cannot save runtime pointer type");
1331 case SND_CONFIG_TYPE_COMPOUND:
1332 snd_output_putc(out, '{');
1333 snd_output_putc(out, '\n');
1334 err = _snd_config_save_leaves(n, out, level + 1, 0);
1337 for (k = 0; k < level; ++k) {
1338 snd_output_putc(out, '\t');
1340 snd_output_putc(out, '}');
1346 static void id_print(snd_config_t *n, snd_output_t *out, unsigned int joins)
1350 id_print(n->father, out, joins - 1);
1351 snd_output_putc(out, '.');
1353 string_print(n->id, 1, out);
1356 static int _snd_config_save_leaves(snd_config_t *config, snd_output_t *out, unsigned int level, unsigned int joins)
1360 snd_config_iterator_t i, next;
1361 assert(config && out);
1362 snd_config_for_each(i, next, config) {
1363 snd_config_t *n = snd_config_iterator_entry(i);
1364 if (n->type == SND_CONFIG_TYPE_COMPOUND &&
1365 n->u.compound.join) {
1366 err = _snd_config_save_leaves(n, out, level, joins + 1);
1371 for (k = 0; k < level; ++k) {
1372 snd_output_putc(out, '\t');
1374 id_print(n, out, joins);
1376 snd_output_putc(out, ' ');
1377 snd_output_putc(out, '=');
1379 snd_output_putc(out, ' ');
1380 err = _snd_config_save_leaf(n, out, level);
1384 snd_output_putc(out, ';');
1386 snd_output_putc(out, '\n');
1394 * \brief Substitutes one configuration node to another.
1395 * \param dst Handle to the destination node.
1396 * \param src Handle to the source node. Must not be the same as \p dst.
1397 * \return Zero if successful, otherwise a negative error code.
1399 * If both nodes are compounds, the source compound node members are
1400 * appended to the destination compound node.
1402 * If the destination node is a compound and the source node is
1403 * an ordinary type, the compound members are deleted (including
1406 * A successful call to this function invalidates the source node.
1408 int snd_config_substitute(snd_config_t *dst, snd_config_t *src)
1411 if (dst->type == SND_CONFIG_TYPE_COMPOUND &&
1412 src->type == SND_CONFIG_TYPE_COMPOUND) { /* append */
1413 snd_config_iterator_t i, next;
1414 snd_config_for_each(i, next, src) {
1415 snd_config_t *n = snd_config_iterator_entry(i);
1418 src->u.compound.fields.next->prev = &dst->u.compound.fields;
1419 src->u.compound.fields.prev->next = &dst->u.compound.fields;
1420 } else if (dst->type == SND_CONFIG_TYPE_COMPOUND) {
1422 err = snd_config_delete_compound_members(dst);
1429 dst->type = src->type;
1436 * \brief Converts an ASCII string to a configuration node type.
1437 * \param ascii A string containing a configuration node type.
1438 * \param type The function puts the node type at the address specified
1440 * \return Zero if successgul, otherwise a negative error code.
1442 int snd_config_get_type_ascii(const char *ascii, snd_config_type_t *type)
1444 assert(ascii && type);
1445 if (!strcmp(ascii, "integer")) {
1446 *type = SND_CONFIG_TYPE_INTEGER;
1449 if (!strcmp(ascii, "integer64")) {
1450 *type = SND_CONFIG_TYPE_INTEGER64;
1453 if (!strcmp(ascii, "real")) {
1454 *type = SND_CONFIG_TYPE_REAL;
1457 if (!strcmp(ascii, "string")) {
1458 *type = SND_CONFIG_TYPE_STRING;
1461 if (!strcmp(ascii, "compound")) {
1462 *type = SND_CONFIG_TYPE_COMPOUND;
1469 * \brief Returns the type of a configuration node.
1470 * \param config Handle to the configuration node.
1471 * \return The node's type.
1473 snd_config_type_t snd_config_get_type(const snd_config_t *config)
1475 return config->type;
1479 * \brief Returns the id of a configuration node.
1480 * \param config Handle to the configuration node.
1481 * \param id The function puts the pointer to the id string at the address
1482 * specified by \p id.
1483 * \return Zero if successful, otherwise a negative error code.
1485 * The returned string is owned by the configuration node; the application
1486 * must not modify or delete it.
1488 int snd_config_get_id(const snd_config_t *config, const char **id)
1490 assert(config && id);
1496 * \brief Sets the id of a configuration node.
1497 * \param config Handle to the configuration node.
1498 * \param id The new node id.
1499 * \return Zero if successful, otherwise a negative error code.
1501 int snd_config_set_id(snd_config_t *config, const char *id)
1504 assert(config && id);
1505 new_id = strdup(id);
1510 config->id = new_id;
1515 * \brief Creates a top level configuration node.
1516 * \param config The function puts the handle to the new node at the address
1517 * specified by \p config.
1518 * \return Zero if successful, otherwise a negative error code.
1520 * The returned node is a compound node.
1522 int snd_config_top(snd_config_t **config)
1525 return _snd_config_make(config, 0, SND_CONFIG_TYPE_COMPOUND);
1528 static int snd_config_load1(snd_config_t *config, snd_input_t *in, int override)
1532 struct filedesc *fd, *fd_next;
1533 assert(config && in);
1534 fd = malloc(sizeof(*fd));
1544 err = parse_defs(config, &input, 0, override);
1549 case LOCAL_UNTERMINATED_STRING:
1550 str = "Unterminated string";
1552 case LOCAL_UNTERMINATED_QUOTE:
1553 str = "Unterminated quote";
1555 case LOCAL_UNEXPECTED_CHAR:
1556 str = "Unexpected char";
1558 case LOCAL_UNEXPECTED_EOF:
1559 str = "Unexpected end of file";
1562 str = strerror(-err);
1565 SNDERR("%s:%d:%d:%s", fd->name ? fd->name : "_toplevel_", fd->line, fd->column, str);
1568 if (get_char(&input) != LOCAL_UNEXPECTED_EOF) {
1569 SNDERR("%s:%d:%d:Unexpected }", fd->name ? fd->name : "", fd->line, fd->column);
1576 snd_input_close(fd->in);
1586 * \brief Loads a configuration tree.
1587 * \param config Handle to a top level configuration node.
1588 * \param in Input handle to read the configuration from.
1589 * \return Zero if successful, otherwise a negative error code.
1591 int snd_config_load(snd_config_t *config, snd_input_t *in)
1593 return snd_config_load1(config, in, 0);
1597 * \brief Loads a configuration tree and overrides existing configuration nodes.
1598 * \param config Handle to a top level configuration node.
1599 * \param in Input handle to read the configuration from.
1600 * \return Zero if successful, otherwise a negative error code.
1602 int snd_config_load_override(snd_config_t *config, snd_input_t *in)
1604 return snd_config_load1(config, in, 1);
1608 * \brief Adds a child to a compound configuration node.
1609 * \param father Handle to the compound configuration node.
1610 * \param leaf Handle to the configuration node to be added to \p father.
1611 * \return Zero if successful, otherwise a negative error code.
1613 int snd_config_add(snd_config_t *father, snd_config_t *leaf)
1615 snd_config_iterator_t i, next;
1616 assert(father && leaf);
1617 snd_config_for_each(i, next, father) {
1618 snd_config_t *n = snd_config_iterator_entry(i);
1619 if (strcmp(leaf->id, n->id) == 0)
1622 leaf->father = father;
1623 list_add_tail(&leaf->list, &father->u.compound.fields);
1628 * \brief Removes a configuration node from its tree.
1629 * \param config Handle to the configuration node to be removed.
1630 * \return Zero if successful, otherwise a negative error code.
1632 * This functions does \e not delete the removed node.
1634 int snd_config_remove(snd_config_t *config)
1638 list_del(&config->list);
1639 config->father = NULL;
1644 * \brief Deletes a configuration node (freeing all its related resources).
1645 * \param config Handle to the configuration node to be deleted.
1646 * \return Zero if successful, otherwise a negative error code.
1648 * If the node is a child node, it is removed from the tree before being
1649 * deleted. If the node is a compound node, all children are deleted
1652 int snd_config_delete(snd_config_t *config)
1655 switch (config->type) {
1656 case SND_CONFIG_TYPE_COMPOUND:
1659 struct list_head *i;
1660 i = config->u.compound.fields.next;
1661 while (i != &config->u.compound.fields) {
1662 struct list_head *nexti = i->next;
1663 snd_config_t *leaf = snd_config_iterator_entry(i);
1664 err = snd_config_delete(leaf);
1671 case SND_CONFIG_TYPE_STRING:
1672 if (config->u.string)
1673 free(config->u.string);
1679 list_del(&config->list);
1687 * \brief Deletes the children of a compound configuration node (freeing all its related resources)
1688 * \param config Handle to the compound configuration node.
1689 * \return Zero if successful, otherwise a negative error code.
1691 * Any compound nodes among the children of \p config are deleted recursively.
1693 int snd_config_delete_compound_members(const snd_config_t *config)
1696 struct list_head *i;
1699 if (config->type != SND_CONFIG_TYPE_COMPOUND)
1701 i = config->u.compound.fields.next;
1702 while (i != &config->u.compound.fields) {
1703 struct list_head *nexti = i->next;
1704 snd_config_t *leaf = snd_config_iterator_entry(i);
1705 err = snd_config_delete(leaf);
1714 * \brief Creates a configuration node.
1715 * \param config The function puts the handle to the new node at the address
1716 * specified by \p config.
1717 * \param id The id of the new node.
1718 * \param type The type of the new node.
1719 * \return Zero if successful, otherwise a negative error code.
1721 int snd_config_make(snd_config_t **config, const char *id,
1722 snd_config_type_t type)
1732 return _snd_config_make(config, &id1, type);
1736 * \brief Creates an integer configuration node.
1737 * \param config The function puts the handle to the new node at the address
1738 * specified by \p config.
1739 * \param id The id of the new node.
1740 * \return Zero if successful, otherwise a negative error code.
1742 * The value of the new node is 0.
1744 int snd_config_make_integer(snd_config_t **config, const char *id)
1746 return snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER);
1750 * \brief Creates an integer64 configuration node.
1751 * \param config The function puts the handle to the new node at the address
1752 * specified by \p config.
1753 * \param id The id of the new node.
1754 * \return Zero if successful, otherwise a negative error code.
1756 * The value of the new node is 0.
1758 int snd_config_make_integer64(snd_config_t **config, const char *id)
1760 return snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER64);
1764 * \brief Creates a real configuration node.
1765 * \param config The function puts the handle to the new node at the address
1766 * specified by \p config.
1767 * \param id The id of the new node.
1768 * \return Zero if successful, otherwise a negative error code.
1770 * The value of the new node is 0.0.
1772 int snd_config_make_real(snd_config_t **config, const char *id)
1774 return snd_config_make(config, id, SND_CONFIG_TYPE_REAL);
1778 * \brief Creates a string configuration node.
1779 * \param config The function puts the handle to the new node at the address
1780 * specified by \p config.
1781 * \param id The id of the new node.
1782 * \return Zero if successful, otherwise a negative error code.
1784 * The value of the new node is \c NULL.
1786 int snd_config_make_string(snd_config_t **config, const char *id)
1788 return snd_config_make(config, id, SND_CONFIG_TYPE_STRING);
1792 * \brief Creates a pointer configuration node.
1793 * \param config The function puts the handle to the new node at the address
1794 * specified by \p config.
1795 * \param id The id of the new node.
1796 * \return Zero if successful, otherwise a negative error code.
1798 * The value of the new node is \c NULL.
1800 int snd_config_make_pointer(snd_config_t **config, const char *id)
1802 return snd_config_make(config, id, SND_CONFIG_TYPE_POINTER);
1806 * \brief Creates an empty compound configuration node.
1807 * \param config The function puts the handle to the new node at the address
1808 * specified by \p config.
1809 * \param id The id of the new node.
1810 * \param join Join flag.
1811 * This is checked in #snd_config_save to change look. (Huh?)
1812 * \return Zero if successful, otherwise a negative error code.
1814 int snd_config_make_compound(snd_config_t **config, const char *id,
1818 err = snd_config_make(config, id, SND_CONFIG_TYPE_COMPOUND);
1821 (*config)->u.compound.join = join;
1826 * \brief Creates an integer configuration node with the given initial value.
1827 * \param config The function puts the handle to the new node at the address
1828 * specified by \p config.
1829 * \param id The id of the new node.
1830 * \param value The initial value of the new node.
1831 * \return Zero if successful, otherwise a negative error code.
1833 int snd_config_imake_integer(snd_config_t **config, const char *id, const long value)
1837 err = snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER);
1840 (*config)->u.integer = value;
1845 * \brief Creates an integer configuration node with the given initial value.
1846 * \param config The function puts the handle to the new node at the address
1847 * specified by \p config.
1848 * \param id The id of the new node.
1849 * \param value The initial value of the new node.
1850 * \return Zero if successful, otherwise a negative error code.
1852 int snd_config_imake_integer64(snd_config_t **config, const char *id, const long long value)
1856 err = snd_config_make(config, id, SND_CONFIG_TYPE_INTEGER64);
1859 (*config)->u.integer64 = value;
1864 * \brief Creates a real configuration node with the given initial value.
1865 * \param config The function puts the handle to the new node at the address
1866 * specified by \p config.
1867 * \param id The id of the new node.
1868 * \param value The initial value of the new node.
1869 * \return Zero if successful, otherwise a negative error code.
1871 int snd_config_imake_real(snd_config_t **config, const char *id, const double value)
1875 err = snd_config_make(config, id, SND_CONFIG_TYPE_REAL);
1878 (*config)->u.real = value;
1883 * \brief Creates a string configuration node with the given initial value.
1884 * \param config The function puts the handle to the new node at the address
1885 * specified by \p config.
1886 * \param id The id of the new node.
1887 * \param value The initial value of the new node. May be \c NULL.
1888 * \return Zero if successful, otherwise a negative error code.
1890 * This function creates the new node with its own copy of the passed string.
1892 int snd_config_imake_string(snd_config_t **config, const char *id, const char *value)
1897 err = snd_config_make(&tmp, id, SND_CONFIG_TYPE_STRING);
1901 tmp->u.string = strdup(value);
1902 if (!tmp->u.string) {
1903 snd_config_delete(tmp);
1907 tmp->u.string = NULL;
1914 * \brief Creates a pointer configuration node with the given initial value.
1915 * \param config The function puts the handle to the new node at the address
1916 * specified by \p config.
1917 * \param id The id of the new node.
1918 * \param value The initial value of the new node. May be \c NULL.
1919 * \return Zero if successful, otherwise a negative error code.
1921 int snd_config_imake_pointer(snd_config_t **config, const char *id, const void *value)
1925 err = snd_config_make(config, id, SND_CONFIG_TYPE_POINTER);
1928 (*config)->u.ptr = value;
1933 * \brief Changes the value of an integer configuration node.
1934 * \param config Handle to the configuration node.
1935 * \param value The new value for the node.
1936 * \return Zero if successful, otherwise a negative error code.
1938 int snd_config_set_integer(snd_config_t *config, long value)
1941 if (config->type != SND_CONFIG_TYPE_INTEGER)
1943 config->u.integer = value;
1948 * \brief Changes the value of an integer64 configuration node.
1949 * \param config Handle to the configuration node.
1950 * \param value The new value for the node.
1951 * \return Zero if successful, otherwise a negative error code.
1953 int snd_config_set_integer64(snd_config_t *config, long long value)
1956 if (config->type != SND_CONFIG_TYPE_INTEGER64)
1958 config->u.integer64 = value;
1963 * \brief Changes the value of a real configuration node.
1964 * \param config Handle to the configuration node.
1965 * \param value The new value for the node.
1966 * \return Zero if successful, otherwise a negative error code.
1968 int snd_config_set_real(snd_config_t *config, double value)
1971 if (config->type != SND_CONFIG_TYPE_REAL)
1973 config->u.real = value;
1978 * \brief Changes the value of a string configuration node.
1979 * \param config Handle to the configuration node.
1980 * \param value The new value for the node. May be \c NULL.
1981 * \return Zero if successful, otherwise a negative error code.
1983 * This function deletes the old string in the node and stores a copy of
1984 * the passed string in the node.
1986 int snd_config_set_string(snd_config_t *config, const char *value)
1990 if (config->type != SND_CONFIG_TYPE_STRING)
1993 new_string = strdup(value);
1999 if (config->u.string)
2000 free(config->u.string);
2001 config->u.string = new_string;
2006 * \brief Changes the value of a pointer configuration node.
2007 * \param config Handle to the configuration node.
2008 * \param value The new value for the node. May be \c NULL.
2009 * \return Zero if successful, otherwise a negative error code.
2011 * This function does not free the old pointer in the node.
2013 int snd_config_set_pointer(snd_config_t *config, const void *value)
2016 if (config->type != SND_CONFIG_TYPE_POINTER)
2018 config->u.ptr = value;
2023 * \brief Changes the value of a configuration node.
2024 * \param config Handle to the configuration node.
2025 * \param ascii The new value for the node as an ASCII string. \p ascii must
2026 * not be \c NULL, not even for a string node.
2027 * \return Zero if successful, otherwise a negative error code.
2029 * The node must have a simple type, and the new value must have the same type.
2031 int snd_config_set_ascii(snd_config_t *config, const char *ascii)
2033 assert(config && ascii);
2034 switch (config->type) {
2035 case SND_CONFIG_TYPE_INTEGER:
2038 int err = safe_strtol(ascii, &i);
2041 config->u.integer = i;
2044 case SND_CONFIG_TYPE_INTEGER64:
2047 int err = safe_strtoll(ascii, &i);
2050 config->u.integer64 = i;
2053 case SND_CONFIG_TYPE_REAL:
2056 int err = safe_strtod(ascii, &d);
2062 case SND_CONFIG_TYPE_STRING:
2064 char *ptr = strdup(ascii);
2067 if (config->u.string)
2068 free(config->u.string);
2069 config->u.string = ptr;
2079 * \brief Returns the value of an integer configuration node.
2080 * \param config Handle to the configuration node.
2081 * \param ptr The function puts the node's value at the address specified
2083 * \return Zero if successful, otherwise a negative error code.
2085 int snd_config_get_integer(const snd_config_t *config, long *ptr)
2087 assert(config && ptr);
2088 if (config->type != SND_CONFIG_TYPE_INTEGER)
2090 *ptr = config->u.integer;
2095 * \brief Returns the value of an integer64 configuration node.
2096 * \param config Handle to the configuration node.
2097 * \param ptr The function puts the node's value at the address specified
2099 * \return Zero if successful, otherwise a negative error code.
2101 int snd_config_get_integer64(const snd_config_t *config, long long *ptr)
2103 assert(config && ptr);
2104 if (config->type != SND_CONFIG_TYPE_INTEGER64)
2106 *ptr = config->u.integer64;
2111 * \brief Returns the value of a real configuration node.
2112 * \param config Handle to the configuration node.
2113 * \param ptr The function puts the node's value at the address specified
2115 * \return Zero if successful, otherwise a negative error code.
2117 int snd_config_get_real(const snd_config_t *config, double *ptr)
2119 assert(config && ptr);
2120 if (config->type != SND_CONFIG_TYPE_REAL)
2122 *ptr = config->u.real;
2127 * \brief Returns the value of a real or integer configuration node.
2128 * \param config Handle to the configuration node.
2129 * \param ptr The function puts the node's value at the address specified
2131 * \return Zero if successful, otherwise a negative error code.
2133 * If the node's type is integer or integer64, the value is converted
2134 * to the \c double type on the fly.
2136 int snd_config_get_ireal(const snd_config_t *config, double *ptr)
2138 assert(config && ptr);
2139 if (config->type == SND_CONFIG_TYPE_REAL)
2140 *ptr = config->u.real;
2141 else if (config->type == SND_CONFIG_TYPE_INTEGER)
2142 *ptr = config->u.integer;
2143 else if (config->type == SND_CONFIG_TYPE_INTEGER64)
2144 *ptr = config->u.integer64;
2151 * \brief Returns the value of a string configuration node.
2152 * \param config Handle to the configuration node.
2153 * \param ptr The function puts the node's value at the address specified
2155 * \return Zero if successful, otherwise a negative error code.
2157 * The returned string is owned by the configuration node; the application
2158 * must not modify or delete it.
2160 int snd_config_get_string(const snd_config_t *config, const char **ptr)
2162 assert(config && ptr);
2163 if (config->type != SND_CONFIG_TYPE_STRING)
2165 *ptr = config->u.string;
2170 * \brief Returns the value of a pointer configuration node.
2171 * \param config Handle to the configuration node.
2172 * \param ptr The function puts the node's value at the address specified
2174 * \return Zero if successful, otherwise a negative error code.
2176 int snd_config_get_pointer(const snd_config_t *config, const void **ptr)
2178 assert(config && ptr);
2179 if (config->type != SND_CONFIG_TYPE_POINTER)
2181 *ptr = config->u.ptr;
2186 * \brief Returns the value of a configuration node as a string.
2187 * \param config Handle to the configuration node.
2188 * \param ascii The function puts the pointer to the returned string at the
2189 * address specified by \p ascii.
2190 * \return Zero if successful, otherwise a negative error code.
2192 * This function dynamically allocates the returned string. The application
2193 * is responsible for deleting it with \c free() when it is no longer used.
2195 int snd_config_get_ascii(const snd_config_t *config, char **ascii)
2197 assert(config && ascii);
2198 switch (config->type) {
2199 case SND_CONFIG_TYPE_INTEGER:
2203 err = snprintf(res, sizeof(res), "%li", config->u.integer);
2204 if (err < 0 || err == sizeof(res)) {
2208 *ascii = strdup(res);
2211 case SND_CONFIG_TYPE_INTEGER64:
2215 err = snprintf(res, sizeof(res), "%Li", config->u.integer64);
2216 if (err < 0 || err == sizeof(res)) {
2220 *ascii = strdup(res);
2223 case SND_CONFIG_TYPE_REAL:
2227 err = snprintf(res, sizeof(res), "%-16g", config->u.real);
2228 if (err < 0 || err == sizeof(res)) {
2232 if (res[0]) { /* trim the string */
2234 ptr = res + strlen(res) - 1;
2235 while (ptr != res && *ptr == ' ')
2241 *ascii = strdup(res);
2244 case SND_CONFIG_TYPE_STRING:
2245 if (config->u.string)
2246 *ascii = strdup(config->u.string);
2261 * \brief Compares the id of a configuration node to a given string.
2262 * \param config Handle to the configuration node.
2263 * \param id ASCII id.
2264 * \return The same value as the result of the \c strcmp function.
2266 int snd_config_test_id(const snd_config_t *config, const char *id)
2268 assert(config && id);
2269 return strcmp(config->id, id);
2273 * \brief Dumps the contents of a configuration node or tree.
2274 * \param config Handle to the (root) configuration node.
2275 * \param out Output handle.
2276 * \return Zero if successful, otherwise a negative error code.
2278 int snd_config_save(snd_config_t *config, snd_output_t *out)
2280 assert(config && out);
2281 if (config->type == SND_CONFIG_TYPE_COMPOUND)
2282 return _snd_config_save_leaves(config, out, 0, 0);
2284 return _snd_config_save_leaf(config, out, 0);
2288 * *** search macros ***
2293 #define SND_CONFIG_SEARCH(config, key, result, extra_code) \
2298 assert(config && key); \
2300 if (config->type != SND_CONFIG_TYPE_COMPOUND) \
2303 p = strchr(key, '.'); \
2305 err = _snd_config_search(config, key, p - key, &n); \
2311 return _snd_config_search(config, key, -1, result); \
2315 #define SND_CONFIG_SEARCHA(root, config, key, result, fcn, extra_code) \
2320 assert(config && key); \
2322 if (config->type != SND_CONFIG_TYPE_COMPOUND) { \
2323 if (snd_config_get_string(config, &p) < 0) \
2325 err = fcn(root, root, p, &config); \
2330 p = strchr(key, '.'); \
2332 err = _snd_config_search(config, key, p - key, &n); \
2338 return _snd_config_search(config, key, -1, result); \
2342 #define SND_CONFIG_SEARCHV(config, result, fcn) \
2347 va_start(arg, result); \
2349 const char *k = va_arg(arg, const char *); \
2353 err = fcn(config, k, &n); \
2364 #define SND_CONFIG_SEARCHVA(root, config, result, fcn) \
2369 va_start(arg, result); \
2371 const char *k = va_arg(arg, const char *); \
2375 err = fcn(root, config, k, &n); \
2386 #define SND_CONFIG_SEARCH_ALIAS(config, base, key, result, fcn1, fcn2) \
2388 snd_config_t *res = NULL; \
2389 int err, first = 1; \
2390 assert(config && key); \
2392 err = first && base ? -EIO : fcn1(config, config, key, &res); \
2396 err = fcn2(config, config, &res, base, key, NULL); \
2401 } while (snd_config_get_string(res, &key) >= 0); \
2409 #endif /* DOC_HIDDEN */
2412 * \brief Searches for a node in a configuration tree.
2413 * \param config Handle to the root of the configuration (sub)tree to search.
2414 * \param key Search key: one or more node keys, separated with dots.
2415 * \param result The function puts the handle to the node found at the address
2416 * specified by \p result.
2417 * \return Zero if successful, otherwise a negative error code.
2419 int snd_config_search(snd_config_t *config, const char *key, snd_config_t **result)
2421 SND_CONFIG_SEARCH(config, key, result, );
2425 * \brief Searches for a node in a configuration tree, expanding aliases.
2426 * \param root Handle to the root configuration node containing alias
2428 * \param config Handle to the root of the configuration (sub)tree to search.
2429 * \param key Search key: one or more node keys, separated with dots.
2430 * \param result The function puts the handle to the node found at the address
2431 * specified by \p result.
2432 * \return Zero if successful, otherwise a negative error code.
2434 int snd_config_searcha(snd_config_t *root, snd_config_t *config, const char *key, snd_config_t **result)
2436 SND_CONFIG_SEARCHA(root, config, key, result, snd_config_searcha, );
2440 * \brief Searches for a node in a configuration tree.
2441 * \param config Handle to the root of the configuration (sub)tree to search.
2442 * \param result The function puts the handle to the node found at the address
2443 * specified by \p result.
2444 * \param ... One or more concatenated dot separated search keys, terminated with \c NULL.
2445 * \return Zero if successful, otherwise a negative error code.
2447 int snd_config_searchv(snd_config_t *config, snd_config_t **result, ...)
2449 SND_CONFIG_SEARCHV(config, result, snd_config_search);
2453 * \brief Searches for a node in a configuration tree, expanding aliases.
2454 * \param root Handle to the root configuration node containing alias
2456 * \param config Handle to the root of the configuration (sub)tree to search.
2457 * \param result The function puts the handle to the node found at the address
2458 * specified by \p result.
2459 * \param ... One or more concatenated dot separated search keys, terminated with \c NULL.
2460 * \return Zero if successful, otherwise a negative error code.
2462 int snd_config_searchva(snd_config_t *root, snd_config_t *config, snd_config_t **result, ...)
2464 SND_CONFIG_SEARCHVA(root, config, result, snd_config_searcha);
2468 * \brief Searches for a node in a configuration tree, using an alias.
2469 * \param config Handle to the root of the configuration (sub)tree to search.
2470 * \param base Search key base, or \c NULL.
2471 * \param key Search key suffix.
2472 * \param result The function puts the handle to the node found at the address
2473 * specified by \p result.
2474 * \return Zero if successful, otherwise a negative error code.
2476 * First \c key is tried, then, if nothing is found, \c base.key is tried.
2477 * If the value found is a string, this is recursively tried in the
2480 int snd_config_search_alias(snd_config_t *config,
2481 const char *base, const char *key,
2482 snd_config_t **result)
2484 SND_CONFIG_SEARCH_ALIAS(config, base, key, result,
2485 snd_config_searcha, snd_config_searchva);
2489 * \brief Searches for a node in a configuration tree and expands hooks.
2490 * \param config Handle to the root of the configuration (sub)tree to search.
2491 * \param key Search key: one or more node keys, separated with dots.
2492 * \param result The function puts the handle to the node found at the address
2493 * specified by \p result.
2494 * \return Zero if successful, otherwise a negative error code.
2496 int snd_config_search_hooks(snd_config_t *config, const char *key, snd_config_t **result)
2498 static int snd_config_hooks(snd_config_t *config, snd_config_t *private_data);
2499 SND_CONFIG_SEARCH(config, key, result, \
2500 err = snd_config_hooks(config, NULL); \
2507 * \brief Searches for a node in a configuration tree, expanding aliases and hooks.
2508 * \param root Handle to the root configuration node containing alias
2510 * \param config Handle to the root of the configuration (sub)tree to search.
2511 * \param key Search key: one or more node keys, separated with dots.
2512 * \param result The function puts the handle to the node found at the address
2513 * specified by \p result.
2514 * \return Zero if successful, otherwise a negative error code.
2516 int snd_config_searcha_hooks(snd_config_t *root, snd_config_t *config, const char *key, snd_config_t **result)
2518 static int snd_config_hooks(snd_config_t *config, snd_config_t *private_data);
2519 SND_CONFIG_SEARCHA(root, config, key, result,
2520 snd_config_searcha_hooks,
2521 err = snd_config_hooks(config, NULL); \
2528 * \brief Searches for a node in a configuration tree, expanding aliases and hooks.
2529 * \param root Handle to the root configuration node containing alias
2531 * \param config Handle to the root of the configuration (sub)tree to search.
2532 * \param result The function puts the handle to the node found at the address
2533 * specified by \p result.
2534 * \param ... One or more concatenated dot separated search keys, terminated with \c NULL.
2535 * \return Zero if successful, otherwise a negative error code.
2537 int snd_config_searchva_hooks(snd_config_t *root, snd_config_t *config,
2538 snd_config_t **result, ...)
2540 SND_CONFIG_SEARCHVA(root, config, result, snd_config_searcha_hooks);
2544 * \brief Searches for a node in a configuration tree, using an alias and expanding hooks.
2545 * \param config Handle to the root of the configuration (sub)tree to search.
2546 * \param base Search key base, or \c NULL.
2547 * \param key Search key suffix.
2548 * \param result The function puts the handle to the node found at the address
2549 * specified by \p result.
2550 * \return Zero if successful, otherwise a negative error code.
2552 * First \c key is tried, then, if nothing is found, \c base.key is tried.
2553 * If the value found is a string, this is recursively tried in the
2556 int snd_config_search_alias_hooks(snd_config_t *config,
2557 const char *base, const char *key,
2558 snd_config_t **result)
2560 SND_CONFIG_SEARCH_ALIAS(config, base, key, result,
2561 snd_config_searcha_hooks,
2562 snd_config_searchva_hooks);
2565 /** The name of the environment variable containing the files list for #snd_config_update. */
2566 #define ALSA_CONFIG_PATH_VAR "ALSA_CONFIG_PATH"
2568 /** The name of the default files used by #snd_config_update. */
2569 #define ALSA_CONFIG_PATH_DEFAULT DATADIR "/alsa/alsa.conf"
2573 * Configuration top level node (the global configuration).
2575 snd_config_t *snd_config = NULL;
2584 struct _snd_config_update {
2586 struct finfo *finfo;
2589 static snd_config_update_t *snd_config_global_update = NULL;
2591 static int snd_config_hooks_call(snd_config_t *root, snd_config_t *config, snd_config_t *private_data)
2594 snd_config_t *c, *func_conf = NULL;
2596 const char *lib = NULL, *func_name = NULL;
2598 int (*func)(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data) = NULL;
2601 err = snd_config_search(config, "func", &c);
2603 SNDERR("Field func is missing");
2606 err = snd_config_get_string(c, &str);
2608 SNDERR("Invalid type for field func");
2611 err = snd_config_search_definition(root, "hook_func", str, &func_conf);
2613 snd_config_iterator_t i, next;
2614 if (snd_config_get_type(func_conf) != SND_CONFIG_TYPE_COMPOUND) {
2615 SNDERR("Invalid type for func %s definition", str);
2618 snd_config_for_each(i, next, func_conf) {
2619 snd_config_t *n = snd_config_iterator_entry(i);
2620 const char *id = n->id;
2621 if (strcmp(id, "comment") == 0)
2623 if (strcmp(id, "lib") == 0) {
2624 err = snd_config_get_string(n, &lib);
2626 SNDERR("Invalid type for %s", id);
2631 if (strcmp(id, "func") == 0) {
2632 err = snd_config_get_string(n, &func_name);
2634 SNDERR("Invalid type for %s", id);
2639 SNDERR("Unknown field %s", id);
2643 int len = 16 + strlen(str) + 1;
2645 snprintf(buf, len, "snd_config_hook_%s", str);
2649 h = snd_dlopen(lib, RTLD_NOW);
2650 func = h ? snd_dlsym(h, func_name, SND_DLSYM_VERSION(SND_CONFIG_DLSYM_VERSION_HOOK)) : NULL;
2653 SNDERR("Cannot open shared library %s", lib);
2656 SNDERR("symbol %s is not defined inside %s", func_name, lib);
2662 snd_config_delete(func_conf);
2664 snd_config_t *nroot;
2665 err = func(root, config, &nroot, private_data);
2667 SNDERR("function %s returned error: %s", func_name, snd_strerror(err));
2669 if (err >= 0 && nroot)
2670 err = snd_config_substitute(root, nroot);
2679 static int snd_config_hooks(snd_config_t *config, snd_config_t *private_data)
2682 snd_config_iterator_t i, next;
2683 int err, hit, idx = 0;
2685 if ((err = snd_config_search(config, "@hooks", &n)) < 0)
2687 snd_config_remove(n);
2690 snd_config_for_each(i, next, n) {
2691 snd_config_t *n = snd_config_iterator_entry(i);
2692 const char *id = n->id;
2694 err = safe_strtol(id, &i);
2696 SNDERR("id of field %s is not and integer", id);
2701 err = snd_config_hooks_call(config, n, private_data);
2711 snd_config_delete(n);
2716 * \brief Loads and parses the given configurations files.
2717 * \param root Handle to the root configuration node.
2718 * \param config Handle to the configuration node for this hook.
2719 * \param dst The function puts the handle to the configuration node loaded
2720 * from the file(s) at the address specified by \p dst.
2721 * \param private_data Handle to the private data configuration node.
2722 * \return Zero if successful, otherwise a negative error code.
2724 int snd_config_hook_load(snd_config_t *root, snd_config_t *config, snd_config_t **dst, snd_config_t *private_data)
2727 snd_config_iterator_t i, next;
2728 struct finfo *fi = NULL;
2729 int err, idx = 0, fi_count = 0, errors = 1, hit;
2731 assert(root && dst);
2732 if ((err = snd_config_search(config, "errors", &n)) >= 0) {
2734 err = snd_config_get_ascii(n, &tmp);
2737 errors = snd_config_get_bool_ascii(tmp);
2740 SNDERR("Invalid bool value in field errors");
2744 if ((err = snd_config_search(config, "files", &n)) < 0) {
2745 SNDERR("Unable to find field files in the pre-load section");
2748 if ((err = snd_config_expand(n, root, NULL, private_data, &n)) < 0) {
2749 SNDERR("Unable to expand filenames in the pre-load section");
2752 if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
2753 SNDERR("Invalid type for field filenames");
2756 snd_config_for_each(i, next, n) {
2757 snd_config_t *c = snd_config_iterator_entry(i);
2759 if ((err = snd_config_get_string(c, &str)) < 0) {
2760 SNDERR("Field %s is not a string", c->id);
2765 fi = calloc(fi_count, sizeof(*fi));
2772 snd_config_for_each(i, next, n) {
2773 snd_config_t *n = snd_config_iterator_entry(i);
2774 const char *id = n->id;
2776 err = safe_strtol(id, &i);
2778 SNDERR("id of field %s is not and integer", id);
2784 if ((err = snd_config_get_ascii(n, &name)) < 0)
2786 if ((err = snd_user_file(name, &fi[idx].name)) < 0)
2794 for (idx = 0; idx < fi_count; idx++) {
2796 if (!errors && access(fi[idx].name, R_OK) < 0)
2798 err = snd_input_stdio_open(&in, fi[idx].name, "r");
2800 err = snd_config_load(root, in);
2801 snd_input_close(in);
2803 SNDERR("%s may be old or corrupted: consider to remove or fix it", fi[idx].name);
2807 SNDERR("cannot access file %s", fi[idx].name);
2813 for (idx = 0; idx < fi_count; idx++)
2818 snd_config_delete(n);
2822 SND_DLSYM_BUILD_VERSION(snd_config_hook_load, SND_CONFIG_DLSYM_VERSION_HOOK);
2826 int snd_determine_driver(int card, char **driver);
2830 * \brief Loads and parses the given configurations files for each installed sound card.
2831 * \param root Handle to the root configuration node.
2832 * \param config Handle to the configuration node for this hook.
2833 * \param dst The function puts the handle to the configuration node loaded
2834 * from the file(s) at the address specified by \p dst.
2835 * \param private_data Handle to the private data configuration node.
2836 * \return Zero if successful, otherwise a negative error code.
2838 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)
2843 err = snd_card_next(&card);
2847 snd_config_t *n, *private_data = NULL;
2849 char *fdriver = NULL;
2850 err = snd_determine_driver(card, &fdriver);
2853 if (snd_config_search(root, fdriver, &n) >= 0) {
2854 if (snd_config_get_string(n, &driver) < 0)
2857 char *s = strchr(driver, '.');
2862 if (snd_config_search(root, driver, &n) >= 0)
2867 err = snd_config_imake_string(&private_data, "string", driver);
2870 err = snd_config_hook_load(root, config, &n, private_data);
2873 snd_config_delete(private_data);
2879 } while (card >= 0);
2884 SND_DLSYM_BUILD_VERSION(snd_config_hook_load_for_all_cards, SND_CONFIG_DLSYM_VERSION_HOOK);
2888 * \brief Updates a configuration tree by rereading the configuration files (if needed).
2889 * \param top Address of the handle to the top level node.
2890 * \param update Address of a pointer to private update information.
2891 * \param cfgs A list of configuration file names, delimited with ':'.
2892 * If \p cfgs is set to \c NULL, the default global configuration
2893 * file is used ("/usr/share/alsa/alsa.conf").
2894 * \return A non-negative value if successful, otherwise a negative error code.
2895 * \retval 0 No action is needed.
2896 * \retval 1 The configuration tree has been rebuilt.
2898 * The global configuration files are specified in the environment variable
2899 * \c ALSA_CONFIG_PATH.
2901 * \warning If the configuration tree is reread, all string pointers and
2902 * configuration node handles previously obtained from this tree become invalid.
2904 int snd_config_update_r(snd_config_t **_top, snd_config_update_t **_update, const char *cfgs)
2907 const char *configs, *c;
2910 snd_config_update_t *local;
2911 snd_config_update_t *update;
2914 assert(_top && _update);
2919 configs = getenv(ALSA_CONFIG_PATH_VAR);
2921 configs = ALSA_CONFIG_PATH_DEFAULT;
2923 for (k = 0, c = configs; (l = strcspn(c, ": ")) > 0; ) {
2934 local = (snd_config_update_t *)calloc(1, sizeof(snd_config_update_t));
2938 local->finfo = calloc(local->count, sizeof(struct finfo));
2939 if (!local->finfo) {
2943 for (k = 0, c = configs; (l = strcspn(c, ": ")) > 0; ) {
2947 err = snd_user_file(name, &local->finfo[k].name);
2956 for (k = 0; k < local->count; ++k) {
2958 struct finfo *lf = &local->finfo[k];
2959 if (stat(lf->name, &st) >= 0) {
2960 lf->dev = st.st_dev;
2961 lf->ino = st.st_ino;
2962 lf->mtime = st.st_mtime;
2964 memmove(&local->finfo[k], &local->finfo[k+1], sizeof(struct finfo) * (local->count - k - 1));
2971 if (local->count != update->count)
2973 for (k = 0; k < local->count; ++k) {
2974 struct finfo *lf = &local->finfo[k];
2975 struct finfo *uf = &update->finfo[k];
2976 if (strcmp(lf->name, uf->name) != 0 ||
2977 lf->dev != uf->dev ||
2978 lf->ino != uf->ino ||
2979 lf->mtime != uf->mtime)
2987 snd_config_delete(top);
2991 snd_config_update_free(update);
2996 snd_config_update_free(local);
3003 snd_config_update_free(update);
3007 snd_config_delete(top);
3010 err = snd_config_top(&top);
3015 for (k = 0; k < local->count; ++k) {
3017 err = snd_input_stdio_open(&in, local->finfo[k].name, "r");
3019 err = snd_config_load(top, in);
3020 snd_input_close(in);
3022 SNDERR("%s may be old or corrupted: consider to remove or fix it", local->finfo[k].name);
3026 SNDERR("cannot access file %s", local->finfo[k].name);
3030 err = snd_config_hooks(top, NULL);
3032 SNDERR("hooks failed, removing configuration");
3040 static pthread_mutex_t snd_config_update_mutex = PTHREAD_MUTEX_INITIALIZER;
3043 * \brief Updates #snd_config by rereading the global configuration files (if needed).
3044 * \return A non-negative value if successful, otherwise a negative error code.
3045 * \retval 0 No action is needed.
3046 * \retval 1 The configuration tree has been rebuilt.
3048 * The global configuration files are specified in the environment variable
3049 * \c ALSA_CONFIG_PATH. If this is not set, the default value is
3050 * "/usr/share/alsa/alsa.conf".
3052 * \warning If the configuration tree is reread, all string pointers and
3053 * configuration node handles previously obtained from this tree become invalid.
3055 int snd_config_update(void)
3059 pthread_mutex_lock(&snd_config_update_mutex);
3060 err = snd_config_update_r(&snd_config, &snd_config_global_update, NULL);
3061 pthread_mutex_unlock(&snd_config_update_mutex);
3066 * \brief Frees a private update structure.
3067 * \param update The private update structure to free.
3068 * \return Zero if successful, otherwise a negative error code.
3070 int snd_config_update_free(snd_config_update_t *update)
3075 assert(update->count > 0 && update->finfo);
3076 for (k = 0; k < update->count; k++)
3077 free(update->finfo[k].name);
3079 free(update->finfo);
3085 * \brief Frees the global configuration tree in #snd_config.
3086 * \return Zero if successful, otherwise a negative error code.
3088 int snd_config_update_free_global(void)
3090 pthread_mutex_lock(&snd_config_update_mutex);
3092 snd_config_delete(snd_config);
3094 if (snd_config_global_update)
3095 snd_config_update_free(snd_config_global_update);
3096 snd_config_global_update = NULL;
3097 pthread_mutex_unlock(&snd_config_update_mutex);
3102 * \brief Returns an iterator pointing to the first child of a compound configuration node.
3103 * \param node Handle to the compound configuration node.
3104 * \return An iterator pointing to the first child.
3106 snd_config_iterator_t snd_config_iterator_first(const snd_config_t *node)
3108 assert(node->type == SND_CONFIG_TYPE_COMPOUND);
3109 return node->u.compound.fields.next;
3113 * \brief Returns an iterator pointing to the next sibling.
3114 * \param iterator An iterator pointing to a child configuration node.
3115 * \return An iterator pointing to the next sibling of \p iterator.
3116 * If \p iterator is the last sibling, the returned value is the same
3117 * as the result of calling #snd_config_iterator_end on the father
3120 snd_config_iterator_t snd_config_iterator_next(const snd_config_iterator_t iterator)
3122 return iterator->next;
3126 * \brief Returns an iterator pointing past the last child of a compound configuration node.
3127 * \param node Handle to the compound configuration node.
3128 * \return An iterator pointing past the last child of \p node.
3130 snd_config_iterator_t snd_config_iterator_end(const snd_config_t *node)
3132 assert(node->type == SND_CONFIG_TYPE_COMPOUND);
3133 return (const snd_config_iterator_t)&node->u.compound.fields;
3137 * \brief Returns the configuration node handle pointed to by an iterator.
3138 * \param iterator A configuration node iterator.
3139 * \return The configuration node handle pointed to by \p iterator.
3141 snd_config_t *snd_config_iterator_entry(const snd_config_iterator_t iterator)
3143 return list_entry(iterator, snd_config_t, list);
3147 typedef enum _snd_config_walk_pass {
3148 SND_CONFIG_WALK_PASS_PRE,
3149 SND_CONFIG_WALK_PASS_POST,
3150 SND_CONFIG_WALK_PASS_LEAF,
3151 } snd_config_walk_pass_t;
3154 /* Return 1 if node needs to be attached to father */
3155 /* Return 2 if compound is replaced with standard node */
3157 typedef int (*snd_config_walk_callback_t)(snd_config_t *src,
3160 snd_config_walk_pass_t pass,
3161 snd_config_t *private_data);
3164 static int snd_config_walk(snd_config_t *src,
3167 snd_config_walk_callback_t callback,
3168 snd_config_t *private_data)
3171 snd_config_iterator_t i, next;
3173 switch (snd_config_get_type(src)) {
3174 case SND_CONFIG_TYPE_COMPOUND:
3175 err = callback(src, root, dst, SND_CONFIG_WALK_PASS_PRE, private_data);
3178 snd_config_for_each(i, next, src) {
3179 snd_config_t *s = snd_config_iterator_entry(i);
3180 snd_config_t *d = NULL;
3182 err = snd_config_walk(s, root, (dst && *dst) ? &d : NULL,
3183 callback, private_data);
3187 err = snd_config_add(*dst, d);
3192 err = callback(src, root, dst, SND_CONFIG_WALK_PASS_POST, private_data);
3196 snd_config_delete(*dst);
3200 err = callback(src, root, dst, SND_CONFIG_WALK_PASS_LEAF, private_data);
3206 static int _snd_config_copy(snd_config_t *src,
3207 snd_config_t *root ATTRIBUTE_UNUSED,
3209 snd_config_walk_pass_t pass,
3210 snd_config_t *private_data ATTRIBUTE_UNUSED)
3213 const char *id = src->id;
3214 snd_config_type_t type = snd_config_get_type(src);
3216 case SND_CONFIG_WALK_PASS_PRE:
3217 err = snd_config_make_compound(dst, id, src->u.compound.join);
3221 case SND_CONFIG_WALK_PASS_LEAF:
3222 err = snd_config_make(dst, id, type);
3226 case SND_CONFIG_TYPE_INTEGER:
3229 err = snd_config_get_integer(src, &v);
3231 snd_config_set_integer(*dst, v);
3234 case SND_CONFIG_TYPE_INTEGER64:
3237 err = snd_config_get_integer64(src, &v);
3239 snd_config_set_integer64(*dst, v);
3242 case SND_CONFIG_TYPE_REAL:
3245 err = snd_config_get_real(src, &v);
3247 snd_config_set_real(*dst, v);
3250 case SND_CONFIG_TYPE_STRING:
3253 err = snd_config_get_string(src, &s);
3255 err = snd_config_set_string(*dst, s);
3271 * \brief Creates a copy of a configuration node.
3272 * \param dst The function puts the handle to the new configuration node
3273 * at the address specified by \p dst.
3274 * \param src Handle to the source configuration node.
3275 * \return A non-negative value if successful, otherwise a negative error code.
3277 int snd_config_copy(snd_config_t **dst,
3280 return snd_config_walk(src, NULL, dst, _snd_config_copy, NULL);
3283 static int _snd_config_expand(snd_config_t *src,
3284 snd_config_t *root ATTRIBUTE_UNUSED,
3286 snd_config_walk_pass_t pass,
3287 snd_config_t *private_data)
3290 const char *id = src->id;
3291 snd_config_type_t type = snd_config_get_type(src);
3293 case SND_CONFIG_WALK_PASS_PRE:
3295 if (strcmp(id, "@args") == 0)
3297 err = snd_config_make_compound(dst, id, src->u.compound.join);
3302 case SND_CONFIG_WALK_PASS_LEAF:
3304 case SND_CONFIG_TYPE_INTEGER:
3307 err = snd_config_get_integer(src, &v);
3309 err = snd_config_imake_integer(dst, id, v);
3314 case SND_CONFIG_TYPE_INTEGER64:
3317 err = snd_config_get_integer64(src, &v);
3319 err = snd_config_imake_integer64(dst, id, v);
3324 case SND_CONFIG_TYPE_REAL:
3327 err = snd_config_get_real(src, &v);
3329 err = snd_config_imake_real(dst, id, v);
3334 case SND_CONFIG_TYPE_STRING:
3338 snd_config_t *vars = private_data;
3339 snd_config_get_string(src, &s);
3342 if (snd_config_search(vars, s, &val) < 0)
3344 err = snd_config_copy(dst, val);
3347 err = snd_config_set_id(*dst, id);
3349 snd_config_delete(*dst);
3353 err = snd_config_imake_string(dst, id, s);
3369 static int _snd_config_evaluate(snd_config_t *src,
3371 snd_config_t **dst ATTRIBUTE_UNUSED,
3372 snd_config_walk_pass_t pass,
3373 snd_config_t *private_data)
3376 if (pass == SND_CONFIG_WALK_PASS_PRE) {
3378 const char *lib = NULL, *func_name = NULL;
3380 int (*func)(snd_config_t **dst, snd_config_t *root,
3381 snd_config_t *src, snd_config_t *private_data) = NULL;
3383 snd_config_t *c, *func_conf = NULL;
3384 err = snd_config_search(src, "@func", &c);
3387 err = snd_config_get_string(c, &str);
3389 SNDERR("Invalid type for @func");
3392 err = snd_config_search_definition(root, "func", str, &func_conf);
3394 snd_config_iterator_t i, next;
3395 if (snd_config_get_type(func_conf) != SND_CONFIG_TYPE_COMPOUND) {
3396 SNDERR("Invalid type for func %s definition", str);
3399 snd_config_for_each(i, next, func_conf) {
3400 snd_config_t *n = snd_config_iterator_entry(i);
3401 const char *id = n->id;
3402 if (strcmp(id, "comment") == 0)
3404 if (strcmp(id, "lib") == 0) {
3405 err = snd_config_get_string(n, &lib);
3407 SNDERR("Invalid type for %s", id);
3412 if (strcmp(id, "func") == 0) {
3413 err = snd_config_get_string(n, &func_name);
3415 SNDERR("Invalid type for %s", id);
3420 SNDERR("Unknown field %s", id);
3424 int len = 9 + strlen(str) + 1;
3426 snprintf(buf, len, "snd_func_%s", str);
3430 h = snd_dlopen(lib, RTLD_NOW);
3432 func = snd_dlsym(h, func_name, SND_DLSYM_VERSION(SND_CONFIG_DLSYM_VERSION_EVALUATE));
3435 SNDERR("Cannot open shared library %s", lib);
3439 SNDERR("symbol %s is not defined inside %s", func_name, lib);
3446 snd_config_delete(func_conf);
3449 err = func(&eval, root, src, private_data);
3451 SNDERR("function %s returned error: %s", func_name, snd_strerror(err));
3453 if (err >= 0 && eval) {
3454 /* substitute merges compound members */
3455 /* we don't want merging at all */
3456 err = snd_config_delete_compound_members(src);
3458 err = snd_config_substitute(src, eval);
3472 * \brief Evaluates a configuration node at runtime.
3473 * \param config Handle to the source configuration node.
3474 * \param root Handle to the root of the source configuration.
3475 * \param private_data Handle to the private data node for runtime evaluation.
3476 * \param result The function puts the handle to the result node at the
3477 * address specified by \p result. \p result is \c NULL for
3478 * in-place evaluation.
3479 * \return A non-negative value if successful, otherwise a negative error code.
3480 * \note Only in-place evaluation is currently implemented.
3482 int snd_config_evaluate(snd_config_t *config, snd_config_t *root,
3483 snd_config_t *private_data, snd_config_t **result)
3485 /* FIXME: Only in place evaluation is currently implemented */
3486 assert(result == NULL);
3487 return snd_config_walk(config, root, result, _snd_config_evaluate, private_data);
3490 static int load_defaults(snd_config_t *subs, snd_config_t *defs)
3492 snd_config_iterator_t d, dnext;
3493 snd_config_for_each(d, dnext, defs) {
3494 snd_config_t *def = snd_config_iterator_entry(d);
3495 snd_config_iterator_t f, fnext;
3496 if (snd_config_get_type(def) != SND_CONFIG_TYPE_COMPOUND)
3498 snd_config_for_each(f, fnext, def) {
3499 snd_config_t *fld = snd_config_iterator_entry(f);
3500 const char *id = fld->id;
3501 if (strcmp(id, "type") == 0)
3503 if (strcmp(id, "default") == 0) {
3504 snd_config_t *deflt;
3506 err = snd_config_copy(&deflt, fld);
3509 err = snd_config_set_id(deflt, def->id);
3511 snd_config_delete(deflt);
3514 err = snd_config_add(subs, deflt);
3516 snd_config_delete(deflt);
3521 SNDERR("Unknown field %s", id);
3528 static void skip_blank(const char **ptr)
3545 static int parse_char(const char **ptr)
3548 assert(**ptr == '\\');
3577 if (c < '0' || c > '7')
3579 num = num * 8 + c - '0';
3592 static int parse_id(const char **ptr)
3613 static int parse_string(const char **ptr, char **val)
3615 const size_t bufsize = 256;
3618 size_t alloc = bufsize;
3626 SNDERR("Unterminated string");
3629 c = parse_char(ptr);
3636 *val = malloc(idx + 1);
3639 memcpy(*val, buf, idx);
3641 if (alloc > bufsize)
3647 size_t old_alloc = alloc;
3649 if (old_alloc == bufsize) {
3650 buf = malloc(alloc);
3651 memcpy(buf, _buf, old_alloc);
3653 buf = realloc(buf, alloc);
3663 /* Parse var=val or val */
3664 static int parse_arg(const char **ptr, unsigned int *varlen, char **val)
3670 if (*str == '"' || *str == '\'') {
3671 err = parse_string(ptr, val);
3677 err = parse_id(ptr);
3680 vallen = *ptr - str;
3690 if (*str == '"' || *str == '\'') {
3691 err = parse_string(ptr, val);
3696 err = parse_id(ptr);
3699 vallen = *ptr - str;
3701 *val = malloc(vallen + 1);
3704 memcpy(*val, str, vallen);
3711 * var1=val1,var2=val2,...
3714 static int parse_args(snd_config_t *subs, const char *str, snd_config_t *defs)
3724 int len = strlen(str);
3726 snd_config_iterator_t i, next;
3728 switch (str[--len]) {
3740 if (str[len] != '}')
3742 err = snd_input_buffer_open(&input, str + 1, len - 1);
3745 err = snd_config_load_override(subs, input);
3746 snd_input_close(input);
3749 snd_config_for_each(i, next, subs) {
3750 snd_config_t *n = snd_config_iterator_entry(i);
3752 const char *id = n->id;
3753 err = snd_config_search(defs, id, &d);
3755 SNDERR("Unknown parameter %s", id);
3764 const char *var = buf;
3765 unsigned int varlen;
3766 snd_config_t *def, *sub, *typ;
3767 const char *new = str;
3770 err = parse_arg(&new, &varlen, &val);
3774 assert(varlen < sizeof(buf));
3775 memcpy(buf, str, varlen);
3778 sprintf(buf, "%d", arg);
3780 err = snd_config_search_alias(defs, NULL, var, &def);
3782 SNDERR("Unknown parameter %s", var);
3785 if (snd_config_get_type(def) != SND_CONFIG_TYPE_COMPOUND) {
3786 SNDERR("Parameter %s definition is not correct", var);
3791 err = snd_config_search(subs, var, &sub);
3793 snd_config_delete(sub);
3794 err = snd_config_search(def, "type", &typ);
3797 SNDERR("Parameter %s definition is missing a valid type info", var);
3800 err = snd_config_get_string(typ, &tmp);
3803 if (strcmp(tmp, "integer") == 0) {
3805 err = snd_config_make(&sub, var, SND_CONFIG_TYPE_INTEGER);
3808 err = safe_strtol(val, &v);
3810 SNDERR("Parameter %s must be an integer", var);
3813 err = snd_config_set_integer(sub, v);
3816 } else if (strcmp(tmp, "integer64") == 0) {
3818 err = snd_config_make(&sub, var, SND_CONFIG_TYPE_INTEGER64);
3821 err = safe_strtoll(val, &v);
3823 SNDERR("Parameter %s must be an integer", var);
3826 err = snd_config_set_integer64(sub, v);
3829 } else if (strcmp(tmp, "real") == 0) {
3831 err = snd_config_make(&sub, var, SND_CONFIG_TYPE_REAL);
3834 err = safe_strtod(val, &v);
3836 SNDERR("Parameter %s must be a real", var);
3839 err = snd_config_set_real(sub, v);
3842 } else if (strcmp(tmp, "string") == 0) {
3843 err = snd_config_make(&sub, var, SND_CONFIG_TYPE_STRING);
3846 err = snd_config_set_string(sub, val);
3853 err = snd_config_set_id(sub, var);
3856 err = snd_config_add(subs, sub);
3874 * \brief Expands a configuration node applying arguments and functions.
3875 * \param config Handle to the configuration node.
3876 * \param root Handle to the root configuration node.
3877 * \param args Arguments string (optional).
3878 * \param private_data Handle to the private data node for functions.
3879 * \param result The function puts the handle to the result configuration node
3880 * at the address specified by \p result.
3881 * \return A non-negative value if successful, otherwise a negative error code.
3883 int snd_config_expand(snd_config_t *config, snd_config_t *root, const char *args,
3884 snd_config_t *private_data, snd_config_t **result)
3887 snd_config_t *defs, *subs = NULL, *res;
3888 err = snd_config_search(config, "@args", &defs);
3890 err = snd_config_copy(&res, config);
3894 err = snd_config_top(&subs);
3897 err = load_defaults(subs, defs);
3899 SNDERR("Load defaults error: %s", snd_strerror(err));
3902 err = parse_args(subs, args, defs);
3904 SNDERR("Parse arguments error: %s", snd_strerror(err));
3907 err = snd_config_evaluate(subs, root, private_data, NULL);
3909 SNDERR("Args evaluate error: %s", snd_strerror(err));
3912 err = snd_config_walk(config, root, &res, _snd_config_expand, subs);
3914 SNDERR("Expand error (walk): %s", snd_strerror(err));
3918 err = snd_config_evaluate(res, root, private_data, NULL);
3920 SNDERR("Evaluate error: %s", snd_strerror(err));
3921 snd_config_delete(res);
3928 snd_config_delete(subs);
3933 * \brief Searches for a definition in a configuration tree, using aliases and expanding hooks and arguments.
3934 * \param config Handle to the configuration (sub)tree to search.
3935 * \param base Implicit key base, or \c NULL for none.
3936 * \param key Key suffix.
3937 * \param result The function puts the handle to the expanded found node at
3938 * the address specified by \p result.
3939 * \return Zero if successful, otherwise a negative error code.
3941 * First the key is tried, then, if nothing is found, base.key is tried.
3942 * If the value found is a string, this is recursively tried in the
3945 * If \p key contains a dot (.), the implicit base is ignored and the key
3946 * starts from the root given by \p config.
3948 int snd_config_search_definition(snd_config_t *config,
3949 const char *base, const char *name,
3950 snd_config_t **result)
3954 const char *args = strchr(name, ':');
3958 key = alloca(args - name);
3959 memcpy(key, name, args - name - 1);
3960 key[args - name - 1] = '\0';
3962 key = (char *) name;
3965 * if key contains dot (.), the implicit base is ignored
3966 * and the key starts from root given by the 'config' parameter
3968 err = snd_config_search_alias_hooks(config, strchr(key, '.') ? NULL : base, key, &conf);
3971 return snd_config_expand(conf, config, args, NULL, result);
3976 /* Not strictly needed, but useful to check for memory leaks */
3977 void _snd_config_end(void) __attribute__ ((destructor));
3979 static void _snd_config_end(void)
3983 snd_config_delete(snd_config);
3985 for (k = 0; k < files_info_count; ++k)
3986 free(files_info[k].name);
3989 files_info_count = 0;