OSDN Git Service

ucm: return error if fixedboot_list is empty
[android-x86/external-alsa-lib.git] / src / confmisc.c
1 /**
2  * \file confmisc.c
3  * \ingroup Configuration
4  * \brief Configuration helper functions
5  * \author Abramo Bagnara <abramo@alsa-project.org>
6  * \author Jaroslav Kysela <perex@perex.cz>
7  * \date 2000-2001
8  * 
9  * Configuration helper functions.
10  *
11  * See the \ref conffunc page for more details.
12  */
13 /*
14  *  Miscellaneous configuration helper functions
15  *  Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>,
16  *                        Jaroslav Kysela <perex@perex.cz>
17  *
18  *
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.
23  *
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.
28  *
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
32  *
33  */
34
35 /*! \page conffunc
36
37 \section conffunc_ref Function reference
38
39 <UL>
40   <LI>The getenv function - snd_func_getenv() - obtains
41       an environment value. The result is a string.
42   <LI>The igetenv function - snd_func_igetenv() - obtains
43       an environment value. The result is an integer.
44   <LI>The concat function - snd_func_concat() - merges all specified
45       strings. The result is a string.
46   <LI>The iadd function - snd_func_iadd() - sum all specified integers.
47       The result is an integer.
48   <LI>The imul function - snd_func_imul() - multiply all specified integers.
49       The result is an integer.
50   <LI>The datadir function - snd_func_datadir() - returns the
51       ALSA data directory. The result is a string.
52   <LI>The refer function - snd_func_refer() - copies the referred
53       configuration. The result has the same type as the referred node.
54   <LI>The card_inum function - snd_func_card_inum() - returns
55       a card number (integers).
56   <LI>The card_driver function - snd_func_card_driver() - returns
57       a driver identification. The result is a string.
58   <LI>The card_id function - snd_func_card_id() - returns
59       a card identification. The result is a string.
60   <LI>The card_name function - snd_func_card_name() - returns
61       a card's name. The result is a string.
62   <LI>The pcm_id function - snd_func_pcm_id() - returns
63       a pcm identification. The result is a string.
64   <LI>The private_string function - snd_func_private_string() - returns the
65       string from the private_data node.
66   <LI>The private_card_driver function - snd_func_private_card_driver() -
67       returns the driver identification from the private_data node.
68       The result is a string.
69   <LI>The private_pcm_subdevice function - snd_func_private_pcm_subdevice() -
70       returns the PCM subdevice number from the private_data node.
71       The result is a string.
72 </UL>
73
74 */
75
76
77 #include <stdlib.h>
78 #include <stdio.h>
79 #include <string.h>
80 #include <ctype.h>
81 #include <limits.h>
82 #include "local.h"
83
84 /**
85  * \brief Gets the boolean value from the given ASCII string.
86  * \param ascii The string to be parsed.
87  * \return 0 or 1 if successful, otherwise a negative error code.
88  */
89 int snd_config_get_bool_ascii(const char *ascii)
90 {
91         unsigned int k;
92         static const struct {
93                 const char str[8];
94                 int val;
95         } b[] = {
96                 { "0", 0 },
97                 { "1", 1 },
98                 { "false", 0 },
99                 { "true", 1 },
100                 { "no", 0 },
101                 { "yes", 1 },
102                 { "off", 0 },
103                 { "on", 1 },
104         };
105         for (k = 0; k < sizeof(b) / sizeof(*b); k++) {
106                 if (strcasecmp(b[k].str, ascii) == 0)
107                         return b[k].val;
108         }
109         return -EINVAL;
110 }
111
112 /**
113  * \brief Gets the boolean value from a configuration node.
114  * \param conf Handle to the configuration node to be parsed.
115  * \return 0 or 1 if successful, otherwise a negative error code.
116  */
117 int snd_config_get_bool(const snd_config_t *conf)
118 {
119         long v;
120         const char *str, *id;
121         int err;
122
123         err = snd_config_get_id(conf, &id);
124         if (err < 0)
125                 return err;
126         err = snd_config_get_integer(conf, &v);
127         if (err >= 0) {
128                 if (v < 0 || v > 1) {
129                 _invalid_value:
130                         SNDERR("Invalid value for %s", id);
131                         return -EINVAL;
132                 }
133                 return v;
134         }
135         err = snd_config_get_string(conf, &str);
136         if (err < 0) {
137                 SNDERR("Invalid type for %s", id);
138                 return -EINVAL;
139         }
140         err = snd_config_get_bool_ascii(str);
141         if (err < 0)
142                 goto _invalid_value;
143         return err;
144 }
145
146 /**
147  * \brief Gets the card number from a configuration node.
148  * \param conf Handle to the configuration node to be parsed.
149  * \return The card number if successful, otherwise a negative error code.
150  */
151 int snd_config_get_card(const snd_config_t *conf)
152 {
153         const char *str, *id;
154         long v;
155         int err;
156
157         if ((err = snd_config_get_integer(conf, &v)) < 0) {
158                 if ((err = snd_config_get_string(conf, &str)) < 0) {
159                         snd_config_get_id(conf, &id);
160                         SNDERR("Invalid field %s", id);
161                         return -EINVAL;
162                 }
163                 err = snd_card_get_index(str);
164                 if (err < 0) {
165                         SNDERR("Cannot get card index for %s", str);
166                         return err;
167                 }
168                 v = err;
169         }
170         if (v < 0 || v > INT_MAX)
171                 return -EINVAL;
172         return v;
173 }
174
175 /**
176  * \brief Gets the control interface index from the given ASCII string.
177  * \param ascii The string to be parsed.
178  * \return The control interface index if successful, otherwise a negative error code.
179  */ 
180 int snd_config_get_ctl_iface_ascii(const char *ascii)
181 {
182         long v;
183         snd_ctl_elem_iface_t idx;
184         if (isdigit(ascii[0])) {
185                 if (safe_strtol(ascii, &v) >= 0) {
186                         if (v < 0 || v > SND_CTL_ELEM_IFACE_LAST)
187                                 return -EINVAL;
188                         return v;
189                 }
190         }
191         for (idx = 0; idx <= SND_CTL_ELEM_IFACE_LAST; idx++) {
192                 if (strcasecmp(snd_ctl_elem_iface_name(idx), ascii) == 0)
193                         return idx;
194         }
195         return -EINVAL;
196 }
197
198 /**
199  * \brief Gets the control interface index from a configuration node.
200  * \param conf Handle to the configuration node to be parsed.
201  * \return The control interface index if successful, otherwise a negative error code.
202  */ 
203 int snd_config_get_ctl_iface(const snd_config_t *conf)
204 {
205         long v;
206         const char *str, *id;
207         int err;
208
209         err = snd_config_get_id(conf, &id);
210         if (err < 0)
211                 return err;
212         err = snd_config_get_integer(conf, &v);
213         if (err >= 0) {
214                 if (v < 0 || v > SND_CTL_ELEM_IFACE_LAST) {
215                 _invalid_value:
216                         SNDERR("Invalid value for %s", id);
217                         return -EINVAL;
218                 }
219                 return v;
220         }
221         err = snd_config_get_string(conf, &str);
222         if (err < 0) {
223                 SNDERR("Invalid type for %s", id);
224                 return -EINVAL;
225         }
226         err = snd_config_get_ctl_iface_ascii(str);
227         if (err < 0)
228                 goto _invalid_value;
229         return err;
230 }
231
232 /*
233  *  Helper functions for the configuration file
234  */
235
236 /**
237  * \brief Returns an environment value.
238  * \param dst The function puts the handle to the result configuration node
239  *            (with type string) at the address specified by \p dst.
240  * \param root Handle to the root source node.
241  * \param src Handle to the source node, with definitions for \c vars and
242  *            \c default.
243  * \param private_data Handle to the \c private_data node.
244  * \return Zero if successful, otherwise a negative error code.
245  *
246  * Example:
247 \code
248         {
249                 @func getenv
250                 vars [ MY_CARD CARD C ]
251                 default 0
252         }
253 \endcode
254  */ 
255 int snd_func_getenv(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
256                     snd_config_t *private_data)
257 {
258         snd_config_t *n, *d;
259         snd_config_iterator_t i, next;
260         const char *res, *id;
261         char *def = NULL;
262         int idx = 0, err, hit;
263         
264         err = snd_config_search(src, "vars", &n);
265         if (err < 0) {
266                 SNDERR("field vars not found");
267                 goto __error;
268         }
269         err = snd_config_evaluate(n, root, private_data, NULL);
270         if (err < 0) {
271                 SNDERR("error evaluating vars");
272                 goto __error;
273         }
274         err = snd_config_search(src, "default", &d);
275         if (err < 0) {
276                 SNDERR("field default not found");
277                 goto __error;
278         }
279         err = snd_config_evaluate(d, root, private_data, NULL);
280         if (err < 0) {
281                 SNDERR("error evaluating default");
282                 goto __error;
283         }
284         err = snd_config_get_ascii(d, &def);
285         if (err < 0) {
286                 SNDERR("error getting field default");
287                 goto __error;
288         }
289         do {
290                 hit = 0;
291                 snd_config_for_each(i, next, n) {
292                         snd_config_t *n = snd_config_iterator_entry(i);
293                         const char *ptr;
294                         long i;
295                         if (snd_config_get_id(n, &id) < 0)
296                                 continue;
297                         if (snd_config_get_type(n) != SND_CONFIG_TYPE_STRING) {
298                                 SNDERR("field %s is not a string", id);
299                                 err = -EINVAL;
300                                 goto __error;
301                         }
302                         err = safe_strtol(id, &i);
303                         if (err < 0) {
304                                 SNDERR("id of field %s is not an integer", id);
305                                 err = -EINVAL;
306                                 goto __error;
307                         }
308                         if (i == idx) {
309                                 idx++;
310                                 err = snd_config_get_string(n, &ptr);
311                                 if (err < 0) {
312                                         SNDERR("invalid string for id %s", id);
313                                         err = -EINVAL;
314                                         goto __error;
315                                 }
316                                 res = getenv(ptr);
317                                 if (res != NULL && *res != '\0')
318                                         goto __ok;
319                                 hit = 1;
320                         }
321                 }
322         } while (hit);
323         res = def;
324       __ok:
325         err = snd_config_get_id(src, &id);
326         if (err >= 0)
327                 err = snd_config_imake_string(dst, id, res);
328       __error:
329         free(def);
330         return err;
331 }
332 #ifndef DOC_HIDDEN
333 SND_DLSYM_BUILD_VERSION(snd_func_getenv, SND_CONFIG_DLSYM_VERSION_EVALUATE);
334 #endif
335
336 /**
337  * \brief Returns an integer environment value.
338  * \param dst The function puts the handle to the result configuration node
339  *            (with type integer) at the address specified by \p dst.
340  * \param root Handle to the root source node.
341  * \param src Handle to the source node, with definitions for \c vars and
342  *            \c default.
343  * \param private_data Handle to the \c private_data node.
344  * \return Zero if successful, otherwise a negative error code.
345  *
346  * Example:
347 \code
348         {
349                 @func igetenv
350                 vars [ MY_DEVICE DEVICE D ]
351                 default 0
352         }
353 \endcode
354  */ 
355 int snd_func_igetenv(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
356                      snd_config_t *private_data)
357 {
358         snd_config_t *d;
359         const char *str, *id;
360         int err;
361         long v;
362
363         err = snd_func_getenv(&d, root, src, private_data);
364         if (err < 0)
365                 return err;
366         err = snd_config_get_string(d, &str);
367         if (err < 0) {
368                 snd_config_delete(d);
369                 return err;
370         }
371         err = safe_strtol(str, &v);
372         if (err < 0) {
373                 snd_config_delete(d);
374                 return err;
375         }
376         snd_config_delete(d);
377         err = snd_config_get_id(src, &id);
378         if (err < 0)
379                 return err;
380         err = snd_config_imake_integer(dst, id, v);
381         if (err < 0)
382                 return err;
383         return 0;
384 }
385 #ifndef DOC_HIDDEN
386 SND_DLSYM_BUILD_VERSION(snd_func_igetenv, SND_CONFIG_DLSYM_VERSION_EVALUATE);
387 #endif
388                 
389 /**
390  * \brief Merges the given strings.
391  * \param dst The function puts the handle to the result configuration node
392  *            (with type string) at the address specified by \p dst.
393  * \param root Handle to the root source node.
394  * \param src Handle to the source node, with a definition for \c strings.
395  * \param private_data Handle to the \c private_data node.
396  * \return A non-negative value if successful, otherwise a negative error code.
397  *
398  * Example (result is "a1b2c3"):
399 \code
400         {
401                 @func concat
402                 strings [ "a1" "b2" "c3" ]
403         }
404 \endcode
405  */ 
406 int snd_func_concat(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
407                     snd_config_t *private_data)
408 {
409         snd_config_t *n;
410         snd_config_iterator_t i, next;
411         const char *id;
412         char *res = NULL, *tmp;
413         int idx = 0, len = 0, len1, err, hit;
414         
415         err = snd_config_search(src, "strings", &n);
416         if (err < 0) {
417                 SNDERR("field strings not found");
418                 goto __error;
419         }
420         err = snd_config_evaluate(n, root, private_data, NULL);
421         if (err < 0) {
422                 SNDERR("error evaluating strings");
423                 goto __error;
424         }
425         do {
426                 hit = 0;
427                 snd_config_for_each(i, next, n) {
428                         snd_config_t *n = snd_config_iterator_entry(i);
429                         char *ptr;
430                         const char *id;
431                         long i;
432                         if (snd_config_get_id(n, &id) < 0)
433                                 continue;
434                         err = safe_strtol(id, &i);
435                         if (err < 0) {
436                                 SNDERR("id of field %s is not an integer", id);
437                                 err = -EINVAL;
438                                 goto __error;
439                         }
440                         if (i == idx) {
441                                 idx++;
442                                 err = snd_config_get_ascii(n, &ptr);
443                                 if (err < 0) {
444                                         SNDERR("invalid ascii string for id %s", id);
445                                         err = -EINVAL;
446                                         goto __error;
447                                 }
448                                 len1 = strlen(ptr);
449                                 tmp = realloc(res, len + len1 + 1);
450                                 if (tmp == NULL) {
451                                         free(ptr);
452                                         err = -ENOMEM;
453                                         goto __error;
454                                 }
455                                 memcpy(tmp + len, ptr, len1);
456                                 free(ptr);
457                                 len += len1;
458                                 tmp[len] = '\0';
459                                 res = tmp;
460                                 hit = 1;
461                         }
462                 }
463         } while (hit);
464         if (res == NULL) {
465                 SNDERR("empty string is not accepted");
466                 err = -EINVAL;
467                 goto __error;
468         }
469         err = snd_config_get_id(src, &id);
470         if (err >= 0)
471                 err = snd_config_imake_string(dst, id, res);
472       __error:
473         free(res);
474         return err;
475 }
476 #ifndef DOC_HIDDEN
477 SND_DLSYM_BUILD_VERSION(snd_func_concat, SND_CONFIG_DLSYM_VERSION_EVALUATE);
478 #endif
479
480
481 static int snd_func_iops(snd_config_t **dst,
482                          snd_config_t *root,
483                          snd_config_t *src,
484                          snd_config_t *private_data,
485                          int op)
486 {
487         snd_config_t *n;
488         snd_config_iterator_t i, next;
489         const char *id;
490         char *res = NULL;
491         long result = 0, val;
492         int idx = 0, err, hit;
493         
494         err = snd_config_search(src, "integers", &n);
495         if (err < 0) {
496                 SNDERR("field integers not found");
497                 goto __error;
498         }
499         err = snd_config_evaluate(n, root, private_data, NULL);
500         if (err < 0) {
501                 SNDERR("error evaluating integers");
502                 goto __error;
503         }
504         do {
505                 hit = 0;
506                 snd_config_for_each(i, next, n) {
507                         snd_config_t *n = snd_config_iterator_entry(i);
508                         const char *id;
509                         long i;
510                         if (snd_config_get_id(n, &id) < 0)
511                                 continue;
512                         err = safe_strtol(id, &i);
513                         if (err < 0) {
514                                 SNDERR("id of field %s is not an integer", id);
515                                 err = -EINVAL;
516                                 goto __error;
517                         }
518                         if (i == idx) {
519                                 idx++;
520                                 err = snd_config_get_integer(n, &val);
521                                 if (err < 0) {
522                                         SNDERR("invalid integer for id %s", id);
523                                         err = -EINVAL;
524                                         goto __error;
525                                 }
526                                 switch (op) {
527                                 case 0: result += val; break;
528                                 case 1: result *= val; break;
529                                 }
530                                 hit = 1;
531                         }
532                 }
533         } while (hit);
534         err = snd_config_get_id(src, &id);
535         if (err >= 0)
536                 err = snd_config_imake_integer(dst, id, result);
537         free(res);
538       __error:
539         return err;
540 }
541
542
543 /**
544  * \brief Sum the given integers.
545  * \param dst The function puts the handle to the result configuration node
546  *            (with type integer) at the address specified by \p dst.
547  * \param root Handle to the root source node.
548  * \param src Handle to the source node, with a definition for \c integers.
549  * \param private_data Handle to the \c private_data node.
550  * \return A non-negative value if successful, otherwise a negative error code.
551  *
552  * Example (result is 10):
553 \code
554         {
555                 @func iadd
556                 integers [ 2 3 5 ]
557         }
558 \endcode
559  */ 
560 int snd_func_iadd(snd_config_t **dst, snd_config_t *root,
561                   snd_config_t *src, snd_config_t *private_data)
562 {
563         return snd_func_iops(dst, root, src, private_data, 0);
564 }
565 #ifndef DOC_HIDDEN
566 SND_DLSYM_BUILD_VERSION(snd_func_iadd, SND_CONFIG_DLSYM_VERSION_EVALUATE);
567 #endif
568
569 /**
570  * \brief Multiply the given integers.
571  * \param dst The function puts the handle to the result configuration node
572  *            (with type integer) at the address specified by \p dst.
573  * \param root Handle to the root source node.
574  * \param src Handle to the source node, with a definition for \c integers.
575  * \param private_data Handle to the \c private_data node.
576  * \return A non-negative value if successful, otherwise a negative error code.
577  *
578  * Example (result is 12):
579 \code
580         {
581                 @func imul
582                 integers [ 2 3 2 ]
583         }
584 \endcode
585  */ 
586 int snd_func_imul(snd_config_t **dst, snd_config_t *root,
587                   snd_config_t *src, snd_config_t *private_data)
588 {
589         return snd_func_iops(dst, root, src, private_data, 1);
590 }
591 #ifndef DOC_HIDDEN
592 SND_DLSYM_BUILD_VERSION(snd_func_imul, SND_CONFIG_DLSYM_VERSION_EVALUATE);
593 #endif
594
595 /**
596  * \brief Returns the ALSA data directory.
597  * \param dst The function puts the handle to the result configuration node
598  *            (with type string) at the address specified by \p dst.
599  * \param root Handle to the root source node.
600  * \param src Handle to the source node.
601  * \param private_data Handle to the \c private_data node. Not used.
602  * \return A non-negative value if successful, otherwise a negative error code.
603  *
604  * Example (result is "/usr/share/alsa" using the default paths):
605 \code
606         {
607                 @func datadir
608         }
609 \endcode
610  */ 
611 int snd_func_datadir(snd_config_t **dst, snd_config_t *root ATTRIBUTE_UNUSED,
612                      snd_config_t *src, snd_config_t *private_data ATTRIBUTE_UNUSED)
613 {
614         int err;
615         const char *id;
616         
617         err = snd_config_get_id(src, &id);
618         if (err < 0)
619                 return err;
620         return snd_config_imake_string(dst, id, snd_config_topdir());
621 }
622 #ifndef DOC_HIDDEN
623 SND_DLSYM_BUILD_VERSION(snd_func_datadir, SND_CONFIG_DLSYM_VERSION_EVALUATE);
624 #endif
625
626 static int open_ctl(long card, snd_ctl_t **ctl)
627 {
628         char name[16];
629         snprintf(name, sizeof(name), "hw:%li", card);
630         name[sizeof(name)-1] = '\0';
631         return snd_ctl_open(ctl, name, 0);
632 }
633
634 #if 0
635 static int string_from_integer(char **dst, long v)
636 {
637         char str[32];
638         char *res;
639         sprintf(str, "%li", v);
640         res = strdup(str);
641         if (res == NULL)
642                 return -ENOMEM;
643         *dst = res;
644         return 0;
645 }
646 #endif
647
648 int _snd_func_private_data(snd_config_t **dst, snd_config_t *src,
649                            snd_config_t **private_data, const char *id)
650 {
651         int err;
652
653         if (*private_data == NULL)
654                 return snd_config_copy(dst, src);
655         if (snd_config_get_type(*private_data) == SND_CONFIG_TYPE_COMPOUND) {
656                 err = snd_config_search(*private_data, id, private_data);
657                 if (err)
658                         goto notfound;
659         }
660         err = snd_config_test_id(*private_data, id);
661         if (err) {
662 notfound:
663                 SNDERR("field %s not found", id);
664                 return -EINVAL;
665         }
666         return 0;
667 }
668
669
670 /**
671  * \brief Returns the string from \c private_data.
672  * \param dst The function puts the handle to the result configuration node
673  *            (with type string) at the address specified by \p dst.
674  * \param root Handle to the root source node.
675  * \param src Handle to the source node.
676  * \param private_data Handle to the \c private_data node (type string,
677  *                     id "string").
678  * \return A non-negative value if successful, otherwise a negative error code.
679  *
680  * Example:
681 \code
682         {
683                 @func private_string
684         }
685 \endcode
686  */ 
687 int snd_func_private_string(snd_config_t **dst, snd_config_t *root ATTRIBUTE_UNUSED,
688                             snd_config_t *src, snd_config_t *private_data)
689 {
690         int err;
691         const char *str, *id;
692
693         err = _snd_func_private_data(dst, src, &private_data, "string");
694         if (err)
695                 return err;
696         err = snd_config_get_string(private_data, &str);
697         if (err < 0) {
698                 SNDERR("field string is not a string");
699                 return err;
700         }
701         err = snd_config_get_id(src, &id);
702         if (err >= 0)
703                 err = snd_config_imake_string(dst, id, str);
704         return err;
705 }
706 #ifndef DOC_HIDDEN
707 SND_DLSYM_BUILD_VERSION(snd_func_private_string, SND_CONFIG_DLSYM_VERSION_EVALUATE);
708 #endif
709
710 /**
711  * \brief Returns the integer from \c private_data.
712  * \param dst The function puts the handle to the result configuration node
713  *            (with type integer) at the address specified by \p dst.
714  * \param root Handle to the root source node.
715  * \param src Handle to the source node.
716  * \param private_data Handle to the \c private_data node (type integer,
717  *                     id "integer").
718  * \return A non-negative value if successful, otherwise a negative error code.
719  *
720  * Example:
721 \code
722         {
723                 @func private_integer
724         }
725 \endcode
726  */
727 int snd_func_private_integer(snd_config_t **dst, snd_config_t *root ATTRIBUTE_UNUSED,
728                              snd_config_t *src, snd_config_t *private_data)
729 {
730         int err;
731         const char *id;
732         long val;
733
734         err = _snd_func_private_data(dst, src, &private_data, "integer");
735         if (err)
736                 return err;
737         err = snd_config_get_integer(private_data, &val);
738         if (err < 0) {
739                 SNDERR("field integer is not a string");
740                 return err;
741         }
742         err = snd_config_get_id(src, &id);
743         if (err >= 0)
744                 err = snd_config_imake_integer(dst, id, val);
745         return err;
746 }
747 #ifndef DOC_HIDDEN
748 SND_DLSYM_BUILD_VERSION(snd_func_private_integer, SND_CONFIG_DLSYM_VERSION_EVALUATE);
749 #endif
750
751 #ifndef DOC_HIDDEN
752 int snd_determine_driver(int card, char **driver)
753 {
754         snd_ctl_t *ctl = NULL;
755         snd_ctl_card_info_t info = {0};
756         char *res = NULL;
757         int err;
758
759         assert(card >= 0 && card <= SND_MAX_CARDS);
760         err = open_ctl(card, &ctl);
761         if (err < 0) {
762                 SNDERR("could not open control for card %i", card);
763                 goto __error;
764         }
765         err = snd_ctl_card_info(ctl, &info);
766         if (err < 0) {
767                 SNDERR("snd_ctl_card_info error: %s", snd_strerror(err));
768                 goto __error;
769         }
770         res = strdup(snd_ctl_card_info_get_driver(&info));
771         if (res == NULL)
772                 err = -ENOMEM;
773         else {
774                 *driver = res;
775                 err = 0;
776         }
777       __error:
778         if (ctl)
779                 snd_ctl_close(ctl);
780         return err;
781 }
782 #endif
783
784 /**
785  * \brief Returns the driver identification from \c private_data.
786  * \param dst The function puts the handle to the result configuration node
787  *            (with type string) at the address specified by \p dst.
788  * \param root Handle to the root source node.
789  * \param src Handle to the source node.
790  * \param private_data Handle to the \c private_data node (type integer,
791  *                     id "card").
792  * \return A non-negative value if successful, otherwise a negative error code.
793  *
794  * Example:
795 \code
796         {
797                 @func private_card_driver
798         }
799 \endcode
800  */ 
801 int snd_func_private_card_driver(snd_config_t **dst, snd_config_t *root ATTRIBUTE_UNUSED, snd_config_t *src,
802                                  snd_config_t *private_data)
803 {
804         char *driver;
805         const char *id;
806         int err;
807         long card;
808
809         err = snd_config_test_id(private_data, "card");
810         if (err) {
811                 SNDERR("field card not found");
812                 return -EINVAL;
813         }
814         err = snd_config_get_integer(private_data, &card);
815         if (err < 0) {
816                 SNDERR("field card is not an integer");
817                 return err;
818         }
819         if ((err = snd_determine_driver(card, &driver)) < 0)
820                 return err;
821         err = snd_config_get_id(src, &id);
822         if (err >= 0)
823                 err = snd_config_imake_string(dst, id, driver);
824         free(driver);
825         return err;
826 }
827 #ifndef DOC_HIDDEN
828 SND_DLSYM_BUILD_VERSION(snd_func_private_card_driver, SND_CONFIG_DLSYM_VERSION_EVALUATE);
829 #endif
830
831 static int parse_card(snd_config_t *root, snd_config_t *src,
832                       snd_config_t *private_data)
833 {
834         snd_config_t *n;
835         char *str;
836         int card, err;
837         
838         err = snd_config_search(src, "card", &n);
839         if (err < 0) {
840                 SNDERR("field card not found");
841                 return err;
842         }
843         err = snd_config_evaluate(n, root, private_data, NULL);
844         if (err < 0) {
845                 SNDERR("error evaluating card");
846                 return err;
847         }
848         err = snd_config_get_ascii(n, &str);
849         if (err < 0) {
850                 SNDERR("field card is not an integer or a string");
851                 return err;
852         }
853         card = snd_card_get_index(str);
854         if (card < 0)
855                 SNDERR("cannot find card '%s'", str);
856         free(str);
857         return card;
858 }
859
860 /**
861  * \brief Returns the card number as integer.
862  * \param dst The function puts the handle to the result configuration node
863  *            (with type string) at the address specified by \p dst.
864  * \param root Handle to the root source node.
865  * \param src Handle to the source node, with a \c card definition.
866  * \param private_data Handle to the \c private_data node.
867  * \return A non-negative value if successful, otherwise a negative error code.
868  *
869  * Example:
870 \code
871         {
872                 @func card_inum
873                 card '0'
874         }
875 \endcode
876  */ 
877 int snd_func_card_inum(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
878                        snd_config_t *private_data)
879 {
880         const char *id;
881         int card, err;
882         
883         card = parse_card(root, src, private_data);
884         if (card < 0)
885                 return card;
886         err = snd_config_get_id(src, &id);
887         if (err >= 0)
888                 err = snd_config_imake_integer(dst, id, card);
889         return err;
890 }
891 #ifndef DOC_HIDDEN
892 SND_DLSYM_BUILD_VERSION(snd_func_card_inum, SND_CONFIG_DLSYM_VERSION_EVALUATE);
893 #endif
894
895 /**
896  * \brief Returns the driver identification for a card.
897  * \param dst The function puts the handle to the result configuration node
898  *            (with type string) at the address specified by \p dst.
899  * \param root Handle to the root source node.
900  * \param src Handle to the source node, with a \c card definition.
901  * \param private_data Handle to the \c private_data node.
902  * \return A non-negative value if successful, otherwise a negative error code.
903  *
904  * Example:
905 \code
906         {
907                 @func card_driver
908                 card 0
909         }
910 \endcode
911  */ 
912 int snd_func_card_driver(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
913                          snd_config_t *private_data)
914 {
915         snd_config_t *val;
916         int card, err;
917         
918         card = parse_card(root, src, private_data);
919         if (card < 0)
920                 return card;
921         err = snd_config_imake_integer(&val, "card", card);
922         if (err < 0)
923                 return err;
924         err = snd_func_private_card_driver(dst, root, src, val);
925         snd_config_delete(val);
926         return err;
927 }
928 #ifndef DOC_HIDDEN
929 SND_DLSYM_BUILD_VERSION(snd_func_card_driver, SND_CONFIG_DLSYM_VERSION_EVALUATE);
930 #endif
931
932 /**
933  * \brief Returns the identification of a card.
934  * \param dst The function puts the handle to the result configuration node
935  *            (with type string) at the address specified by \p dst.
936  * \param root Handle to the root source node.
937  * \param src Handle to the source node, with a \c card definition.
938  * \param private_data Handle to the \c private_data node.
939  * \return A non-negative value if successful, otherwise a negative error code.
940  *
941  * Example:
942 \code
943         {
944                 @func card_id
945                 card 0
946         }
947 \endcode
948  */ 
949 int snd_func_card_id(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
950                      snd_config_t *private_data)
951 {
952         snd_ctl_t *ctl = NULL;
953         snd_ctl_card_info_t info = {0};
954         const char *id;
955         int card, err;
956         
957         card = parse_card(root, src, private_data);
958         if (card < 0)
959                 return card;
960         err = open_ctl(card, &ctl);
961         if (err < 0) {
962                 SNDERR("could not open control for card %i", card);
963                 goto __error;
964         }
965         err = snd_ctl_card_info(ctl, &info);
966         if (err < 0) {
967                 SNDERR("snd_ctl_card_info error: %s", snd_strerror(err));
968                 goto __error;
969         }
970         err = snd_config_get_id(src, &id);
971         if (err >= 0)
972                 err = snd_config_imake_string(dst, id,
973                                               snd_ctl_card_info_get_id(&info));
974       __error:
975         if (ctl)
976                 snd_ctl_close(ctl);
977         return err;
978 }
979 #ifndef DOC_HIDDEN
980 SND_DLSYM_BUILD_VERSION(snd_func_card_id, SND_CONFIG_DLSYM_VERSION_EVALUATE);
981 #endif
982
983 /**
984  * \brief Returns the name of a card.
985  * \param dst The function puts the handle to the result configuration node
986  *            (with type string) at the address specified by \p dst.
987  * \param root Handle to the root source node.
988  * \param src Handle to the source node, with a \c card definition.
989  * \param private_data Handle to the \c private_data node.
990  * \return A non-negative value if successful, otherwise a negative error code.
991  *
992  * Example:
993 \code
994         {
995                 @func card_name
996                 card 0
997         }
998 \endcode
999  */ 
1000 int snd_func_card_name(snd_config_t **dst, snd_config_t *root,
1001                        snd_config_t *src, snd_config_t *private_data)
1002 {
1003         snd_ctl_t *ctl = NULL;
1004         snd_ctl_card_info_t info = {0};
1005         const char *id;
1006         int card, err;
1007         
1008         card = parse_card(root, src, private_data);
1009         if (card < 0)
1010                 return card;
1011         err = open_ctl(card, &ctl);
1012         if (err < 0) {
1013                 SNDERR("could not open control for card %i", card);
1014                 goto __error;
1015         }
1016         err = snd_ctl_card_info(ctl, &info);
1017         if (err < 0) {
1018                 SNDERR("snd_ctl_card_info error: %s", snd_strerror(err));
1019                 goto __error;
1020         }
1021         err = snd_config_get_id(src, &id);
1022         if (err >= 0)
1023                 err = snd_config_imake_safe_string(dst, id,
1024                                         snd_ctl_card_info_get_name(&info));
1025       __error:
1026         if (ctl)
1027                 snd_ctl_close(ctl);
1028         return err;
1029 }
1030 #ifndef DOC_HIDDEN
1031 SND_DLSYM_BUILD_VERSION(snd_func_card_name, SND_CONFIG_DLSYM_VERSION_EVALUATE);
1032 #endif
1033
1034 #ifdef BUILD_PCM
1035
1036 /**
1037  * \brief Returns the pcm identification of a device.
1038  * \param dst The function puts the handle to the result configuration node
1039  *            (with type string) at the address specified by \p dst.
1040  * \param root Handle to the root source node.
1041  * \param src Handle to the source node, with definitions for \c card,
1042  *            \c device and (optionally) \c subdevice.
1043  * \param private_data Handle to the \c private_data node.
1044  * \return A non-negative value if successful, otherwise a negative error code.
1045  *
1046  * Example:
1047 \code
1048         {
1049                 @func pcm_id
1050                 card 0
1051                 device 0
1052                 subdevice 0     # optional
1053         }
1054 \endcode
1055  */ 
1056 int snd_func_pcm_id(snd_config_t **dst, snd_config_t *root, snd_config_t *src, void *private_data)
1057 {
1058         snd_config_t *n;
1059         snd_ctl_t *ctl = NULL;
1060         snd_pcm_info_t info = {0};
1061         const char *id;
1062         long card, device, subdevice = 0;
1063         int err;
1064         
1065         card = parse_card(root, src, private_data);
1066         if (card < 0)
1067                 return card;
1068         err = snd_config_search(src, "device", &n);
1069         if (err < 0) {
1070                 SNDERR("field device not found");
1071                 goto __error;
1072         }
1073         err = snd_config_evaluate(n, root, private_data, NULL);
1074         if (err < 0) {
1075                 SNDERR("error evaluating device");
1076                 goto __error;
1077         }
1078         err = snd_config_get_integer(n, &device);
1079         if (err < 0) {
1080                 SNDERR("field device is not an integer");
1081                 goto __error;
1082         }
1083         if (snd_config_search(src, "subdevice", &n) >= 0) {
1084                 err = snd_config_evaluate(n, root, private_data, NULL);
1085                 if (err < 0) {
1086                         SNDERR("error evaluating subdevice");
1087                         goto __error;
1088                 }
1089                 err = snd_config_get_integer(n, &subdevice);
1090                 if (err < 0) {
1091                         SNDERR("field subdevice is not an integer");
1092                         goto __error;
1093                 }
1094         }
1095         err = open_ctl(card, &ctl);
1096         if (err < 0) {
1097                 SNDERR("could not open control for card %li", card);
1098                 goto __error;
1099         }
1100         snd_pcm_info_set_device(&info, device);
1101         snd_pcm_info_set_subdevice(&info, subdevice);
1102         err = snd_ctl_pcm_info(ctl, &info);
1103         if (err < 0) {
1104                 SNDERR("snd_ctl_pcm_info error: %s", snd_strerror(err));
1105                 goto __error;
1106         }
1107         err = snd_config_get_id(src, &id);
1108         if (err >= 0)
1109                 err = snd_config_imake_string(dst, id,
1110                                                 snd_pcm_info_get_id(&info));
1111       __error:
1112         if (ctl)
1113                 snd_ctl_close(ctl);
1114         return err;
1115 }
1116 #ifndef DOC_HIDDEN
1117 SND_DLSYM_BUILD_VERSION(snd_func_pcm_id, SND_CONFIG_DLSYM_VERSION_EVALUATE);
1118 #endif
1119
1120 /**
1121  * \brief Returns the pcm card and device arguments (in form CARD=N,DEV=M)
1122  *                for pcm specified by class and index.
1123  * \param dst The function puts the handle to the result configuration node
1124  *            (with type string) at the address specified by \p dst.
1125  * \param root Handle to the root source node.
1126  * \param src Handle to the source node, with definitions for \c class
1127  *            and \c index.
1128  * \param private_data Handle to the \c private_data node.
1129  * \return A non-negative value if successful, otherwise a negative error code.
1130  *
1131  * Example:
1132 \code
1133         {
1134                 @func pcm_args_by_class
1135                 class 0
1136                 index 0
1137         }
1138 \endcode
1139  */ 
1140 int snd_func_pcm_args_by_class(snd_config_t **dst, snd_config_t *root, snd_config_t *src, void *private_data)
1141 {
1142         snd_config_t *n;
1143         snd_ctl_t *ctl = NULL;
1144         snd_pcm_info_t info = {0};
1145         const char *id;
1146         int card = -1, dev;
1147         long class, index;
1148         int idx = 0;
1149         int err;
1150
1151         err = snd_config_search(src, "class", &n);
1152         if (err < 0) {
1153                 SNDERR("field class not found");
1154                 goto __out;
1155         }
1156         err = snd_config_evaluate(n, root, private_data, NULL);
1157         if (err < 0) {
1158                 SNDERR("error evaluating class");
1159                 goto __out;
1160         }
1161         err = snd_config_get_integer(n, &class);
1162         if (err < 0) {
1163                 SNDERR("field class is not an integer");
1164                 goto __out;
1165         }
1166         err = snd_config_search(src, "index", &n);
1167         if (err < 0) {
1168                 SNDERR("field index not found");
1169                 goto __out;
1170         }
1171         err = snd_config_evaluate(n, root, private_data, NULL);
1172         if (err < 0) {
1173                 SNDERR("error evaluating index");
1174                 goto __out;
1175         }
1176         err = snd_config_get_integer(n, &index);
1177         if (err < 0) {
1178                 SNDERR("field index is not an integer");
1179                 goto __out;
1180         }
1181
1182         while(1) {
1183                 err = snd_card_next(&card);
1184                 if (err < 0) {
1185                         SNDERR("could not get next card");
1186                         goto __out;
1187                 }
1188                 if (card < 0)
1189                         break;
1190                 err = open_ctl(card, &ctl);
1191                 if (err < 0) {
1192                         SNDERR("could not open control for card %i", card);
1193                         goto __out;
1194                 }
1195                 dev = -1;
1196                 while(1) {
1197                         err = snd_ctl_pcm_next_device(ctl, &dev);
1198                         if (err < 0) {
1199                                 SNDERR("could not get next pcm for card %i", card);
1200                                 goto __out;
1201                         }
1202                         if (dev < 0)
1203                                 break;
1204                         snd_pcm_info_set_device(&info, dev);
1205                         err = snd_ctl_pcm_info(ctl, &info);
1206                         if (err < 0)
1207                                 continue;
1208                         if (snd_pcm_info_get_class(&info) == (snd_pcm_class_t)class &&
1209                                         index == idx++)
1210                                 goto __out;
1211                 }
1212                 snd_ctl_close(ctl);
1213                 ctl = NULL;
1214         }
1215         err = -ENODEV;
1216
1217       __out:
1218         if (ctl)
1219                 snd_ctl_close(ctl);
1220         if (err < 0)
1221                 return err;
1222         if((err = snd_config_get_id(src, &id)) >= 0) {
1223                 char name[32];
1224                 snprintf(name, sizeof(name), "CARD=%i,DEV=%i", card, dev);
1225                 err = snd_config_imake_string(dst, id, name);
1226         }
1227         return err;
1228 }
1229 #ifndef DOC_HIDDEN
1230 SND_DLSYM_BUILD_VERSION(snd_func_pcm_args_by_class, SND_CONFIG_DLSYM_VERSION_EVALUATE);
1231 #endif
1232
1233 /**
1234  * \brief Returns the PCM subdevice from \c private_data.
1235  * \param dst The function puts the handle to the result configuration node
1236  *            (with type integer) at the address specified by \p dst.
1237  * \param root Handle to the root source node.
1238  * \param src Handle to the source node.
1239  * \param private_data Handle to the \c private_data node (type pointer,
1240  *                     id "pcm_handle").
1241  * \return A non-negative value if successful, otherwise a negative error code.
1242  *
1243  * Example:
1244 \code
1245         {
1246                 @func private_pcm_subdevice
1247         }
1248 \endcode
1249  */ 
1250 int snd_func_private_pcm_subdevice(snd_config_t **dst, snd_config_t *root ATTRIBUTE_UNUSED,
1251                                    snd_config_t *src, snd_config_t *private_data)
1252 {
1253         snd_pcm_info_t info = {0};
1254         const char *id;
1255         const void *data;
1256         snd_pcm_t *pcm;
1257         int err;
1258
1259         if (private_data == NULL)
1260                 return snd_config_copy(dst, src);
1261         err = snd_config_test_id(private_data, "pcm_handle");
1262         if (err) {
1263                 SNDERR("field pcm_handle not found");
1264                 return -EINVAL;
1265         }
1266         err = snd_config_get_pointer(private_data, &data);
1267         pcm = (snd_pcm_t *)data;
1268         if (err < 0) {
1269                 SNDERR("field pcm_handle is not a pointer");
1270                 return err;
1271         }
1272         err = snd_pcm_info(pcm, &info);
1273         if (err < 0) {
1274                 SNDERR("snd_ctl_pcm_info error: %s", snd_strerror(err));
1275                 return err;
1276         }
1277         err = snd_config_get_id(src, &id);
1278         if (err >= 0)
1279                 err = snd_config_imake_integer(dst, id,
1280                                         snd_pcm_info_get_subdevice(&info));
1281         return err;
1282 }
1283 #ifndef DOC_HIDDEN
1284 SND_DLSYM_BUILD_VERSION(snd_func_private_pcm_subdevice, SND_CONFIG_DLSYM_VERSION_EVALUATE);
1285 #endif
1286
1287 #endif /* BUILD_PCM */
1288
1289 /**
1290  * \brief Copies the specified configuration node.
1291  * \param dst The function puts the handle to the result configuration node
1292  *            (with the same type as the specified node) at the address
1293  *            specified by \p dst.
1294  * \param root Handle to the root source node.
1295  * \param src Handle to the source node, with definitions for \c name and
1296  *            (optionally) \c file.
1297  * \param private_data Handle to the \c private_data node.
1298  * \return A non-negative value if successful, otherwise a negative error code.
1299  * \note The root source node can be modified!
1300  *
1301  * Example:
1302 \code
1303         {
1304                 @func refer
1305                 file "/etc/myconf.conf"         # optional
1306                 name "id1.id2.id3"
1307         }
1308 \endcode
1309  */ 
1310 int snd_func_refer(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
1311                    snd_config_t *private_data)
1312 {
1313         snd_config_t *n;
1314         const char *file = NULL, *name = NULL;
1315         int err;
1316         
1317         err = snd_config_search(src, "file", &n);
1318         if (err >= 0) {
1319                 err = snd_config_evaluate(n, root, private_data, NULL);
1320                 if (err < 0) {
1321                         SNDERR("error evaluating file");
1322                         goto _end;
1323                 }
1324                 err = snd_config_get_string(n, &file);
1325                 if (err < 0) {
1326                         SNDERR("file is not a string");
1327                         goto _end;
1328                 }
1329         }
1330         err = snd_config_search(src, "name", &n);
1331         if (err >= 0) {
1332                 err = snd_config_evaluate(n, root, private_data, NULL);
1333                 if (err < 0) {
1334                         SNDERR("error evaluating name");
1335                         goto _end;
1336                 }
1337                 err = snd_config_get_string(n, &name);
1338                 if (err < 0) {
1339                         SNDERR("name is not a string");
1340                         goto _end;
1341                 }
1342         }
1343         if (!name) {
1344                 err = -EINVAL;
1345                 SNDERR("name is not specified");
1346                 goto _end;
1347         }
1348         if (file) {
1349                 snd_input_t *input;
1350                 err = snd_input_stdio_open(&input, file, "r");
1351                 if (err < 0) {
1352                         SNDERR("Unable to open file %s: %s", file, snd_strerror(err));
1353                         goto _end;
1354                 }
1355                 err = snd_config_load(root, input);
1356                 snd_input_close(input);
1357                 if (err < 0)
1358                         goto _end;
1359         }
1360         err = snd_config_search_definition(root, NULL, name, dst);
1361         if (err >= 0) {
1362                 const char *id;
1363                 err = snd_config_get_id(src, &id);
1364                 if (err >= 0)
1365                         err = snd_config_set_id(*dst, id);
1366         } else {
1367                 err = snd_config_search(src, "default", &n);
1368                 if (err < 0)
1369                         SNDERR("Unable to find definition '%s'", name);
1370                 else {
1371                         const char *id;
1372                         err = snd_config_evaluate(n, root, private_data, NULL);
1373                         if (err < 0)
1374                                 return err;
1375                         if ((err = snd_config_copy(dst, n)) >= 0) {
1376                                 if ((err = snd_config_get_id(src, &id)) < 0 ||
1377                                     (err = snd_config_set_id(*dst, id)) < 0)
1378                                         snd_config_delete(*dst);
1379                         }
1380                 }
1381         }
1382  _end:
1383         return err;
1384 }
1385 #ifndef DOC_HIDDEN
1386 SND_DLSYM_BUILD_VERSION(snd_func_refer, SND_CONFIG_DLSYM_VERSION_EVALUATE);
1387 #endif
1388
1389 #ifndef DOC_HIDDEN
1390 int _snd_conf_generic_id(const char *id)
1391 {
1392         static const char ids[3][8] = { "comment", "type", "hint" };
1393         unsigned int k;
1394         for (k = 0; k < sizeof(ids) / sizeof(ids[0]); ++k) {
1395                 if (strcmp(id, ids[k]) == 0)
1396                         return 1;
1397         }
1398         return 0;
1399 }
1400 #endif