New upstream version 1.2.4
Jordi Mallach
3 years ago
0 | 0 | #! /bin/sh |
1 | 1 | # Guess values for system-dependent variables and create Makefiles. |
2 | # Generated by GNU Autoconf 2.69 for alsa-lib 1.2.3.2. | |
2 | # Generated by GNU Autoconf 2.69 for alsa-lib 1.2.4. | |
3 | 3 | # |
4 | 4 | # |
5 | 5 | # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. |
586 | 586 | # Identity of this package. |
587 | 587 | PACKAGE_NAME='alsa-lib' |
588 | 588 | PACKAGE_TARNAME='alsa-lib' |
589 | PACKAGE_VERSION='1.2.3.2' | |
590 | PACKAGE_STRING='alsa-lib 1.2.3.2' | |
589 | PACKAGE_VERSION='1.2.4' | |
590 | PACKAGE_STRING='alsa-lib 1.2.4' | |
591 | 591 | PACKAGE_BUGREPORT='' |
592 | 592 | PACKAGE_URL='' |
593 | 593 | |
902 | 902 | with_pythonlibs |
903 | 903 | with_pythonincludes |
904 | 904 | with_pcm_plugins |
905 | enable_lockless_dmix | |
905 | 906 | with_ctl_plugins |
906 | 907 | with_max_cards |
907 | 908 | enable_thread_safety |
1456 | 1457 | # Omit some internal or obsolete options to make the list less imposing. |
1457 | 1458 | # This message is too long to be a string in the A/UX 3.1 sh. |
1458 | 1459 | cat <<_ACEOF |
1459 | \`configure' configures alsa-lib 1.2.3.2 to adapt to many kinds of systems. | |
1460 | \`configure' configures alsa-lib 1.2.4 to adapt to many kinds of systems. | |
1460 | 1461 | |
1461 | 1462 | Usage: $0 [OPTION]... [VAR=VALUE]... |
1462 | 1463 | |
1526 | 1527 | |
1527 | 1528 | if test -n "$ac_init_help"; then |
1528 | 1529 | case $ac_init_help in |
1529 | short | recursive ) echo "Configuration of alsa-lib 1.2.3.2:";; | |
1530 | short | recursive ) echo "Configuration of alsa-lib 1.2.4:";; | |
1530 | 1531 | esac |
1531 | 1532 | cat <<\_ACEOF |
1532 | 1533 | |
1568 | 1569 | --enable-mixer-pymods enable the mixer python modules (experimental) |
1569 | 1570 | --disable-python disable the python components |
1570 | 1571 | --enable-python2 prefer python2 |
1572 | --enable-lockless-dmix use lockless dmix as default on x86 | |
1571 | 1573 | --disable-thread-safety disable thread-safe API functions |
1572 | 1574 | |
1573 | 1575 | Optional Packages: |
1687 | 1689 | test -n "$ac_init_help" && exit $ac_status |
1688 | 1690 | if $ac_init_version; then |
1689 | 1691 | cat <<\_ACEOF |
1690 | alsa-lib configure 1.2.3.2 | |
1692 | alsa-lib configure 1.2.4 | |
1691 | 1693 | generated by GNU Autoconf 2.69 |
1692 | 1694 | |
1693 | 1695 | Copyright (C) 2012 Free Software Foundation, Inc. |
2098 | 2100 | This file contains any messages produced by compilers while |
2099 | 2101 | running configure, to aid debugging if configure makes a mistake. |
2100 | 2102 | |
2101 | It was created by alsa-lib $as_me 1.2.3.2, which was | |
2103 | It was created by alsa-lib $as_me 1.2.4, which was | |
2102 | 2104 | generated by GNU Autoconf 2.69. Invocation command line was |
2103 | 2105 | |
2104 | 2106 | $ $0 $@ |
3036 | 3038 | |
3037 | 3039 | # Define the identity of the package. |
3038 | 3040 | PACKAGE='alsa-lib' |
3039 | VERSION='1.2.3.2' | |
3041 | VERSION='1.2.4' | |
3040 | 3042 | |
3041 | 3043 | |
3042 | 3044 | cat >>confdefs.h <<_ACEOF |
14041 | 14043 | |
14042 | 14044 | fi |
14043 | 14045 | |
14046 | if test "$build_pcm_dmix" = "yes"; then | |
14047 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default lockless dmix" >&5 | |
14048 | $as_echo_n "checking for default lockless dmix... " >&6; } | |
14049 | # Check whether --enable-lockless-dmix was given. | |
14050 | if test "${enable_lockless_dmix+set}" = set; then : | |
14051 | enableval=$enable_lockless_dmix; lockless_dmix="$enableval" | |
14052 | else | |
14053 | lockless_dmix="no" | |
14054 | fi | |
14055 | ||
14056 | if test "$lockless_dmix" = "yes"; then | |
14057 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 | |
14058 | $as_echo "yes" >&6; } | |
14059 | ||
14060 | $as_echo "#define LOCKLESS_DMIX_DEFAULT \"1\"" >>confdefs.h | |
14061 | ||
14062 | else | |
14063 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 | |
14064 | $as_echo "no" >&6; } | |
14065 | fi | |
14066 | fi | |
14044 | 14067 | |
14045 | 14068 | rm -f "$srcdir"/src/pcm/pcm_symbols_list.c |
14046 | 14069 | touch "$srcdir"/src/pcm/pcm_symbols_list.c |
14886 | 14909 | # report actual input values of CONFIG_FILES etc. instead of their |
14887 | 14910 | # values after options handling. |
14888 | 14911 | ac_log=" |
14889 | This file was extended by alsa-lib $as_me 1.2.3.2, which was | |
14912 | This file was extended by alsa-lib $as_me 1.2.4, which was | |
14890 | 14913 | generated by GNU Autoconf 2.69. Invocation command line was |
14891 | 14914 | |
14892 | 14915 | CONFIG_FILES = $CONFIG_FILES |
14952 | 14975 | cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 |
14953 | 14976 | ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" |
14954 | 14977 | ac_cs_version="\\ |
14955 | alsa-lib config.status 1.2.3.2 | |
14978 | alsa-lib config.status 1.2.4 | |
14956 | 14979 | configured by $0, generated by GNU Autoconf 2.69, |
14957 | 14980 | with options \\"\$ac_cs_config\\" |
14958 | 14981 |
0 | 0 | dnl Process this file with autoconf to produce a configure script. |
1 | 1 | AC_PREREQ(2.59) |
2 | AC_INIT(alsa-lib, 1.2.3.2) | |
2 | AC_INIT(alsa-lib, 1.2.4) | |
3 | 3 | |
4 | 4 | AC_CONFIG_SRCDIR([src/control/control.c]) |
5 | 5 | AC_CONFIG_MACRO_DIR([m4]) |
628 | 628 | AC_DEFINE([BUILD_PCM_PLUGIN_MMAP_EMUL], "1", [Build PCM mmap-emul plugin]) |
629 | 629 | fi |
630 | 630 | |
631 | if test "$build_pcm_dmix" = "yes"; then | |
632 | AC_MSG_CHECKING(for default lockless dmix) | |
633 | AC_ARG_ENABLE(lockless-dmix, | |
634 | AS_HELP_STRING([--enable-lockless-dmix], | |
635 | [use lockless dmix as default on x86]), | |
636 | lockless_dmix="$enableval", lockless_dmix="no") | |
637 | if test "$lockless_dmix" = "yes"; then | |
638 | AC_MSG_RESULT(yes) | |
639 | AC_DEFINE([LOCKLESS_DMIX_DEFAULT], "1", [Lockless dmix as default]) | |
640 | else | |
641 | AC_MSG_RESULT(no) | |
642 | fi | |
643 | fi | |
631 | 644 | |
632 | 645 | dnl Create PCM plugin symbol list for static library |
633 | 646 | rm -f "$srcdir"/src/pcm/pcm_symbols_list.c |
130 | 130 | |
131 | 131 | /* Define to 1 if compiler supports __thread */ |
132 | 132 | #undef HAVE___THREAD |
133 | ||
134 | /* Lockless dmix as default */ | |
135 | #undef LOCKLESS_DMIX_DEFAULT | |
133 | 136 | |
134 | 137 | /* Define to the sub-directory where libtool stores uninstalled libraries. */ |
135 | 138 | #undef LT_OBJDIR |
55 | 55 | /** CTL element identifier container */ |
56 | 56 | typedef struct _snd_ctl_elem_id snd_ctl_elem_id_t; |
57 | 57 | |
58 | /** CTL element identifier list container */ | |
58 | /** CTL element list container | |
59 | * | |
60 | * This is a list of CTL elements. The list contains management | |
61 | * information (e.g. how many elements the sound card has) as well as | |
62 | * the element identifiers. All functions which operate on the list | |
63 | * are named snd_ctl_elem_list_*(). | |
64 | * | |
65 | * \par Memory management | |
66 | * | |
67 | * There are two memory areas to deal with: The list container itself | |
68 | * and the memory for the element identifiers. | |
69 | * | |
70 | * To manage the area for the list container, the following functions | |
71 | * are used: | |
72 | * | |
73 | * - snd_ctl_elem_list_malloc() / snd_ctl_elem_list_free() to allocate | |
74 | * and free memory on the heap, or | |
75 | * - snd_ctl_elem_list_alloca() to allocate the memory on the | |
76 | * stack. This memory is auto-released when the stack is unwound. | |
77 | * | |
78 | * To manage the space for the element identifiers, the | |
79 | * snd_ctl_elem_list_alloc_space() and snd_ctl_elem_list_free_space() | |
80 | * are used. Allocating the right amount of space can be achieved by | |
81 | * first obtaining the number of elements and then calling | |
82 | * snd_ctl_elem_list_alloc_space(): | |
83 | * | |
84 | * \code | |
85 | * snd_ctl_elem_list_t* list; | |
86 | * int count; | |
87 | * | |
88 | * // Initialise list | |
89 | * snd_ctl_elem_list_malloc(&list); | |
90 | * | |
91 | * // Get number of elements | |
92 | * snd_ctl_elem_list(ctl, list); | |
93 | * count = snd_ctl_elem_list_get_count(list); | |
94 | * | |
95 | * // Allocate space for identifiers | |
96 | * snd_ctl_elem_list_alloc_space(list, count); | |
97 | * | |
98 | * // Get identifiers | |
99 | * snd_ctl_elem_list(ctl, list); // yes, this is same as above :) | |
100 | * | |
101 | * // Do something useful with the list... | |
102 | * | |
103 | * // Cleanup | |
104 | * snd_ctl_elem_list_free_space(list); | |
105 | * snd_ctl_elem_list_free(list); | |
106 | * \endcode | |
107 | * | |
108 | * | |
109 | * \par The Elements | |
110 | * | |
111 | * The elements in the list are accessed using an index. This index is | |
112 | * the location in the list; Don't confuse it with the 'index' of the | |
113 | * element identifier. For example: | |
114 | * | |
115 | * \code | |
116 | * snd_ctl_elem_list_t list; | |
117 | * unsigned int element_index; | |
118 | * | |
119 | * // Allocate space, fill list ... | |
120 | * | |
121 | * element_index = snd_ctl_elem_list_get_index(&list, 2); | |
122 | * \endcode | |
123 | * | |
124 | * This will access the 3rd element in the list (index=2) and get the | |
125 | * elements index from the driver (which might be 13, for example). | |
126 | */ | |
59 | 127 | typedef struct _snd_ctl_elem_list snd_ctl_elem_list_t; |
60 | 128 | |
61 | 129 | /** CTL element info container */ |
62 | 130 | typedef struct _snd_ctl_elem_info snd_ctl_elem_info_t; |
63 | 131 | |
64 | /** CTL element value container */ | |
132 | /** CTL element value container | |
133 | * | |
134 | * Contains the value(s) (i.e. members) of a single element. All | |
135 | * values of a given element are of the same type. | |
136 | * | |
137 | * \par Memory management | |
138 | * | |
139 | * To access a value, a snd_ctl_elem_value_t must be allocated using | |
140 | * snd_ctl_elem_value_alloca() or snd_ctl_elem_value_malloc(). When | |
141 | * using the latter, it must be freed again using | |
142 | * snd_ctl_elem_value_free(). | |
143 | * | |
144 | * \par Identifier | |
145 | * | |
146 | * Then, the ID must be filled. It is sufficient to fill only the | |
147 | * numid, if known. Otherwise, interface type, device, subdevice, | |
148 | * name, index must all be given. The following functions can be used | |
149 | * to fill the ID: | |
150 | * | |
151 | * - snd_ctl_elem_value_set_id(): Set the ID. Requires an | |
152 | * snd_ctl_elem_id_t object. | |
153 | * - snd_ctl_elem_value_set_numid(): Set the numid. | |
154 | * - Or use all of the following: | |
155 | * | |
156 | * - snd_ctl_elem_value_set_interface() | |
157 | * - snd_ctl_elem_value_set_device() | |
158 | * - snd_ctl_elem_value_set_subdevice() | |
159 | * - snd_ctl_elem_value_set_name() | |
160 | * - snd_ctl_elem_value_set_index() | |
161 | * | |
162 | * When communicating with the driver (snd_ctl_elem_read(), | |
163 | * snd_ctl_elem_write()), and the numid was given, the interface, | |
164 | * device, ... are filled (even if you set the before). When the numid | |
165 | * is unset (i.e. it is 0), it is filled. | |
166 | * | |
167 | * \par Communicating with the driver | |
168 | * | |
169 | * After the value container was created and filled with the ID of the | |
170 | * desired element, the value(s) can be fetched from the driver (and | |
171 | * thus from the hardware) or written to the driver. | |
172 | * | |
173 | * To fetch a value, use snd_ctl_elem_read(). Thereafter, use the | |
174 | * snd_ctl_elem_value_get_*() functions to obtain the actual value. | |
175 | * | |
176 | * To write a new value, first use a snd_ctl_elem_value_set_*() to set | |
177 | * it, then call snd_ctl_elem_write() to write it to the driver. | |
178 | */ | |
65 | 179 | typedef struct _snd_ctl_elem_value snd_ctl_elem_value_t; |
66 | 180 | |
67 | 181 | /** CTL event container */ |
353 | 467 | snd_ctl_event_type_t snd_ctl_event_get_type(const snd_ctl_event_t *obj); |
354 | 468 | |
355 | 469 | size_t snd_ctl_elem_list_sizeof(void); |
470 | ||
356 | 471 | /** \hideinitializer |
357 | * \brief allocate an invalid #snd_ctl_elem_list_t using standard alloca | |
358 | * \param ptr returned pointer | |
472 | * | |
473 | * \brief Allocate a #snd_ctl_elem_list_t using standard alloca. | |
474 | * | |
475 | * The memory is allocated on the stack and will automatically be | |
476 | * released when the stack unwinds (i.e. no free() is needed). | |
477 | * | |
478 | * \param ptr Pointer to allocated memory. | |
359 | 479 | */ |
360 | 480 | #define snd_ctl_elem_list_alloca(ptr) __snd_alloca(ptr, snd_ctl_elem_list) |
481 | ||
361 | 482 | int snd_ctl_elem_list_malloc(snd_ctl_elem_list_t **ptr); |
362 | 483 | void snd_ctl_elem_list_free(snd_ctl_elem_list_t *obj); |
363 | 484 | void snd_ctl_elem_list_clear(snd_ctl_elem_list_t *obj); |
453 | 574 | int snd_ctl_elem_remove(snd_ctl_t *ctl, snd_ctl_elem_id_t *id); |
454 | 575 | |
455 | 576 | size_t snd_ctl_elem_value_sizeof(void); |
577 | ||
456 | 578 | /** \hideinitializer |
457 | * \brief allocate an invalid #snd_ctl_elem_value_t using standard alloca | |
458 | * \param ptr returned pointer | |
579 | * \brief Allocate an invalid #snd_ctl_elem_value_t on the stack. | |
580 | * | |
581 | * Allocate space for a value object on the stack. The allocated | |
582 | * memory need not be freed, because is on the stack. | |
583 | * | |
584 | * See snd_ctl_elem_value_t for details. | |
585 | * | |
586 | * \param ptr Pointer to a snd_ctl_elem_value_t pointer. The address | |
587 | * of the allocated space will returned here. | |
459 | 588 | */ |
460 | 589 | #define snd_ctl_elem_value_alloca(ptr) __snd_alloca(ptr, snd_ctl_elem_value) |
590 | ||
461 | 591 | int snd_ctl_elem_value_malloc(snd_ctl_elem_value_t **ptr); |
462 | 592 | void snd_ctl_elem_value_free(snd_ctl_elem_value_t *obj); |
463 | 593 | void snd_ctl_elem_value_clear(snd_ctl_elem_value_t *obj); |
3 | 3 | |
4 | 4 | #define SND_LIB_MAJOR 1 /**< major number of library version */ |
5 | 5 | #define SND_LIB_MINOR 2 /**< minor number of library version */ |
6 | #define SND_LIB_SUBMINOR 3 /**< subminor number of library version */ | |
6 | #define SND_LIB_SUBMINOR 4 /**< subminor number of library version */ | |
7 | 7 | #define SND_LIB_EXTRAVER 1000000 /**< extra version number, used mainly for betas */ |
8 | 8 | /** library version */ |
9 | 9 | #define SND_LIB_VERSION ((SND_LIB_MAJOR<<16)|\ |
10 | 10 | (SND_LIB_MINOR<<8)|\ |
11 | 11 | SND_LIB_SUBMINOR) |
12 | 12 | /** library version (string) */ |
13 | #define SND_LIB_VERSION_STR "1.2.3.2" | |
13 | #define SND_LIB_VERSION_STR "1.2.4" | |
14 | 14 |
0 | 0 | #! /bin/sh |
1 | # Generated automatically by config.status (alsa-lib) 1.2.3.2 | |
1 | # Generated automatically by config.status (alsa-lib) 1.2.4 | |
2 | 2 | # Libtool was configured on host e010f88cea4a: |
3 | 3 | # NOTE: Changes made to this file will be lost: look at ltmain.sh. |
4 | 4 |
41 | 41 | "ASUS XONAR U5" 1 |
42 | 42 | "XONAR U5" 1 |
43 | 43 | "XONAR SOUND CARD" 1 |
44 | "Xonar SoundCard" 2 | |
44 | 45 | |
45 | 46 | # The below don't have digital in/out, so prevent them from being opened. |
46 | 47 | "Andrea PureAudio USB-SA Headset" 999 |
61 | 62 | "Scarlett 2i4 USB" 999 |
62 | 63 | "Sennheiser USB headset" 999 |
63 | 64 | "SWTOR Gaming Headset by Razer" 999 |
65 | "ThinkStation P620 Main" 999 | |
66 | "ThinkStation P620 Rear" 999 | |
64 | 67 | "Thunderbolt Dock Audio Headset" 999 |
65 | 68 | "Thunderbolt Dock Audio Module" 999 |
66 | 69 | "USB Device 0x46d_0x821" 999 |
1535 | 1535 | case ']': |
1536 | 1536 | case '\'': |
1537 | 1537 | case '"': |
1538 | case '*': | |
1539 | case '#': | |
1538 | 1540 | goto quoted; |
1539 | 1541 | default: |
1540 | 1542 | if (*p <= 31 || *p >= 127) |
30 | 30 | /*! \page control Control interface |
31 | 31 | |
32 | 32 | <P>Control interface is designed to access primitive controls. There is |
33 | also interface notifying about control and structure changes. | |
33 | also an interface for notifying about control and structure changes. | |
34 | 34 | |
35 | 35 | \section control_general_overview General overview |
36 | 36 | |
37 | 37 | In ALSA control feature, each sound card can have control elements. The elements |
38 | 38 | are managed according to below model. |
39 | 39 | |
40 | - element set | |
40 | - Element set | |
41 | ||
41 | 42 | - A set of elements with the same attribute (i.e. name, get/put operations). |
42 | 43 | Some element sets can be added to a sound card by drivers in kernel and |
43 | 44 | userspace applications. |
44 | - element | |
45 | - An element can be identified by userspace applications. Each element has | |
46 | own identical information. | |
47 | - member | |
48 | - An element includes some members to have a value. The value of each member | |
49 | can be changed by both of userspace applications and drivers in kernel. | |
50 | ||
51 | Each element can be identified by two ways; a combination of name and index, or | |
52 | numerical number (numid). | |
53 | ||
54 | The type of element set is one of integer, integerr64, boolean, enumerators, | |
45 | ||
46 | - Element | |
47 | ||
48 | - A control element might be a master volume control, for example, or a | |
49 | read-only indicator, such as a sync status. An element has a type (e.g. | |
50 | SNDRV_CTL_ELEM_TYPE_INTEGER or SNDRV_CTL_ELEM_TYPE_BOOLEAN) and - depending | |
51 | on the type - min/max values, a step size, a set of possible values (for | |
52 | enums), etc. | |
53 | ||
54 | - Member | |
55 | ||
56 | - An element usually includes one or more member(s) to have a value. For | |
57 | example, a stereo volume control element has two members (for left/right), | |
58 | while a mono volume has only one member. The member count can be obtained | |
59 | using snd_ctl_elem_info_get_count(). Elements of type | |
60 | "SNDRV_CTL_ELEM_TYPE_BYTES" or "SNDRV_CTL_ELEM_TYPE_IEC958" have no members | |
61 | at all (and thus no member count), they have just a single value. The | |
62 | members share the same properties (e.g. both volume control members have | |
63 | the same min/max values). The value of each member can be changed by both | |
64 | of userspace applications and drivers in kernel. | |
65 | ||
66 | ||
67 | \section identifying_elements Identifying Elements | |
68 | ||
69 | Each element has the following identifying properties: | |
70 | ||
71 | - The numid (a numeric identifier, assigned when the sound card is | |
72 | detected, constant while the sound card is kept connected) | |
73 | - The interface type (e.g. MIXER, CARD or PCM) | |
74 | - The device | |
75 | - The subdevice | |
76 | - Its name | |
77 | - Its index | |
78 | ||
79 | An element can be identified either by its numid or by the tuple | |
80 | (interface type, device, subdevice, name, index). This tuple is always | |
81 | the same (driver updates can change it, but in practice this is | |
82 | rare). The numid can change on each boot. In case of an USB sound | |
83 | card, the numid can also change when it is reconnected. | |
84 | ||
85 | ||
86 | \section element_lists Element Lists | |
87 | ||
88 | An element list can be used to obtain a list of all elements of the | |
89 | sound card. The list contains generic information (e.g. how many | |
90 | elements the card has), and the identifying properties of the elements | |
91 | (numid, card, name, ...). See #snd_ctl_elem_list_t to learn more about | |
92 | element lists. | |
93 | ||
94 | ||
95 | \section working_with_elements Working with Elements | |
96 | ||
97 | It is possible to obtain information about an element using the | |
98 | snd_ctl_elem_info_*() functions. For enums, the allowed values can be | |
99 | obtained, for integers, the min/max values can be obtained, and so | |
100 | on. In addition, these functions can report the identifying | |
101 | properties. E.g. when the element is addressed using its numid, the | |
102 | functions complements the name, index, etc. | |
103 | ||
104 | To access the members (i.e. values) of a control, use the | |
105 | snd_ctl_elem_value*() functions. These allow to get and set the | |
106 | actual values or settings. It is also possible to get and set the ID | |
107 | values (such as the numid or the name). | |
108 | ||
109 | ||
110 | \section element_sets Element Sets | |
111 | ||
112 | The type of element set is one of integer, integer64, boolean, enumerators, | |
55 | 113 | bytes and IEC958 structure. This indicates the type of value for each member in |
56 | 114 | elements included in the element set. |
57 | 115 | |
58 | When the value of member is changed, corresponding events are transferred to | |
116 | ||
117 | \section events Events | |
118 | ||
119 | When the value of a member is changed, corresponding events are transferred to | |
59 | 120 | userspace applications. The applications should subscribe any events in advance. |
60 | 121 | |
61 | 122 | \section tlv_blob Supplemental data for elements in an element set |
279 | 340 | |
280 | 341 | /** |
281 | 342 | * \brief Get a list of element identifiers |
343 | * | |
344 | * Before calling this function, memoru must be allocated using | |
345 | * snd_ctl_elem_list_malloc(). | |
346 | * | |
347 | * This function obtains data from the sound card driver and puts it | |
348 | * into the list. | |
349 | * | |
350 | * If there was space allocated for the element identifiers (using | |
351 | * snd_ctl_elem_list_alloc_space()), information will be filled in. If | |
352 | * too little space was allocated, only a part of the elements will be | |
353 | * queried. If there was too much space allocated, some of it remains | |
354 | * unused. Use snd_ctl_elem_list_get_count() and | |
355 | * snd_ctl_elem_list_get_used() to obtain information about space | |
356 | * usage. See #snd_ctl_elem_list_t to learn more. | |
357 | * | |
282 | 358 | * \param ctl CTL handle |
283 | 359 | * \param list CTL element identifiers list pointer |
284 | 360 | * \return 0 on success otherwise a negative error code |
861 | 937 | } |
862 | 938 | |
863 | 939 | /** |
864 | * \brief Get CTL element value | |
865 | * \param ctl CTL handle | |
866 | * \param data Data of an element. | |
867 | * \return 0 on success otherwise a negative error code | |
940 | * \brief Get CTL element value. | |
941 | * | |
942 | * Read information from sound card. You must set the ID of the | |
943 | * element before calling this function. | |
944 | * | |
945 | * See snd_ctl_elem_value_t for details. | |
946 | * | |
947 | * \param ctl CTL handle. | |
948 | * \param data The element value. The ID must be set before calling | |
949 | * the function, and the actual value will be returned | |
950 | * here. | |
951 | * | |
952 | * \return 0 on success otherwise a negative error code. | |
868 | 953 | */ |
869 | 954 | int snd_ctl_elem_read(snd_ctl_t *ctl, snd_ctl_elem_value_t *data) |
870 | 955 | { |
873 | 958 | } |
874 | 959 | |
875 | 960 | /** |
876 | * \brief Set CTL element value | |
877 | * \param ctl CTL handle | |
878 | * \param data Data of an element. | |
961 | * \brief Set CTL element value. | |
962 | * | |
963 | * Write new value(s) to the sound card. You must set the ID and the | |
964 | * value of the element before calling this function. | |
965 | * | |
966 | * See snd_ctl_elem_value_t for details. | |
967 | * | |
968 | * \param ctl CTL handle. | |
969 | * \param data The new value. | |
970 | * | |
879 | 971 | * \retval 0 on success |
880 | 972 | * \retval >0 on success when value was changed |
881 | 973 | * \retval <0 a negative error code |
1507 | 1599 | |
1508 | 1600 | /** |
1509 | 1601 | * \brief allocate space for CTL element identifiers list |
1510 | * \param obj CTL element identifiers list | |
1511 | * \param entries Entries to allocate | |
1512 | * \return 0 on success otherwise a negative error code | |
1602 | * | |
1603 | * The space can be released with snd_ctl_elem_list_free_space(). | |
1604 | * | |
1605 | * \param obj CTL element identifiers list. | |
1606 | * \param entries How many entries to allocate. See | |
1607 | * #snd_ctl_elem_list_t to learn how to obtain | |
1608 | * this number in advance. | |
1609 | * \return 0 on success otherwise a negative error code. | |
1513 | 1610 | */ |
1514 | 1611 | int snd_ctl_elem_list_alloc_space(snd_ctl_elem_list_t *obj, unsigned int entries) |
1515 | 1612 | { |
1525 | 1622 | |
1526 | 1623 | /** |
1527 | 1624 | * \brief free previously allocated space for CTL element identifiers list |
1625 | * | |
1626 | * Releases space previously allocated using | |
1627 | * snd_ctl_elem_list_alloc_space(). | |
1628 | * | |
1528 | 1629 | * \param obj CTL element identifiers list |
1529 | 1630 | */ |
1530 | 1631 | void snd_ctl_elem_list_free_space(snd_ctl_elem_list_t *obj) |
2015 | 2116 | } |
2016 | 2117 | |
2017 | 2118 | /** |
2018 | * \brief get size of #snd_ctl_elem_list_t | |
2119 | * \brief get size of #snd_ctl_elem_list_t. | |
2019 | 2120 | * \return size in bytes |
2020 | 2121 | */ |
2021 | 2122 | size_t snd_ctl_elem_list_sizeof() |
2024 | 2125 | } |
2025 | 2126 | |
2026 | 2127 | /** |
2027 | * \brief allocate an invalid #snd_ctl_elem_list_t using standard malloc | |
2128 | * \brief allocate a #snd_ctl_elem_list_t using standard malloc. | |
2129 | * | |
2130 | * The memory can be released using snd_ctl_elem_list_free(). | |
2131 | * | |
2028 | 2132 | * \param ptr returned pointer |
2029 | 2133 | * \return 0 on success otherwise negative error code |
2030 | 2134 | */ |
2038 | 2142 | } |
2039 | 2143 | |
2040 | 2144 | /** |
2041 | * \brief frees a previously allocated #snd_ctl_elem_list_t | |
2145 | * \brief frees a previously allocated #snd_ctl_elem_list_t. | |
2146 | * | |
2147 | * Release memory previously allocated using | |
2148 | * snd_ctl_elem_list_malloc(). | |
2149 | * | |
2150 | * If you used snd_ctl_elem_list_alloc_space() on the list, you must | |
2151 | * use snd_ctl_elem_list_free_space() \em before calling this | |
2152 | * function. | |
2153 | * | |
2042 | 2154 | * \param obj pointer to object to free |
2043 | 2155 | */ |
2044 | 2156 | void snd_ctl_elem_list_free(snd_ctl_elem_list_t *obj) |
2047 | 2159 | } |
2048 | 2160 | |
2049 | 2161 | /** |
2050 | * \brief clear given #snd_ctl_elem_list_t object | |
2162 | * \brief Clear given #snd_ctl_elem_list_t object. | |
2163 | * | |
2164 | * This will make the stored identifiers inaccessible without freeing | |
2165 | * their space. | |
2166 | * | |
2167 | * \warning The element identifier space cannot be freed after calling | |
2168 | * this function. Therefore, snd_ctl_elem_list_free_space() | |
2169 | * must be called in advance. | |
2170 | * | |
2051 | 2171 | * \param obj pointer to object to clear |
2052 | 2172 | */ |
2053 | 2173 | void snd_ctl_elem_list_clear(snd_ctl_elem_list_t *obj) |
2056 | 2176 | } |
2057 | 2177 | |
2058 | 2178 | /** |
2059 | * \brief copy one #snd_ctl_elem_list_t to another | |
2179 | * \brief copy one #snd_ctl_elem_list_t to another. | |
2180 | * | |
2181 | * This performs a shallow copy. That means the both lists will share | |
2182 | * the same space for the elements. The elements will not be copied. | |
2183 | * | |
2060 | 2184 | * \param dst pointer to destination |
2061 | 2185 | * \param src pointer to source |
2062 | 2186 | */ |
2079 | 2203 | |
2080 | 2204 | /** |
2081 | 2205 | * \brief Get number of used entries in CTL element identifiers list |
2206 | * | |
2207 | * This function returns how many entries are actually filled with | |
2208 | * useful information. | |
2209 | * | |
2210 | * See also snd_ctl_elem_list_get_count(). | |
2211 | * | |
2082 | 2212 | * \param obj CTL element identifier list |
2083 | 2213 | * \return number of used entries |
2084 | 2214 | */ |
2089 | 2219 | } |
2090 | 2220 | |
2091 | 2221 | /** |
2092 | * \brief Get total count of elements present in CTL device (information present in every filled CTL element identifiers list) | |
2222 | * \brief Get total count of elements present in CTL device | |
2223 | * | |
2224 | * This function returns how many entries were allocated using | |
2225 | * snd_ctl_elem_list_alloc_space(). This information is present after | |
2226 | * snd_ctl_elem_list() was called. | |
2227 | * | |
2228 | * See also snd_ctl_elem_list_get_used(). | |
2229 | * | |
2093 | 2230 | * \param obj CTL element identifier list |
2094 | 2231 | * \return total number of elements |
2095 | 2232 | */ |
2139 | 2276 | } |
2140 | 2277 | |
2141 | 2278 | /** |
2142 | * \brief Get device part of CTL element identifier for an entry of a CTL element identifiers list | |
2279 | * \brief Get the device part of CTL element identifier for an entry of a CTL element identifiers list | |
2143 | 2280 | * \param obj CTL element identifier list |
2144 | 2281 | * \param idx Index of entry |
2145 | 2282 | * \return CTL element related device |
2762 | 2899 | } |
2763 | 2900 | |
2764 | 2901 | /** |
2765 | * \brief Allocate an invalid #snd_ctl_elem_value_t using standard malloc(3). | |
2766 | * \param ptr Returned pointer for data of an element. | |
2767 | * \return 0 on success otherwise negative error code. | |
2902 | * \brief Allocate an invalid #snd_ctl_elem_value_t on the heap. | |
2903 | * | |
2904 | * Allocate space for a value object on the head. The allocated memory | |
2905 | * must be freed using snd_ctl_elem_value_free(). | |
2906 | * | |
2907 | * See snd_ctl_elem_value_t for details. | |
2908 | * | |
2909 | * \param ptr Pointer to a snd_ctl_elem_value_t pointer. The address | |
2910 | * of the allocated space will be returned here. | |
2911 | * \return 0 on success, otherwise a negative error code. | |
2768 | 2912 | */ |
2769 | 2913 | int snd_ctl_elem_value_malloc(snd_ctl_elem_value_t **ptr) |
2770 | 2914 | { |
2776 | 2920 | } |
2777 | 2921 | |
2778 | 2922 | /** |
2779 | * \brief Frees a previously allocated data of an element. | |
2923 | * \brief Free an #snd_ctl_elem_value_t previously allocated using | |
2924 | * snd_ctl_elem_value_malloc(). | |
2925 | * | |
2926 | * \param obj Pointer to the snd_ctl_elem_value_t. | |
2927 | */ | |
2928 | void snd_ctl_elem_value_free(snd_ctl_elem_value_t *obj) | |
2929 | { | |
2930 | free(obj); | |
2931 | } | |
2932 | ||
2933 | /** | |
2934 | * \brief Clear given data of an element. | |
2935 | * | |
2936 | * See snd_ctl_elem_value_t for details. | |
2937 | * | |
2780 | 2938 | * \param obj Data of an element. |
2781 | 2939 | */ |
2782 | void snd_ctl_elem_value_free(snd_ctl_elem_value_t *obj) | |
2783 | { | |
2784 | free(obj); | |
2785 | } | |
2786 | ||
2787 | /** | |
2788 | * \brief Clear given data of an element. | |
2789 | * \param obj Data of an element. | |
2790 | */ | |
2791 | 2940 | void snd_ctl_elem_value_clear(snd_ctl_elem_value_t *obj) |
2792 | 2941 | { |
2793 | 2942 | memset(obj, 0, sizeof(snd_ctl_elem_value_t)); |
2794 | 2943 | } |
2795 | 2944 | |
2796 | 2945 | /** |
2797 | * \brief Copy two data of elements. | |
2946 | * \brief Bitwise copy of a snd_ctl_elem_value_t value. | |
2798 | 2947 | * \param dst Pointer to destination. |
2799 | 2948 | * \param src Pointer to source. |
2800 | 2949 | */ |
2806 | 2955 | } |
2807 | 2956 | |
2808 | 2957 | /** |
2809 | * \brief Compare one data of an element to the other. | |
2810 | * \param left Pointer to first data. | |
2811 | * \param right Pointer to second data. | |
2958 | * \brief Compare two snd_ctl_elem_value_t values, bytewise. | |
2959 | * | |
2960 | * \param left First value. | |
2961 | * \param right Second value. | |
2812 | 2962 | * \return 0 on match, less than or greater than otherwise, see memcmp(3). |
2813 | 2963 | */ |
2814 | 2964 | int snd_ctl_elem_value_compare(snd_ctl_elem_value_t *left, |
2819 | 2969 | } |
2820 | 2970 | |
2821 | 2971 | /** |
2822 | * \brief Get element identifier from given data of an element. | |
2823 | * \param obj Data of an element. | |
2824 | * \param ptr Pointer for element identifier. | |
2972 | * \brief Get the element identifier from the given element value. | |
2973 | * | |
2974 | * See snd_ctl_elem_value_t for more details. | |
2975 | * | |
2976 | * \param obj The element value. | |
2977 | * \param ptr Pointer to an identifier object. The identifier is | |
2978 | * stored there. | |
2825 | 2979 | */ |
2826 | 2980 | void snd_ctl_elem_value_get_id(const snd_ctl_elem_value_t *obj, snd_ctl_elem_id_t *ptr) |
2827 | 2981 | { |
2830 | 2984 | } |
2831 | 2985 | |
2832 | 2986 | /** |
2833 | * \brief Get element numeric identifier from given data of an element. | |
2834 | * \param obj Data of an element. | |
2835 | * \return Element numeric identifier. | |
2987 | * \brief Get the identifiers 'numid' part from the given element value. | |
2988 | * | |
2989 | * See snd_ctl_elem_value_t for more details. | |
2990 | * | |
2991 | * \param obj The element value. | |
2992 | * \return The numid. | |
2836 | 2993 | */ |
2837 | 2994 | unsigned int snd_ctl_elem_value_get_numid(const snd_ctl_elem_value_t *obj) |
2838 | 2995 | { |
2841 | 2998 | } |
2842 | 2999 | |
2843 | 3000 | /** |
2844 | * \brief Get interface part of element identifier from given data of an | |
2845 | * element. | |
2846 | * \param obj Data of an element. | |
2847 | * \return Interface part of element identifier. | |
3001 | * \brief Get the identifiers 'interface' part from the given element value. | |
3002 | * | |
3003 | * See snd_ctl_elem_value_t for more details. | |
3004 | * | |
3005 | * \param obj The element value. | |
3006 | * \return The interface part of element identifier. | |
2848 | 3007 | */ |
2849 | 3008 | snd_ctl_elem_iface_t snd_ctl_elem_value_get_interface(const snd_ctl_elem_value_t *obj) |
2850 | 3009 | { |
2853 | 3012 | } |
2854 | 3013 | |
2855 | 3014 | /** |
2856 | * \brief Get device part of element identifier from given data of an element. | |
2857 | * \param obj Data of an element. | |
2858 | * \return Device part of element identifier. | |
3015 | * \brief Get the identifiers 'device' part from the given element value. | |
3016 | * | |
3017 | * See snd_ctl_elem_value_t for more details. | |
3018 | * | |
3019 | * \param obj The element value. | |
3020 | * \return The device part of element identifier. | |
2859 | 3021 | */ |
2860 | 3022 | unsigned int snd_ctl_elem_value_get_device(const snd_ctl_elem_value_t *obj) |
2861 | 3023 | { |
2864 | 3026 | } |
2865 | 3027 | |
2866 | 3028 | /** |
2867 | * \brief Get subdevice part of element identifier from given data of an | |
2868 | * element. | |
2869 | * \param obj Data of an element. | |
2870 | * \return Subdevice part of element identifier. | |
3029 | * \brief Get the identifiers 'subdevice' part from the given element value. | |
3030 | * | |
3031 | * See snd_ctl_elem_value_t for more details. | |
3032 | * | |
3033 | * \param obj The element value. | |
3034 | * \return The subdevice part of element identifier. | |
2871 | 3035 | */ |
2872 | 3036 | unsigned int snd_ctl_elem_value_get_subdevice(const snd_ctl_elem_value_t *obj) |
2873 | 3037 | { |
2876 | 3040 | } |
2877 | 3041 | |
2878 | 3042 | /** |
2879 | * \brief Get name part of element identifier from given data of an element. | |
2880 | * \param obj Data of an element. | |
2881 | * \return Name part of element identifier. | |
3043 | * \brief Get the identifiers 'name' part from the given element value. | |
3044 | * | |
3045 | * See snd_ctl_elem_value_t for more details. | |
3046 | * | |
3047 | * \param obj The element value. | |
3048 | * \return The "name" part of element identifier. | |
2882 | 3049 | */ |
2883 | 3050 | const char *snd_ctl_elem_value_get_name(const snd_ctl_elem_value_t *obj) |
2884 | 3051 | { |
2887 | 3054 | } |
2888 | 3055 | |
2889 | 3056 | /** |
2890 | * \brief Get index part of element identifier from given data of an element. | |
2891 | * \param obj Data of an element. | |
2892 | * \return Index part of element identifier. | |
3057 | * \brief Get the identifiers 'index' part from the given element value. | |
3058 | * | |
3059 | * See snd_ctl_elem_value_t for more details. | |
3060 | * | |
3061 | * \param obj The element value. | |
3062 | * \return The index part of element identifier. | |
2893 | 3063 | */ |
2894 | 3064 | unsigned int snd_ctl_elem_value_get_index(const snd_ctl_elem_value_t *obj) |
2895 | 3065 | { |
2897 | 3067 | return obj->id.index; |
2898 | 3068 | } |
2899 | 3069 | |
2900 | /** | |
2901 | * \brief Set element identifier to given data of an element. | |
2902 | * \param obj Data of an element. | |
2903 | * \param ptr Pointer to an element identifier. | |
3070 | ||
3071 | /** | |
3072 | * \brief Set the element identifier within the given element value. | |
3073 | * | |
3074 | * See snd_ctl_elem_value_t for more details. | |
3075 | * | |
3076 | * \param obj The element value. | |
3077 | * \param ptr The new identifier. | |
2904 | 3078 | */ |
2905 | 3079 | void snd_ctl_elem_value_set_id(snd_ctl_elem_value_t *obj, const snd_ctl_elem_id_t *ptr) |
2906 | 3080 | { |
2909 | 3083 | } |
2910 | 3084 | |
2911 | 3085 | /** |
2912 | * \brief Set numeric identifier to given data of an element. | |
2913 | * \param obj Data of an element. | |
2914 | * \param val Value for numeric identifier. | |
3086 | * \brief Set the identifiers 'numid' part within the given element value. | |
3087 | * | |
3088 | * See snd_ctl_elem_value_t for more details. | |
3089 | * | |
3090 | * \param obj The element value. | |
3091 | * \param val The new numid. | |
2915 | 3092 | */ |
2916 | 3093 | void snd_ctl_elem_value_set_numid(snd_ctl_elem_value_t *obj, unsigned int val) |
2917 | 3094 | { |
2920 | 3097 | } |
2921 | 3098 | |
2922 | 3099 | /** |
2923 | * \brief Set interface part of element identifier to given data of an element. | |
2924 | * \param obj Data of an element. | |
2925 | * \param val Value for interface part of element identifier. | |
3100 | * \brief Set the identifiers 'interface' part within the given element value. | |
3101 | * | |
3102 | * See snd_ctl_elem_value_t for more details. | |
3103 | * | |
3104 | * \param obj The element value. | |
3105 | * \param val The new interface. | |
2926 | 3106 | */ |
2927 | 3107 | void snd_ctl_elem_value_set_interface(snd_ctl_elem_value_t *obj, snd_ctl_elem_iface_t val) |
2928 | 3108 | { |
2931 | 3111 | } |
2932 | 3112 | |
2933 | 3113 | /** |
2934 | * \brief Set device part of element identifier to given data of an element. | |
2935 | * \param obj Data of an element. | |
2936 | * \param val Value for device part of element identifier. | |
3114 | * \brief Set the identifiers 'device' part within the given element value. | |
3115 | * | |
3116 | * See snd_ctl_elem_value_t for more details. | |
3117 | * | |
3118 | * \param obj The element value. | |
3119 | * \param val The new device. | |
2937 | 3120 | */ |
2938 | 3121 | void snd_ctl_elem_value_set_device(snd_ctl_elem_value_t *obj, unsigned int val) |
2939 | 3122 | { |
2942 | 3125 | } |
2943 | 3126 | |
2944 | 3127 | /** |
2945 | * \brief Set subdevice part of element identifier to given data of an element. | |
2946 | * \param obj Data of an element. | |
2947 | * \param val Value for subdevice part of element identifier. | |
3128 | * \brief Set the identifiers 'subdevice' part within the given element value. | |
3129 | * | |
3130 | * See snd_ctl_elem_value_t for more details. | |
3131 | * | |
3132 | * \param obj The element value. | |
3133 | * \param val The new subdevice. | |
2948 | 3134 | */ |
2949 | 3135 | void snd_ctl_elem_value_set_subdevice(snd_ctl_elem_value_t *obj, unsigned int val) |
2950 | 3136 | { |
2953 | 3139 | } |
2954 | 3140 | |
2955 | 3141 | /** |
2956 | * \brief Set name part of element identifier to given data of an element. | |
2957 | * \param obj Data of an element. | |
2958 | * \param val Value for name part of element identifier, | |
3142 | * \brief Set the identifiers 'name' part within the given element value. | |
3143 | * | |
3144 | * See snd_ctl_elem_value_t for more details. | |
3145 | * | |
3146 | * \param obj The element value. | |
3147 | * \param val The new name. | |
2959 | 3148 | */ |
2960 | 3149 | void snd_ctl_elem_value_set_name(snd_ctl_elem_value_t *obj, const char *val) |
2961 | 3150 | { |
2964 | 3153 | } |
2965 | 3154 | |
2966 | 3155 | /** |
2967 | * \brief Set index part of element identifier to given data of an element. | |
2968 | * \param obj Data of an element. | |
2969 | * \param val Value for index part of element identifier. | |
3156 | * \brief Set the identifiers 'index' part within the given element value. | |
3157 | * | |
3158 | * See snd_ctl_elem_value_t for more details. | |
3159 | * | |
3160 | * \param obj The element value. | |
3161 | * \param val The new index. | |
2970 | 3162 | */ |
2971 | 3163 | void snd_ctl_elem_value_set_index(snd_ctl_elem_value_t *obj, unsigned int val) |
2972 | 3164 | { |
2975 | 3167 | } |
2976 | 3168 | |
2977 | 3169 | /** |
2978 | * \brief Get value of a specified member from given data as an element of | |
2979 | * boolean type. | |
2980 | * \param obj Data of an element. | |
2981 | * \param idx Index of member in the element. | |
2982 | * \return Value for the member. | |
2983 | */ | |
3170 | * \brief Get an element members value. | |
3171 | * | |
3172 | * Use this function if the element is of type SNDRV_CTL_ELEM_TYPE_BOOLEAN. It | |
3173 | * returns the value of one member. See \ref snd_ctl_elem_value_t and \ref | |
3174 | * control for more details. | |
3175 | * | |
3176 | * \param obj The element value object | |
3177 | * \param idx The index of the member. | |
3178 | * \return The members value. | |
3179 | */ | |
2984 | 3180 | int snd_ctl_elem_value_get_boolean(const snd_ctl_elem_value_t *obj, unsigned int idx) |
2985 | 3181 | { |
2986 | 3182 | assert(obj); |
2989 | 3185 | } |
2990 | 3186 | |
2991 | 3187 | /** |
2992 | * \brief Get value of a specified member from given data as an element of | |
2993 | * integer type. | |
2994 | * \param obj Data of an element. | |
2995 | * \param idx Index of member in the element. | |
2996 | * \return Value for the member. | |
2997 | */ | |
3188 | * \brief Get an element members value. | |
3189 | * | |
3190 | * Use this function if the element is of type SNDRV_CTL_ELEM_TYPE_INTEGER. It | |
3191 | * returns the value of one member. See \ref snd_ctl_elem_value_t and \ref | |
3192 | * control for more details. | |
3193 | * | |
3194 | * \param obj The element value object. | |
3195 | * \param idx The index of the member. | |
3196 | * \return The members value. | |
3197 | */ | |
2998 | 3198 | long snd_ctl_elem_value_get_integer(const snd_ctl_elem_value_t *obj, unsigned int idx) |
2999 | 3199 | { |
3000 | 3200 | assert(obj); |
3003 | 3203 | } |
3004 | 3204 | |
3005 | 3205 | /** |
3006 | * \brief Get value of a specified member from given data as an element of | |
3007 | * integer64 type. | |
3008 | * \param obj Data of an element. | |
3009 | * \param idx Index of member in the element. | |
3010 | * \return Value for the member. | |
3011 | */ | |
3206 | * \brief Get an element members value. | |
3207 | * | |
3208 | * Use this function if the element is of type SNDRV_CTL_ELEM_TYPE_INTEGER64. It | |
3209 | * returns the value of one member. See \ref snd_ctl_elem_value_t and \ref | |
3210 | * control for more details. | |
3211 | * | |
3212 | * \param obj The element value object. | |
3213 | * \param idx The index of the member. | |
3214 | * \return The members value. | |
3215 | */ | |
3012 | 3216 | long long snd_ctl_elem_value_get_integer64(const snd_ctl_elem_value_t *obj, unsigned int idx) |
3013 | 3217 | { |
3014 | 3218 | assert(obj); |
3017 | 3221 | } |
3018 | 3222 | |
3019 | 3223 | /** |
3020 | * \brief Get value of a specified member from given data as an element of | |
3021 | * enumerated type. | |
3022 | * \param obj Data of an element. | |
3023 | * \param idx Index of member in the element. | |
3024 | * \return Value for the member. This is an index of name set in the element. | |
3025 | */ | |
3224 | * \brief Get an element members value. | |
3225 | * | |
3226 | * Use this function if the element is of type | |
3227 | * SNDRV_CTL_ELEM_TYPE_ENUMERATED. It returns the index of the active item. See | |
3228 | * \ref snd_ctl_elem_value_t and \ref control for more details. | |
3229 | * | |
3230 | * \param obj The element value object. | |
3231 | * \param idx The index of the requested member. | |
3232 | * \return The index of the active item. | |
3233 | */ | |
3026 | 3234 | unsigned int snd_ctl_elem_value_get_enumerated(const snd_ctl_elem_value_t *obj, unsigned int idx) |
3027 | 3235 | { |
3028 | 3236 | assert(obj); |
3031 | 3239 | } |
3032 | 3240 | |
3033 | 3241 | /** |
3034 | * \brief Get value of a specified member from given data as an element of | |
3035 | * bytes type. | |
3036 | * \param obj Data of an element. | |
3037 | * \param idx Index of member in the element. | |
3038 | * \return Value for the member. | |
3039 | */ | |
3242 | * \brief Get an element members value. | |
3243 | * | |
3244 | * Use this function if the element is of type SNDRV_CTL_ELEM_TYPE_BYTE. It | |
3245 | * returns the value of one member. See \ref snd_ctl_elem_value_t and \ref | |
3246 | * control for more details. | |
3247 | * | |
3248 | * \param obj The element value object. | |
3249 | * \param idx The index of the member. | |
3250 | * \return The members value. | |
3251 | */ | |
3040 | 3252 | unsigned char snd_ctl_elem_value_get_byte(const snd_ctl_elem_value_t *obj, unsigned int idx) |
3041 | 3253 | { |
3042 | 3254 | assert(obj); |
3045 | 3257 | } |
3046 | 3258 | |
3047 | 3259 | /** |
3048 | * \brief Set value of a specified member to given data as an element of | |
3049 | * boolean type. | |
3050 | * \param obj Data of an element. | |
3051 | * \param idx Index of member in the element. | |
3052 | * \param val Value for the member. | |
3053 | */ | |
3260 | * \brief Set an element members value. | |
3261 | * | |
3262 | * Use this function if the element is of type SNDRV_CTL_ELEM_TYPE_BOOLEAN. It | |
3263 | * sets the value of one member. See \ref snd_ctl_elem_value_t and \ref control | |
3264 | * for more details. | |
3265 | * | |
3266 | * \param obj The element value object. | |
3267 | * \param idx The index of the member. | |
3268 | * \param val The new value. | |
3269 | */ | |
3054 | 3270 | void snd_ctl_elem_value_set_boolean(snd_ctl_elem_value_t *obj, unsigned int idx, long val) |
3055 | 3271 | { |
3056 | 3272 | assert(obj); |
3059 | 3275 | } |
3060 | 3276 | |
3061 | 3277 | /** |
3062 | * \brief Set value of a specified member to given data as an element of | |
3063 | * integer type. | |
3064 | * \param obj Data of an element. | |
3065 | * \param idx Index of member in the element. | |
3066 | * \param val Value for the member. | |
3067 | */ | |
3278 | * \brief Set an element members value. | |
3279 | * | |
3280 | * Use this function if the element is of type SNDRV_CTL_ELEM_TYPE_INTEGER. It | |
3281 | * sets the value of one member. See \ref snd_ctl_elem_value_t and \ref control | |
3282 | * for more details. | |
3283 | * | |
3284 | * \param obj The element value object. | |
3285 | * \param idx The index of the member. | |
3286 | * \param val The new value. | |
3287 | */ | |
3068 | 3288 | void snd_ctl_elem_value_set_integer(snd_ctl_elem_value_t *obj, unsigned int idx, long val) |
3069 | 3289 | { |
3070 | 3290 | assert(obj); |
3073 | 3293 | } |
3074 | 3294 | |
3075 | 3295 | /** |
3076 | * \brief Set value of a specified member to given data as an element of | |
3077 | * integer64 type. | |
3078 | * \param obj Data of an element. | |
3079 | * \param idx Index of member in the element. | |
3080 | * \param val Value for the member. | |
3081 | */ | |
3296 | * \brief Set an element members value. | |
3297 | * | |
3298 | * Use this function if the element is of type SNDRV_CTL_ELEM_TYPE_INTEGER64. It | |
3299 | * sets the value of one member. See \ref snd_ctl_elem_value_t and \ref control | |
3300 | * for more details. | |
3301 | * | |
3302 | * \param obj The element value object. | |
3303 | * \param idx The index of the member. | |
3304 | * \param val The new value. | |
3305 | */ | |
3082 | 3306 | void snd_ctl_elem_value_set_integer64(snd_ctl_elem_value_t *obj, unsigned int idx, long long val) |
3083 | 3307 | { |
3084 | 3308 | assert(obj); |
3087 | 3311 | } |
3088 | 3312 | |
3089 | 3313 | /** |
3090 | * \brief Set value of a specified member to given data as an element of | |
3091 | * enumerated type. | |
3092 | * \param obj Data of an element. | |
3093 | * \param idx Index of member in the element. | |
3094 | * \param val Value for the member. | |
3095 | */ | |
3314 | * \brief Set an element members value. | |
3315 | * | |
3316 | * Use this function if the element is of type | |
3317 | * SNDRV_CTL_ELEM_TYPE_ENUMERATED. It activates the specified item. See \ref | |
3318 | * snd_ctl_elem_value_t and \ref control for more details. | |
3319 | * | |
3320 | * \param obj The element value object. | |
3321 | * \param idx The index of the requested member. | |
3322 | * \param val The new index of the item to be activated. | |
3323 | */ | |
3096 | 3324 | void snd_ctl_elem_value_set_enumerated(snd_ctl_elem_value_t *obj, unsigned int idx, unsigned int val) |
3097 | 3325 | { |
3098 | 3326 | assert(obj); |
3101 | 3329 | } |
3102 | 3330 | |
3103 | 3331 | /** |
3104 | * \brief Set value for a specified member to given data as an element of byte | |
3105 | * type. | |
3106 | * \param obj Data of an element. | |
3107 | * \param idx Index of member in the element. | |
3108 | * \param val Value for the member. | |
3109 | */ | |
3332 | * \brief Set an element members value. | |
3333 | * | |
3334 | * Use this function if the element is of type SNDRV_CTL_ELEM_TYPE_BYTE. It | |
3335 | * sets the value of one member. See \ref snd_ctl_elem_value_t and \ref control | |
3336 | * for more details. | |
3337 | * | |
3338 | * \param obj The element value object. | |
3339 | * \param idx The index of the member. | |
3340 | * \param val The new value. | |
3341 | */ | |
3110 | 3342 | void snd_ctl_elem_value_set_byte(snd_ctl_elem_value_t *obj, unsigned int idx, unsigned char val) |
3111 | 3343 | { |
3112 | 3344 | assert(obj); |
3115 | 3347 | } |
3116 | 3348 | |
3117 | 3349 | /** |
3118 | * \brief Set values to given data as an element of bytes type. | |
3119 | * \param obj Data of an element. | |
3120 | * \param data Pointer for byte array. | |
3121 | * \param size The number of bytes included in the memory block. | |
3350 | * \brief Replace the data stored within the element. | |
3351 | * | |
3352 | * Use this function if the element is of type SNDRV_CTL_ELEM_TYPE_BYTES. It | |
3353 | * replaces the data stored in the element. Note that "bytes" elements don't | |
3354 | * have members. They have only one single block of data. | |
3355 | * | |
3356 | * See \ref snd_ctl_elem_value_t and \ref control for more details. | |
3357 | * | |
3358 | * \param obj The element value object. | |
3359 | * \param data Pointer to the new data. | |
3360 | * \param size The size of the new data, in bytes. | |
3122 | 3361 | */ |
3123 | 3362 | void snd_ctl_elem_set_bytes(snd_ctl_elem_value_t *obj, void *data, size_t size) |
3124 | 3363 | { |
3128 | 3367 | } |
3129 | 3368 | |
3130 | 3369 | /** |
3131 | * \brief Get memory block from given data as an element of bytes type. | |
3132 | * \param obj Data of an element. | |
3133 | * \return Pointer for byte array. | |
3134 | */ | |
3370 | * \brief Get the data stored within the element. | |
3371 | * | |
3372 | * Use this function if the element is of type SNDRV_CTL_ELEM_TYPE_BYTES. It | |
3373 | * returns the data stored in the element. Note that "bytes" elements don't have | |
3374 | * members. They have only one single block of data. | |
3375 | * | |
3376 | * See \ref snd_ctl_elem_value_t and \ref control for more details. | |
3377 | * | |
3378 | * \param obj The element value object. | |
3379 | * \return Pointer to the elements data. | |
3380 | */ | |
3135 | 3381 | const void * snd_ctl_elem_value_get_bytes(const snd_ctl_elem_value_t *obj) |
3136 | 3382 | { |
3137 | 3383 | assert(obj); |
3139 | 3385 | } |
3140 | 3386 | |
3141 | 3387 | /** |
3142 | * \brief Get value from given data to given pointer as an element of IEC958 | |
3143 | * type. | |
3144 | * \param obj Data of an element. | |
3145 | * \param ptr Pointer to IEC958 data. | |
3146 | */ | |
3388 | * \brief Get an elements IEC958 data. | |
3389 | * | |
3390 | * Use this function if the element is of type SNDRV_CTL_ELEM_TYPE_IEC958. Note that | |
3391 | * "IEC958" elements don't have members. They have only one single | |
3392 | * IEC958 information block. | |
3393 | * | |
3394 | * See \ref snd_ctl_elem_value_t and \ref control for more details. | |
3395 | * | |
3396 | * \param obj The element value object. | |
3397 | * \param ptr Pointer to an IEC958 structure. The data is stored there. | |
3398 | */ | |
3147 | 3399 | void snd_ctl_elem_value_get_iec958(const snd_ctl_elem_value_t *obj, snd_aes_iec958_t *ptr) |
3148 | 3400 | { |
3149 | 3401 | assert(obj && ptr); |
3151 | 3403 | } |
3152 | 3404 | |
3153 | 3405 | /** |
3154 | * \brief Set value from given pointer to given data as an element of IEC958 | |
3155 | * type. | |
3156 | * \param obj Data of an element. | |
3157 | * \param ptr Pointer to IEC958 data. | |
3158 | */ | |
3406 | * \brief Set an elements IEC958 data. | |
3407 | * | |
3408 | * Use this function if the element is of type SNDRV_CTL_ELEM_TYPE_IEC958. Note | |
3409 | * that "IEC958" elements don't have members. They have only one single IEC958 | |
3410 | * information block. | |
3411 | * | |
3412 | * See \ref snd_ctl_elem_value_t and \ref control for more details. | |
3413 | * | |
3414 | * \param obj The element value object. | |
3415 | * \param ptr Pointer to the new IEC958 data. | |
3416 | */ | |
3159 | 3417 | void snd_ctl_elem_value_set_iec958(snd_ctl_elem_value_t *obj, const snd_aes_iec958_t *ptr) |
3160 | 3418 | { |
3161 | 3419 | assert(obj && ptr); |
281 | 281 | if (items <= 0) |
282 | 282 | return -1; |
283 | 283 | |
284 | end = *ptr; | |
285 | if (end == '\'' || end == '"') | |
286 | ptr++; | |
287 | else | |
288 | end = '\0'; | |
289 | ||
284 | 290 | for (i = 0; i < items; i++) { |
285 | 291 | snd_ctl_elem_info_set_item(info, i); |
286 | 292 | if (snd_ctl_elem_info(handle, info) < 0) |
287 | 293 | return -1; |
288 | 294 | name = snd_ctl_elem_info_get_item_name(info); |
289 | end = *ptr; | |
290 | if (end == '\'' || end == '"') | |
291 | ptr++; | |
292 | else | |
293 | end = '\0'; | |
294 | 295 | len = strlen(name); |
295 | if (strncmp(name, ptr, len) == 0) { | |
296 | if (ptr[len] == end || ptr[len] == ',' || ptr[len] == '\n') { | |
297 | ptr += len; | |
298 | *ptrp = ptr; | |
299 | return i; | |
300 | } | |
296 | if (strncmp(name, ptr, len)) | |
297 | continue; | |
298 | if (end == '\0' && (ptr[len] == '\0' || ptr[len] == ',' || ptr[len] == '\n')) { | |
299 | *ptrp = ptr + len; | |
300 | return i; | |
301 | } | |
302 | if (end != '\0' && ptr[len] == end) { | |
303 | *ptrp = ptr + len + 1; | |
304 | return i; | |
301 | 305 | } |
302 | 306 | } |
303 | 307 | return -1; |
42 | 42 | struct snd_dlsym_link *snd_dlsym_start = NULL; |
43 | 43 | #endif |
44 | 44 | #ifdef DL_ORIGIN_AVAILABLE |
45 | static int snd_libdir_plugin_dir_set = 0; | |
46 | static char *snd_libdir_origin = NULL; | |
45 | static int snd_plugin_dir_set = 0; | |
46 | static char *snd_plugin_dir = NULL; | |
47 | 47 | #endif |
48 | 48 | #endif |
49 | 49 | |
63 | 63 | static inline void snd_dlpath_lock(void) {} |
64 | 64 | static inline void snd_dlpath_unlock(void) {} |
65 | 65 | #endif |
66 | ||
67 | static void snd_dlinfo_origin(char *path, size_t path_len) | |
68 | { | |
69 | #ifdef DL_ORIGIN_AVAILABLE | |
70 | struct link_map *links; | |
71 | Dl_info info; | |
72 | char origin[PATH_MAX]; | |
73 | if (dladdr1(&snd_dlpath, &info, (void**)&links, RTLD_DL_LINKMAP) == 0) | |
74 | return; | |
75 | if (dlinfo(links, RTLD_DI_ORIGIN, origin)) | |
76 | return; | |
77 | snprintf(path, path_len, "%s/alsa-lib", origin); | |
78 | if (access(path, X_OK) == 0) | |
79 | snd_plugin_dir = strdup(path); | |
80 | #endif | |
81 | } | |
66 | 82 | |
67 | 83 | /** |
68 | 84 | * |
74 | 90 | */ |
75 | 91 | int snd_dlpath(char *path, size_t path_len, const char *name) |
76 | 92 | { |
77 | #ifdef DL_ORIGIN_AVAILABLE | |
78 | 93 | snd_dlpath_lock(); |
79 | if (!snd_libdir_plugin_dir_set) { | |
80 | struct link_map *links; | |
81 | Dl_info info; | |
82 | char origin[PATH_MAX]; | |
83 | if (dladdr1(&snd_dlpath, &info, (void**)&links, RTLD_DL_LINKMAP) == 0) | |
84 | links = NULL; | |
85 | if (links != NULL && dlinfo(links, RTLD_DI_ORIGIN, origin) == 0) { | |
86 | snprintf(path, path_len, "%s/alsa-lib", origin); | |
87 | if (access(path, X_OK) == 0) | |
88 | snd_libdir_origin = strdup(origin); | |
94 | if (!snd_plugin_dir_set) { | |
95 | const char *env = getenv("ALSA_PLUGIN_DIR"); | |
96 | if (env) { | |
97 | snd_plugin_dir = strdup(env); | |
98 | } else { | |
99 | snd_dlinfo_origin(path, path_len); | |
89 | 100 | } |
90 | snd_libdir_plugin_dir_set = 1; | |
91 | } | |
92 | if (snd_libdir_origin) { | |
93 | snprintf(path, path_len, "%s/alsa-lib/%s", snd_libdir_origin, name); | |
94 | } else { | |
95 | snprintf(path, path_len, "%s/%s", ALSA_PLUGIN_DIR, name); | |
96 | } | |
101 | snd_plugin_dir_set = 1; | |
102 | } | |
103 | snprintf(path, path_len, "%s/%s", | |
104 | snd_plugin_dir ? snd_plugin_dir : ALSA_PLUGIN_DIR, name); | |
97 | 105 | snd_dlpath_unlock(); |
98 | #else | |
99 | snprintf(path, path_len, "%s/%s", ALSA_PLUGIN_DIR, name); | |
100 | #endif | |
101 | 106 | return 0; |
102 | 107 | } |
103 | 108 | |
141 | 146 | * via ld.so.conf. |
142 | 147 | */ |
143 | 148 | void *handle = NULL; |
144 | const char *filename = NULL; | |
149 | const char *filename = name; | |
145 | 150 | char path[PATH_MAX]; |
146 | 151 | |
147 | 152 | if (name && name[0] != '/') { |
148 | if (snd_dlpath(path, sizeof(path), name) == 0) { | |
153 | if (snd_dlpath(path, sizeof(path), name) == 0) | |
149 | 154 | filename = path; |
150 | handle = dlopen(filename, mode); | |
151 | if (!handle) { | |
152 | /* if the filename exists and cannot be opened */ | |
153 | /* return immediately */ | |
154 | if (access(filename, X_OK) == 0) | |
155 | goto errpath; | |
156 | } | |
157 | } | |
158 | } | |
159 | if (!handle) { | |
160 | filename = name; | |
161 | handle = dlopen(name, mode); | |
162 | if (!handle) | |
163 | goto errpath; | |
164 | } | |
155 | } | |
156 | handle = dlopen(filename, mode); | |
157 | if (!handle) | |
158 | goto errpath; | |
165 | 159 | return handle; |
166 | 160 | errpath: |
167 | 161 | if (errbuf) |
168 | snprintf(errbuf, errbuflen, "%s: %s", filename, dlerror()); | |
162 | snprintf(errbuf, errbuflen, "%s", dlerror()); | |
169 | 163 | #endif |
170 | 164 | return NULL; |
171 | 165 | } |
172 | 166 | |
173 | 167 | #ifndef DOXYGEN |
174 | void *INTERNAL(snd_dlopen_old)(const char *name, int mode) | |
168 | EXPORT_SYMBOL void *INTERNAL(snd_dlopen_old)(const char *name, int mode) | |
175 | 169 | { |
176 | 170 | return INTERNAL(snd_dlopen)(name, mode, NULL, 0); |
177 | 171 | } |
449 | 443 | snd_dlobj_unlock(); |
450 | 444 | #ifdef DL_ORIGIN_AVAILABLE |
451 | 445 | snd_dlpath_lock(); |
452 | snd_libdir_plugin_dir_set = 0; | |
453 | free(snd_libdir_origin); | |
454 | snd_libdir_origin = NULL; | |
446 | snd_plugin_dir_set = 0; | |
447 | free(snd_plugin_dir); | |
448 | snd_plugin_dir = NULL; | |
455 | 449 | snd_dlpath_unlock(); |
456 | 450 | #endif |
457 | 451 | } |
7833 | 7833 | #endif /* USE_VERSIONED_SYMBOLS */ |
7834 | 7834 | |
7835 | 7835 | #define __P_OLD_GET(pfx, name, val_type, ret_type) \ |
7836 | ret_type pfx##name(const snd_pcm_hw_params_t *params) \ | |
7836 | EXPORT_SYMBOL ret_type pfx##name(const snd_pcm_hw_params_t *params) \ | |
7837 | 7837 | { \ |
7838 | 7838 | val_type val; \ |
7839 | 7839 | if (INTERNAL(name)(params, &val) < 0) \ |
7842 | 7842 | } |
7843 | 7843 | |
7844 | 7844 | #define __P_OLD_GET1(pfx, name, val_type, ret_type) \ |
7845 | ret_type pfx##name(const snd_pcm_hw_params_t *params, int *dir) \ | |
7845 | EXPORT_SYMBOL ret_type pfx##name(const snd_pcm_hw_params_t *params, int *dir) \ | |
7846 | 7846 | { \ |
7847 | 7847 | val_type val; \ |
7848 | 7848 | if (INTERNAL(name)(params, &val, dir) < 0) \ |
7884 | 7884 | __OLD_GET1(snd_pcm_hw_params_get_tick_time_max, unsigned int, unsigned int); |
7885 | 7885 | |
7886 | 7886 | #define __P_OLD_NEAR(pfx, name, ret_type) \ |
7887 | ret_type pfx##name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, ret_type val) \ | |
7887 | EXPORT_SYMBOL ret_type pfx##name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, ret_type val) \ | |
7888 | 7888 | { \ |
7889 | 7889 | if (INTERNAL(name)(pcm, params, &val) < 0) \ |
7890 | 7890 | return 0; \ |
7892 | 7892 | } |
7893 | 7893 | |
7894 | 7894 | #define __P_OLD_NEAR1(pfx, name, ret_type) \ |
7895 | ret_type pfx##name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, ret_type val, int *dir) \ | |
7895 | EXPORT_SYMBOL ret_type pfx##name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, ret_type val, int *dir) \ | |
7896 | 7896 | { \ |
7897 | 7897 | if (INTERNAL(name)(pcm, params, &val, dir) < 0) \ |
7898 | 7898 | return 0; \ |
7912 | 7912 | __OLD_NEAR1(snd_pcm_hw_params_set_tick_time_near, unsigned int); |
7913 | 7913 | |
7914 | 7914 | #define __P_OLD_SET_FL(pfx, name, ret_type) \ |
7915 | ret_type pfx##name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) \ | |
7915 | EXPORT_SYMBOL ret_type pfx##name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params) \ | |
7916 | 7916 | { \ |
7917 | 7917 | ret_type val; \ |
7918 | 7918 | if (INTERNAL(name)(pcm, params, &val) < 0) \ |
7921 | 7921 | } |
7922 | 7922 | |
7923 | 7923 | #define __P_OLD_SET_FL1(pfx, name, ret_type) \ |
7924 | ret_type pfx##name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, int *dir) \ | |
7924 | EXPORT_SYMBOL ret_type pfx##name(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, int *dir) \ | |
7925 | 7925 | { \ |
7926 | 7926 | ret_type val; \ |
7927 | 7927 | if (INTERNAL(name)(pcm, params, &val, dir) < 0) \ |
7957 | 7957 | __OLD_SET_FL1(snd_pcm_hw_params_set_tick_time_last, unsigned int); |
7958 | 7958 | |
7959 | 7959 | #define __P_OLD_GET_SW(pfx, name, ret_type) \ |
7960 | ret_type pfx##name(snd_pcm_sw_params_t *params) \ | |
7960 | EXPORT_SYMBOL ret_type pfx##name(snd_pcm_sw_params_t *params) \ | |
7961 | 7961 | { \ |
7962 | 7962 | ret_type val; \ |
7963 | 7963 | if (INTERNAL(name)(params, &val) < 0) \ |
81 | 81 | return 0; |
82 | 82 | } |
83 | 83 | |
84 | #define SND_PCM_DIRECT_MAGIC (0xa15ad300 + sizeof(snd_pcm_direct_share_t)) | |
84 | static unsigned int snd_pcm_direct_magic(snd_pcm_direct_t *dmix) | |
85 | { | |
86 | if (!dmix->direct_memory_access) | |
87 | return 0xa15ad300 + sizeof(snd_pcm_direct_share_t); | |
88 | else | |
89 | return 0xb15ad300 + sizeof(snd_pcm_direct_share_t); | |
90 | } | |
85 | 91 | |
86 | 92 | /* |
87 | 93 | * global shared memory area |
131 | 137 | buf.shm_perm.gid = dmix->ipc_gid; |
132 | 138 | shmctl(dmix->shmid, IPC_SET, &buf); |
133 | 139 | } |
134 | dmix->shmptr->magic = SND_PCM_DIRECT_MAGIC; | |
140 | dmix->shmptr->magic = snd_pcm_direct_magic(dmix); | |
135 | 141 | return 1; |
136 | 142 | } else { |
137 | if (dmix->shmptr->magic != SND_PCM_DIRECT_MAGIC) { | |
143 | if (dmix->shmptr->magic != snd_pcm_direct_magic(dmix)) { | |
138 | 144 | snd_pcm_direct_shm_discard(dmix); |
139 | 145 | return -EINVAL; |
140 | 146 | } |
1891 | 1897 | rec->slowptr = 1; |
1892 | 1898 | rec->max_periods = 0; |
1893 | 1899 | rec->var_periodsize = 0; |
1900 | #ifdef LOCKLESS_DMIX_DEFAULT | |
1894 | 1901 | rec->direct_memory_access = 1; |
1902 | #else | |
1903 | rec->direct_memory_access = 0; | |
1904 | #endif | |
1895 | 1905 | rec->hw_ptr_alignment = SND_PCM_HW_PTR_ALIGNMENT_AUTO; |
1896 | 1906 | rec->tstamp_type = -1; |
1897 | 1907 |
185 | 185 | mix_areas_32_t *remix_areas_32; |
186 | 186 | mix_areas_24_t *remix_areas_24; |
187 | 187 | mix_areas_u8_t *remix_areas_u8; |
188 | unsigned int use_sem; | |
188 | 189 | } dmix; |
189 | 190 | struct { |
190 | 191 | unsigned long long chn_mask; |
211 | 211 | do_mix_areas(size, |
212 | 212 | ((unsigned char *)dst_areas[dchn].addr + dst_areas[dchn].first / 8) + dst_ofs * dst_step, |
213 | 213 | ((unsigned char *)src_areas[chn].addr + src_areas[chn].first / 8) + src_ofs * src_step, |
214 | dmix->u.dmix.sum_buffer + channels * dst_ofs + chn, | |
214 | dmix->u.dmix.sum_buffer + dmix->shmptr->s.channels * dst_ofs + dchn, | |
215 | 215 | dst_step, |
216 | 216 | src_step, |
217 | channels * sizeof(signed int)); | |
217 | dmix->shmptr->s.channels * sizeof(signed int)); | |
218 | 218 | } |
219 | 219 | } |
220 | 220 | |
279 | 279 | do_remix_areas(size, |
280 | 280 | ((unsigned char *)dst_areas[dchn].addr + dst_areas[dchn].first / 8) + dst_ofs * dst_step, |
281 | 281 | ((unsigned char *)src_areas[chn].addr + src_areas[chn].first / 8) + src_ofs * src_step, |
282 | dmix->u.dmix.sum_buffer + channels * dst_ofs + chn, | |
282 | dmix->u.dmix.sum_buffer + dmix->shmptr->s.channels * dst_ofs + dchn, | |
283 | 283 | dst_step, |
284 | 284 | src_step, |
285 | channels * sizeof(signed int)); | |
285 | dmix->shmptr->s.channels * sizeof(signed int)); | |
286 | 286 | } |
287 | 287 | } |
288 | 288 | |
291 | 291 | * the area via semaphore |
292 | 292 | */ |
293 | 293 | #ifndef DOC_HIDDEN |
294 | #ifdef NO_CONCURRENT_ACCESS | |
295 | #define dmix_down_sem(dmix) snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT) | |
296 | #define dmix_up_sem(dmix) snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT) | |
297 | #else | |
298 | #define dmix_down_sem(dmix) | |
299 | #define dmix_up_sem(dmix) | |
300 | #endif | |
294 | static void dmix_down_sem(snd_pcm_direct_t *dmix) | |
295 | { | |
296 | if (dmix->u.dmix.use_sem) | |
297 | snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT); | |
298 | } | |
299 | ||
300 | static void dmix_up_sem(snd_pcm_direct_t *dmix) | |
301 | { | |
302 | if (dmix->u.dmix.use_sem) | |
303 | snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT); | |
304 | } | |
301 | 305 | #endif |
302 | 306 | |
303 | 307 | /* |
314 | 318 | /* check the available size in the local buffer |
315 | 319 | * last_appl_ptr keeps the last updated position |
316 | 320 | */ |
317 | size = dmix->appl_ptr - dmix->last_appl_ptr; | |
321 | size = pcm_frame_diff2(dmix->appl_ptr, dmix->last_appl_ptr, pcm->boundary); | |
318 | 322 | if (! size) |
319 | 323 | return; |
320 | if (size >= pcm->boundary / 2) | |
321 | size = pcm->boundary - size; | |
322 | 324 | |
323 | 325 | /* the slave_app_ptr can be far behind the slave_hw_ptr */ |
324 | 326 | /* reduce mixing and errors here - just skip not catched writes */ |
325 | if (dmix->slave_hw_ptr <= dmix->slave_appl_ptr) | |
326 | slave_size = dmix->slave_appl_ptr - dmix->slave_hw_ptr; | |
327 | else | |
328 | slave_size = dmix->slave_appl_ptr + (dmix->slave_boundary - dmix->slave_hw_ptr); | |
327 | slave_size = pcm_frame_diff(dmix->slave_appl_ptr, dmix->slave_hw_ptr, dmix->slave_boundary); | |
329 | 328 | if (slave_size > dmix->slave_buffer_size) { |
330 | 329 | transfer = dmix->slave_buffer_size - slave_size; |
331 | 330 | if (transfer > size) |
334 | 333 | dmix->last_appl_ptr %= pcm->boundary; |
335 | 334 | dmix->slave_appl_ptr += transfer; |
336 | 335 | dmix->slave_appl_ptr %= dmix->slave_boundary; |
337 | size = dmix->appl_ptr - dmix->last_appl_ptr; | |
336 | size = pcm_frame_diff2(dmix->appl_ptr, dmix->last_appl_ptr, pcm->boundary); | |
338 | 337 | if (! size) |
339 | 338 | return; |
340 | if (size >= pcm->boundary / 2) | |
341 | size = pcm->boundary - size; | |
342 | 339 | } |
343 | 340 | |
344 | 341 | /* check the available size in the slave PCM buffer */ |
350 | 347 | slave_hw_ptr += dmix->slave_buffer_size; |
351 | 348 | if (slave_hw_ptr >= dmix->slave_boundary) |
352 | 349 | slave_hw_ptr -= dmix->slave_boundary; |
353 | if (slave_hw_ptr < dmix->slave_appl_ptr) | |
354 | slave_size = slave_hw_ptr + (dmix->slave_boundary - dmix->slave_appl_ptr); | |
355 | else | |
356 | slave_size = slave_hw_ptr - dmix->slave_appl_ptr; | |
350 | slave_size = pcm_frame_diff(slave_hw_ptr, dmix->slave_appl_ptr, dmix->slave_boundary); | |
357 | 351 | if (slave_size < size) |
358 | 352 | size = slave_size; |
359 | 353 | if (! size) |
721 | 715 | * So they can be remixed. |
722 | 716 | */ |
723 | 717 | |
724 | if (dmix->last_appl_ptr < dmix->appl_ptr) | |
725 | size = dmix->appl_ptr - dmix->last_appl_ptr; | |
726 | else | |
727 | size = dmix->appl_ptr + (pcm->boundary - dmix->last_appl_ptr); | |
718 | size = pcm_frame_diff(dmix->last_appl_ptr, dmix->appl_ptr, pcm->boundary); | |
728 | 719 | if (frames < size) |
729 | 720 | size = frames; |
730 | 721 | snd_pcm_mmap_appl_backward(pcm, size); |
736 | 727 | /* Always at this point last_appl_ptr == appl_ptr |
737 | 728 | * So (appl_ptr - hw_ptr) indicates the frames which can be remixed |
738 | 729 | */ |
739 | if (dmix->hw_ptr < dmix->appl_ptr) | |
740 | size = dmix->appl_ptr - dmix->hw_ptr; | |
741 | else | |
742 | size = dmix->appl_ptr + (pcm->boundary - dmix->hw_ptr); | |
730 | size = pcm_frame_diff(dmix->appl_ptr, dmix->hw_ptr, pcm->boundary); | |
743 | 731 | if (size > frames) |
744 | 732 | size = frames; |
745 | if (dmix->slave_hw_ptr < dmix->slave_appl_ptr) | |
746 | slave_size = dmix->slave_appl_ptr - dmix->slave_hw_ptr; | |
747 | else | |
748 | slave_size = dmix->slave_appl_ptr + (pcm->boundary - dmix->slave_hw_ptr); | |
733 | slave_size = pcm_frame_diff(dmix->slave_appl_ptr, dmix->slave_hw_ptr, pcm->boundary); | |
749 | 734 | if (slave_size < size) |
750 | 735 | size = slave_size; |
751 | 736 |
42 | 42 | #ifndef ARCH_ADD |
43 | 43 | #define ARCH_ADD(p,a) (*(p) += (a)) |
44 | 44 | #define ARCH_CMPXCHG(p,a,b) (*(p)) /* fake */ |
45 | #define NO_CONCURRENT_ACCESS /* use semaphore to avoid race */ | |
46 | 45 | #define IS_CONCURRENT 0 /* no race check */ |
47 | 46 | #endif |
48 | 47 | |
529 | 528 | dmix->u.dmix.mix_areas_u8 = generic_mix_areas_u8; |
530 | 529 | dmix->u.dmix.remix_areas_24 = generic_remix_areas_24; |
531 | 530 | dmix->u.dmix.remix_areas_u8 = generic_remix_areas_u8; |
531 | dmix->u.dmix.use_sem = 1; | |
532 | 532 | } |
533 | 533 | |
534 | 534 | #endif |
134 | 134 | dmix->u.dmix.mix_areas_24 = smp > 1 ? mix_areas_24_smp: mix_areas_24; |
135 | 135 | dmix->u.dmix.remix_areas_24 = smp > 1 ? remix_areas_24_smp: remix_areas_24; |
136 | 136 | } |
137 | dmix->u.dmix.use_sem = 0; | |
137 | 138 | } |
101 | 101 | dmix->u.dmix.remix_areas_32 = smp > 1 ? remix_areas_32_smp : remix_areas_32; |
102 | 102 | dmix->u.dmix.mix_areas_24 = smp > 1 ? mix_areas_24_smp : mix_areas_24; |
103 | 103 | dmix->u.dmix.remix_areas_24 = smp > 1 ? remix_areas_24_smp : remix_areas_24; |
104 | dmix->u.dmix.use_sem = 0; | |
104 | 105 | } |
111 | 111 | const snd_pcm_channel_area_t *src_areas, *dst_areas; |
112 | 112 | |
113 | 113 | /* calculate the size to transfer */ |
114 | size = dshare->appl_ptr - dshare->last_appl_ptr; | |
114 | size = pcm_frame_diff(dshare->appl_ptr, dshare->last_appl_ptr, pcm->boundary); | |
115 | 115 | if (! size) |
116 | 116 | return; |
117 | 117 | slave_hw_ptr = dshare->slave_hw_ptr; |
122 | 122 | slave_hw_ptr += dshare->slave_buffer_size; |
123 | 123 | if (slave_hw_ptr >= dshare->slave_boundary) |
124 | 124 | slave_hw_ptr -= dshare->slave_boundary; |
125 | if (slave_hw_ptr < dshare->slave_appl_ptr) | |
126 | slave_size = slave_hw_ptr + (dshare->slave_boundary - dshare->slave_appl_ptr); | |
127 | else | |
128 | slave_size = slave_hw_ptr - dshare->slave_appl_ptr; | |
125 | slave_size = pcm_frame_diff(slave_hw_ptr, dshare->slave_appl_ptr, dshare->slave_boundary); | |
129 | 126 | if (slave_size < size) |
130 | 127 | size = slave_size; |
131 | 128 | if (! size) |
168 | 165 | |
169 | 166 | old_slave_hw_ptr = dshare->slave_hw_ptr; |
170 | 167 | dshare->slave_hw_ptr = slave_hw_ptr; |
171 | diff = slave_hw_ptr - old_slave_hw_ptr; | |
168 | diff = pcm_frame_diff(slave_hw_ptr, old_slave_hw_ptr, dshare->slave_boundary); | |
172 | 169 | if (diff == 0) /* fast path */ |
173 | 170 | return 0; |
174 | 171 | if (dshare->state != SND_PCM_STATE_RUNNING && |
175 | 172 | dshare->state != SND_PCM_STATE_DRAINING) |
176 | 173 | /* not really started yet - don't update hw_ptr */ |
177 | 174 | return 0; |
178 | if (diff < 0) { | |
179 | slave_hw_ptr += dshare->slave_boundary; | |
180 | diff = slave_hw_ptr - old_slave_hw_ptr; | |
181 | } | |
182 | 175 | dshare->hw_ptr += diff; |
183 | 176 | dshare->hw_ptr %= pcm->boundary; |
184 | 177 | // printf("sync ptr diff = %li\n", diff); |
151 | 151 | old_slave_hw_ptr = dsnoop->slave_hw_ptr; |
152 | 152 | snoop_timestamp(pcm); |
153 | 153 | slave_hw_ptr = dsnoop->slave_hw_ptr; |
154 | diff = slave_hw_ptr - old_slave_hw_ptr; | |
154 | diff = pcm_frame_diff(slave_hw_ptr, old_slave_hw_ptr, dsnoop->slave_boundary); | |
155 | 155 | if (diff == 0) /* fast path */ |
156 | 156 | return 0; |
157 | if (diff < 0) { | |
158 | slave_hw_ptr += dsnoop->slave_boundary; | |
159 | diff = slave_hw_ptr - old_slave_hw_ptr; | |
160 | } | |
161 | 157 | snd_pcm_dsnoop_sync_area(pcm, old_slave_hw_ptr, diff); |
162 | 158 | dsnoop->hw_ptr += diff; |
163 | 159 | dsnoop->hw_ptr %= pcm->boundary; |
98 | 98 | #define TO_LE32(x) bswap_32(x) |
99 | 99 | #define TO_LE16(x) bswap_16(x) |
100 | 100 | #endif |
101 | ||
102 | static ssize_t safe_write(int fd, const void *buf, size_t len) | |
103 | { | |
104 | while (1) { | |
105 | ssize_t r = write(fd, buf, len); | |
106 | if (r < 0) { | |
107 | if (errno == EINTR) | |
108 | continue; | |
109 | if (errno == EPIPE) | |
110 | return -EIO; | |
111 | return -errno; | |
112 | } | |
113 | return r; | |
114 | } | |
115 | } | |
101 | 116 | |
102 | 117 | static int snd_pcm_file_append_value(char **string_p, char **index_ch_p, |
103 | 118 | int *len_p, const char *value) |
338 | 353 | |
339 | 354 | setup_wav_header(pcm, &file->wav_header); |
340 | 355 | |
341 | res = write(file->fd, header, sizeof(header)); | |
356 | res = safe_write(file->fd, header, sizeof(header)); | |
342 | 357 | if (res != sizeof(header)) |
343 | 358 | goto write_error; |
344 | 359 | |
345 | res = write(file->fd, &file->wav_header, sizeof(file->wav_header)); | |
360 | res = safe_write(file->fd, &file->wav_header, sizeof(file->wav_header)); | |
346 | 361 | if (res != sizeof(file->wav_header)) |
347 | 362 | goto write_error; |
348 | 363 | |
349 | res = write(file->fd, header2, sizeof(header2)); | |
364 | res = safe_write(file->fd, header2, sizeof(header2)); | |
350 | 365 | if (res != sizeof(header2)) |
351 | 366 | goto write_error; |
352 | 367 | |
380 | 395 | len = (file->filelen + 0x24) > 0x7fffffff ? |
381 | 396 | 0x7fffffff : (int)(file->filelen + 0x24); |
382 | 397 | len = TO_LE32(len); |
383 | ret = write(file->fd, &len, 4); | |
398 | ret = safe_write(file->fd, &len, 4); | |
384 | 399 | if (ret < 0) |
385 | 400 | return; |
386 | 401 | } |
389 | 404 | len = file->filelen > 0x7fffffff ? |
390 | 405 | 0x7fffffff : (int)file->filelen; |
391 | 406 | len = TO_LE32(len); |
392 | ret = write(file->fd, &len, 4); | |
407 | ret = safe_write(file->fd, &len, 4); | |
393 | 408 | if (ret < 0) |
394 | 409 | return; |
395 | 410 | } |
420 | 435 | size_t cont = file->wbuf_size_bytes - file->file_ptr_bytes; |
421 | 436 | if (n > cont) |
422 | 437 | n = cont; |
423 | err = write(file->fd, file->wbuf + file->file_ptr_bytes, n); | |
438 | err = safe_write(file->fd, file->wbuf + file->file_ptr_bytes, n); | |
424 | 439 | if (err < 0) { |
425 | err = -errno; | |
426 | 440 | file->wbuf_used_bytes = 0; |
427 | 441 | file->file_ptr_bytes = 0; |
428 | 442 | SYSERR("%s write failed, file data may be corrupt", file->fname); |
62 | 62 | unsigned int byteswap; |
63 | 63 | unsigned char preamble[3]; /* B/M/W or Z/X/Y */ |
64 | 64 | snd_pcm_fast_ops_t fops; |
65 | int hdmi_mode; | |
65 | 66 | }; |
66 | 67 | |
67 | 68 | enum { PREAMBLE_Z, PREAMBLE_X, PREAMBLE_Y }; |
192 | 193 | unsigned int channel; |
193 | 194 | int32_t sample = 0; |
194 | 195 | int counter = iec->counter; |
196 | int single_stream = iec->hdmi_mode && | |
197 | (iec->status[0] & IEC958_AES0_NONAUDIO) && | |
198 | (channels == 8); | |
199 | int counter_step = single_stream ? ((channels + 1) >> 1) : 1; | |
195 | 200 | for (channel = 0; channel < channels; ++channel) { |
196 | 201 | const char *src; |
197 | 202 | uint32_t *dst; |
204 | 209 | src_step = snd_pcm_channel_area_step(src_area); |
205 | 210 | dst_step = snd_pcm_channel_area_step(dst_area) / sizeof(uint32_t); |
206 | 211 | frames1 = frames; |
207 | iec->counter = counter; | |
212 | ||
213 | if (single_stream) | |
214 | iec->counter = (counter + (channel >> 1)) % 192; | |
215 | else | |
216 | iec->counter = counter; | |
217 | ||
208 | 218 | while (frames1-- > 0) { |
209 | 219 | goto *get; |
210 | 220 | #define GET32_END after |
216 | 226 | *dst = sample; |
217 | 227 | src += src_step; |
218 | 228 | dst += dst_step; |
219 | iec->counter++; | |
229 | iec->counter += counter_step; | |
220 | 230 | iec->counter %= 192; |
221 | 231 | } |
232 | if (single_stream) /* set counter to ch0 value for next iteration */ | |
233 | iec->counter = (counter + frames * counter_step) % 192; | |
222 | 234 | } |
223 | 235 | } |
224 | 236 | #endif /* DOC_HIDDEN */ |
352 | 364 | iec->byteswap = format != SND_PCM_FORMAT_IEC958_SUBFRAME; |
353 | 365 | } |
354 | 366 | } |
355 | /* FIXME: needs to adjust status_bits according to the format | |
356 | * and sample rate | |
357 | */ | |
367 | ||
368 | if ((iec->status[0] & IEC958_AES0_PROFESSIONAL) == 0) { | |
369 | if ((iec->status[3] & IEC958_AES3_CON_FS) == IEC958_AES3_CON_FS_NOTID) { | |
370 | unsigned int rate = 0; | |
371 | unsigned char fs; | |
372 | ||
373 | err = INTERNAL(snd_pcm_hw_params_get_rate)(params, &rate, 0); | |
374 | if (err < 0) | |
375 | rate = 0; | |
376 | ||
377 | switch (rate) { | |
378 | case 22050: | |
379 | fs = IEC958_AES3_CON_FS_22050; | |
380 | break; | |
381 | case 24000: | |
382 | fs = IEC958_AES3_CON_FS_24000; | |
383 | break; | |
384 | case 32000: | |
385 | fs = IEC958_AES3_CON_FS_32000; | |
386 | break; | |
387 | case 44100: | |
388 | fs = IEC958_AES3_CON_FS_44100; | |
389 | break; | |
390 | case 48000: | |
391 | fs = IEC958_AES3_CON_FS_48000; | |
392 | break; | |
393 | case 88200: | |
394 | fs = IEC958_AES3_CON_FS_88200; | |
395 | break; | |
396 | case 96000: | |
397 | fs = IEC958_AES3_CON_FS_96000; | |
398 | break; | |
399 | case 176400: | |
400 | fs = IEC958_AES3_CON_FS_176400; | |
401 | break; | |
402 | case 192000: | |
403 | fs = IEC958_AES3_CON_FS_192000; | |
404 | break; | |
405 | case 768000: | |
406 | fs = IEC958_AES3_CON_FS_768000; | |
407 | break; | |
408 | default: | |
409 | fs = IEC958_AES3_CON_FS_NOTID; | |
410 | break; | |
411 | } | |
412 | ||
413 | iec->status[3] &= ~IEC958_AES3_CON_FS; | |
414 | iec->status[3] |= fs; | |
415 | } | |
416 | ||
417 | if ((iec->status[4] & IEC958_AES4_CON_WORDLEN) == IEC958_AES4_CON_WORDLEN_NOTID) { | |
418 | unsigned char ws; | |
419 | switch (snd_pcm_format_width(format)) { | |
420 | case 16: | |
421 | ws = IEC958_AES4_CON_WORDLEN_20_16; | |
422 | break; | |
423 | case 18: | |
424 | ws = IEC958_AES4_CON_WORDLEN_22_18; | |
425 | break; | |
426 | case 20: | |
427 | ws = IEC958_AES4_CON_WORDLEN_20_16 | IEC958_AES4_CON_MAX_WORDLEN_24; | |
428 | break; | |
429 | case 24: | |
430 | case 32: /* Assume 24-bit width for 32-bit samples. */ | |
431 | ws = IEC958_AES4_CON_WORDLEN_24_20 | IEC958_AES4_CON_MAX_WORDLEN_24; | |
432 | break; | |
433 | default: | |
434 | ws = IEC958_AES4_CON_WORDLEN_NOTID; | |
435 | break; | |
436 | } | |
437 | iec->status[4] &= ~(IEC958_AES4_CON_MAX_WORDLEN_24 | IEC958_AES4_CON_WORDLEN); | |
438 | iec->status[4] |= ws; | |
439 | } | |
440 | } | |
358 | 441 | return 0; |
359 | 442 | } |
360 | 443 | |
472 | 555 | * \param close_slave When set, the slave PCM handle is closed with copy PCM |
473 | 556 | * \param status_bits The IEC958 status bits |
474 | 557 | * \param preamble_vals The preamble byte values |
558 | * \param hdmi_mode When set, enable HDMI compliant formatting | |
475 | 559 | * \retval zero on success otherwise a negative error code |
476 | 560 | * \warning Using of this function might be dangerous in the sense |
477 | 561 | * of compatibility reasons. The prototype might be freely |
480 | 564 | int snd_pcm_iec958_open(snd_pcm_t **pcmp, const char *name, snd_pcm_format_t sformat, |
481 | 565 | snd_pcm_t *slave, int close_slave, |
482 | 566 | const unsigned char *status_bits, |
483 | const unsigned char *preamble_vals) | |
567 | const unsigned char *preamble_vals, | |
568 | int hdmi_mode) | |
484 | 569 | { |
485 | 570 | snd_pcm_t *pcm; |
486 | 571 | snd_pcm_iec958_t *iec; |
489 | 574 | IEC958_AES0_CON_EMPHASIS_NONE, |
490 | 575 | IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER, |
491 | 576 | 0, |
492 | IEC958_AES3_CON_FS_48000 | |
577 | IEC958_AES3_CON_FS_NOTID, /* will be set in hwparams */ | |
578 | IEC958_AES4_CON_WORDLEN_NOTID /* will be set in hwparams */ | |
493 | 579 | }; |
494 | 580 | |
495 | 581 | assert(pcmp && slave); |
517 | 603 | memcpy(iec->status, default_status_bits, sizeof(default_status_bits)); |
518 | 604 | |
519 | 605 | memcpy(iec->preamble, preamble_vals, 3); |
606 | ||
607 | iec->hdmi_mode = hdmi_mode; | |
520 | 608 | |
521 | 609 | err = snd_pcm_new(&pcm, SND_PCM_TYPE_IEC958, name, slave->stream, slave->mode); |
522 | 610 | if (err < 0) { |
565 | 653 | [preamble.z or preamble.b val] |
566 | 654 | [preamble.x or preamble.m val] |
567 | 655 | [preamble.y or preamble.w val] |
656 | [hdmi_mode true] | |
568 | 657 | } |
569 | 658 | \endcode |
659 | ||
660 | When <code>hdmi_mode</code> is true, 8-channel compressed data is | |
661 | formatted as 4 contiguous frames of a single IEC958 stream as required | |
662 | by the HDMI HBR specification. | |
570 | 663 | |
571 | 664 | \subsection pcm_plugins_iec958_funcref Function reference |
572 | 665 | |
604 | 697 | unsigned char preamble_vals[3] = { |
605 | 698 | 0x08, 0x02, 0x04 /* Z, X, Y */ |
606 | 699 | }; |
700 | int hdmi_mode = 0; | |
607 | 701 | |
608 | 702 | snd_config_for_each(i, next, conf) { |
609 | 703 | snd_config_t *n = snd_config_iterator_entry(i); |
630 | 724 | return -EINVAL; |
631 | 725 | } |
632 | 726 | preamble = n; |
727 | continue; | |
728 | } | |
729 | if (strcmp(id, "hdmi_mode") == 0) { | |
730 | err = snd_config_get_bool(n); | |
731 | if (err < 0) | |
732 | continue; | |
733 | hdmi_mode = err; | |
633 | 734 | continue; |
634 | 735 | } |
635 | 736 | SNDERR("Unknown field %s", id); |
706 | 807 | return err; |
707 | 808 | err = snd_pcm_iec958_open(pcmp, name, sformat, spcm, 1, |
708 | 809 | status ? status_bits : NULL, |
709 | preamble_vals); | |
810 | preamble_vals, hdmi_mode); | |
710 | 811 | if (err < 0) |
711 | 812 | snd_pcm_close(spcm); |
712 | 813 | return err; |
1169 | 1169 | |
1170 | 1170 | #define PCMINABORT(pcm) (((pcm)->mode & SND_PCM_ABORT) != 0) |
1171 | 1171 | |
1172 | static inline snd_pcm_sframes_t pcm_frame_diff(snd_pcm_uframes_t ptr1, | |
1173 | snd_pcm_uframes_t ptr2, | |
1174 | snd_pcm_uframes_t boundary) | |
1175 | { | |
1176 | if (ptr1 < ptr2) | |
1177 | return ptr1 + (boundary - ptr2); | |
1178 | else | |
1179 | return ptr1 - ptr2; | |
1180 | } | |
1181 | ||
1182 | static inline snd_pcm_sframes_t pcm_frame_diff2(snd_pcm_uframes_t ptr1, | |
1183 | snd_pcm_uframes_t ptr2, | |
1184 | snd_pcm_uframes_t boundary) | |
1185 | { | |
1186 | snd_pcm_sframes_t r = ptr1 - ptr2; | |
1187 | if (r >= (snd_pcm_sframes_t)boundary / 2) | |
1188 | return boundary - r; | |
1189 | return r; | |
1190 | } | |
1191 | ||
1172 | 1192 | #ifdef THREAD_SAFE_API |
1173 | 1193 | /* |
1174 | 1194 | * __snd_pcm_lock() and __snd_pcm_unlock() are used to lock/unlock the plugin |
78 | 78 | snd_pcm_uframes_t frames) |
79 | 79 | { |
80 | 80 | snd_pcm_meter_t *meter = pcm->private_data; |
81 | if (frames > pcm->buffer_size) | |
82 | frames = pcm->buffer_size; | |
81 | 83 | while (frames > 0) { |
82 | 84 | snd_pcm_uframes_t n = frames; |
83 | 85 | snd_pcm_uframes_t dst_offset = ptr % meter->buf_size; |
1099 | 1101 | size = meter->now - s16->old; |
1100 | 1102 | if (size < 0) |
1101 | 1103 | size += spcm->boundary; |
1104 | if (size > (snd_pcm_sframes_t)s16->pcm->buffer_size) | |
1105 | size = s16->pcm->buffer_size; | |
1102 | 1106 | offset = s16->old % meter->buf_size; |
1103 | 1107 | while (size > 0) { |
1104 | 1108 | snd_pcm_uframes_t frames = size; |
540 | 540 | static int snd_pcm_plugin_status(snd_pcm_t *pcm, snd_pcm_status_t * status) |
541 | 541 | { |
542 | 542 | snd_pcm_plugin_t *plugin = pcm->private_data; |
543 | snd_pcm_sframes_t err; | |
543 | snd_pcm_sframes_t err, avail; | |
544 | 544 | |
545 | 545 | /* sync with the latest hw and appl ptrs */ |
546 | snd_pcm_plugin_avail_update(pcm); | |
546 | avail = snd_pcm_plugin_avail_update(pcm); | |
547 | if (avail < 0) | |
548 | return avail; | |
547 | 549 | |
548 | 550 | err = snd_pcm_status(plugin->gen.slave, status); |
549 | 551 | if (err < 0) |
550 | 552 | return err; |
551 | 553 | status->appl_ptr = *pcm->appl.ptr; |
552 | 554 | status->hw_ptr = *pcm->hw.ptr; |
555 | status->avail = avail; | |
556 | status->delay = snd_pcm_mmap_delay(pcm); | |
553 | 557 | return 0; |
554 | 558 | } |
555 | 559 |
54 | 54 | " offset 0x%zx is %s by %ld bytes", |
55 | 55 | tplg->next_hdr_pos, tplg->bin_pos, |
56 | 56 | tplg->bin_pos > tplg->next_hdr_pos ? "ahead" : "behind", |
57 | labs(tplg->bin_pos - tplg->next_hdr_pos)); | |
57 | tplg->bin_pos - tplg->next_hdr_pos); | |
58 | 58 | return -EINVAL; |
59 | 59 | } |
60 | 60 |
137 | 137 | |
138 | 138 | int tplg_save_channels(snd_tplg_t *tplg ATTRIBUTE_UNUSED, |
139 | 139 | struct snd_soc_tplg_channel *channel, |
140 | unsigned int count, char **dst, const char *pfx) | |
140 | unsigned int count, struct tplg_buf *dst, | |
141 | const char *pfx) | |
141 | 142 | { |
142 | 143 | struct snd_soc_tplg_channel *c; |
143 | 144 | const char *s; |
104 | 104 | |
105 | 105 | /* Save Access */ |
106 | 106 | static int tplg_save_access(snd_tplg_t *tplg ATTRIBUTE_UNUSED, |
107 | struct snd_soc_tplg_ctl_hdr *hdr, char **dst, | |
108 | const char *pfx) | |
107 | struct snd_soc_tplg_ctl_hdr *hdr, | |
108 | struct tplg_buf *dst, const char *pfx) | |
109 | 109 | { |
110 | 110 | const char *last; |
111 | 111 | unsigned int j, count, access, cval; |
398 | 398 | /* save TLV data */ |
399 | 399 | int tplg_save_tlv(snd_tplg_t *tplg ATTRIBUTE_UNUSED, |
400 | 400 | struct tplg_elem *elem, |
401 | char **dst, const char *pfx) | |
401 | struct tplg_buf *dst, const char *pfx) | |
402 | 402 | { |
403 | 403 | struct snd_soc_tplg_ctl_tlv *tlv = elem->tlv; |
404 | 404 | struct snd_soc_tplg_tlv_dbscale *scale; |
556 | 556 | /* save control bytes */ |
557 | 557 | int tplg_save_control_bytes(snd_tplg_t *tplg ATTRIBUTE_UNUSED, |
558 | 558 | struct tplg_elem *elem, |
559 | char **dst, const char *pfx) | |
559 | struct tplg_buf *dst, const char *pfx) | |
560 | 560 | { |
561 | 561 | struct snd_soc_tplg_bytes_control *be = elem->bytes_ext; |
562 | 562 | char pfx2[16]; |
696 | 696 | /* save control eunm */ |
697 | 697 | int tplg_save_control_enum(snd_tplg_t *tplg ATTRIBUTE_UNUSED, |
698 | 698 | struct tplg_elem *elem, |
699 | char **dst, const char *pfx) | |
699 | struct tplg_buf *dst, const char *pfx) | |
700 | 700 | { |
701 | 701 | struct snd_soc_tplg_enum_control *ec = elem->enum_ctrl; |
702 | 702 | char pfx2[16]; |
857 | 857 | } |
858 | 858 | |
859 | 859 | int tplg_save_control_mixer(snd_tplg_t *tplg ATTRIBUTE_UNUSED, |
860 | struct tplg_elem *elem, char **dst, | |
861 | const char *pfx) | |
860 | struct tplg_elem *elem, | |
861 | struct tplg_buf *dst, const char *pfx) | |
862 | 862 | { |
863 | 863 | struct snd_soc_tplg_mixer_control *mc = elem->mixer_ctrl; |
864 | 864 | char pfx2[16]; |
878 | 878 | if (err >= 0 && mc->max > 0) |
879 | 879 | err = tplg_save_printf(dst, pfx, "\tmax %u\n", mc->max); |
880 | 880 | if (err >= 0 && mc->invert > 0) |
881 | err = tplg_save_printf(dst, pfx, "\tinvert 1\n", mc->max); | |
881 | err = tplg_save_printf(dst, pfx, "\tinvert 1\n"); | |
882 | 882 | if (err >= 0 && mc->invert > 0) |
883 | err = tplg_save_printf(dst, pfx, "\tinvert 1\n", mc->max); | |
883 | err = tplg_save_printf(dst, pfx, "\tinvert 1\n"); | |
884 | 884 | if (err >= 0) |
885 | 885 | err = tplg_save_ops(tplg, &mc->hdr, dst, pfx2); |
886 | 886 | if (err >= 0) |
1087 | 1087 | } |
1088 | 1088 | |
1089 | 1089 | if (enum_ctl->texts != NULL) { |
1090 | struct tplg_elem *texts = tplg_elem_new_common(tplg, NULL, | |
1091 | enum_ctl->hdr.name, SND_TPLG_TYPE_TEXT); | |
1092 | ||
1093 | texts->texts->num_items = num_items; | |
1090 | 1094 | for (i = 0; i < num_items; i++) { |
1091 | if (enum_ctl->texts[i] != NULL) | |
1092 | snd_strlcpy(ec->texts[i], enum_ctl->texts[i], | |
1093 | SNDRV_CTL_ELEM_ID_NAME_MAXLEN); | |
1094 | } | |
1095 | if (!enum_ctl->texts[i]) | |
1096 | continue; | |
1097 | snd_strlcpy(ec->texts[i], enum_ctl->texts[i], | |
1098 | SNDRV_CTL_ELEM_ID_NAME_MAXLEN); | |
1099 | snd_strlcpy(texts->texts->items[i], enum_ctl->texts[i], | |
1100 | SNDRV_CTL_ELEM_ID_NAME_MAXLEN); | |
1101 | } | |
1102 | tplg_ref_add(elem, SND_TPLG_TYPE_TEXT, enum_ctl->hdr.name); | |
1095 | 1103 | } |
1096 | 1104 | |
1097 | 1105 | if (enum_ctl->values != NULL) { |
1326 | 1334 | struct list_head *heap, |
1327 | 1335 | struct snd_tplg_enum_template *et, |
1328 | 1336 | size_t pos, |
1329 | void *bin, size_t size) | |
1330 | { | |
1331 | struct snd_soc_tplg_enum_control *ec = bin; | |
1332 | struct snd_tplg_channel_map_template cmt; | |
1337 | struct snd_soc_tplg_enum_control *ec) | |
1338 | { | |
1333 | 1339 | int i; |
1334 | 1340 | |
1335 | if (size < sizeof(*ec)) { | |
1336 | SNDERR("enum: small size %d", size); | |
1337 | return -EINVAL; | |
1338 | } | |
1339 | ||
1340 | tplg_log(tplg, 'D', pos, "enum: size %d private size %d", | |
1341 | ec->size, ec->priv.size); | |
1342 | if (size != ec->size + ec->priv.size) { | |
1343 | SNDERR("enum: unexpected element size %d", size); | |
1344 | return -EINVAL; | |
1345 | } | |
1346 | 1341 | if (ec->num_channels > SND_TPLG_MAX_CHAN || |
1347 | 1342 | ec->num_channels > SND_SOC_TPLG_MAX_CHAN) { |
1348 | 1343 | SNDERR("enum: unexpected channel count %d", ec->num_channels); |
1367 | 1362 | et->texts = tplg_calloc(heap, sizeof(char *) * ec->items); |
1368 | 1363 | if (!et->texts) |
1369 | 1364 | return -ENOMEM; |
1370 | for (i = 0; ec->items; i++) { | |
1371 | unsigned int j = i * sizeof(int) * ENUM_VAL_SIZE; | |
1365 | for (i = 0; (unsigned int)i < ec->items; i++) | |
1372 | 1366 | et->texts[i] = ec->texts[i]; |
1373 | et->values[i] = (int *)&ec->values[j]; | |
1374 | } | |
1375 | } | |
1376 | ||
1377 | et->map = &cmt; | |
1378 | memset(&cmt, 0, sizeof(cmt)); | |
1379 | cmt.num_channels = ec->num_channels; | |
1380 | for (i = 0; i < cmt.num_channels; i++) { | |
1381 | struct snd_tplg_channel_elem *channel = &cmt.channel[i]; | |
1367 | } | |
1368 | ||
1369 | et->map = tplg_calloc(heap, sizeof(struct snd_tplg_channel_map_template)); | |
1370 | if (!et->map) | |
1371 | return -ENOMEM; | |
1372 | et->map->num_channels = ec->num_channels; | |
1373 | for (i = 0; i < et->map->num_channels; i++) { | |
1374 | struct snd_tplg_channel_elem *channel = &et->map->channel[i]; | |
1375 | ||
1382 | 1376 | tplg_log(tplg, 'D', pos + ((void *)&ec->channel[i] - (void *)ec), |
1383 | 1377 | "enum: channel size %d", ec->channel[i].size); |
1384 | 1378 | channel->reg = ec->channel[i].reg; |
1420 | 1414 | return -EINVAL; |
1421 | 1415 | } |
1422 | 1416 | |
1423 | err = tplg_decode_control_enum1(tplg, &heap, &et, pos, bin, size); | |
1417 | tplg_log(tplg, 'D', pos, "enum: size %d private size %d", | |
1418 | ec->size, ec->priv.size); | |
1419 | ||
1420 | err = tplg_decode_control_enum1(tplg, &heap, &et, pos, ec); | |
1424 | 1421 | if (err >= 0) { |
1425 | 1422 | t.enum_ctl = &et; |
1426 | 1423 | err = snd_tplg_add_object(tplg, &t); |
415 | 415 | } |
416 | 416 | |
417 | 417 | /* save DAPM graph */ |
418 | int tplg_save_dapm_graph(snd_tplg_t *tplg, int index, char **dst, const char *pfx) | |
418 | int tplg_save_dapm_graph(snd_tplg_t *tplg, int index, | |
419 | struct tplg_buf *dst, const char *pfx) | |
419 | 420 | { |
420 | 421 | struct snd_soc_tplg_dapm_graph_elem *route; |
421 | 422 | struct list_head *pos; |
481 | 482 | } |
482 | 483 | if (first) { |
483 | 484 | first = 0; |
484 | err = tplg_save_printf(dst, pfx, "\t\tlines [\n", elem->index); | |
485 | err = tplg_save_printf(dst, pfx, "\t\tlines [\n"); | |
485 | 486 | if (err < 0) |
486 | 487 | return err; |
487 | 488 | } |
668 | 669 | /* save DAPM widget */ |
669 | 670 | int tplg_save_dapm_widget(snd_tplg_t *tplg ATTRIBUTE_UNUSED, |
670 | 671 | struct tplg_elem *elem, |
671 | char **dst, const char *pfx) | |
672 | struct tplg_buf *dst, const char *pfx) | |
672 | 673 | { |
673 | 674 | struct snd_soc_tplg_dapm_widget *widget = elem->widget; |
674 | 675 | const char *s; |
971 | 972 | err = -EINVAL; |
972 | 973 | goto retval; |
973 | 974 | } |
974 | err = tplg_decode_control_enum1(tplg, &heap, et, pos, | |
975 | bin, size2); | |
975 | err = tplg_decode_control_enum1(tplg, &heap, et, pos, ec); | |
976 | 976 | break; |
977 | 977 | case SND_SOC_TPLG_TYPE_BYTES: |
978 | 978 | bt = tplg_calloc(&heap, sizeof(*bt)); |
120 | 120 | /* save references */ |
121 | 121 | int tplg_save_refs(snd_tplg_t *tplg ATTRIBUTE_UNUSED, |
122 | 122 | struct tplg_elem *elem, unsigned int type, |
123 | const char *id, char **dst, const char *pfx) | |
123 | const char *id, struct tplg_buf *dst, | |
124 | const char *pfx) | |
124 | 125 | { |
125 | 126 | struct tplg_ref *ref, *last; |
126 | 127 | struct list_head *pos; |
889 | 890 | /* save tuple set */ |
890 | 891 | static int tplg_save_tuple_set(struct tplg_vendor_tuples *tuples, |
891 | 892 | unsigned int set_index, |
892 | char **dst, const char *pfx) | |
893 | struct tplg_buf *dst, const char *pfx) | |
893 | 894 | { |
894 | 895 | struct tplg_tuple_set *set; |
895 | 896 | struct tplg_tuple *tuple; |
928 | 929 | err = tplg_save_printf(dst, pfx, "\t'%s' ", |
929 | 930 | tuple->token); |
930 | 931 | } |
932 | if (err < 0) | |
933 | return err; | |
931 | 934 | switch (set->type) { |
932 | 935 | case SND_SOC_TPLG_TUPLE_TYPE_UUID: |
933 | 936 | err = tplg_save_printf(dst, NULL, "'" UUID_FORMAT "'\n", |
1013 | 1016 | /* save tuple sets */ |
1014 | 1017 | int tplg_save_tuple_sets(snd_tplg_t *tplg ATTRIBUTE_UNUSED, |
1015 | 1018 | struct tplg_elem *elem, |
1016 | char **dst, const char *pfx) | |
1019 | struct tplg_buf *dst, const char *pfx) | |
1017 | 1020 | { |
1018 | 1021 | struct tplg_vendor_tuples *tuples = elem->tuples; |
1019 | 1022 | unsigned int i; |
1084 | 1087 | /* save vendor tokens */ |
1085 | 1088 | int tplg_save_tokens(snd_tplg_t *tplg ATTRIBUTE_UNUSED, |
1086 | 1089 | struct tplg_elem *elem, |
1087 | char **dst, const char *pfx) | |
1090 | struct tplg_buf *dst, const char *pfx) | |
1088 | 1091 | { |
1089 | 1092 | struct tplg_vendor_tokens *tokens = elem->tokens; |
1090 | 1093 | unsigned int i; |
1155 | 1158 | /* save vendor tuples */ |
1156 | 1159 | int tplg_save_tuples(snd_tplg_t *tplg ATTRIBUTE_UNUSED, |
1157 | 1160 | struct tplg_elem *elem, |
1158 | char **dst, const char *pfx) | |
1161 | struct tplg_buf *dst, const char *pfx) | |
1159 | 1162 | { |
1160 | 1163 | char pfx2[16]; |
1161 | 1164 | int err; |
1241 | 1244 | |
1242 | 1245 | /* save manifest data */ |
1243 | 1246 | int tplg_save_manifest_data(snd_tplg_t *tplg ATTRIBUTE_UNUSED, |
1244 | struct tplg_elem *elem, char **dst, | |
1247 | struct tplg_elem *elem, struct tplg_buf *dst, | |
1245 | 1248 | const char *pfx) |
1246 | 1249 | { |
1247 | 1250 | struct list_head *pos; |
1274 | 1277 | elem->id, index, ref->id); |
1275 | 1278 | } else { |
1276 | 1279 | err = tplg_save_printf(dst, pfx, "\t'%s'\n", ref->id); |
1277 | if (err < 0) | |
1278 | return err; | |
1279 | } | |
1280 | } | |
1281 | if (err < 0) | |
1282 | return err; | |
1280 | 1283 | index++; |
1281 | 1284 | } |
1282 | 1285 | if (count > 1) { |
1419 | 1422 | /* save data element */ |
1420 | 1423 | int tplg_save_data(snd_tplg_t *tplg ATTRIBUTE_UNUSED, |
1421 | 1424 | struct tplg_elem *elem, |
1422 | char **dst, const char *pfx) | |
1425 | struct tplg_buf *dst, const char *pfx) | |
1423 | 1426 | { |
1424 | 1427 | struct snd_soc_tplg_private *priv = elem->data; |
1425 | 1428 | struct list_head *pos; |
1610 | 1613 | if (!elem) |
1611 | 1614 | return -ENOMEM; |
1612 | 1615 | |
1613 | tplg_log(tplg, 'D', pos, "manifest: private size %d", size); | |
1616 | tplg_log(tplg, 'D', pos, "manifest: private size %zd", size); | |
1614 | 1617 | return tplg_add_data(tplg, elem, bin, size); |
1615 | 1618 | } |
1616 | 1619 | |
1670 | 1673 | |
1671 | 1674 | va = bin; |
1672 | 1675 | if (size < sizeof(*va) || size < va->size) { |
1673 | tplg_log(tplg, 'A', pos, "tuple set verify: wrong size %d", size); | |
1676 | tplg_log(tplg, 'A', pos, "tuple set verify: wrong size %zd", size); | |
1674 | 1677 | return -EINVAL; |
1675 | 1678 | } |
1676 | 1679 | |
1717 | 1720 | |
1718 | 1721 | va = bin; |
1719 | 1722 | if (size < sizeof(*va) || size < va->size) { |
1720 | SNDERR("tuples: wrong size %d", size); | |
1723 | SNDERR("tuples: wrong size %zd", size); | |
1721 | 1724 | return -EINVAL; |
1722 | 1725 | } |
1723 | 1726 | |
1804 | 1807 | int err; |
1805 | 1808 | |
1806 | 1809 | if (size < sizeof(*va)) { |
1807 | tplg_log(tplg, 'A', pos, "tuples: small size %d", size); | |
1810 | tplg_log(tplg, 'A', pos, "tuples: small size %zd", size); | |
1808 | 1811 | return -EINVAL; |
1809 | 1812 | } |
1810 | 1813 | |
1811 | 1814 | next: |
1812 | 1815 | va = bin; |
1813 | 1816 | if (size < sizeof(*va)) { |
1814 | tplg_log(tplg, 'A', pos, "tuples: unexpected vendor arry size %d", size); | |
1817 | tplg_log(tplg, 'A', pos, "tuples: unexpected vendor arry size %zd", size); | |
1815 | 1818 | return -EINVAL; |
1816 | 1819 | } |
1817 | 1820 | |
1840 | 1843 | int err; |
1841 | 1844 | |
1842 | 1845 | if (size < sizeof(*va)) { |
1843 | SNDERR("tuples: small size %d", size); | |
1846 | SNDERR("tuples: small size %zd", size); | |
1844 | 1847 | return -EINVAL; |
1845 | 1848 | } |
1846 | 1849 | |
1847 | 1850 | next: |
1848 | 1851 | va = bin; |
1849 | 1852 | if (size < sizeof(*va)) { |
1850 | SNDERR("tuples: unexpected vendor arry size %d", size); | |
1853 | SNDERR("tuples: unexpected vendor arry size %zd", size); | |
1851 | 1854 | return -EINVAL; |
1852 | 1855 | } |
1853 | 1856 | |
1892 | 1895 | next: |
1893 | 1896 | tp = bin; |
1894 | 1897 | if (off + size < tp->size) { |
1895 | SNDERR("data: unexpected element size %d", size); | |
1898 | SNDERR("data: unexpected element size %zd", size); | |
1896 | 1899 | return -EINVAL; |
1897 | 1900 | } |
1898 | 1901 |
104 | 104 | |
105 | 105 | /* save control operations */ |
106 | 106 | int tplg_save_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, |
107 | struct snd_soc_tplg_ctl_hdr *hdr, char **dst, | |
108 | const char *pfx) | |
107 | struct snd_soc_tplg_ctl_hdr *hdr, | |
108 | struct tplg_buf *dst, const char *pfx) | |
109 | 109 | { |
110 | 110 | const char *s; |
111 | 111 | int err; |
190 | 190 | /* save external control operations */ |
191 | 191 | int tplg_save_ext_ops(snd_tplg_t *tplg ATTRIBUTE_UNUSED, |
192 | 192 | struct snd_soc_tplg_bytes_control *be, |
193 | char **dst, const char *pfx) | |
193 | struct tplg_buf *dst, const char *pfx) | |
194 | 194 | { |
195 | 195 | const char *s; |
196 | 196 | int err; |
426 | 426 | |
427 | 427 | static bool is_little_endian(void) |
428 | 428 | { |
429 | #ifdef __BYTE_ORDER | |
430 | #if __BYTE_ORDER == __LITTLE_ENDIAN | |
431 | return true; | |
432 | #endif | |
429 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && __SIZEOF_INT__ == 4 | |
430 | return true; | |
433 | 431 | #endif |
434 | 432 | return false; |
435 | 433 | } |
375 | 375 | return 0; |
376 | 376 | } |
377 | 377 | |
378 | static int parse_unsigned(snd_config_t *n, unsigned int *dst) | |
378 | static int parse_unsigned(snd_config_t *n, void *dst) | |
379 | 379 | { |
380 | 380 | int ival; |
381 | 381 | |
382 | 382 | if (tplg_get_integer(n, &ival, 0) < 0) |
383 | 383 | return -EINVAL; |
384 | 384 | |
385 | *dst = ival; | |
385 | unaligned_put32(dst, ival); | |
386 | 386 | #if TPLG_DEBUG |
387 | 387 | { |
388 | 388 | const char *id; |
389 | 389 | if (snd_config_get_id(n, &id) >= 0) |
390 | tplg_dbg("\t\t%s: %d", id, *dst); | |
390 | tplg_dbg("\t\t%s: %d", id, ival); | |
391 | 391 | } |
392 | 392 | #endif |
393 | 393 | return 0; |
537 | 537 | /* save stream caps */ |
538 | 538 | int tplg_save_stream_caps(snd_tplg_t *tplg ATTRIBUTE_UNUSED, |
539 | 539 | struct tplg_elem *elem, |
540 | char **dst, const char *pfx) | |
540 | struct tplg_buf *dst, const char *pfx) | |
541 | 541 | { |
542 | 542 | struct snd_soc_tplg_stream_caps *sc = elem->stream_caps; |
543 | 543 | const char *s; |
548 | 548 | if (err >= 0 && sc->formats) { |
549 | 549 | err = tplg_save_printf(dst, pfx, "\tformats '"); |
550 | 550 | first = 1; |
551 | for (i = 0; err >= 0 && i < SND_PCM_FORMAT_LAST; i++) { | |
551 | for (i = 0; err >= 0 && i <= SND_PCM_FORMAT_LAST; i++) { | |
552 | 552 | if (sc->formats & (1ULL << i)) { |
553 | 553 | s = snd_pcm_format_name(i); |
554 | 554 | err = tplg_save_printf(dst, NULL, "%s%s", |
562 | 562 | if (err >= 0 && sc->rates) { |
563 | 563 | err = tplg_save_printf(dst, pfx, "\trates '"); |
564 | 564 | first = 1; |
565 | for (i = 0; err >= 0 && i < SND_PCM_RATE_LAST; i++) { | |
565 | for (i = 0; err >= 0 && i <= SND_PCM_RATE_LAST; i++) { | |
566 | 566 | if (sc->rates & (1ULL << i)) { |
567 | 567 | s = get_rate_name(i); |
568 | 568 | err = tplg_save_printf(dst, NULL, "%s%s", |
603 | 603 | if (err >= 0 && sc->buffer_size_max) |
604 | 604 | err = tplg_save_printf(dst, pfx, "\tbuffer_size_max %u\n", |
605 | 605 | sc->buffer_size_max); |
606 | if (err >= 0 && sc->sig_bits) | |
607 | err = tplg_save_printf(dst, pfx, "\tsig_bits %u\n", | |
608 | sc->sig_bits); | |
606 | 609 | if (err >= 0) |
607 | 610 | err = tplg_save_printf(dst, pfx, "}\n"); |
608 | 611 | return err; |
617 | 620 | struct tplg_elem *elem = private; |
618 | 621 | struct snd_soc_tplg_pcm *pcm; |
619 | 622 | struct snd_soc_tplg_dai *dai; |
620 | unsigned int *playback, *capture; | |
623 | void *playback, *capture; | |
621 | 624 | struct snd_soc_tplg_stream_caps *caps; |
622 | 625 | const char *id, *value; |
623 | 626 | int stream; |
647 | 650 | |
648 | 651 | if (strcmp(id, "playback") == 0) { |
649 | 652 | stream = SND_SOC_TPLG_STREAM_PLAYBACK; |
650 | *playback = 1; | |
653 | unaligned_put32(playback, 1); | |
651 | 654 | } else if (strcmp(id, "capture") == 0) { |
652 | 655 | stream = SND_SOC_TPLG_STREAM_CAPTURE; |
653 | *capture = 1; | |
656 | unaligned_put32(capture, 1); | |
654 | 657 | } else |
655 | 658 | return -EINVAL; |
656 | 659 | |
682 | 685 | /* Save the caps and config of a pcm stream */ |
683 | 686 | int tplg_save_streams(snd_tplg_t *tplg ATTRIBUTE_UNUSED, |
684 | 687 | struct tplg_elem *elem, |
685 | char **dst, const char *pfx) | |
688 | struct tplg_buf *dst, const char *pfx) | |
686 | 689 | { |
687 | 690 | static const char *stream_ids[2] = { |
688 | 691 | "playback", |
743 | 746 | snd_config_iterator_t i, next; |
744 | 747 | snd_config_t *n; |
745 | 748 | const char *id; |
749 | unsigned int dai_id; | |
746 | 750 | |
747 | 751 | snd_config_get_id(cfg, &id); |
748 | 752 | tplg_dbg("\t\tFE DAI %s:", id); |
757 | 761 | continue; |
758 | 762 | |
759 | 763 | if (strcmp(id, "id") == 0) { |
760 | if (tplg_get_unsigned(n, &pcm->dai_id, 0)) { | |
764 | if (tplg_get_unsigned(n, &dai_id, 0)) { | |
761 | 765 | SNDERR("invalid fe dai ID"); |
762 | 766 | return -EINVAL; |
763 | 767 | } |
764 | 768 | |
765 | tplg_dbg("\t\t\tindex: %d", pcm->dai_id); | |
769 | unaligned_put32(&pcm->dai_id, dai_id); | |
770 | tplg_dbg("\t\t\tindex: %d", dai_id); | |
766 | 771 | } |
767 | 772 | } |
768 | 773 | |
772 | 777 | /* Save the caps and config of a pcm stream */ |
773 | 778 | int tplg_save_fe_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED, |
774 | 779 | struct tplg_elem *elem, |
775 | char **dst, const char *pfx) | |
780 | struct tplg_buf *dst, const char *pfx) | |
776 | 781 | { |
777 | 782 | struct snd_soc_tplg_pcm *pcm = elem->pcm; |
778 | 783 | int err = 0; |
779 | 784 | |
780 | if (pcm->dai_id > 0) | |
785 | if (strlen(pcm->dai_name)) | |
786 | err = tplg_save_printf(dst, pfx, "dai.'%s'.id %u\n", pcm->dai_name, pcm->dai_id); | |
787 | else if (pcm->dai_id > 0) | |
781 | 788 | err = tplg_save_printf(dst, pfx, "dai.0.id %u\n", pcm->dai_id); |
782 | 789 | return err; |
783 | 790 | } |
784 | 791 | |
785 | 792 | /* parse a flag bit of the given mask */ |
786 | 793 | static int parse_flag(snd_config_t *n, unsigned int mask_in, |
787 | unsigned int *mask, unsigned int *flags) | |
794 | void *mask, void *flags) | |
788 | 795 | { |
789 | 796 | int ret; |
790 | 797 | |
792 | 799 | if (ret < 0) |
793 | 800 | return ret; |
794 | 801 | |
795 | *mask |= mask_in; | |
802 | unaligned_put32(mask, unaligned_get32(mask) | mask_in); | |
796 | 803 | if (ret) |
797 | *flags |= mask_in; | |
804 | unaligned_put32(flags, unaligned_get32(flags) | mask_in); | |
798 | 805 | else |
799 | *flags &= ~mask_in; | |
806 | unaligned_put32(flags, unaligned_get32(flags) & (~mask_in)); | |
800 | 807 | |
801 | 808 | return 0; |
802 | 809 | } |
803 | 810 | |
804 | 811 | static int save_flags(unsigned int flags, unsigned int mask, |
805 | char **dst, const char *pfx) | |
812 | struct tplg_buf *dst, const char *pfx) | |
806 | 813 | { |
807 | 814 | static unsigned int flag_masks[3] = { |
808 | 815 | SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_RATES, |
936 | 943 | /* save PCM */ |
937 | 944 | int tplg_save_pcm(snd_tplg_t *tplg ATTRIBUTE_UNUSED, |
938 | 945 | struct tplg_elem *elem, |
939 | char **dst, const char *pfx) | |
946 | struct tplg_buf *dst, const char *pfx) | |
940 | 947 | { |
941 | 948 | struct snd_soc_tplg_pcm *pcm = elem->pcm; |
942 | 949 | char pfx2[16]; |
1073 | 1080 | /* save DAI */ |
1074 | 1081 | int tplg_save_dai(snd_tplg_t *tplg ATTRIBUTE_UNUSED, |
1075 | 1082 | struct tplg_elem *elem, |
1076 | char **dst, const char *pfx) | |
1083 | struct tplg_buf *dst, const char *pfx) | |
1077 | 1084 | { |
1078 | 1085 | struct snd_soc_tplg_dai *dai = elem->dai; |
1079 | 1086 | char pfx2[16]; |
1227 | 1234 | /* save physical link */ |
1228 | 1235 | int tplg_save_link(snd_tplg_t *tplg ATTRIBUTE_UNUSED, |
1229 | 1236 | struct tplg_elem *elem, |
1230 | char **dst, const char *pfx) | |
1237 | struct tplg_buf *dst, const char *pfx) | |
1231 | 1238 | { |
1232 | 1239 | struct snd_soc_tplg_link_config *link = elem->link; |
1233 | 1240 | char pfx2[16]; |
1307 | 1314 | /* save CC */ |
1308 | 1315 | int tplg_save_cc(snd_tplg_t *tplg ATTRIBUTE_UNUSED, |
1309 | 1316 | struct tplg_elem *elem, |
1310 | char **dst, const char *pfx) | |
1317 | struct tplg_buf *dst, const char *pfx) | |
1311 | 1318 | { |
1312 | 1319 | struct snd_soc_tplg_link_config *link = elem->link; |
1313 | 1320 | char pfx2[16]; |
1603 | 1610 | /* save hw config */ |
1604 | 1611 | int tplg_save_hw_config(snd_tplg_t *tplg ATTRIBUTE_UNUSED, |
1605 | 1612 | struct tplg_elem *elem, |
1606 | char **dst, const char *pfx) | |
1613 | struct tplg_buf *dst, const char *pfx) | |
1607 | 1614 | { |
1608 | 1615 | struct snd_soc_tplg_hw_config *hc = elem->hw_cfg; |
1609 | 1616 | int err; |
18 | 18 | #include "tplg_local.h" |
19 | 19 | |
20 | 20 | #define SAVE_ALLOC_SHIFT (13) /* 8192 bytes */ |
21 | ||
22 | int tplg_save_printf(char **dst, const char *pfx, const char *fmt, ...) | |
21 | #define PRINT_ALLOC_SHIFT (10) /* 1024 bytes */ | |
22 | #define PRINT_BUF_SIZE_MAX (1024 * 1024) | |
23 | #define NEXT_CHUNK(val, shift) ((((val) >> (shift)) + 1) << (shift)) | |
24 | ||
25 | void tplg_buf_init(struct tplg_buf *buf) | |
26 | { | |
27 | buf->dst = NULL; | |
28 | buf->dst_len = 0; | |
29 | buf->printf_buf = NULL; | |
30 | buf->printf_buf_size = 0; | |
31 | } | |
32 | ||
33 | void tplg_buf_free(struct tplg_buf *buf) | |
34 | { | |
35 | free(buf->dst); | |
36 | free(buf->printf_buf); | |
37 | } | |
38 | ||
39 | char *tplg_buf_detach(struct tplg_buf *buf) | |
40 | { | |
41 | char *ret = buf->dst; | |
42 | free(buf->printf_buf); | |
43 | return ret; | |
44 | } | |
45 | ||
46 | int tplg_save_printf(struct tplg_buf *dst, const char *pfx, const char *fmt, ...) | |
23 | 47 | { |
24 | 48 | va_list va; |
25 | char buf[1024], *s; | |
49 | char *s; | |
26 | 50 | size_t n, l, t, pl; |
51 | int ret = 0; | |
27 | 52 | |
28 | 53 | if (pfx == NULL) |
29 | 54 | pfx = ""; |
30 | 55 | |
31 | 56 | va_start(va, fmt); |
32 | n = vsnprintf(buf, sizeof(buf), fmt, va); | |
57 | n = vsnprintf(dst->printf_buf, dst->printf_buf_size, fmt, va); | |
33 | 58 | va_end(va); |
34 | 59 | |
35 | if (n >= sizeof(buf)) | |
36 | return -EOVERFLOW; | |
60 | if (n >= PRINT_BUF_SIZE_MAX) { | |
61 | ret = -EOVERFLOW; | |
62 | goto end; | |
63 | } | |
64 | ||
65 | if (n >= dst->printf_buf_size) { | |
66 | t = NEXT_CHUNK(n + 1, PRINT_ALLOC_SHIFT); | |
67 | s = realloc(dst->printf_buf, t); | |
68 | if (!s) { | |
69 | ret = -ENOMEM; | |
70 | goto end; | |
71 | } | |
72 | dst->printf_buf = s; | |
73 | dst->printf_buf_size = t; | |
74 | va_start(va, fmt); | |
75 | n = vsnprintf(dst->printf_buf, n + 1, fmt, va); | |
76 | va_end(va); | |
77 | } | |
37 | 78 | |
38 | 79 | pl = strlen(pfx); |
39 | l = *dst ? strlen(*dst) : 0; | |
80 | l = dst->dst_len; | |
40 | 81 | t = l + pl + n + 1; |
41 | 82 | /* allocate chunks */ |
42 | if (*dst == NULL || | |
83 | if (dst->dst == NULL || | |
43 | 84 | (l >> SAVE_ALLOC_SHIFT) != (t >> SAVE_ALLOC_SHIFT)) { |
44 | s = realloc(*dst, ((t >> SAVE_ALLOC_SHIFT) + 1) << | |
45 | SAVE_ALLOC_SHIFT); | |
85 | s = realloc(dst->dst, NEXT_CHUNK(t, SAVE_ALLOC_SHIFT)); | |
46 | 86 | if (s == NULL) { |
47 | free(*dst); | |
48 | *dst = NULL; | |
49 | return -ENOMEM; | |
87 | ret = -ENOMEM; | |
88 | goto end; | |
50 | 89 | } |
51 | 90 | } else { |
52 | s = *dst; | |
91 | s = dst->dst; | |
53 | 92 | } |
54 | 93 | |
55 | 94 | if (pl > 0) |
56 | 95 | strcpy(s + l, pfx); |
57 | strcpy(s + l + pl, buf); | |
58 | *dst = s; | |
59 | return 0; | |
96 | strcpy(s + l + pl, dst->printf_buf); | |
97 | dst->dst = s; | |
98 | dst->dst_len = t - 1; | |
99 | end: | |
100 | return ret; | |
60 | 101 | } |
61 | 102 | |
62 | 103 | int tplg_nice_value_format(char *dst, size_t dst_size, unsigned int value) |
118 | 159 | int index, array, count; |
119 | 160 | |
120 | 161 | if (snd_config_get_type(src) != SND_CONFIG_TYPE_COMPOUND) { |
121 | ||
122 | 162 | if (snd_config_copy(&dst, src) >= 0) |
123 | 163 | return dst; |
124 | 164 | return NULL; |
130 | 170 | if (a == NULL) |
131 | 171 | return NULL; |
132 | 172 | array = snd_config_is_array(src); |
133 | if (array <= 0) { | |
134 | index = 0; | |
135 | snd_config_for_each(i, next, src) { | |
136 | snd_config_t *s = snd_config_iterator_entry(i); | |
137 | a[index++] = s; | |
138 | } | |
173 | index = 0; | |
174 | snd_config_for_each(i, next, src) { | |
175 | snd_config_t *s = snd_config_iterator_entry(i); | |
176 | a[index++] = s; | |
177 | } | |
178 | if (array <= 0) | |
139 | 179 | qsort(a, count, sizeof(a[0]), _compar); |
140 | } | |
141 | 180 | if (snd_config_make_compound(&dst, id, count == 1)) { |
142 | 181 | free(a); |
143 | 182 | return NULL; |
186 | 225 | return 0; |
187 | 226 | } |
188 | 227 | |
189 | static int tplg_save_quoted(char **dst, const char *str) | |
228 | static int tplg_save_quoted(struct tplg_buf *dst, const char *str) | |
190 | 229 | { |
191 | 230 | static const char nibble[16] = "0123456789abcdef"; |
192 | 231 | unsigned char *p, *d, *t; |
240 | 279 | return tplg_save_printf(dst, NULL, "'%s'", d); |
241 | 280 | } |
242 | 281 | |
243 | static int tplg_save_string(char **dst, const char *str, int id) | |
282 | static int tplg_save_string(struct tplg_buf *dst, const char *str, int id) | |
244 | 283 | { |
245 | 284 | const unsigned char *p = (const unsigned char *)str; |
246 | 285 | |
256 | 295 | return tplg_save_printf(dst, NULL, "%s", str); |
257 | 296 | } |
258 | 297 | |
259 | static int save_config(char **dst, int level, const char *delim, snd_config_t *src) | |
298 | static int save_config(struct tplg_buf *dst, int level, const char *delim, snd_config_t *src) | |
260 | 299 | { |
261 | 300 | snd_config_iterator_t i, next; |
262 | 301 | snd_config_t *s; |
355 | 394 | err = tplg_save_quoted(dst, id); |
356 | 395 | } else { |
357 | 396 | err = tplg_save_string(dst, id, 1); |
358 | if (err < 0) | |
359 | return err; | |
360 | } | |
397 | } | |
398 | if (err < 0) | |
399 | return err; | |
361 | 400 | } else { |
362 | 401 | delim = ""; |
363 | 402 | } |
377 | 416 | return 0; |
378 | 417 | } |
379 | 418 | |
380 | static int tplg_save(snd_tplg_t *tplg, char **dst, int gindex, const char *prefix) | |
419 | static int tplg_save(snd_tplg_t *tplg, struct tplg_buf *dst, | |
420 | int gindex, const char *prefix) | |
381 | 421 | { |
382 | 422 | struct tplg_table *tptr; |
383 | 423 | struct tplg_elem *elem; |
461 | 501 | return 0; |
462 | 502 | |
463 | 503 | _err: |
464 | free(*dst); | |
465 | *dst = NULL; | |
466 | 504 | return err; |
467 | 505 | } |
468 | 506 | |
517 | 555 | |
518 | 556 | int snd_tplg_save(snd_tplg_t *tplg, char **dst, int flags) |
519 | 557 | { |
558 | struct tplg_buf buf, buf2; | |
520 | 559 | snd_input_t *in; |
521 | 560 | snd_config_t *top, *top2; |
522 | char *dst2; | |
523 | 561 | int *indexes, *a; |
524 | 562 | int err; |
525 | 563 | |
527 | 565 | assert(dst); |
528 | 566 | *dst = NULL; |
529 | 567 | |
568 | tplg_buf_init(&buf); | |
569 | ||
530 | 570 | if (flags & SND_TPLG_SAVE_GROUPS) { |
531 | 571 | err = tplg_index_groups(tplg, &indexes); |
532 | 572 | if (err < 0) |
533 | 573 | return err; |
534 | 574 | for (a = indexes; err >= 0 && *a >= 0; a++) { |
535 | err = tplg_save_printf(dst, NULL, | |
575 | err = tplg_save_printf(&buf, NULL, | |
536 | 576 | "IndexGroup.%d {\n", |
537 | 577 | *a); |
538 | 578 | if (err >= 0) |
539 | err = tplg_save(tplg, dst, *a, "\t"); | |
579 | err = tplg_save(tplg, &buf, *a, "\t"); | |
540 | 580 | if (err >= 0) |
541 | err = tplg_save_printf(dst, NULL, "}\n"); | |
581 | err = tplg_save_printf(&buf, NULL, "}\n"); | |
542 | 582 | } |
543 | 583 | free(indexes); |
544 | 584 | } else { |
545 | err = tplg_save(tplg, dst, -1, NULL); | |
585 | err = tplg_save(tplg, &buf, -1, NULL); | |
546 | 586 | } |
547 | 587 | |
548 | 588 | if (err < 0) |
549 | 589 | goto _err; |
550 | 590 | |
551 | if (*dst == NULL) | |
552 | return -EINVAL; | |
553 | ||
554 | if (flags & SND_TPLG_SAVE_NOCHECK) | |
591 | if (buf.dst == NULL) { | |
592 | err = -EINVAL; | |
593 | goto _err; | |
594 | } | |
595 | ||
596 | if (flags & SND_TPLG_SAVE_NOCHECK) { | |
597 | *dst = tplg_buf_detach(&buf); | |
555 | 598 | return 0; |
599 | } | |
556 | 600 | |
557 | 601 | /* always load configuration - check */ |
558 | err = snd_input_buffer_open(&in, *dst, strlen(*dst)); | |
602 | err = snd_input_buffer_open(&in, buf.dst, strlen(buf.dst)); | |
559 | 603 | if (err < 0) { |
560 | 604 | SNDERR("could not create input buffer"); |
561 | 605 | goto _err; |
587 | 631 | top = top2; |
588 | 632 | } |
589 | 633 | |
590 | dst2 = NULL; | |
591 | err = save_config(&dst2, 0, NULL, top); | |
634 | tplg_buf_init(&buf2); | |
635 | err = save_config(&buf2, 0, NULL, top); | |
592 | 636 | snd_config_delete(top); |
593 | 637 | if (err < 0) { |
594 | 638 | SNDERR("could not save configuration"); |
595 | 639 | goto _err; |
596 | 640 | } |
597 | 641 | |
598 | free(*dst); | |
599 | *dst = dst2; | |
642 | tplg_buf_free(&buf); | |
643 | *dst = tplg_buf_detach(&buf2); | |
600 | 644 | return 0; |
601 | 645 | |
602 | 646 | _err: |
603 | free(*dst); | |
647 | tplg_buf_free(&buf); | |
604 | 648 | *dst = NULL; |
605 | 649 | return err; |
606 | 650 | } |
92 | 92 | /* save text data */ |
93 | 93 | int tplg_save_text(snd_tplg_t *tplg ATTRIBUTE_UNUSED, |
94 | 94 | struct tplg_elem *elem, |
95 | char **dst, const char *pfx) | |
95 | struct tplg_buf *dst, const char *pfx) | |
96 | 96 | { |
97 | 97 | struct tplg_texts *texts = elem->texts; |
98 | 98 | unsigned int i; |
102 | 102 | return 0; |
103 | 103 | err = tplg_save_printf(dst, pfx, "'%s'.values [\n", elem->id); |
104 | 104 | for (i = 0; err >= 0 && i < texts->num_items; i++) |
105 | err = tplg_save_printf(dst, pfx, "\t'%s'\n", texts->items[i][0]); | |
105 | err = tplg_save_printf(dst, pfx, "\t'%s'\n", texts->items[i]); | |
106 | 106 | if (err >= 0) |
107 | 107 | err = tplg_save_printf(dst, pfx, "]\n"); |
108 | 108 | return err; |
15 | 15 | |
16 | 16 | #include "local.h" |
17 | 17 | #include "list.h" |
18 | #include "bswap.h" | |
18 | 19 | #include "topology.h" |
19 | 20 | |
20 | 21 | #include <sound/type_compat.h> |
199 | 200 | int id; |
200 | 201 | }; |
201 | 202 | |
203 | /* output buffer */ | |
204 | struct tplg_buf { | |
205 | char *dst; | |
206 | size_t dst_len; | |
207 | char *printf_buf; | |
208 | size_t printf_buf_size; | |
209 | }; | |
210 | ||
202 | 211 | /* mapping table */ |
203 | 212 | struct tplg_table { |
204 | 213 | const char *name; |
213 | 222 | void (*free)(void *); |
214 | 223 | int (*parse)(snd_tplg_t *tplg, snd_config_t *cfg, void *priv); |
215 | 224 | int (*save)(snd_tplg_t *tplg, struct tplg_elem *elem, |
216 | char **dst, const char *prefix); | |
225 | struct tplg_buf *dst, const char *prefix); | |
217 | 226 | int (*gsave)(snd_tplg_t *tplg, int index, |
218 | char **dst, const char *prefix); | |
227 | struct tplg_buf *dst, const char *prefix); | |
219 | 228 | int (*decod)(snd_tplg_t *tplg, size_t pos, |
220 | 229 | struct snd_soc_tplg_hdr *hdr, |
221 | 230 | void *bin, size_t size); |
223 | 232 | |
224 | 233 | extern struct tplg_table tplg_table[]; |
225 | 234 | extern unsigned int tplg_table_items; |
235 | ||
236 | #if __SIZEOF_INT__ == 4 | |
237 | static inline unsigned int unaligned_get32(void *src) | |
238 | { | |
239 | unsigned int ret; | |
240 | memcpy(&ret, src, sizeof(ret)); | |
241 | #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ | |
242 | ret = bswap_32(ret); | |
243 | #endif | |
244 | return ret; | |
245 | } | |
246 | static inline void unaligned_put32(void *dst, unsigned int val) | |
247 | { | |
248 | #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ | |
249 | val = bswap_32(val); | |
250 | #endif | |
251 | memcpy(dst, &val, sizeof(val)); | |
252 | } | |
253 | #endif | |
226 | 254 | |
227 | 255 | #define tplg_log(tplg, type, pos, fmt, args...) do { \ |
228 | 256 | if ((tplg)->verbose) \ |
334 | 362 | |
335 | 363 | int tplg_nice_value_format(char *dst, size_t dst_size, unsigned int value); |
336 | 364 | |
337 | int tplg_save_printf(char **dst, const char *prefix, const char *fmt, ...); | |
365 | int tplg_save_printf(struct tplg_buf *dst, const char *prefix, const char *fmt, ...); | |
338 | 366 | int tplg_save_refs(snd_tplg_t *tplg, struct tplg_elem *elem, unsigned int type, |
339 | const char *id, char **dst, const char *pfx); | |
367 | const char *id, struct tplg_buf *dst, const char *pfx); | |
340 | 368 | int tplg_save_channels(snd_tplg_t *tplg, struct snd_soc_tplg_channel *channel, |
341 | unsigned int channel_count, char **dst, const char *pfx); | |
369 | unsigned int channel_count, struct tplg_buf *dst, const char *pfx); | |
342 | 370 | int tplg_save_ops(snd_tplg_t *tplg, struct snd_soc_tplg_ctl_hdr *hdr, |
343 | char **dst, const char *pfx); | |
371 | struct tplg_buf *dst, const char *pfx); | |
344 | 372 | int tplg_save_ext_ops(snd_tplg_t *tplg, struct snd_soc_tplg_bytes_control *be, |
345 | char **dst, const char *pfx); | |
373 | struct tplg_buf *dst, const char *pfx); | |
346 | 374 | int tplg_save_manifest_data(snd_tplg_t *tplg, struct tplg_elem *elem, |
347 | char **dst, const char *pfx); | |
375 | struct tplg_buf *dst, const char *pfx); | |
348 | 376 | int tplg_save_control_mixer(snd_tplg_t *tplg, struct tplg_elem *elem, |
349 | char **dst, const char *pfx); | |
377 | struct tplg_buf *dst, const char *pfx); | |
350 | 378 | int tplg_save_control_enum(snd_tplg_t *tplg, struct tplg_elem *elem, |
351 | char **dst, const char *pfx); | |
379 | struct tplg_buf *dst, const char *pfx); | |
352 | 380 | int tplg_save_control_bytes(snd_tplg_t *tplg, struct tplg_elem *elem, |
353 | char **dst, const char *pfx); | |
381 | struct tplg_buf *dst, const char *pfx); | |
354 | 382 | int tplg_save_tlv(snd_tplg_t *tplg, struct tplg_elem *elem, |
355 | char **dst, const char *pfx); | |
383 | struct tplg_buf *dst, const char *pfx); | |
356 | 384 | int tplg_save_data(snd_tplg_t *tplg, struct tplg_elem *elem, |
357 | char **dst, const char *pfx); | |
385 | struct tplg_buf *dst, const char *pfx); | |
358 | 386 | int tplg_save_text(snd_tplg_t *tplg, struct tplg_elem *elem, |
359 | char **dst, const char *pfx); | |
387 | struct tplg_buf *dst, const char *pfx); | |
360 | 388 | int tplg_save_tokens(snd_tplg_t *tplg, struct tplg_elem *elem, |
361 | char **dst, const char *pfx); | |
389 | struct tplg_buf *dst, const char *pfx); | |
362 | 390 | int tplg_save_tuples(snd_tplg_t *tplg, struct tplg_elem *elem, |
363 | char **dst, const char *pfx); | |
391 | struct tplg_buf *dst, const char *pfx); | |
364 | 392 | int tplg_save_dapm_graph(snd_tplg_t *tplg, int index, |
365 | char **dst, const char *pfx); | |
393 | struct tplg_buf *dst, const char *pfx); | |
366 | 394 | int tplg_save_dapm_widget(snd_tplg_t *tplg, struct tplg_elem *elem, |
367 | char **dst, const char *pfx); | |
395 | struct tplg_buf *dst, const char *pfx); | |
368 | 396 | int tplg_save_link(snd_tplg_t *tplg, struct tplg_elem *elem, |
369 | char **dst, const char *pfx); | |
397 | struct tplg_buf *dst, const char *pfx); | |
370 | 398 | int tplg_save_cc(snd_tplg_t *tplg, struct tplg_elem *elem, |
371 | char **dst, const char *pfx); | |
399 | struct tplg_buf *dst, const char *pfx); | |
372 | 400 | int tplg_save_pcm(snd_tplg_t *tplg, struct tplg_elem *elem, |
373 | char **dst, const char *pfx); | |
401 | struct tplg_buf *dst, const char *pfx); | |
374 | 402 | int tplg_save_hw_config(snd_tplg_t *tplg, struct tplg_elem *elem, |
375 | char **dst, const char *pfx); | |
403 | struct tplg_buf *dst, const char *pfx); | |
376 | 404 | int tplg_save_stream_caps(snd_tplg_t *tplg, struct tplg_elem *elem, |
377 | char **dst, const char *pfx); | |
405 | struct tplg_buf *dst, const char *pfx); | |
378 | 406 | int tplg_save_dai(snd_tplg_t *tplg, struct tplg_elem *elem, |
379 | char **dst, const char *pfx); | |
407 | struct tplg_buf *dst, const char *pfx); | |
380 | 408 | |
381 | 409 | int tplg_decode_template(snd_tplg_t *tplg, |
382 | 410 | size_t pos, |
397 | 425 | struct list_head *heap, |
398 | 426 | struct snd_tplg_enum_template *et, |
399 | 427 | size_t pos, |
400 | void *bin, size_t size); | |
428 | struct snd_soc_tplg_enum_control *ec); | |
401 | 429 | int tplg_decode_control_enum(snd_tplg_t *tplg, size_t pos, |
402 | 430 | struct snd_soc_tplg_hdr *hdr, |
403 | 431 | void *bin, size_t size); |
40 | 40 | * misc |
41 | 41 | */ |
42 | 42 | |
43 | static int get_value(snd_use_case_mgr_t *uc_mgr, | |
44 | const char *identifier, | |
45 | char **value, | |
46 | const char *mod_dev_name, | |
47 | const char *verb_name, | |
48 | int exact); | |
43 | 49 | static int get_value1(snd_use_case_mgr_t *uc_mgr, char **value, |
44 | 50 | struct list_head *value_list, const char *identifier); |
45 | 51 | static int get_value3(snd_use_case_mgr_t *uc_mgr, |
568 | 574 | } |
569 | 575 | |
570 | 576 | /** |
577 | * \brief Check, if the UCM configuration is empty | |
578 | * \param uc_mgr Use case Manager | |
579 | * \return zero on success, otherwise a negative error code | |
580 | */ | |
581 | static int check_empty_configuration(snd_use_case_mgr_t *uc_mgr) | |
582 | { | |
583 | int err; | |
584 | char *value; | |
585 | ||
586 | err = get_value(uc_mgr, "Linked", &value, NULL, NULL, 1); | |
587 | if (err >= 0) { | |
588 | err = strcasecmp(value, "true") == 0 || | |
589 | strcmp(value, "1") == 0; | |
590 | free(value); | |
591 | if (err) | |
592 | return 0; | |
593 | } | |
594 | if (!list_empty(&uc_mgr->verb_list)) | |
595 | return 0; | |
596 | if (!list_empty(&uc_mgr->boot_list)) | |
597 | return 0; | |
598 | return -ENXIO; | |
599 | } | |
600 | ||
601 | /** | |
571 | 602 | * \brief Universal find - string in a list |
572 | 603 | * \param list List of structures |
573 | 604 | * \param offset Offset of list structure |
961 | 992 | if (mgr == NULL) |
962 | 993 | return -ENOMEM; |
963 | 994 | INIT_LIST_HEAD(&mgr->verb_list); |
964 | INIT_LIST_HEAD(&mgr->once_list); | |
995 | INIT_LIST_HEAD(&mgr->boot_list); | |
965 | 996 | INIT_LIST_HEAD(&mgr->default_list); |
966 | 997 | INIT_LIST_HEAD(&mgr->value_list); |
967 | 998 | INIT_LIST_HEAD(&mgr->active_modifiers); |
980 | 1011 | err = import_master_config(mgr); |
981 | 1012 | if (err < 0) { |
982 | 1013 | uc_error("error: failed to import %s use case configuration %d", |
983 | card_name, err); | |
984 | goto err; | |
1014 | card_name, err); | |
1015 | goto _err; | |
1016 | } | |
1017 | ||
1018 | err = check_empty_configuration(mgr); | |
1019 | if (err < 0) { | |
1020 | uc_error("error: failed to import %s (empty configuration)", card_name); | |
1021 | goto _err; | |
985 | 1022 | } |
986 | 1023 | |
987 | 1024 | *uc_mgr = mgr; |
988 | 1025 | return 0; |
989 | 1026 | |
990 | err: | |
1027 | _err: | |
991 | 1028 | uc_mgr_free(mgr); |
992 | 1029 | return err; |
993 | 1030 | } |
1857 | 1894 | uc_error("error: wrong value for _boot (%s)", value); |
1858 | 1895 | return -EINVAL; |
1859 | 1896 | } |
1860 | err = execute_sequence(uc_mgr, &uc_mgr->once_list, | |
1897 | err = execute_sequence(uc_mgr, &uc_mgr->boot_list, | |
1861 | 1898 | &uc_mgr->value_list, NULL, NULL); |
1862 | 1899 | if (err < 0) { |
1863 | uc_error("Unable to execute once sequence"); | |
1900 | uc_error("Unable to execute boot sequence"); | |
1864 | 1901 | return err; |
1865 | 1902 | } |
1866 | 1903 | return err; |
233 | 233 | if (err < 0) |
234 | 234 | return err; |
235 | 235 | } |
236 | if (!parse_is_name_safe(id)) | |
237 | return -EINVAL; | |
238 | return get_string3(uc_mgr, id, name); | |
236 | err = get_string3(uc_mgr, id, name); | |
237 | if (err < 0) | |
238 | return err; | |
239 | if (!parse_is_name_safe(*name)) { | |
240 | free(*name); | |
241 | return -EINVAL; | |
242 | } | |
243 | return 0; | |
244 | } | |
245 | ||
246 | /* | |
247 | * Handle 'Error' configuration node. | |
248 | */ | |
249 | static int error_node(snd_use_case_mgr_t *uc_mgr, snd_config_t *cfg) | |
250 | { | |
251 | int err; | |
252 | char *s; | |
253 | ||
254 | err = parse_string_substitute3(uc_mgr, cfg, &s); | |
255 | if (err < 0) { | |
256 | uc_error("error: failed to get Error string"); | |
257 | return err; | |
258 | } | |
259 | uc_error("%s", s); | |
260 | free(s); | |
261 | return -ENXIO; | |
239 | 262 | } |
240 | 263 | |
241 | 264 | /* |
1722 | 1745 | { |
1723 | 1746 | int err; |
1724 | 1747 | |
1725 | if (!list_empty(&uc_mgr->once_list)) { | |
1726 | uc_error("Once list is not empty"); | |
1727 | return -EINVAL; | |
1728 | } | |
1729 | err = parse_sequence(uc_mgr, &uc_mgr->once_list, cfg); | |
1748 | if (!list_empty(&uc_mgr->boot_list)) { | |
1749 | uc_error("Boot list is not empty"); | |
1750 | return -EINVAL; | |
1751 | } | |
1752 | err = parse_sequence(uc_mgr, &uc_mgr->boot_list, cfg); | |
1730 | 1753 | if (err < 0) { |
1731 | 1754 | uc_error("Unable to parse BootSequence"); |
1732 | 1755 | return err; |
1849 | 1872 | continue; |
1850 | 1873 | |
1851 | 1874 | if (strcmp(id, "Comment") == 0) { |
1852 | err = parse_string(n, &uc_mgr->comment); | |
1875 | err = parse_string_substitute3(uc_mgr, n, &uc_mgr->comment); | |
1853 | 1876 | if (err < 0) { |
1854 | 1877 | uc_error("error: failed to get master comment"); |
1855 | 1878 | return err; |
1892 | 1915 | } |
1893 | 1916 | continue; |
1894 | 1917 | } |
1918 | ||
1919 | /* error */ | |
1920 | if (strcmp(id, "Error") == 0) | |
1921 | return error_node(uc_mgr, n); | |
1895 | 1922 | |
1896 | 1923 | uc_error("uknown master file field %s", id); |
1897 | 1924 | } |
400 | 400 | err = uc_mgr_evaluate_inplace(uc_mgr, a); |
401 | 401 | if (err < 0) |
402 | 402 | return err; |
403 | err = uc_mgr_config_tree_merge(parent, a, before, after); | |
403 | err = uc_mgr_config_tree_merge(uc_mgr, parent, a, before, after); | |
404 | 404 | if (err < 0) |
405 | 405 | return err; |
406 | 406 | snd_config_delete(a); |
205 | 205 | return 0; |
206 | 206 | } |
207 | 207 | |
208 | int uc_mgr_config_tree_merge(snd_config_t *parent, snd_config_t *new_ctx, | |
208 | int uc_mgr_config_tree_merge(snd_use_case_mgr_t *uc_mgr, | |
209 | snd_config_t *parent, snd_config_t *new_ctx, | |
209 | 210 | snd_config_t *before, snd_config_t *after) |
210 | 211 | { |
211 | 212 | snd_config_iterator_t i, next; |
212 | 213 | snd_config_t *n, *parent2; |
213 | 214 | const char *id; |
214 | 215 | int err; |
216 | ||
217 | err = uc_mgr_substitute_tree(uc_mgr, new_ctx); | |
218 | if (err < 0) | |
219 | return err; | |
215 | 220 | |
216 | 221 | snd_config_for_each(i, next, new_ctx) { |
217 | 222 | n = snd_config_iterator_entry(i); |
270 | 275 | err = uc_mgr_evaluate_inplace(uc_mgr, a); |
271 | 276 | if (err < 0) |
272 | 277 | return err; |
273 | err = uc_mgr_config_tree_merge(parent, a, before, after); | |
278 | err = uc_mgr_config_tree_merge(uc_mgr, parent, a, before, after); | |
274 | 279 | if (err < 0) |
275 | 280 | return err; |
276 | 281 | snd_config_delete(a); |
222 | 222 | struct list_head verb_list; |
223 | 223 | |
224 | 224 | /* boot settings - sequence */ |
225 | struct list_head once_list; | |
225 | struct list_head boot_list; | |
226 | 226 | |
227 | 227 | /* default settings - sequence */ |
228 | 228 | struct list_head default_list; |
306 | 306 | char **_rvalue, |
307 | 307 | const char *value); |
308 | 308 | |
309 | int uc_mgr_config_tree_merge(snd_config_t *parent, snd_config_t *new_ctx, | |
309 | int uc_mgr_substitute_tree(snd_use_case_mgr_t *uc_mgr, | |
310 | snd_config_t *node); | |
311 | ||
312 | int uc_mgr_config_tree_merge(snd_use_case_mgr_t *uc_mgr, | |
313 | snd_config_t *parent, snd_config_t *new_ctx, | |
310 | 314 | snd_config_t *before, snd_config_t *after); |
311 | 315 | |
312 | 316 | int uc_mgr_evaluate_inplace(snd_use_case_mgr_t *uc_mgr, |
302 | 302 | } else if (value[1] != '{') { |
303 | 303 | goto __std; |
304 | 304 | } |
305 | allow_empty = false; | |
306 | 305 | fcn2 = NULL; |
307 | 306 | MATCH_VARIABLE(value, "${OpenName}", rval_open_name, false); |
308 | 307 | MATCH_VARIABLE(value, "${ConfTopDir}", rval_conf_topdir, false); |
364 | 363 | } |
365 | 364 | strncpy(r, value, idsize); |
366 | 365 | r[idsize] = '\0'; |
367 | uc_error("variable '%s' is not defined in this context!", r); | |
366 | uc_error("variable '%s' is %s in this context!", r, | |
367 | rval ? "empty" : "not defined"); | |
368 | 368 | err = -EINVAL; |
369 | 369 | goto __error; |
370 | 370 | } |
394 | 394 | free(r); |
395 | 395 | return err; |
396 | 396 | } |
397 | ||
398 | static inline int uc_mgr_substitute_check(const char *s) | |
399 | { | |
400 | return s && strstr(s, "${") != NULL; | |
401 | } | |
402 | ||
403 | int uc_mgr_substitute_tree(snd_use_case_mgr_t *uc_mgr, snd_config_t *node) | |
404 | { | |
405 | snd_config_iterator_t i, next; | |
406 | snd_config_t *n; | |
407 | const char *id, *s2; | |
408 | char *s; | |
409 | int err; | |
410 | ||
411 | err = snd_config_get_id(node, &id); | |
412 | if (err < 0) | |
413 | return err; | |
414 | if (uc_mgr_substitute_check(id)) { | |
415 | err = uc_mgr_get_substituted_value(uc_mgr, &s, id); | |
416 | if (err < 0) | |
417 | return err; | |
418 | err = snd_config_set_id(node, s); | |
419 | free(s); | |
420 | if (err < 0) { | |
421 | uc_error("unable to set substituted id '%s' (old id '%s')", s, id); | |
422 | return err; | |
423 | } | |
424 | } | |
425 | if (snd_config_get_type(node) != SND_CONFIG_TYPE_COMPOUND) { | |
426 | if (snd_config_get_type(node) == SND_CONFIG_TYPE_STRING) { | |
427 | err = snd_config_get_string(node, &s2); | |
428 | if (err < 0) | |
429 | return err; | |
430 | if (!uc_mgr_substitute_check(s2)) | |
431 | return 0; | |
432 | err = uc_mgr_get_substituted_value(uc_mgr, &s, s2); | |
433 | if (err < 0) | |
434 | return err; | |
435 | err = snd_config_set_string(node, s); | |
436 | free(s); | |
437 | if (err < 0) | |
438 | return err; | |
439 | } | |
440 | return 0; | |
441 | } | |
442 | snd_config_for_each(i, next, node) { | |
443 | n = snd_config_iterator_entry(i); | |
444 | err = uc_mgr_substitute_tree(uc_mgr, n); | |
445 | if (err < 0) | |
446 | return err; | |
447 | } | |
448 | return 0; | |
449 | } |