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:
198 case SNDRV_PCM_FORMAT_DSD_U8:
200 case SNDRV_PCM_FORMAT_S16_LE:
201 case SNDRV_PCM_FORMAT_S16_BE:
202 case SNDRV_PCM_FORMAT_U16_LE:
203 case SNDRV_PCM_FORMAT_U16_BE:
204 case SNDRV_PCM_FORMAT_DSD_U16_LE:
206 case SNDRV_PCM_FORMAT_S18_3LE:
207 case SNDRV_PCM_FORMAT_S18_3BE:
208 case SNDRV_PCM_FORMAT_U18_3LE:
209 case SNDRV_PCM_FORMAT_U18_3BE:
211 case SNDRV_PCM_FORMAT_S20_3LE:
212 case SNDRV_PCM_FORMAT_S20_3BE:
213 case SNDRV_PCM_FORMAT_U20_3LE:
214 case SNDRV_PCM_FORMAT_U20_3BE:
216 case SNDRV_PCM_FORMAT_S24_LE:
217 case SNDRV_PCM_FORMAT_S24_BE:
218 case SNDRV_PCM_FORMAT_U24_LE:
219 case SNDRV_PCM_FORMAT_U24_BE:
220 case SNDRV_PCM_FORMAT_S24_3LE:
221 case SNDRV_PCM_FORMAT_S24_3BE:
222 case SNDRV_PCM_FORMAT_U24_3LE:
223 case SNDRV_PCM_FORMAT_U24_3BE:
225 case SNDRV_PCM_FORMAT_S32_LE:
226 case SNDRV_PCM_FORMAT_S32_BE:
227 case SNDRV_PCM_FORMAT_U32_LE:
228 case SNDRV_PCM_FORMAT_U32_BE:
229 case SNDRV_PCM_FORMAT_FLOAT_LE:
230 case SNDRV_PCM_FORMAT_FLOAT_BE:
232 case SNDRV_PCM_FORMAT_FLOAT64_LE:
233 case SNDRV_PCM_FORMAT_FLOAT64_BE:
235 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
236 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
238 case SNDRV_PCM_FORMAT_MU_LAW:
239 case SNDRV_PCM_FORMAT_A_LAW:
241 case SNDRV_PCM_FORMAT_IMA_ADPCM:
249 * \brief Return bits needed to store a PCM sample
250 * \param format Sample format
251 * \return bits per sample, a negative error code if not applicable
253 int snd_pcm_format_physical_width(snd_pcm_format_t format)
256 case SNDRV_PCM_FORMAT_S8:
257 case SNDRV_PCM_FORMAT_U8:
258 case SNDRV_PCM_FORMAT_DSD_U8:
260 case SNDRV_PCM_FORMAT_S16_LE:
261 case SNDRV_PCM_FORMAT_S16_BE:
262 case SNDRV_PCM_FORMAT_U16_LE:
263 case SNDRV_PCM_FORMAT_U16_BE:
264 case SNDRV_PCM_FORMAT_DSD_U16_LE:
266 case SNDRV_PCM_FORMAT_S18_3LE:
267 case SNDRV_PCM_FORMAT_S18_3BE:
268 case SNDRV_PCM_FORMAT_U18_3LE:
269 case SNDRV_PCM_FORMAT_U18_3BE:
270 case SNDRV_PCM_FORMAT_S20_3LE:
271 case SNDRV_PCM_FORMAT_S20_3BE:
272 case SNDRV_PCM_FORMAT_U20_3LE:
273 case SNDRV_PCM_FORMAT_U20_3BE:
274 case SNDRV_PCM_FORMAT_S24_3LE:
275 case SNDRV_PCM_FORMAT_S24_3BE:
276 case SNDRV_PCM_FORMAT_U24_3LE:
277 case SNDRV_PCM_FORMAT_U24_3BE:
279 case SNDRV_PCM_FORMAT_S24_LE:
280 case SNDRV_PCM_FORMAT_S24_BE:
281 case SNDRV_PCM_FORMAT_U24_LE:
282 case SNDRV_PCM_FORMAT_U24_BE:
283 case SNDRV_PCM_FORMAT_S32_LE:
284 case SNDRV_PCM_FORMAT_S32_BE:
285 case SNDRV_PCM_FORMAT_U32_LE:
286 case SNDRV_PCM_FORMAT_U32_BE:
287 case SNDRV_PCM_FORMAT_FLOAT_LE:
288 case SNDRV_PCM_FORMAT_FLOAT_BE:
289 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
290 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
292 case SNDRV_PCM_FORMAT_FLOAT64_LE:
293 case SNDRV_PCM_FORMAT_FLOAT64_BE:
295 case SNDRV_PCM_FORMAT_MU_LAW:
296 case SNDRV_PCM_FORMAT_A_LAW:
298 case SNDRV_PCM_FORMAT_IMA_ADPCM:
306 * \brief Return bytes needed to store a quantity of PCM sample
307 * \param format Sample format
308 * \param samples Samples count
309 * \return bytes needed, a negative error code if not integer or unknown
311 ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples)
314 case SNDRV_PCM_FORMAT_S8:
315 case SNDRV_PCM_FORMAT_U8:
317 case SNDRV_PCM_FORMAT_S16_LE:
318 case SNDRV_PCM_FORMAT_S16_BE:
319 case SNDRV_PCM_FORMAT_U16_LE:
320 case SNDRV_PCM_FORMAT_U16_BE:
322 case SNDRV_PCM_FORMAT_S18_3LE:
323 case SNDRV_PCM_FORMAT_S18_3BE:
324 case SNDRV_PCM_FORMAT_U18_3LE:
325 case SNDRV_PCM_FORMAT_U18_3BE:
326 case SNDRV_PCM_FORMAT_S20_3LE:
327 case SNDRV_PCM_FORMAT_S20_3BE:
328 case SNDRV_PCM_FORMAT_U20_3LE:
329 case SNDRV_PCM_FORMAT_U20_3BE:
330 case SNDRV_PCM_FORMAT_S24_3LE:
331 case SNDRV_PCM_FORMAT_S24_3BE:
332 case SNDRV_PCM_FORMAT_U24_3LE:
333 case SNDRV_PCM_FORMAT_U24_3BE:
335 case SNDRV_PCM_FORMAT_S24_LE:
336 case SNDRV_PCM_FORMAT_S24_BE:
337 case SNDRV_PCM_FORMAT_U24_LE:
338 case SNDRV_PCM_FORMAT_U24_BE:
339 case SNDRV_PCM_FORMAT_S32_LE:
340 case SNDRV_PCM_FORMAT_S32_BE:
341 case SNDRV_PCM_FORMAT_U32_LE:
342 case SNDRV_PCM_FORMAT_U32_BE:
343 case SNDRV_PCM_FORMAT_FLOAT_LE:
344 case SNDRV_PCM_FORMAT_FLOAT_BE:
346 case SNDRV_PCM_FORMAT_FLOAT64_LE:
347 case SNDRV_PCM_FORMAT_FLOAT64_BE:
349 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
350 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
352 case SNDRV_PCM_FORMAT_MU_LAW:
353 case SNDRV_PCM_FORMAT_A_LAW:
355 case SNDRV_PCM_FORMAT_IMA_ADPCM:
366 * \brief Return 64 bit expressing silence for a PCM sample format
367 * \param format Sample format
368 * \return silence 64 bit word
370 u_int64_t snd_pcm_format_silence_64(snd_pcm_format_t format)
373 case SNDRV_PCM_FORMAT_S8:
374 case SNDRV_PCM_FORMAT_S16_LE:
375 case SNDRV_PCM_FORMAT_S16_BE:
376 case SNDRV_PCM_FORMAT_S24_LE:
377 case SNDRV_PCM_FORMAT_S24_BE:
378 case SNDRV_PCM_FORMAT_S32_LE:
379 case SNDRV_PCM_FORMAT_S32_BE:
380 case SNDRV_PCM_FORMAT_S24_3LE:
381 case SNDRV_PCM_FORMAT_S24_3BE:
382 case SNDRV_PCM_FORMAT_S20_3LE:
383 case SNDRV_PCM_FORMAT_S20_3BE:
384 case SNDRV_PCM_FORMAT_S18_3LE:
385 case SNDRV_PCM_FORMAT_S18_3BE:
387 case SNDRV_PCM_FORMAT_U8:
388 return 0x8080808080808080ULL;
389 #ifdef SNDRV_LITTLE_ENDIAN
390 case SNDRV_PCM_FORMAT_U16_LE:
391 return 0x8000800080008000ULL;
392 case SNDRV_PCM_FORMAT_U24_LE:
393 return 0x0080000000800000ULL;
394 case SNDRV_PCM_FORMAT_U32_LE:
395 return 0x8000000080000000ULL;
396 case SNDRV_PCM_FORMAT_U16_BE:
397 return 0x0080008000800080ULL;
398 case SNDRV_PCM_FORMAT_U24_BE:
399 return 0x0000800000008000ULL;
400 case SNDRV_PCM_FORMAT_U32_BE:
401 return 0x0000008000000080ULL;
402 case SNDRV_PCM_FORMAT_U24_3LE:
403 return 0x0000800000800000ULL;
404 case SNDRV_PCM_FORMAT_U24_3BE:
405 return 0x0080000080000080ULL;
406 case SNDRV_PCM_FORMAT_U20_3LE:
407 return 0x0000080000080000ULL;
408 case SNDRV_PCM_FORMAT_U20_3BE:
409 return 0x0008000008000008ULL;
410 case SNDRV_PCM_FORMAT_U18_3LE:
411 return 0x0000020000020000ULL;
412 case SNDRV_PCM_FORMAT_U18_3BE:
413 return 0x0002000002000002ULL;
415 case SNDRV_PCM_FORMAT_U16_LE:
416 return 0x0080008000800080ULL;
417 case SNDRV_PCM_FORMAT_U24_LE:
418 return 0x0000800000008000ULL;
419 case SNDRV_PCM_FORMAT_U32_LE:
420 return 0x0000008000000080ULL;
421 case SNDRV_PCM_FORMAT_U16_BE:
422 return 0x8000800080008000ULL;
423 case SNDRV_PCM_FORMAT_U24_BE:
424 return 0x0080000000800000ULL;
425 case SNDRV_PCM_FORMAT_U32_BE:
426 return 0x8000000080000000ULL;
427 case SNDRV_PCM_FORMAT_U24_3LE:
428 return 0x0080000080000080ULL;
429 case SNDRV_PCM_FORMAT_U24_3BE:
430 return 0x0000800000800000ULL;
431 case SNDRV_PCM_FORMAT_U20_3LE:
432 return 0x0008000008000008ULL;
433 case SNDRV_PCM_FORMAT_U20_3BE:
434 return 0x0000080000080000ULL;
435 case SNDRV_PCM_FORMAT_U18_3LE:
436 return 0x0002000002000002ULL;
437 case SNDRV_PCM_FORMAT_U18_3BE:
438 return 0x0000020000020000ULL;
440 case SNDRV_PCM_FORMAT_FLOAT_LE:
446 u.f[0] = u.f[1] = 0.0;
447 #ifdef SNDRV_LITTLE_ENDIAN
450 return bswap_64(u.i);
453 case SNDRV_PCM_FORMAT_FLOAT64_LE:
460 #ifdef SNDRV_LITTLE_ENDIAN
463 return bswap_64(u.i);
466 case SNDRV_PCM_FORMAT_FLOAT_BE:
472 u.f[0] = u.f[1] = 0.0;
473 #ifdef SNDRV_LITTLE_ENDIAN
474 return bswap_64(u.i);
479 case SNDRV_PCM_FORMAT_FLOAT64_BE:
486 #ifdef SNDRV_LITTLE_ENDIAN
487 return bswap_64(u.i);
492 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE:
493 case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE:
495 case SNDRV_PCM_FORMAT_MU_LAW:
496 return 0x7f7f7f7f7f7f7f7fULL;
497 case SNDRV_PCM_FORMAT_A_LAW:
498 return 0x5555555555555555ULL;
499 case SNDRV_PCM_FORMAT_IMA_ADPCM: /* special case */
500 case SNDRV_PCM_FORMAT_MPEG:
501 case SNDRV_PCM_FORMAT_GSM:
502 case SNDRV_PCM_FORMAT_SPECIAL:
512 * \brief Return 32 bit expressing silence for a PCM sample format
513 * \param format Sample format
514 * \return silence 32 bit word
516 u_int32_t snd_pcm_format_silence_32(snd_pcm_format_t format)
518 assert(snd_pcm_format_physical_width(format) <= 32);
519 return (u_int32_t)snd_pcm_format_silence_64(format);
523 * \brief Return 16 bit expressing silence for a PCM sample format
524 * \param format Sample format
525 * \return silence 16 bit word
527 u_int16_t snd_pcm_format_silence_16(snd_pcm_format_t format)
529 assert(snd_pcm_format_physical_width(format) <= 16);
530 return (u_int16_t)snd_pcm_format_silence_64(format);
534 * \brief Return 8 bit expressing silence for a PCM sample format
535 * \param format Sample format
536 * \return silence 8 bit word
538 u_int8_t snd_pcm_format_silence(snd_pcm_format_t format)
540 assert(snd_pcm_format_physical_width(format) <= 8);
541 return (u_int8_t)snd_pcm_format_silence_64(format);
545 * \brief Silence a PCM samples buffer
546 * \param format Sample format
548 * \param samples Samples count
549 * \return 0 if successful or a negative error code
551 int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int samples)
555 switch (snd_pcm_format_physical_width(format)) {
557 u_int8_t silence = snd_pcm_format_silence_64(format);
558 unsigned int samples1;
559 if (samples % 2 != 0)
561 samples1 = samples / 2;
562 memset(data, silence, samples1);
566 u_int8_t silence = snd_pcm_format_silence_64(format);
567 memset(data, silence, samples);
571 u_int16_t silence = snd_pcm_format_silence_64(format);
572 u_int16_t *pdata = (u_int16_t *)data;
574 memset(data, 0, samples * 2);
576 while (samples-- > 0)
582 u_int32_t silence = snd_pcm_format_silence_64(format);
583 u_int8_t *pdata = (u_int8_t *)data;
585 memset(data, 0, samples * 3);
587 while (samples-- > 0) {
588 #ifdef SNDRV_LITTLE_ENDIAN
589 *pdata++ = silence >> 0;
590 *pdata++ = silence >> 8;
591 *pdata++ = silence >> 16;
593 *pdata++ = silence >> 16;
594 *pdata++ = silence >> 8;
595 *pdata++ = silence >> 0;
602 u_int32_t silence = snd_pcm_format_silence_64(format);
603 u_int32_t *pdata = (u_int32_t *)data;
605 memset(data, 0, samples * 4);
607 while (samples-- > 0)
613 u_int64_t silence = snd_pcm_format_silence_64(format);
614 u_int64_t *pdata = (u_int64_t *)data;
616 memset(data, 0, samples * 8);
618 while (samples-- > 0)
630 static const int linear_formats[4][2][2] = {
631 { { SNDRV_PCM_FORMAT_S8, SNDRV_PCM_FORMAT_S8 },
632 { SNDRV_PCM_FORMAT_U8, SNDRV_PCM_FORMAT_U8 } },
633 { { SNDRV_PCM_FORMAT_S16_LE, SNDRV_PCM_FORMAT_S16_BE },
634 { SNDRV_PCM_FORMAT_U16_LE, SNDRV_PCM_FORMAT_U16_BE } },
635 { { SNDRV_PCM_FORMAT_S24_LE, SNDRV_PCM_FORMAT_S24_BE },
636 { SNDRV_PCM_FORMAT_U24_LE, SNDRV_PCM_FORMAT_U24_BE } },
637 { { SNDRV_PCM_FORMAT_S32_LE, SNDRV_PCM_FORMAT_S32_BE },
638 { SNDRV_PCM_FORMAT_U32_LE, SNDRV_PCM_FORMAT_U32_BE } }
641 static const int linear24_formats[3][2][2] = {
642 { { SNDRV_PCM_FORMAT_S24_3LE, SNDRV_PCM_FORMAT_S24_3BE },
643 { SNDRV_PCM_FORMAT_U24_3LE, SNDRV_PCM_FORMAT_U24_3BE } },
644 { { SNDRV_PCM_FORMAT_S20_3LE, SNDRV_PCM_FORMAT_S20_3BE },
645 { SNDRV_PCM_FORMAT_U20_3LE, SNDRV_PCM_FORMAT_U20_3BE } },
646 { { SNDRV_PCM_FORMAT_S18_3LE, SNDRV_PCM_FORMAT_S18_3BE },
647 { SNDRV_PCM_FORMAT_U18_3LE, SNDRV_PCM_FORMAT_U18_3BE } },
651 * \brief Compose a PCM sample linear format
652 * \param width Nominal bits per sample
653 * \param pwidth Physical bit width of the format
654 * \param unsignd Sign: 0 signed, 1 unsigned
655 * \param big_endian Endian: 0 little endian, 1 big endian
656 * \return The matching format type, or #SND_PCM_FORMAT_UNKNOWN if no match
658 snd_pcm_format_t snd_pcm_build_linear_format(int width, int pwidth, int unsignd, int big_endian)
672 return SND_PCM_FORMAT_UNKNOWN;
674 return linear24_formats[width][!!unsignd][!!big_endian];
690 return SND_PCM_FORMAT_UNKNOWN;
692 return linear_formats[width][!!unsignd][!!big_endian];
697 * \brief Parse control element id from the config
698 * \param conf the config tree to parse
699 * \param ctl_id the pointer to store the resultant control element id
700 * \param cardp the pointer to store the card index
701 * \param cchannelsp the pointer to store the number of channels (optional)
702 * \param hwctlp the pointer to store the h/w control flag (optional)
703 * \return 0 if successful, or a negative error code
705 * This function parses the given config tree to retrieve the control element id
706 * and the card index. It's used by softvol. External PCM plugins can use this
707 * function for creating or assigining their controls.
709 * cchannelsp and hwctlp arguments are optional. Set NULL if not necessary.
711 int snd_pcm_parse_control_id(snd_config_t *conf, snd_ctl_elem_id_t *ctl_id, int *cardp,
712 int *cchannelsp, int *hwctlp)
714 snd_config_iterator_t i, next;
715 int iface = SND_CTL_ELEM_IFACE_MIXER;
716 const char *name = NULL;
722 assert(ctl_id && cardp);
727 snd_config_for_each(i, next, conf) {
728 snd_config_t *n = snd_config_iterator_entry(i);
730 if (snd_config_get_id(n, &id) < 0)
732 if (strcmp(id, "comment") == 0)
734 if (strcmp(id, "card") == 0) {
737 if ((err = snd_config_get_integer(n, &v)) < 0) {
738 if ((err = snd_config_get_string(n, &str)) < 0) {
739 SNDERR("Invalid field %s", id);
742 *cardp = snd_card_get_index(str);
744 SNDERR("Cannot get index for %s", str);
752 if (strcmp(id, "iface") == 0 || strcmp(id, "interface") == 0) {
754 if ((err = snd_config_get_string(n, &ptr)) < 0) {
755 SNDERR("field %s is not a string", id);
758 if ((err = snd_config_get_ctl_iface_ascii(ptr)) < 0) {
759 SNDERR("Invalid value for '%s'", id);
765 if (strcmp(id, "name") == 0) {
766 if ((err = snd_config_get_string(n, &name)) < 0) {
767 SNDERR("field %s is not a string", id);
772 if (strcmp(id, "index") == 0) {
773 if ((err = snd_config_get_integer(n, &index)) < 0) {
774 SNDERR("field %s is not an integer", id);
779 if (strcmp(id, "device") == 0) {
780 if ((err = snd_config_get_integer(n, &device)) < 0) {
781 SNDERR("field %s is not an integer", id);
786 if (strcmp(id, "subdevice") == 0) {
787 if ((err = snd_config_get_integer(n, &subdevice)) < 0) {
788 SNDERR("field %s is not an integer", id);
793 if (cchannelsp && strcmp(id, "count") == 0) {
795 if ((err = snd_config_get_integer(n, &v)) < 0) {
796 SNDERR("field %s is not an integer", id);
799 if (v < 1 || v > 2) {
800 SNDERR("Invalid count %ld", v);
806 if (hwctlp && strcmp(id, "hwctl") == 0) {
807 if ((err = snd_config_get_bool(n)) < 0) {
808 SNDERR("The field %s must be a boolean type", id);
814 SNDERR("Unknown field %s", id);
818 SNDERR("Missing control name");
827 snd_ctl_elem_id_set_interface(ctl_id, iface);
828 snd_ctl_elem_id_set_name(ctl_id, name);
829 snd_ctl_elem_id_set_index(ctl_id, index);
830 snd_ctl_elem_id_set_device(ctl_id, device);
831 snd_ctl_elem_id_set_subdevice(ctl_id, subdevice);