2 * PCM Interface - misc routines
3 * Copyright (c) 1998 by Jaroslav Kysela <perex@perex.cz>
6 * This library is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "pcm_local.h"
31 * \brief Return sign info for a PCM sample linear format
32 * \param format Format
33 * \return 0 unsigned, 1 signed, a negative error code if format is not linear
35 int snd_pcm_format_signed(snd_pcm_format_t format)
38 case SNDRV_PCM_FORMAT_S8:
39 case SNDRV_PCM_FORMAT_S16_LE:
40 case SNDRV_PCM_FORMAT_S16_BE:
41 case SNDRV_PCM_FORMAT_S24_LE:
42 case SNDRV_PCM_FORMAT_S24_BE:
43 case SNDRV_PCM_FORMAT_S32_LE:
44 case SNDRV_PCM_FORMAT_S32_BE:
45 case SNDRV_PCM_FORMAT_S24_3LE:
46 case SNDRV_PCM_FORMAT_S24_3BE:
47 case SNDRV_PCM_FORMAT_S20_3LE:
48 case SNDRV_PCM_FORMAT_S20_3BE:
49 case SNDRV_PCM_FORMAT_S18_3LE:
50 case SNDRV_PCM_FORMAT_S18_3BE:
52 case SNDRV_PCM_FORMAT_U8:
53 case SNDRV_PCM_FORMAT_U16_LE:
54 case SNDRV_PCM_FORMAT_U16_BE:
55 case SNDRV_PCM_FORMAT_U24_LE:
56 case SNDRV_PCM_FORMAT_U24_BE:
57 case SNDRV_PCM_FORMAT_U32_LE:
58 case SNDRV_PCM_FORMAT_U32_BE:
59 case SNDRV_PCM_FORMAT_U24_3LE:
60 case SNDRV_PCM_FORMAT_U24_3BE:
61 case SNDRV_PCM_FORMAT_U20_3LE:
62 case SNDRV_PCM_FORMAT_U20_3BE:
63 case SNDRV_PCM_FORMAT_U18_3LE:
64 case SNDRV_PCM_FORMAT_U18_3BE:
72 * \brief Return sign info for a PCM sample linear format
73 * \param format Format
74 * \return 0 signed, 1 unsigned, a negative error code if format is not linear
76 int snd_pcm_format_unsigned(snd_pcm_format_t format)
80 val = snd_pcm_format_signed(format);
87 * \brief Return linear info for a PCM sample format
88 * \param format Format
89 * \return 0 non linear, 1 linear
91 int snd_pcm_format_linear(snd_pcm_format_t format)
93 return snd_pcm_format_signed(format) >= 0;
97 * \brief Return float info for a PCM sample format
98 * \param format Format
99 * \return 0 non float, 1 float
101 int snd_pcm_format_float(snd_pcm_format_t format)
104 case SNDRV_PCM_FORMAT_FLOAT_LE:
105 case SNDRV_PCM_FORMAT_FLOAT_BE:
106 case SNDRV_PCM_FORMAT_FLOAT64_LE:
107 case SNDRV_PCM_FORMAT_FLOAT64_BE:
115 * \brief Return endian info for a PCM sample format
116 * \param format Format
117 * \return 0 big endian, 1 little endian, a negative error code if endian independent
119 int snd_pcm_format_little_endian(snd_pcm_format_t format)
122 case SNDRV_PCM_FORMAT_S16_LE:
123 case SNDRV_PCM_FORMAT_U16_LE:
124 case SNDRV_PCM_FORMAT_S24_LE:
125 case SNDRV_PCM_FORMAT_U24_LE:
126 case SNDRV_PCM_FORMAT_S32_LE:
127 case SNDRV_PCM_FORMAT_U32_LE:
128 case SNDRV_PCM_FORMAT_FLOAT_LE:
129 case SNDRV_PCM_FORMAT_FLOAT64_LE:
130 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
131 case SNDRV_PCM_FORMAT_S24_3LE:
132 case SNDRV_PCM_FORMAT_S20_3LE:
133 case SNDRV_PCM_FORMAT_S18_3LE:
134 case SNDRV_PCM_FORMAT_U24_3LE:
135 case SNDRV_PCM_FORMAT_U20_3LE:
136 case SNDRV_PCM_FORMAT_U18_3LE:
138 case SNDRV_PCM_FORMAT_S16_BE:
139 case SNDRV_PCM_FORMAT_U16_BE:
140 case SNDRV_PCM_FORMAT_S24_BE:
141 case SNDRV_PCM_FORMAT_U24_BE:
142 case SNDRV_PCM_FORMAT_S32_BE:
143 case SNDRV_PCM_FORMAT_U32_BE:
144 case SNDRV_PCM_FORMAT_FLOAT_BE:
145 case SNDRV_PCM_FORMAT_FLOAT64_BE:
146 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
147 case SNDRV_PCM_FORMAT_S24_3BE:
148 case SNDRV_PCM_FORMAT_S20_3BE:
149 case SNDRV_PCM_FORMAT_S18_3BE:
150 case SNDRV_PCM_FORMAT_U24_3BE:
151 case SNDRV_PCM_FORMAT_U20_3BE:
152 case SNDRV_PCM_FORMAT_U18_3BE:
160 * \brief Return endian info for a PCM sample format
161 * \param format Format
162 * \return 0 little endian, 1 big endian, a negative error code if endian independent
164 int snd_pcm_format_big_endian(snd_pcm_format_t format)
168 val = snd_pcm_format_little_endian(format);
175 * \brief Return endian info for a PCM sample format
176 * \param format Format
177 * \return 0 swapped, 1 CPU endian, a negative error code if endian independent
179 int snd_pcm_format_cpu_endian(snd_pcm_format_t format)
181 #ifdef SNDRV_LITTLE_ENDIAN
182 return snd_pcm_format_little_endian(format);
184 return snd_pcm_format_big_endian(format);
189 * \brief Return nominal bits per a PCM sample
190 * \param format Sample format
191 * \return bits per sample, a negative error code if not applicable
193 int snd_pcm_format_width(snd_pcm_format_t format)
196 case SNDRV_PCM_FORMAT_S8:
197 case SNDRV_PCM_FORMAT_U8:
199 case SNDRV_PCM_FORMAT_S16_LE:
200 case SNDRV_PCM_FORMAT_S16_BE:
201 case SNDRV_PCM_FORMAT_U16_LE:
202 case SNDRV_PCM_FORMAT_U16_BE:
204 case SNDRV_PCM_FORMAT_S18_3LE:
205 case SNDRV_PCM_FORMAT_S18_3BE:
206 case SNDRV_PCM_FORMAT_U18_3LE:
207 case SNDRV_PCM_FORMAT_U18_3BE:
209 case SNDRV_PCM_FORMAT_S20_3LE:
210 case SNDRV_PCM_FORMAT_S20_3BE:
211 case SNDRV_PCM_FORMAT_U20_3LE:
212 case SNDRV_PCM_FORMAT_U20_3BE:
214 case SNDRV_PCM_FORMAT_S24_LE:
215 case SNDRV_PCM_FORMAT_S24_BE:
216 case SNDRV_PCM_FORMAT_U24_LE:
217 case SNDRV_PCM_FORMAT_U24_BE:
218 case SNDRV_PCM_FORMAT_S24_3LE:
219 case SNDRV_PCM_FORMAT_S24_3BE:
220 case SNDRV_PCM_FORMAT_U24_3LE:
221 case SNDRV_PCM_FORMAT_U24_3BE:
223 case SNDRV_PCM_FORMAT_S32_LE:
224 case SNDRV_PCM_FORMAT_S32_BE:
225 case SNDRV_PCM_FORMAT_U32_LE:
226 case SNDRV_PCM_FORMAT_U32_BE:
227 case SNDRV_PCM_FORMAT_FLOAT_LE:
228 case SNDRV_PCM_FORMAT_FLOAT_BE:
230 case SNDRV_PCM_FORMAT_FLOAT64_LE:
231 case SNDRV_PCM_FORMAT_FLOAT64_BE:
233 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
234 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
236 case SNDRV_PCM_FORMAT_MU_LAW:
237 case SNDRV_PCM_FORMAT_A_LAW:
239 case SNDRV_PCM_FORMAT_IMA_ADPCM:
247 * \brief Return bits needed to store a PCM sample
248 * \param format Sample format
249 * \return bits per sample, a negative error code if not applicable
251 int snd_pcm_format_physical_width(snd_pcm_format_t format)
254 case SNDRV_PCM_FORMAT_S8:
255 case SNDRV_PCM_FORMAT_U8:
257 case SNDRV_PCM_FORMAT_S16_LE:
258 case SNDRV_PCM_FORMAT_S16_BE:
259 case SNDRV_PCM_FORMAT_U16_LE:
260 case SNDRV_PCM_FORMAT_U16_BE:
262 case SNDRV_PCM_FORMAT_S18_3LE:
263 case SNDRV_PCM_FORMAT_S18_3BE:
264 case SNDRV_PCM_FORMAT_U18_3LE:
265 case SNDRV_PCM_FORMAT_U18_3BE:
266 case SNDRV_PCM_FORMAT_S20_3LE:
267 case SNDRV_PCM_FORMAT_S20_3BE:
268 case SNDRV_PCM_FORMAT_U20_3LE:
269 case SNDRV_PCM_FORMAT_U20_3BE:
270 case SNDRV_PCM_FORMAT_S24_3LE:
271 case SNDRV_PCM_FORMAT_S24_3BE:
272 case SNDRV_PCM_FORMAT_U24_3LE:
273 case SNDRV_PCM_FORMAT_U24_3BE:
275 case SNDRV_PCM_FORMAT_S24_LE:
276 case SNDRV_PCM_FORMAT_S24_BE:
277 case SNDRV_PCM_FORMAT_U24_LE:
278 case SNDRV_PCM_FORMAT_U24_BE:
279 case SNDRV_PCM_FORMAT_S32_LE:
280 case SNDRV_PCM_FORMAT_S32_BE:
281 case SNDRV_PCM_FORMAT_U32_LE:
282 case SNDRV_PCM_FORMAT_U32_BE:
283 case SNDRV_PCM_FORMAT_FLOAT_LE:
284 case SNDRV_PCM_FORMAT_FLOAT_BE:
285 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
286 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
288 case SNDRV_PCM_FORMAT_FLOAT64_LE:
289 case SNDRV_PCM_FORMAT_FLOAT64_BE:
291 case SNDRV_PCM_FORMAT_MU_LAW:
292 case SNDRV_PCM_FORMAT_A_LAW:
294 case SNDRV_PCM_FORMAT_IMA_ADPCM:
302 * \brief Return bytes needed to store a quantity of PCM sample
303 * \param format Sample format
304 * \param samples Samples count
305 * \return bytes needed, a negative error code if not integer or unknown
307 ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples)
310 case SNDRV_PCM_FORMAT_S8:
311 case SNDRV_PCM_FORMAT_U8:
313 case SNDRV_PCM_FORMAT_S16_LE:
314 case SNDRV_PCM_FORMAT_S16_BE:
315 case SNDRV_PCM_FORMAT_U16_LE:
316 case SNDRV_PCM_FORMAT_U16_BE:
318 case SNDRV_PCM_FORMAT_S18_3LE:
319 case SNDRV_PCM_FORMAT_S18_3BE:
320 case SNDRV_PCM_FORMAT_U18_3LE:
321 case SNDRV_PCM_FORMAT_U18_3BE:
322 case SNDRV_PCM_FORMAT_S20_3LE:
323 case SNDRV_PCM_FORMAT_S20_3BE:
324 case SNDRV_PCM_FORMAT_U20_3LE:
325 case SNDRV_PCM_FORMAT_U20_3BE:
326 case SNDRV_PCM_FORMAT_S24_3LE:
327 case SNDRV_PCM_FORMAT_S24_3BE:
328 case SNDRV_PCM_FORMAT_U24_3LE:
329 case SNDRV_PCM_FORMAT_U24_3BE:
331 case SNDRV_PCM_FORMAT_S24_LE:
332 case SNDRV_PCM_FORMAT_S24_BE:
333 case SNDRV_PCM_FORMAT_U24_LE:
334 case SNDRV_PCM_FORMAT_U24_BE:
335 case SNDRV_PCM_FORMAT_S32_LE:
336 case SNDRV_PCM_FORMAT_S32_BE:
337 case SNDRV_PCM_FORMAT_U32_LE:
338 case SNDRV_PCM_FORMAT_U32_BE:
339 case SNDRV_PCM_FORMAT_FLOAT_LE:
340 case SNDRV_PCM_FORMAT_FLOAT_BE:
342 case SNDRV_PCM_FORMAT_FLOAT64_LE:
343 case SNDRV_PCM_FORMAT_FLOAT64_BE:
345 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
346 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
348 case SNDRV_PCM_FORMAT_MU_LAW:
349 case SNDRV_PCM_FORMAT_A_LAW:
351 case SNDRV_PCM_FORMAT_IMA_ADPCM:
362 * \brief Return 64 bit expressing silence for a PCM sample format
363 * \param format Sample format
364 * \return silence 64 bit word
366 u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format)
369 case SNDRV_PCM_FORMAT_S8:
370 case SNDRV_PCM_FORMAT_S16_LE:
371 case SNDRV_PCM_FORMAT_S16_BE:
372 case SNDRV_PCM_FORMAT_S24_LE:
373 case SNDRV_PCM_FORMAT_S24_BE:
374 case SNDRV_PCM_FORMAT_S32_LE:
375 case SNDRV_PCM_FORMAT_S32_BE:
376 case SNDRV_PCM_FORMAT_S24_3LE:
377 case SNDRV_PCM_FORMAT_S24_3BE:
378 case SNDRV_PCM_FORMAT_S20_3LE:
379 case SNDRV_PCM_FORMAT_S20_3BE:
380 case SNDRV_PCM_FORMAT_S18_3LE:
381 case SNDRV_PCM_FORMAT_S18_3BE:
383 case SNDRV_PCM_FORMAT_U8:
384 return 0x8080808080808080ULL;
385 #ifdef SNDRV_LITTLE_ENDIAN
386 case SNDRV_PCM_FORMAT_U16_LE:
387 return 0x8000800080008000ULL;
388 case SNDRV_PCM_FORMAT_U24_LE:
389 return 0x0080000000800000ULL;
390 case SNDRV_PCM_FORMAT_U32_LE:
391 return 0x8000000080000000ULL;
392 case SNDRV_PCM_FORMAT_U16_BE:
393 return 0x0080008000800080ULL;
394 case SNDRV_PCM_FORMAT_U24_BE:
395 return 0x0000800000008000ULL;
396 case SNDRV_PCM_FORMAT_U32_BE:
397 return 0x0000008000000080ULL;
398 case SNDRV_PCM_FORMAT_U24_3LE:
399 return 0x0000800000800000ULL;
400 case SNDRV_PCM_FORMAT_U24_3BE:
401 return 0x0080000080000080ULL;
402 case SNDRV_PCM_FORMAT_U20_3LE:
403 return 0x0000080000080000ULL;
404 case SNDRV_PCM_FORMAT_U20_3BE:
405 return 0x0008000008000008ULL;
406 case SNDRV_PCM_FORMAT_U18_3LE:
407 return 0x0000020000020000ULL;
408 case SNDRV_PCM_FORMAT_U18_3BE:
409 return 0x0002000002000002ULL;
411 case SNDRV_PCM_FORMAT_U16_LE:
412 return 0x0080008000800080ULL;
413 case SNDRV_PCM_FORMAT_U24_LE:
414 return 0x0000800000008000ULL;
415 case SNDRV_PCM_FORMAT_U32_LE:
416 return 0x0000008000000080ULL;
417 case SNDRV_PCM_FORMAT_U16_BE:
418 return 0x8000800080008000ULL;
419 case SNDRV_PCM_FORMAT_U24_BE:
420 return 0x0080000000800000ULL;
421 case SNDRV_PCM_FORMAT_U32_BE:
422 return 0x8000000080000000ULL;
423 case SNDRV_PCM_FORMAT_U24_3LE:
424 return 0x0080000080000080ULL;
425 case SNDRV_PCM_FORMAT_U24_3BE:
426 return 0x0000800000800000ULL;
427 case SNDRV_PCM_FORMAT_U20_3LE:
428 return 0x0008000008000008ULL;
429 case SNDRV_PCM_FORMAT_U20_3BE:
430 return 0x0000080000080000ULL;
431 case SNDRV_PCM_FORMAT_U18_3LE:
432 return 0x0002000002000002ULL;
433 case SNDRV_PCM_FORMAT_U18_3BE:
434 return 0x0000020000020000ULL;
436 case SNDRV_PCM_FORMAT_FLOAT_LE:
442 u.f[0] = u.f[1] = 0.0;
443 #ifdef SNDRV_LITTLE_ENDIAN
446 return bswap_64(u.i);
449 case SNDRV_PCM_FORMAT_FLOAT64_LE:
456 #ifdef SNDRV_LITTLE_ENDIAN
459 return bswap_64(u.i);
462 case SNDRV_PCM_FORMAT_FLOAT_BE:
468 u.f[0] = u.f[1] = 0.0;
469 #ifdef SNDRV_LITTLE_ENDIAN
470 return bswap_64(u.i);
475 case SNDRV_PCM_FORMAT_FLOAT64_BE:
482 #ifdef SNDRV_LITTLE_ENDIAN
483 return bswap_64(u.i);
488 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
489 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
491 case SNDRV_PCM_FORMAT_MU_LAW:
492 return 0x7f7f7f7f7f7f7f7fULL;
493 case SNDRV_PCM_FORMAT_A_LAW:
494 return 0x5555555555555555ULL;
495 case SNDRV_PCM_FORMAT_IMA_ADPCM: /* special case */
496 case SNDRV_PCM_FORMAT_MPEG:
497 case SNDRV_PCM_FORMAT_GSM:
498 case SNDRV_PCM_FORMAT_SPECIAL:
508 * \brief Return 32 bit expressing silence for a PCM sample format
509 * \param format Sample format
510 * \return silence 32 bit word
512 u_int32_t snd_pcm_format_silence_32(snd_pcm_format_t format)
514 assert(snd_pcm_format_physical_width(format) <= 32);
515 return (u_int32_t)snd_pcm_format_silence_64(format);
519 * \brief Return 16 bit expressing silence for a PCM sample format
520 * \param format Sample format
521 * \return silence 16 bit word
523 u_int16_t snd_pcm_format_silence_16(snd_pcm_format_t format)
525 assert(snd_pcm_format_physical_width(format) <= 16);
526 return (u_int16_t)snd_pcm_format_silence_64(format);
530 * \brief Return 8 bit expressing silence for a PCM sample format
531 * \param format Sample format
532 * \return silence 8 bit word
534 u_int8_t snd_pcm_format_silence(snd_pcm_format_t format)
536 assert(snd_pcm_format_physical_width(format) <= 8);
537 return (u_int8_t)snd_pcm_format_silence_64(format);
541 * \brief Silence a PCM samples buffer
542 * \param format Sample format
544 * \param samples Samples count
545 * \return 0 if successful or a negative error code
547 int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int samples)
551 switch (snd_pcm_format_physical_width(format)) {
553 u_int8_t silence = snd_pcm_format_silence_64(format);
554 unsigned int samples1;
555 if (samples % 2 != 0)
557 samples1 = samples / 2;
558 memset(data, silence, samples1);
562 u_int8_t silence = snd_pcm_format_silence_64(format);
563 memset(data, silence, samples);
567 u_int16_t silence = snd_pcm_format_silence_64(format);
568 u_int16_t *pdata = (u_int16_t *)data;
570 memset(data, 0, samples * 2);
572 while (samples-- > 0)
578 u_int32_t silence = snd_pcm_format_silence_64(format);
579 u_int8_t *pdata = (u_int8_t *)data;
581 memset(data, 0, samples * 3);
583 while (samples-- > 0) {
584 #ifdef SNDRV_LITTLE_ENDIAN
585 *pdata++ = silence >> 0;
586 *pdata++ = silence >> 8;
587 *pdata++ = silence >> 16;
589 *pdata++ = silence >> 16;
590 *pdata++ = silence >> 8;
591 *pdata++ = silence >> 0;
598 u_int32_t silence = snd_pcm_format_silence_64(format);
599 u_int32_t *pdata = (u_int32_t *)data;
601 memset(data, 0, samples * 4);
603 while (samples-- > 0)
609 u_int64_t silence = snd_pcm_format_silence_64(format);
610 u_int64_t *pdata = (u_int64_t *)data;
612 memset(data, 0, samples * 8);
614 while (samples-- > 0)
626 static const int linear_formats[4][2][2] = {
627 { { SNDRV_PCM_FORMAT_S8, SNDRV_PCM_FORMAT_S8 },
628 { SNDRV_PCM_FORMAT_U8, SNDRV_PCM_FORMAT_U8 } },
629 { { SNDRV_PCM_FORMAT_S16_LE, SNDRV_PCM_FORMAT_S16_BE },
630 { SNDRV_PCM_FORMAT_U16_LE, SNDRV_PCM_FORMAT_U16_BE } },
631 { { SNDRV_PCM_FORMAT_S24_LE, SNDRV_PCM_FORMAT_S24_BE },
632 { SNDRV_PCM_FORMAT_U24_LE, SNDRV_PCM_FORMAT_U24_BE } },
633 { { SNDRV_PCM_FORMAT_S32_LE, SNDRV_PCM_FORMAT_S32_BE },
634 { SNDRV_PCM_FORMAT_U32_LE, SNDRV_PCM_FORMAT_U32_BE } }
637 static const int linear24_formats[3][2][2] = {
638 { { SNDRV_PCM_FORMAT_S24_3LE, SNDRV_PCM_FORMAT_S24_3BE },
639 { SNDRV_PCM_FORMAT_U24_3LE, SNDRV_PCM_FORMAT_U24_3BE } },
640 { { SNDRV_PCM_FORMAT_S20_3LE, SNDRV_PCM_FORMAT_S20_3BE },
641 { SNDRV_PCM_FORMAT_U20_3LE, SNDRV_PCM_FORMAT_U20_3BE } },
642 { { SNDRV_PCM_FORMAT_S18_3LE, SNDRV_PCM_FORMAT_S18_3BE },
643 { SNDRV_PCM_FORMAT_U18_3LE, SNDRV_PCM_FORMAT_U18_3BE } },
647 * \brief Compose a PCM sample linear format
648 * \param width Nominal bits per sample
649 * \param pwidth Physical bit width of the format
650 * \param unsignd Sign: 0 signed, 1 unsigned
651 * \param big_endian Endian: 0 little endian, 1 big endian
652 * \return The matching format type, or #SND_PCM_FORMAT_UNKNOWN if no match
654 snd_pcm_format_t snd_pcm_build_linear_format(int width, int pwidth, int unsignd, int big_endian)
668 return SND_PCM_FORMAT_UNKNOWN;
670 return linear24_formats[width][!!unsignd][!!big_endian];
686 return SND_PCM_FORMAT_UNKNOWN;
688 return linear_formats[width][!!unsignd][!!big_endian];
693 * \brief Parse control element id from the config
694 * \param conf the config tree to parse
695 * \param ctl_id the pointer to store the resultant control element id
696 * \param cardp the pointer to store the card index
697 * \param cchannelsp the pointer to store the number of channels (optional)
698 * \param hwctlp the pointer to store the h/w control flag (optional)
699 * \return 0 if successful, or a negative error code
701 * This function parses the given config tree to retrieve the control element id
702 * and the card index. It's used by softvol. External PCM plugins can use this
703 * function for creating or assigining their controls.
705 * cchannelsp and hwctlp arguments are optional. Set NULL if not necessary.
707 int snd_pcm_parse_control_id(snd_config_t *conf, snd_ctl_elem_id_t *ctl_id, int *cardp,
708 int *cchannelsp, int *hwctlp)
710 snd_config_iterator_t i, next;
711 int iface = SND_CTL_ELEM_IFACE_MIXER;
712 const char *name = NULL;
718 assert(ctl_id && cardp);
723 snd_config_for_each(i, next, conf) {
724 snd_config_t *n = snd_config_iterator_entry(i);
726 if (snd_config_get_id(n, &id) < 0)
728 if (strcmp(id, "comment") == 0)
730 if (strcmp(id, "card") == 0) {
733 if ((err = snd_config_get_integer(n, &v)) < 0) {
734 if ((err = snd_config_get_string(n, &str)) < 0) {
735 SNDERR("Invalid field %s", id);
738 *cardp = snd_card_get_index(str);
740 SNDERR("Cannot get index for %s", str);
748 if (strcmp(id, "iface") == 0 || strcmp(id, "interface") == 0) {
750 if ((err = snd_config_get_string(n, &ptr)) < 0) {
751 SNDERR("field %s is not a string", id);
754 if ((err = snd_config_get_ctl_iface_ascii(ptr)) < 0) {
755 SNDERR("Invalid value for '%s'", id);
761 if (strcmp(id, "name") == 0) {
762 if ((err = snd_config_get_string(n, &name)) < 0) {
763 SNDERR("field %s is not a string", id);
768 if (strcmp(id, "index") == 0) {
769 if ((err = snd_config_get_integer(n, &index)) < 0) {
770 SNDERR("field %s is not an integer", id);
775 if (strcmp(id, "device") == 0) {
776 if ((err = snd_config_get_integer(n, &device)) < 0) {
777 SNDERR("field %s is not an integer", id);
782 if (strcmp(id, "subdevice") == 0) {
783 if ((err = snd_config_get_integer(n, &subdevice)) < 0) {
784 SNDERR("field %s is not an integer", id);
789 if (cchannelsp && strcmp(id, "count") == 0) {
791 if ((err = snd_config_get_integer(n, &v)) < 0) {
792 SNDERR("field %s is not an integer", id);
795 if (v < 1 || v > 2) {
796 SNDERR("Invalid count %ld", v);
802 if (hwctlp && strcmp(id, "hwctl") == 0) {
803 if ((err = snd_config_get_bool(n)) < 0) {
804 SNDERR("The field %s must be a boolean type", id);
810 SNDERR("Unknown field %s", id);
814 SNDERR("Missing control name");
823 snd_ctl_elem_id_set_interface(ctl_id, iface);
824 snd_ctl_elem_id_set_name(ctl_id, name);
825 snd_ctl_elem_id_set_index(ctl_id, index);
826 snd_ctl_elem_id_set_device(ctl_id, device);
827 snd_ctl_elem_id_set_subdevice(ctl_id, subdevice);