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