1 /** 2 * \file confmisc.c 3 * \ingroup Configuration 4 * \brief Configuration helper functions 5 * \author Abramo Bagnara <abramo (at) alsa-project.org> 6 * \author Jaroslav Kysela <perex (at) 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 (at) alsa-project.org>, 16 * Jaroslav Kysela <perex (at) 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 1305