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