00001
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00069 #include <stdlib.h>
00070 #include <stdio.h>
00071 #include <string.h>
00072 #include <ctype.h>
00073 #include "local.h"
00074
00080 int snd_config_get_bool_ascii(const char *ascii)
00081 {
00082 unsigned int k;
00083 static struct {
00084 const char *str;
00085 int val;
00086 } b[] = {
00087 { "0", 0 },
00088 { "1", 1 },
00089 { "false", 0 },
00090 { "true", 1 },
00091 { "no", 0 },
00092 { "yes", 1 },
00093 { "off", 0 },
00094 { "on", 1 },
00095 };
00096 for (k = 0; k < sizeof(b) / sizeof(*b); k++) {
00097 if (strcasecmp(b[k].str, ascii) == 0)
00098 return b[k].val;
00099 }
00100 return -EINVAL;
00101 }
00102
00108 int snd_config_get_bool(const snd_config_t *conf)
00109 {
00110 long v;
00111 const char *str, *id;
00112 int err;
00113
00114 err = snd_config_get_id(conf, &id);
00115 if (err < 0)
00116 return err;
00117 err = snd_config_get_integer(conf, &v);
00118 if (err >= 0) {
00119 if (v < 0 || v > 1) {
00120 _invalid_value:
00121 SNDERR("Invalid value for %s", id);
00122 return -EINVAL;
00123 }
00124 return v;
00125 }
00126 err = snd_config_get_string(conf, &str);
00127 if (err < 0) {
00128 SNDERR("Invalid type for %s", id);
00129 return -EINVAL;
00130 }
00131 err = snd_config_get_bool_ascii(str);
00132 if (err < 0)
00133 goto _invalid_value;
00134 return err;
00135 }
00136
00142 int snd_config_get_ctl_iface_ascii(const char *ascii)
00143 {
00144 long v;
00145 snd_ctl_elem_iface_t idx;
00146 if (isdigit(ascii[0])) {
00147 if (safe_strtol(ascii, &v) >= 0) {
00148 if (v < 0 || v > SND_CTL_ELEM_IFACE_LAST)
00149 return -EINVAL;
00150 return v;
00151 }
00152 }
00153 for (idx = 0; idx <= SND_CTL_ELEM_IFACE_LAST; idx++) {
00154 if (strcasecmp(snd_ctl_elem_iface_name(idx), ascii) == 0)
00155 return idx;
00156 }
00157 return -EINVAL;
00158 }
00159
00165 int snd_config_get_ctl_iface(const snd_config_t *conf)
00166 {
00167 long v;
00168 const char *str, *id;
00169 int err;
00170
00171 err = snd_config_get_id(conf, &id);
00172 if (err < 0)
00173 return err;
00174 err = snd_config_get_integer(conf, &v);
00175 if (err >= 0) {
00176 if (v < 0 || v > SND_CTL_ELEM_IFACE_LAST) {
00177 _invalid_value:
00178 SNDERR("Invalid value for %s", id);
00179 return -EINVAL;
00180 }
00181 return v;
00182 }
00183 err = snd_config_get_string(conf, &str);
00184 if (err < 0) {
00185 SNDERR("Invalid type for %s", id);
00186 return -EINVAL;
00187 }
00188 err = snd_config_get_ctl_iface_ascii(str);
00189 if (err < 0)
00190 goto _invalid_value;
00191 return err;
00192 }
00193
00194
00195
00196
00197
00217 int snd_func_getenv(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
00218 snd_config_t *private_data)
00219 {
00220 snd_config_t *n, *d;
00221 snd_config_iterator_t i, next;
00222 char *res, *def = NULL;
00223 int idx = 0, err, hit;
00224
00225 err = snd_config_search(src, "vars", &n);
00226 if (err < 0) {
00227 SNDERR("field vars not found");
00228 goto __error;
00229 }
00230 err = snd_config_evaluate(n, root, private_data, NULL);
00231 if (err < 0) {
00232 SNDERR("error evaluating vars");
00233 goto __error;
00234 }
00235 err = snd_config_search(src, "default", &d);
00236 if (err < 0) {
00237 SNDERR("field default not found");
00238 goto __error;
00239 }
00240 err = snd_config_evaluate(d, root, private_data, NULL);
00241 if (err < 0) {
00242 SNDERR("error evaluating default");
00243 goto __error;
00244 }
00245 err = snd_config_get_ascii(d, &def);
00246 if (err < 0) {
00247 SNDERR("error getting field default");
00248 goto __error;
00249 }
00250 do {
00251 hit = 0;
00252 snd_config_for_each(i, next, n) {
00253 snd_config_t *n = snd_config_iterator_entry(i);
00254 const char *id, *ptr, *env;
00255 long i;
00256 if (snd_config_get_id(n, &id) < 0)
00257 continue;
00258 if (snd_config_get_type(n) != SND_CONFIG_TYPE_STRING) {
00259 SNDERR("field %s is not a string", id);
00260 err = -EINVAL;
00261 goto __error;
00262 }
00263 err = safe_strtol(id, &i);
00264 if (err < 0) {
00265 SNDERR("id of field %s is not an integer", id);
00266 err = -EINVAL;
00267 goto __error;
00268 }
00269 if (i == idx) {
00270 idx++;
00271 err = snd_config_get_string(n, &ptr);
00272 if (err < 0) {
00273 SNDERR("invalid string for id %s", id);
00274 err = -EINVAL;
00275 goto __error;
00276 }
00277 env = getenv(ptr);
00278 if (env != NULL && *env != '\0') {
00279 res = strdup(env);
00280 goto __ok;
00281 }
00282 hit = 1;
00283 }
00284 }
00285 } while (hit);
00286 res = def;
00287 def = NULL;
00288 __ok:
00289 err = res == NULL ? -ENOMEM : 0;
00290 if (err >= 0) {
00291 const char *id;
00292 err = snd_config_get_id(src, &id);
00293 if (err >= 0)
00294 err = snd_config_imake_string(dst, id, res);
00295 free(res);
00296 }
00297 __error:
00298 free(def);
00299 return err;
00300 }
00301 #ifndef DOC_HIDDEN
00302 SND_DLSYM_BUILD_VERSION(snd_func_getenv, SND_CONFIG_DLSYM_VERSION_EVALUATE);
00303 #endif
00304
00324 int snd_func_igetenv(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
00325 snd_config_t *private_data)
00326 {
00327 snd_config_t *d;
00328 const char *str, *id;
00329 int err;
00330 long v;
00331
00332 err = snd_func_getenv(&d, root, src, private_data);
00333 if (err < 0)
00334 return err;
00335 err = snd_config_get_string(d, &str);
00336 if (err < 0) {
00337 snd_config_delete(d);
00338 return err;
00339 }
00340 err = safe_strtol(str, &v);
00341 if (err < 0) {
00342 snd_config_delete(d);
00343 return err;
00344 }
00345 snd_config_delete(d);
00346 err = snd_config_get_id(src, &id);
00347 if (err < 0)
00348 return err;
00349 err = snd_config_imake_integer(dst, id, v);
00350 if (err < 0)
00351 return err;
00352 return 0;
00353 }
00354 #ifndef DOC_HIDDEN
00355 SND_DLSYM_BUILD_VERSION(snd_func_igetenv, SND_CONFIG_DLSYM_VERSION_EVALUATE);
00356 #endif
00357
00375 int snd_func_concat(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
00376 snd_config_t *private_data)
00377 {
00378 snd_config_t *n;
00379 snd_config_iterator_t i, next;
00380 const char *id;
00381 char *res = NULL, *tmp;
00382 int idx = 0, len = 0, len1, err, hit;
00383
00384 err = snd_config_search(src, "strings", &n);
00385 if (err < 0) {
00386 SNDERR("field strings not found");
00387 goto __error;
00388 }
00389 err = snd_config_evaluate(n, root, private_data, NULL);
00390 if (err < 0) {
00391 SNDERR("error evaluating strings");
00392 goto __error;
00393 }
00394 do {
00395 hit = 0;
00396 snd_config_for_each(i, next, n) {
00397 snd_config_t *n = snd_config_iterator_entry(i);
00398 char *ptr;
00399 const char *id;
00400 long i;
00401 if (snd_config_get_id(n, &id) < 0)
00402 continue;
00403 err = safe_strtol(id, &i);
00404 if (err < 0) {
00405 SNDERR("id of field %s is not an integer", id);
00406 err = -EINVAL;
00407 goto __error;
00408 }
00409 if (i == idx) {
00410 idx++;
00411 err = snd_config_get_ascii(n, &ptr);
00412 if (err < 0) {
00413 SNDERR("invalid ascii string for id %s", id);
00414 err = -EINVAL;
00415 goto __error;
00416 }
00417 len1 = strlen(ptr);
00418 tmp = realloc(res, len + len1 + 1);
00419 if (tmp == NULL) {
00420 free(ptr);
00421 free(res);
00422 err = -ENOMEM;
00423 goto __error;
00424 }
00425 memcpy(tmp + len, ptr, len1);
00426 free(ptr);
00427 len += len1;
00428 tmp[len] = '\0';
00429 res = tmp;
00430 hit = 1;
00431 }
00432 }
00433 } while (hit);
00434 if (res == NULL) {
00435 SNDERR("empty string is not accepted");
00436 err = -EINVAL;
00437 goto __error;
00438 }
00439 err = snd_config_get_id(src, &id);
00440 if (err >= 0)
00441 err = snd_config_imake_string(dst, id, res);
00442 free(res);
00443 __error:
00444 return err;
00445 }
00446 #ifndef DOC_HIDDEN
00447 SND_DLSYM_BUILD_VERSION(snd_func_concat, SND_CONFIG_DLSYM_VERSION_EVALUATE);
00448 #endif
00449
00466 int snd_func_datadir(snd_config_t **dst, snd_config_t *root ATTRIBUTE_UNUSED,
00467 snd_config_t *src, snd_config_t *private_data ATTRIBUTE_UNUSED)
00468 {
00469 int err;
00470 const char *id;
00471
00472 err = snd_config_get_id(src, &id);
00473 if (err < 0)
00474 return err;
00475 return snd_config_imake_string(dst, id, "/share" "/alsa");
00476 }
00477 #ifndef DOC_HIDDEN
00478 SND_DLSYM_BUILD_VERSION(snd_func_datadir, SND_CONFIG_DLSYM_VERSION_EVALUATE);
00479 #endif
00480
00481 static int open_ctl(long card, snd_ctl_t **ctl)
00482 {
00483 char name[16];
00484 snprintf(name, sizeof(name), "hw:%li", card);
00485 name[sizeof(name)-1] = '\0';
00486 return snd_ctl_open(ctl, name, 0);
00487 }
00488
00489 #if 0
00490 static int string_from_integer(char **dst, long v)
00491 {
00492 char str[32];
00493 char *res;
00494 sprintf(str, "%li", v);
00495 res = strdup(str);
00496 if (res == NULL)
00497 return -ENOMEM;
00498 *dst = res;
00499 return 0;
00500 }
00501 #endif
00502
00520 int snd_func_private_string(snd_config_t **dst, snd_config_t *root ATTRIBUTE_UNUSED,
00521 snd_config_t *src, snd_config_t *private_data)
00522 {
00523 int err;
00524 const char *str, *id;
00525
00526 if (private_data == NULL)
00527 return snd_config_copy(dst, src);
00528 err = snd_config_test_id(private_data, "string");
00529 if (err) {
00530 SNDERR("field string not found");
00531 return -EINVAL;
00532 }
00533 err = snd_config_get_string(private_data, &str);
00534 if (err < 0) {
00535 SNDERR("field string is not a string");
00536 return err;
00537 }
00538 err = snd_config_get_id(src, &id);
00539 if (err >= 0)
00540 err = snd_config_imake_string(dst, id, str);
00541 return err;
00542 }
00543 #ifndef DOC_HIDDEN
00544 SND_DLSYM_BUILD_VERSION(snd_func_private_string, SND_CONFIG_DLSYM_VERSION_EVALUATE);
00545 #endif
00546
00547 #ifndef DOC_HIDDEN
00548 int snd_determine_driver(int card, char **driver)
00549 {
00550 snd_ctl_t *ctl = NULL;
00551 snd_ctl_card_info_t *info;
00552 char *res = NULL;
00553 int err;
00554
00555 assert(card >= 0 && card <= 32);
00556 err = open_ctl(card, &ctl);
00557 if (err < 0) {
00558 SNDERR("could not open control for card %li", card);
00559 goto __error;
00560 }
00561 snd_ctl_card_info_alloca(&info);
00562 err = snd_ctl_card_info(ctl, info);
00563 if (err < 0) {
00564 SNDERR("snd_ctl_card_info error: %s", snd_strerror(err));
00565 goto __error;
00566 }
00567 res = strdup(snd_ctl_card_info_get_driver(info));
00568 if (res == NULL)
00569 err = -ENOMEM;
00570 else {
00571 *driver = res;
00572 err = 0;
00573 }
00574 __error:
00575 if (ctl)
00576 snd_ctl_close(ctl);
00577 return err;
00578 }
00579 #endif
00580
00598 int snd_func_private_card_driver(snd_config_t **dst, snd_config_t *root ATTRIBUTE_UNUSED, snd_config_t *src,
00599 snd_config_t *private_data)
00600 {
00601 char *driver;
00602 const char *id;
00603 int err;
00604 long card;
00605
00606 err = snd_config_test_id(private_data, "card");
00607 if (err) {
00608 SNDERR("field card not found");
00609 return -EINVAL;
00610 }
00611 err = snd_config_get_integer(private_data, &card);
00612 if (err < 0) {
00613 SNDERR("field card is not an integer");
00614 return err;
00615 }
00616 if ((err = snd_determine_driver(card, &driver)) < 0)
00617 return err;
00618 err = snd_config_get_id(src, &id);
00619 if (err >= 0)
00620 err = snd_config_imake_string(dst, id, driver);
00621 free(driver);
00622 return err;
00623 }
00624 #ifndef DOC_HIDDEN
00625 SND_DLSYM_BUILD_VERSION(snd_func_private_card_driver, SND_CONFIG_DLSYM_VERSION_EVALUATE);
00626 #endif
00627
00645 int snd_func_card_driver(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
00646 snd_config_t *private_data)
00647 {
00648 snd_config_t *n, *val;
00649 char *str;
00650 long v;
00651 int err;
00652
00653 err = snd_config_search(src, "card", &n);
00654 if (err < 0) {
00655 SNDERR("field card not found");
00656 return err;
00657 }
00658 err = snd_config_evaluate(n, root, private_data, NULL);
00659 if (err < 0) {
00660 SNDERR("error evaluating card");
00661 return err;
00662 }
00663 err = snd_config_get_ascii(n, &str);
00664 if (err < 0) {
00665 SNDERR("field card is not an integer or a string");
00666 return err;
00667 }
00668 v = snd_card_get_index(str);
00669 if (v < 0) {
00670 SNDERR("cannot find card '%s'", str);
00671 free(str);
00672 return v;
00673 }
00674 free(str);
00675 err = snd_config_imake_integer(&val, "card", v);
00676 if (err < 0)
00677 return err;
00678 err = snd_func_private_card_driver(dst, root, src, val);
00679 snd_config_delete(val);
00680 return err;
00681 }
00682 #ifndef DOC_HIDDEN
00683 SND_DLSYM_BUILD_VERSION(snd_func_card_driver, SND_CONFIG_DLSYM_VERSION_EVALUATE);
00684 #endif
00685
00703 int snd_func_card_id(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
00704 snd_config_t *private_data)
00705 {
00706 snd_config_t *n;
00707 char *res = NULL;
00708 snd_ctl_t *ctl = NULL;
00709 snd_ctl_card_info_t *info;
00710 const char *id;
00711 long v;
00712 int err;
00713
00714 err = snd_config_search(src, "card", &n);
00715 if (err < 0) {
00716 SNDERR("field card not found");
00717 goto __error;
00718 }
00719 err = snd_config_evaluate(n, root, private_data, NULL);
00720 if (err < 0) {
00721 SNDERR("error evaluating card");
00722 goto __error;
00723 }
00724 err = snd_config_get_integer(n, &v);
00725 if (err < 0) {
00726 SNDERR("field card is not an integer");
00727 goto __error;
00728 }
00729 err = open_ctl(v, &ctl);
00730 if (err < 0) {
00731 SNDERR("could not open control for card %li", v);
00732 goto __error;
00733 }
00734 snd_ctl_card_info_alloca(&info);
00735 err = snd_ctl_card_info(ctl, info);
00736 if (err < 0) {
00737 SNDERR("snd_ctl_card_info error: %s", snd_strerror(err));
00738 goto __error;
00739 }
00740 res = strdup(snd_ctl_card_info_get_id(info));
00741 if (res == NULL) {
00742 err = -ENOMEM;
00743 goto __error;
00744 }
00745 err = snd_config_get_id(src, &id);
00746 if (err >= 0)
00747 err = snd_config_imake_string(dst, id, res);
00748 free(res);
00749 __error:
00750 if (ctl)
00751 snd_ctl_close(ctl);
00752 return err;
00753 }
00754 #ifndef DOC_HIDDEN
00755 SND_DLSYM_BUILD_VERSION(snd_func_card_id, SND_CONFIG_DLSYM_VERSION_EVALUATE);
00756 #endif
00757
00778 int snd_func_pcm_id(snd_config_t **dst, snd_config_t *root, snd_config_t *src, void *private_data)
00779 {
00780 snd_config_t *n;
00781 snd_ctl_t *ctl = NULL;
00782 snd_pcm_info_t *info;
00783 const char *id;
00784 long card, device, subdevice = 0;
00785 int err;
00786
00787 err = snd_config_search(src, "card", &n);
00788 if (err < 0) {
00789 SNDERR("field card not found");
00790 goto __error;
00791 }
00792 err = snd_config_evaluate(n, root, private_data, NULL);
00793 if (err < 0) {
00794 SNDERR("error evaluating card");
00795 goto __error;
00796 }
00797 err = snd_config_get_integer(n, &card);
00798 if (err < 0) {
00799 SNDERR("field card is not an integer");
00800 goto __error;
00801 }
00802 err = snd_config_search(src, "device", &n);
00803 if (err < 0) {
00804 SNDERR("field device not found");
00805 goto __error;
00806 }
00807 err = snd_config_evaluate(n, root, private_data, NULL);
00808 if (err < 0) {
00809 SNDERR("error evaluating device");
00810 goto __error;
00811 }
00812 err = snd_config_get_integer(n, &device);
00813 if (err < 0) {
00814 SNDERR("field device is not an integer");
00815 goto __error;
00816 }
00817 if (snd_config_search(src, "subdevice", &n) >= 0) {
00818 err = snd_config_evaluate(n, root, private_data, NULL);
00819 if (err < 0) {
00820 SNDERR("error evaluating subdevice");
00821 goto __error;
00822 }
00823 err = snd_config_get_integer(n, &subdevice);
00824 if (err < 0) {
00825 SNDERR("field subdevice is not an integer");
00826 goto __error;
00827 }
00828 }
00829 err = open_ctl(card, &ctl);
00830 if (err < 0) {
00831 SNDERR("could not open control for card %li", card);
00832 goto __error;
00833 }
00834 snd_pcm_info_alloca(&info);
00835 snd_pcm_info_set_device(info, device);
00836 snd_pcm_info_set_subdevice(info, subdevice);
00837 err = snd_ctl_pcm_info(ctl, info);
00838 if (err < 0) {
00839 SNDERR("snd_ctl_pcm_info error: %s", snd_strerror(err));
00840 goto __error;
00841 }
00842 err = snd_config_get_id(src, &id);
00843 if (err >= 0)
00844 err = snd_config_imake_string(dst, id, snd_pcm_info_get_id(info));
00845 __error:
00846 if (ctl)
00847 snd_ctl_close(ctl);
00848 return err;
00849 }
00850 #ifndef DOC_HIDDEN
00851 SND_DLSYM_BUILD_VERSION(snd_func_pcm_id, SND_CONFIG_DLSYM_VERSION_EVALUATE);
00852 #endif
00853
00874 int snd_func_pcm_args_by_class(snd_config_t **dst, snd_config_t *root, snd_config_t *src, void *private_data)
00875 {
00876 snd_config_t *n;
00877 snd_ctl_t *ctl = NULL;
00878 snd_pcm_info_t *info;
00879 const char *id;
00880 int card = -1, dev;
00881 long class, index;
00882 int idx = 0;
00883 int err;
00884
00885 err = snd_config_search(src, "class", &n);
00886 if (err < 0) {
00887 SNDERR("field class not found");
00888 goto __out;
00889 }
00890 err = snd_config_evaluate(n, root, private_data, NULL);
00891 if (err < 0) {
00892 SNDERR("error evaluating class");
00893 goto __out;
00894 }
00895 err = snd_config_get_integer(n, &class);
00896 if (err < 0) {
00897 SNDERR("field class is not an integer");
00898 goto __out;
00899 }
00900 err = snd_config_search(src, "index", &n);
00901 if (err < 0) {
00902 SNDERR("field index not found");
00903 goto __out;
00904 }
00905 err = snd_config_evaluate(n, root, private_data, NULL);
00906 if (err < 0) {
00907 SNDERR("error evaluating index");
00908 goto __out;
00909 }
00910 err = snd_config_get_integer(n, &index);
00911 if (err < 0) {
00912 SNDERR("field index is not an integer");
00913 goto __out;
00914 }
00915
00916 snd_pcm_info_alloca(&info);
00917 while(1) {
00918 err = snd_card_next(&card);
00919 if (err < 0) {
00920 SNDERR("could not get next card");
00921 goto __out;
00922 }
00923 if (card < 0)
00924 break;
00925 err = open_ctl(card, &ctl);
00926 if (err < 0) {
00927 SNDERR("could not open control for card %li", card);
00928 goto __out;
00929 }
00930 dev = -1;
00931 memset(info, 0, snd_pcm_info_sizeof());
00932 while(1) {
00933 err = snd_ctl_pcm_next_device(ctl, &dev);
00934 if (err < 0) {
00935 SNDERR("could not get next pcm for card %li", card);
00936 goto __out;
00937 }
00938 if (dev < 0)
00939 break;
00940 snd_pcm_info_set_device(info, dev);
00941 err = snd_ctl_pcm_info(ctl, info);
00942 if (err < 0)
00943 continue;
00944 if (snd_pcm_info_get_class(info) == (snd_pcm_class_t)class &&
00945 index == idx++)
00946 goto __out;
00947 }
00948 snd_ctl_close(ctl);
00949 ctl = NULL;
00950 }
00951 err = -ENODEV;
00952
00953 __out:
00954 if (ctl)
00955 snd_ctl_close(ctl);
00956 if (err < 0)
00957 return err;
00958 if((err = snd_config_get_id(src, &id)) >= 0) {
00959 char name[32], *s;
00960 snprintf(name, sizeof(name), "CARD=%i,DEV=%i", card, dev);
00961 if (!(s = strdup(name)))
00962 return -ENOMEM;
00963 err = snd_config_imake_string(dst, id, s);
00964 }
00965 return err;
00966 }
00967 #ifndef DOC_HIDDEN
00968 SND_DLSYM_BUILD_VERSION(snd_func_pcm_args_by_class, SND_CONFIG_DLSYM_VERSION_EVALUATE);
00969 #endif
00970
00988 int snd_func_private_pcm_subdevice(snd_config_t **dst, snd_config_t *root ATTRIBUTE_UNUSED,
00989 snd_config_t *src, snd_config_t *private_data)
00990 {
00991 snd_pcm_info_t *info;
00992 const char *id;
00993 const void *data;
00994 snd_pcm_t *pcm;
00995 int err;
00996
00997 if (private_data == NULL)
00998 return snd_config_copy(dst, src);
00999 err = snd_config_test_id(private_data, "pcm_handle");
01000 if (err) {
01001 SNDERR("field pcm_handle not found");
01002 return -EINVAL;
01003 }
01004 err = snd_config_get_pointer(private_data, &data);
01005 pcm = (snd_pcm_t *)data;
01006 if (err < 0) {
01007 SNDERR("field pcm_handle is not a pointer");
01008 return err;
01009 }
01010 snd_pcm_info_alloca(&info);
01011 err = snd_pcm_info(pcm, info);
01012 if (err < 0) {
01013 SNDERR("snd_ctl_pcm_info error: %s", snd_strerror(err));
01014 return err;
01015 }
01016 err = snd_config_get_id(src, &id);
01017 if (err >= 0)
01018 err = snd_config_imake_integer(dst, id, snd_pcm_info_get_subdevice(info));
01019 return err;
01020 }
01021 #ifndef DOC_HIDDEN
01022 SND_DLSYM_BUILD_VERSION(snd_func_private_pcm_subdevice, SND_CONFIG_DLSYM_VERSION_EVALUATE);
01023 #endif
01024
01046 int snd_func_refer(snd_config_t **dst, snd_config_t *root, snd_config_t *src,
01047 snd_config_t *private_data)
01048 {
01049 snd_config_t *n;
01050 const char *file = NULL, *name = NULL;
01051 int err;
01052
01053 err = snd_config_search(src, "file", &n);
01054 if (err >= 0) {
01055 err = snd_config_evaluate(n, root, private_data, NULL);
01056 if (err < 0) {
01057 SNDERR("error evaluating file");
01058 goto _end;
01059 }
01060 err = snd_config_get_string(n, &file);
01061 if (err < 0) {
01062 SNDERR("file is not a string");
01063 goto _end;
01064 }
01065 }
01066 err = snd_config_search(src, "name", &n);
01067 if (err >= 0) {
01068 err = snd_config_evaluate(n, root, private_data, NULL);
01069 if (err < 0) {
01070 SNDERR("error evaluating name");
01071 goto _end;
01072 }
01073 err = snd_config_get_string(n, &name);
01074 if (err < 0) {
01075 SNDERR("name is not a string");
01076 goto _end;
01077 }
01078 }
01079 if (!name) {
01080 err = -EINVAL;
01081 SNDERR("name is not specified");
01082 goto _end;
01083 }
01084 if (file) {
01085 snd_input_t *input;
01086 err = snd_input_stdio_open(&input, file, "r");
01087 if (err < 0) {
01088 SNDERR("Unable to open file %s: %s", file, snd_strerror(err));
01089 goto _end;
01090 }
01091 err = snd_config_load(root, input);
01092 snd_input_close(input);
01093 if (err < 0)
01094 goto _end;
01095 }
01096 err = snd_config_search_definition(root, NULL, name, dst);
01097 if (err >= 0) {
01098 const char *id;
01099 err = snd_config_get_id(src, &id);
01100 if (err >= 0)
01101 err = snd_config_set_id(*dst, id);
01102 } else {
01103 err = snd_config_search(src, "default", &n);
01104 if (err < 0)
01105 SNDERR("Unable to find definition '%s'", name);
01106 else {
01107 const char *id;
01108 err = snd_config_evaluate(n, root, private_data, NULL);
01109 if (err < 0)
01110 return err;
01111 if ((err = snd_config_copy(dst, n)) >= 0) {
01112 if ((err = snd_config_get_id(src, &id)) < 0 ||
01113 (err = snd_config_set_id(*dst, id)) < 0)
01114 snd_config_delete(*dst);
01115 }
01116 }
01117 }
01118 _end:
01119 return err;
01120 }
01121 #ifndef DOC_HIDDEN
01122 SND_DLSYM_BUILD_VERSION(snd_func_refer, SND_CONFIG_DLSYM_VERSION_EVALUATE);
01123 #endif