1/**
2 * \file mixer/simple.c
3 * \brief Mixer Simple Element Class Interface
4 * \author Jaroslav Kysela <perex@perex.cz>
5 * \author Abramo Bagnara <abramo@alsa-project.org>
6 * \date 2001-2004
7 *
8 * Mixer simple element class interface.
9 */
10/*
11 *  Mixer Interface - simple controls
12 *  Copyright (c) 2000,2004 by Jaroslav Kysela <perex@perex.cz>
13 *  Copyright (c) 2001 by Abramo Bagnara <abramo@alsa-project.org>
14 *
15 *
16 *   This library is free software; you can redistribute it and/or modify
17 *   it under the terms of the GNU Lesser General Public License as
18 *   published by the Free Software Foundation; either version 2.1 of
19 *   the License, or (at your option) any later version.
20 *
21 *   This program is distributed in the hope that it will be useful,
22 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
23 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 *   GNU Lesser General Public License for more details.
25 *
26 *   You should have received a copy of the GNU Lesser General Public
27 *   License along with this library; if not, write to the Free Software
28 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
29 *
30 */
31
32#include <stdio.h>
33#include <stdlib.h>
34#include <unistd.h>
35#include <string.h>
36#include <fcntl.h>
37#include <sys/ioctl.h>
38#include <math.h>
39#include "mixer_local.h"
40#include "mixer_simple.h"
41
42/**
43 * \brief Register mixer simple element class
44 * \param mixer Mixer handle
45 * \param options Options container
46 * \param classp Pointer to returned mixer simple element class handle (or NULL)
47 * \return 0 on success otherwise a negative error code
48 */
49int snd_mixer_selem_register(snd_mixer_t *mixer,
50			     struct snd_mixer_selem_regopt *options,
51			     snd_mixer_class_t **classp)
52{
53	if (options && options->ver == 1) {
54		if (options->device != NULL &&
55		    (options->playback_pcm != NULL ||
56		     options->capture_pcm != NULL))
57			return -EINVAL;
58		if (options->device == NULL &&
59		    options->playback_pcm == NULL &&
60		    options->capture_pcm == NULL)
61			return -EINVAL;
62	}
63	if (options == NULL ||
64	    (options->ver == 1 && options->abstract == SND_MIXER_SABSTRACT_NONE)) {
65		int err = snd_mixer_simple_none_register(mixer, options, classp);
66		if (err < 0)
67			return err;
68		if (options != NULL) {
69			err = snd_mixer_attach(mixer, options->device);
70			if (err < 0)
71				return err;
72		}
73		return 0;
74	} else if (options->ver == 1) {
75		if (options->abstract == SND_MIXER_SABSTRACT_BASIC)
76			return snd_mixer_simple_basic_register(mixer, options, classp);
77	}
78	return -ENXIO;
79}
80
81#ifndef DOC_HIDDEN
82
83#define CHECK_BASIC(xelem) \
84{ \
85	assert(xelem); \
86	assert((xelem)->type == SND_MIXER_ELEM_SIMPLE); \
87}
88
89#define CHECK_DIR(xelem, xwhat) \
90{ \
91	unsigned int xcaps = ((sm_selem_t *)(elem)->private_data)->caps; \
92	if (! (xcaps & (xwhat))) \
93		return -EINVAL; \
94}
95
96#define CHECK_DIR_CHN(xelem, xwhat, xjoin, xchannel) \
97{ \
98	unsigned int xcaps = ((sm_selem_t *)(elem)->private_data)->caps; \
99	if (! (xcaps & (xwhat))) \
100		return -EINVAL; \
101	if (xcaps & (xjoin)) \
102		xchannel = 0; \
103}
104
105#define CHECK_ENUM(xelem) \
106	if (!(((sm_selem_t *)(elem)->private_data)->caps & (SM_CAP_PENUM|SM_CAP_CENUM))) \
107		return -EINVAL;
108
109#define COND_CAPS(xelem, what) \
110	!!(((sm_selem_t *)(elem)->private_data)->caps & (what))
111
112#endif /* !DOC_HIDDEN */
113
114#ifndef DOC_HIDDEN
115int snd_mixer_selem_compare(const snd_mixer_elem_t *c1, const snd_mixer_elem_t *c2)
116{
117	sm_selem_t *s1 = c1->private_data;
118	sm_selem_t *s2 = c2->private_data;
119	int res = strcmp(s1->id->name, s2->id->name);
120	if (res)
121		return res;
122	return s1->id->index - s2->id->index;
123}
124#endif
125
126/**
127 * \brief Find a mixer simple element
128 * \param mixer Mixer handle
129 * \param id Mixer simple element identifier
130 * \return mixer simple element handle or NULL if not found
131 */
132snd_mixer_elem_t *snd_mixer_find_selem(snd_mixer_t *mixer,
133				       const snd_mixer_selem_id_t *id)
134{
135	struct list_head *list;
136	snd_mixer_elem_t *e;
137	sm_selem_t *s;
138
139	list_for_each(list, &mixer->elems) {
140		e = list_entry(list, snd_mixer_elem_t, list);
141		if (e->type != SND_MIXER_ELEM_SIMPLE)
142			continue;
143		s = e->private_data;
144		if (!strcmp(s->id->name, id->name) && s->id->index == id->index)
145			return e;
146	}
147	return NULL;
148}
149
150/**
151 * \brief Get mixer simple element identifier
152 * \param elem Mixer simple element handle
153 * \param id returned mixer simple element identifier
154 */
155void snd_mixer_selem_get_id(snd_mixer_elem_t *elem,
156			    snd_mixer_selem_id_t *id)
157{
158	sm_selem_t *s;
159	assert(id);
160	CHECK_BASIC(elem);
161	s = elem->private_data;
162	*id = *s->id;
163}
164
165/**
166 * \brief Get name part of mixer simple element identifier
167 * \param elem Mixer simple element handle
168 * \return name part of simple element identifier
169 */
170const char *snd_mixer_selem_get_name(snd_mixer_elem_t *elem)
171{
172	sm_selem_t *s;
173	CHECK_BASIC(elem);
174	s = elem->private_data;
175	return s->id->name;
176}
177
178/**
179 * \brief Get index part of mixer simple element identifier
180 * \param elem Mixer simple element handle
181 * \return index part of simple element identifier
182 */
183unsigned int snd_mixer_selem_get_index(snd_mixer_elem_t *elem)
184{
185	sm_selem_t *s;
186	CHECK_BASIC(elem);
187	s = elem->private_data;
188	return s->id->index;
189}
190
191/**
192 * \brief Return true if mixer simple element has only one volume control for both playback and capture
193 * \param elem Mixer simple element handle
194 * \return 0 separated control, 1 common control
195 */
196int snd_mixer_selem_has_common_volume(snd_mixer_elem_t *elem)
197{
198	CHECK_BASIC(elem);
199	return COND_CAPS(elem, SM_CAP_GVOLUME);
200}
201
202/**
203 * \brief Return true if mixer simple element has only one switch control for both playback and capture
204 * \param elem Mixer simple element handle
205 * \return 0 separated control, 1 common control
206 */
207int snd_mixer_selem_has_common_switch(snd_mixer_elem_t *elem)
208{
209	CHECK_BASIC(elem);
210	return COND_CAPS(elem, SM_CAP_GSWITCH);
211}
212
213/**
214 * \brief Return name of mixer simple element channel
215 * \param channel mixer simple element channel identifier
216 * \return channel name
217 */
218const char *snd_mixer_selem_channel_name(snd_mixer_selem_channel_id_t channel)
219{
220	static const char *const array[SND_MIXER_SCHN_LAST + 1] = {
221		[SND_MIXER_SCHN_FRONT_LEFT] = "Front Left",
222		[SND_MIXER_SCHN_FRONT_RIGHT] = "Front Right",
223		[SND_MIXER_SCHN_REAR_LEFT] = "Rear Left",
224		[SND_MIXER_SCHN_REAR_RIGHT] = "Rear Right",
225		[SND_MIXER_SCHN_FRONT_CENTER] = "Front Center",
226		[SND_MIXER_SCHN_WOOFER] = "Woofer",
227		[SND_MIXER_SCHN_SIDE_LEFT] = "Side Left",
228		[SND_MIXER_SCHN_SIDE_RIGHT] = "Side Right",
229		[SND_MIXER_SCHN_REAR_CENTER] = "Rear Center"
230	};
231	const char *p;
232	assert(channel <= SND_MIXER_SCHN_LAST);
233	p = array[channel];
234	if (!p)
235		return "?";
236	return p;
237}
238
239/**
240 * \brief Get info about the active state of a mixer simple element
241 * \param elem Mixer simple element handle
242 * \return 0 if not active, 1 if active
243 */
244int snd_mixer_selem_is_active(snd_mixer_elem_t *elem)
245{
246	CHECK_BASIC(elem);
247	return sm_selem_ops(elem)->is(elem, SM_PLAY, SM_OPS_IS_ACTIVE, 0);
248}
249
250/**
251 * \brief Get info about channels of playback stream of a mixer simple element
252 * \param elem Mixer simple element handle
253 * \return 0 if not mono, 1 if mono
254 */
255int snd_mixer_selem_is_playback_mono(snd_mixer_elem_t *elem)
256{
257	CHECK_BASIC(elem);
258	return sm_selem_ops(elem)->is(elem, SM_PLAY, SM_OPS_IS_MONO, 0);
259}
260
261/**
262 * \brief Get info about channels of playback stream of a mixer simple element
263 * \param elem Mixer simple element handle
264 * \param channel Mixer simple element channel identifier
265 * \return 0 if channel is not present, 1 if present
266 */
267int snd_mixer_selem_has_playback_channel(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel)
268{
269	CHECK_BASIC(elem);
270	return sm_selem_ops(elem)->is(elem, SM_PLAY, SM_OPS_IS_CHANNEL, (int)channel);
271}
272
273/**
274 * \brief Get range for playback volume of a mixer simple element
275 * \param elem Mixer simple element handle
276 * \param min Pointer to returned minimum
277 * \param max Pointer to returned maximum
278 */
279int snd_mixer_selem_get_playback_volume_range(snd_mixer_elem_t *elem,
280					       long *min, long *max)
281{
282	CHECK_BASIC(elem);
283	CHECK_DIR(elem, SM_CAP_PVOLUME);
284	return sm_selem_ops(elem)->get_range(elem, SM_PLAY, min, max);
285}
286
287/**
288 * \brief Get range in dB for playback volume of a mixer simple element
289 * \param elem Mixer simple element handle
290 * \param min Pointer to returned minimum (dB * 100)
291 * \param max Pointer to returned maximum (dB * 100)
292 */
293int snd_mixer_selem_get_playback_dB_range(snd_mixer_elem_t *elem,
294					  long *min, long *max)
295{
296	CHECK_BASIC(elem);
297	CHECK_DIR(elem, SM_CAP_PVOLUME);
298	return sm_selem_ops(elem)->get_dB_range(elem, SM_PLAY, min, max);
299}
300
301/**
302 * \brief Set range for playback volume of a mixer simple element
303 * \param elem Mixer simple element handle
304 * \param min minimum volume value
305 * \param max maximum volume value
306 */
307int snd_mixer_selem_set_playback_volume_range(snd_mixer_elem_t *elem,
308					      long min, long max)
309{
310	CHECK_BASIC(elem);
311	assert(min < max);
312	CHECK_DIR(elem, SM_CAP_PVOLUME);
313	return sm_selem_ops(elem)->set_range(elem, SM_PLAY, min, max);
314}
315
316/**
317 * \brief Return info about playback volume control of a mixer simple element
318 * \param elem Mixer simple element handle
319 * \return 0 if no control is present, 1 if it's present
320 */
321int snd_mixer_selem_has_playback_volume(snd_mixer_elem_t *elem)
322{
323	CHECK_BASIC(elem);
324	return COND_CAPS(elem, SM_CAP_PVOLUME);
325}
326
327/**
328 * \brief Return info about playback volume control of a mixer simple element
329 * \param elem Mixer simple element handle
330 * \return 0 if control is separated per channel, 1 if control acts on all channels together
331 */
332int snd_mixer_selem_has_playback_volume_joined(snd_mixer_elem_t *elem)
333{
334	CHECK_BASIC(elem);
335	return COND_CAPS(elem, SM_CAP_PVOLUME_JOIN);
336}
337
338/**
339 * \brief Return info about playback switch control existence of a mixer simple element
340 * \param elem Mixer simple element handle
341 * \return 0 if no control is present, 1 if it's present
342 */
343int snd_mixer_selem_has_playback_switch(snd_mixer_elem_t *elem)
344{
345	CHECK_BASIC(elem);
346	return COND_CAPS(elem, SM_CAP_PSWITCH);
347}
348
349/**
350 * \brief Return info about playback switch control of a mixer simple element
351 * \param elem Mixer simple element handle
352 * \return 0 if control is separated per channel, 1 if control acts on all channels together
353 */
354int snd_mixer_selem_has_playback_switch_joined(snd_mixer_elem_t *elem)
355{
356	CHECK_BASIC(elem);
357	return COND_CAPS(elem, SM_CAP_PSWITCH_JOIN);
358}
359
360/**
361 * \brief Return corresponding dB value to an integer playback volume for a mixer simple element
362 * \param elem Mixer simple element handle
363 * \param value value to be converted to dB range
364 * \param dBvalue pointer to returned dB value
365 * \return 0 on success otherwise a negative error code
366 */
367int snd_mixer_selem_ask_playback_vol_dB(snd_mixer_elem_t *elem, long value, long *dBvalue)
368{
369	CHECK_BASIC(elem);
370	CHECK_DIR(elem, SM_CAP_PVOLUME);
371	return sm_selem_ops(elem)->ask_vol_dB(elem, SM_PLAY, value, dBvalue);
372}
373
374/**
375 * \brief Return corresponding integer playback volume for given dB value for a mixer simple element
376 * \param elem Mixer simple element handle
377 * \param value value to be converted to dB range
378 * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
379 * \param dBvalue pointer to returned dB value
380 * \return 0 on success otherwise a negative error code
381 */
382int snd_mixer_selem_ask_playback_dB_vol(snd_mixer_elem_t *elem, long dBvalue, int dir, long *value)
383{
384	CHECK_BASIC(elem);
385	CHECK_DIR(elem, SM_CAP_PVOLUME);
386	return sm_selem_ops(elem)->ask_dB_vol(elem, SM_PLAY, dBvalue, value, dir);
387}
388
389/**
390 * \brief Return value of playback volume control of a mixer simple element
391 * \param elem Mixer simple element handle
392 * \param channel mixer simple element channel identifier
393 * \param value pointer to returned value
394 * \return 0 on success otherwise a negative error code
395 */
396int snd_mixer_selem_get_playback_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value)
397{
398	CHECK_BASIC(elem);
399	CHECK_DIR_CHN(elem, SM_CAP_PVOLUME, SM_CAP_PVOLUME_JOIN, channel);
400	return sm_selem_ops(elem)->get_volume(elem, SM_PLAY, channel, value);
401}
402
403/**
404 * \brief Return value of playback volume in dB control of a mixer simple element
405 * \param elem Mixer simple element handle
406 * \param channel mixer simple element channel identifier
407 * \param value pointer to returned value (dB * 100)
408 * \return 0 on success otherwise a negative error code
409 */
410int snd_mixer_selem_get_playback_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value)
411{
412	unsigned int caps;
413
414	CHECK_BASIC(elem);
415	caps = ((sm_selem_t *)elem->private_data)->caps;
416	if (!(caps & SM_CAP_PVOLUME))
417		return -EINVAL;
418	if (caps & SM_CAP_PVOLUME_JOIN)
419		channel = 0;
420	return sm_selem_ops(elem)->get_dB(elem, SM_PLAY, channel, value);
421}
422
423/**
424 * \brief Return value of playback switch control of a mixer simple element
425 * \param elem Mixer simple element handle
426 * \param channel mixer simple element channel identifier
427 * \param value pointer to returned value
428 * \return 0 on success otherwise a negative error code
429 */
430int snd_mixer_selem_get_playback_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int *value)
431{
432	CHECK_BASIC(elem);
433	CHECK_DIR_CHN(elem, SM_CAP_PSWITCH, SM_CAP_PSWITCH_JOIN, channel);
434	return sm_selem_ops(elem)->get_switch(elem, SM_PLAY, channel, value);
435}
436
437/**
438 * \brief Set value of playback volume control of a mixer simple element
439 * \param elem Mixer simple element handle
440 * \param channel mixer simple element channel identifier
441 * \param value control value
442 * \return 0 on success otherwise a negative error code
443 */
444int snd_mixer_selem_set_playback_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value)
445{
446	CHECK_BASIC(elem);
447	CHECK_DIR_CHN(elem, SM_CAP_PVOLUME, SM_CAP_PVOLUME_JOIN, channel);
448	return sm_selem_ops(elem)->set_volume(elem, SM_PLAY, channel, value);
449}
450
451/**
452 * \brief Set value in dB of playback volume control of a mixer simple element
453 * \param elem Mixer simple element handle
454 * \param channel mixer simple element channel identifier
455 * \param value control value in dB * 100
456 * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
457 * \return 0 on success otherwise a negative error code
458 */
459int snd_mixer_selem_set_playback_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value, int dir)
460{
461	CHECK_BASIC(elem);
462	CHECK_DIR_CHN(elem, SM_CAP_PVOLUME, SM_CAP_PVOLUME_JOIN, channel);
463	return sm_selem_ops(elem)->set_dB(elem, SM_PLAY, channel, value, dir);
464}
465
466/**
467 * \brief Set value of playback volume control for all channels of a mixer simple element
468 * \param elem Mixer simple element handle
469 * \param value control value
470 * \return 0 on success otherwise a negative error code
471 */
472int snd_mixer_selem_set_playback_volume_all(snd_mixer_elem_t *elem, long value)
473{
474	snd_mixer_selem_channel_id_t chn;
475	int err;
476
477	for (chn = 0; chn < 32; chn++) {
478		if (!snd_mixer_selem_has_playback_channel(elem, chn))
479			continue;
480		err = snd_mixer_selem_set_playback_volume(elem, chn, value);
481		if (err < 0)
482			return err;
483		if (chn == 0 && snd_mixer_selem_has_playback_volume_joined(elem))
484			return 0;
485	}
486	return 0;
487}
488
489/**
490 * \brief Set value in dB of playback volume control for all channels of a mixer simple element
491 * \param elem Mixer simple element handle
492 * \param value control value in dB * 100
493 * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
494 * \return 0 on success otherwise a negative error code
495 */
496int snd_mixer_selem_set_playback_dB_all(snd_mixer_elem_t *elem, long value, int dir)
497{
498	snd_mixer_selem_channel_id_t chn;
499	int err;
500
501	for (chn = 0; chn < 32; chn++) {
502		if (!snd_mixer_selem_has_playback_channel(elem, chn))
503			continue;
504		err = snd_mixer_selem_set_playback_dB(elem, chn, value, dir);
505		if (err < 0)
506			return err;
507		if (chn == 0 && snd_mixer_selem_has_playback_volume_joined(elem))
508			return 0;
509	}
510	return 0;
511}
512
513/**
514 * \brief Set value of playback switch control of a mixer simple element
515 * \param elem Mixer simple element handle
516 * \param channel mixer simple element channel identifier
517 * \param value control value
518 * \return 0 on success otherwise a negative error code
519 */
520int snd_mixer_selem_set_playback_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int value)
521{
522	CHECK_BASIC(elem);
523	CHECK_DIR_CHN(elem, SM_CAP_PSWITCH, SM_CAP_PSWITCH_JOIN, channel);
524	return sm_selem_ops(elem)->set_switch(elem, SM_PLAY, channel, value);
525}
526
527/**
528 * \brief Set value of playback switch control for all channels of a mixer simple element
529 * \param elem Mixer simple element handle
530 * \param value control value
531 * \return 0 on success otherwise a negative error code
532 */
533int snd_mixer_selem_set_playback_switch_all(snd_mixer_elem_t *elem, int value)
534{
535	snd_mixer_selem_channel_id_t chn;
536	int err;
537
538	CHECK_BASIC(elem);
539	for (chn = 0; chn < 32; chn++) {
540		if (!snd_mixer_selem_has_playback_channel(elem, chn))
541			continue;
542		err = snd_mixer_selem_set_playback_switch(elem, chn, value);
543		if (err < 0)
544			return err;
545		if (chn == 0 && snd_mixer_selem_has_playback_switch_joined(elem))
546			return 0;
547	}
548	return 0;
549}
550
551/**
552 * \brief Get info about channels of capture stream of a mixer simple element
553 * \param elem Mixer simple element handle
554 * \return 0 if not mono, 1 if mono
555 */
556int snd_mixer_selem_is_capture_mono(snd_mixer_elem_t *elem)
557{
558	CHECK_BASIC(elem);
559	CHECK_DIR(elem, SM_CAP_CVOLUME|SM_CAP_CSWITCH);
560	return sm_selem_ops(elem)->is(elem, SM_CAPT, SM_OPS_IS_MONO, 0);
561}
562
563/**
564 * \brief Get info about channels of capture stream of a mixer simple element
565 * \param elem Mixer simple element handle
566 * \param channel Mixer simple element channel identifier
567 * \return 0 if channel is not present, 1 if present
568 */
569int snd_mixer_selem_has_capture_channel(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel)
570{
571	CHECK_BASIC(elem);
572	CHECK_DIR(elem, SM_CAP_CVOLUME|SM_CAP_CSWITCH);
573	return sm_selem_ops(elem)->is(elem, SM_CAPT, SM_OPS_IS_CHANNEL, channel);
574}
575
576/**
577 * \brief Get range for capture volume of a mixer simple element
578 * \param elem Mixer simple element handle
579 * \param min Pointer to returned minimum
580 * \param max Pointer to returned maximum
581 */
582int snd_mixer_selem_get_capture_volume_range(snd_mixer_elem_t *elem,
583					     long *min, long *max)
584{
585	CHECK_BASIC(elem);
586	CHECK_DIR(elem, SM_CAP_CVOLUME);
587	return sm_selem_ops(elem)->get_range(elem, SM_CAPT, min, max);
588}
589
590/**
591 * \brief Get range in dB for capture volume of a mixer simple element
592 * \param elem Mixer simple element handle
593 * \param min Pointer to returned minimum (dB * 100)
594 * \param max Pointer to returned maximum (dB * 100)
595 */
596int snd_mixer_selem_get_capture_dB_range(snd_mixer_elem_t *elem,
597					 long *min, long *max)
598{
599	CHECK_BASIC(elem);
600	CHECK_DIR(elem, SM_CAP_CVOLUME);
601	return sm_selem_ops(elem)->get_dB_range(elem, SM_CAPT, min, max);
602}
603
604/**
605 * \brief Set range for capture volume of a mixer simple element
606 * \param elem Mixer simple element handle
607 * \param min minimum volume value
608 * \param max maximum volume value
609 */
610int snd_mixer_selem_set_capture_volume_range(snd_mixer_elem_t *elem,
611					     long min, long max)
612{
613	CHECK_BASIC(elem);
614	assert(min < max);
615	CHECK_DIR(elem, SM_CAP_CVOLUME);
616	return sm_selem_ops(elem)->set_range(elem, SM_CAPT, min, max);
617}
618
619/**
620 * \brief Return info about capture volume control of a mixer simple element
621 * \param elem Mixer simple element handle
622 * \return 0 if no control is present, 1 if it's present
623 */
624int snd_mixer_selem_has_capture_volume(snd_mixer_elem_t *elem)
625{
626	CHECK_BASIC(elem);
627	return COND_CAPS(elem, SM_CAP_CVOLUME);
628}
629
630/**
631 * \brief Return info about capture volume control of a mixer simple element
632 * \param elem Mixer simple element handle
633 * \return 0 if control is separated per channel, 1 if control acts on all channels together
634 */
635int snd_mixer_selem_has_capture_volume_joined(snd_mixer_elem_t *elem)
636{
637	CHECK_BASIC(elem);
638	return COND_CAPS(elem, SM_CAP_CVOLUME_JOIN);
639}
640
641/**
642 * \brief Return info about capture switch control existence of a mixer simple element
643 * \param elem Mixer simple element handle
644 * \return 0 if no control is present, 1 if it's present
645 */
646int snd_mixer_selem_has_capture_switch(snd_mixer_elem_t *elem)
647{
648	CHECK_BASIC(elem);
649	return COND_CAPS(elem, SM_CAP_CSWITCH);
650}
651
652/**
653 * \brief Return info about capture switch control of a mixer simple element
654 * \param elem Mixer simple element handle
655 * \return 0 if control is separated per channel, 1 if control acts on all channels together
656 */
657int snd_mixer_selem_has_capture_switch_joined(snd_mixer_elem_t *elem)
658{
659	CHECK_BASIC(elem);
660	return COND_CAPS(elem, SM_CAP_CSWITCH_JOIN);
661}
662
663/**
664 * \brief Return info about capture switch control of a mixer simple element
665 * \param elem Mixer simple element handle
666 * \return 0 if control is separated per element, 1 if control acts on other elements too (i.e. only one active at a time inside a group)
667 */
668int snd_mixer_selem_has_capture_switch_exclusive(snd_mixer_elem_t *elem)
669{
670	CHECK_BASIC(elem);
671	return COND_CAPS(elem, SM_CAP_CSWITCH_EXCL);
672}
673
674/**
675 * \brief Return info about capture switch control of a mixer simple element
676 * \param elem Mixer simple element handle
677 * \return group for switch exclusivity (see #snd_mixer_selem_has_capture_switch_exclusive)
678 */
679int snd_mixer_selem_get_capture_group(snd_mixer_elem_t *elem)
680{
681	sm_selem_t *s;
682	CHECK_BASIC(elem);
683	s = elem->private_data;
684	if (! (s->caps & SM_CAP_CSWITCH_EXCL))
685		return -EINVAL;
686	return s->capture_group;
687}
688
689/**
690 * \brief Return corresponding dB value to an integer capture volume for a mixer simple element
691 * \param elem Mixer simple element handle
692 * \param value value to be converted to dB range
693 * \param dBvalue pointer to returned dB value
694 * \return 0 on success otherwise a negative error code
695 */
696int snd_mixer_selem_ask_capture_vol_dB(snd_mixer_elem_t *elem, long value, long *dBvalue)
697{
698	CHECK_BASIC(elem);
699	CHECK_DIR(elem, SM_CAP_CVOLUME);
700	return sm_selem_ops(elem)->ask_vol_dB(elem, SM_CAPT, value, dBvalue);
701}
702
703/**
704 * \brief Return corresponding integer capture volume for given dB value for a mixer simple element
705 * \param elem Mixer simple element handle
706 * \param dBvalue dB value to be converted to integer range
707 * \param value pointer to returned integer value
708 * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
709 * \return 0 on success otherwise a negative error code
710 */
711int snd_mixer_selem_ask_capture_dB_vol(snd_mixer_elem_t *elem, long dBvalue, int dir, long *value)
712{
713	CHECK_BASIC(elem);
714	CHECK_DIR(elem, SM_CAP_CVOLUME);
715	return sm_selem_ops(elem)->ask_dB_vol(elem, SM_CAPT, dBvalue, value, dir);
716}
717
718/**
719 * \brief Return value of capture volume control of a mixer simple element
720 * \param elem Mixer simple element handle
721 * \param channel mixer simple element channel identifier
722 * \param value pointer to returned value
723 * \return 0 on success otherwise a negative error code
724 */
725int snd_mixer_selem_get_capture_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value)
726{
727	CHECK_BASIC(elem);
728	CHECK_DIR_CHN(elem, SM_CAP_CVOLUME, SM_CAP_CVOLUME_JOIN, channel);
729	return sm_selem_ops(elem)->get_volume(elem, SM_CAPT, channel, value);
730}
731
732/**
733 * \brief Return value of capture volume in dB control of a mixer simple element
734 * \param elem Mixer simple element handle
735 * \param channel mixer simple element channel identifier
736 * \param value pointer to returned value (dB * 100)
737 * \return 0 on success otherwise a negative error code
738 */
739int snd_mixer_selem_get_capture_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value)
740{
741	CHECK_BASIC(elem);
742	CHECK_DIR_CHN(elem, SM_CAP_CVOLUME, SM_CAP_CVOLUME_JOIN, channel);
743	return sm_selem_ops(elem)->get_dB(elem, SM_CAPT, channel, value);
744}
745
746/**
747 * \brief Return value of capture switch control of a mixer simple element
748 * \param elem Mixer simple element handle
749 * \param channel mixer simple element channel identifier
750 * \param value pointer to returned value
751 * \return 0 on success otherwise a negative error code
752 */
753int snd_mixer_selem_get_capture_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int *value)
754{
755	CHECK_BASIC(elem);
756	CHECK_DIR_CHN(elem, SM_CAP_CSWITCH, SM_CAP_CSWITCH_JOIN, channel);
757	return sm_selem_ops(elem)->get_switch(elem, SM_CAPT, channel, value);
758}
759
760/**
761 * \brief Set value of capture volume control of a mixer simple element
762 * \param elem Mixer simple element handle
763 * \param channel mixer simple element channel identifier
764 * \param value control value
765 * \return 0 on success otherwise a negative error code
766 */
767int snd_mixer_selem_set_capture_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value)
768{
769	CHECK_BASIC(elem);
770	CHECK_DIR_CHN(elem, SM_CAP_CVOLUME, SM_CAP_CVOLUME_JOIN, channel);
771	return sm_selem_ops(elem)->set_volume(elem, SM_CAPT, channel, value);
772}
773
774/**
775 * \brief Set value in dB of capture volume control of a mixer simple element
776 * \param elem Mixer simple element handle
777 * \param channel mixer simple element channel identifier
778 * \param value control value in dB * 100
779 * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
780 * \return 0 on success otherwise a negative error code
781 */
782int snd_mixer_selem_set_capture_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value, int dir)
783{
784	CHECK_BASIC(elem);
785	CHECK_DIR_CHN(elem, SM_CAP_CVOLUME, SM_CAP_CVOLUME_JOIN, channel);
786	return sm_selem_ops(elem)->set_dB(elem, SM_CAPT, channel, value, dir);
787}
788
789/**
790 * \brief Set value of capture volume control for all channels of a mixer simple element
791 * \param elem Mixer simple element handle
792 * \param value control value
793 * \return 0 on success otherwise a negative error code
794 */
795int snd_mixer_selem_set_capture_volume_all(snd_mixer_elem_t *elem, long value)
796{
797	snd_mixer_selem_channel_id_t chn;
798	int err;
799
800	for (chn = 0; chn < 32; chn++) {
801		if (!snd_mixer_selem_has_capture_channel(elem, chn))
802			continue;
803		err = snd_mixer_selem_set_capture_volume(elem, chn, value);
804		if (err < 0)
805			return err;
806		if (chn == 0 && snd_mixer_selem_has_capture_volume_joined(elem))
807			return 0;
808	}
809	return 0;
810}
811
812/**
813 * \brief Set value in dB of capture volume control for all channels of a mixer simple element
814 * \param elem Mixer simple element handle
815 * \param value control value in dB * 100
816 * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
817 * \return 0 on success otherwise a negative error code
818 */
819int snd_mixer_selem_set_capture_dB_all(snd_mixer_elem_t *elem, long value, int dir)
820{
821	snd_mixer_selem_channel_id_t chn;
822	int err;
823
824	for (chn = 0; chn < 32; chn++) {
825		if (!snd_mixer_selem_has_capture_channel(elem, chn))
826			continue;
827		err = snd_mixer_selem_set_capture_dB(elem, chn, value, dir);
828		if (err < 0)
829			return err;
830		if (chn == 0 && snd_mixer_selem_has_capture_volume_joined(elem))
831			return 0;
832	}
833	return 0;
834}
835
836/**
837 * \brief Set value of capture switch control of a mixer simple element
838 * \param elem Mixer simple element handle
839 * \param channel mixer simple element channel identifier
840 * \param value control value
841 * \return 0 on success otherwise a negative error code
842 */
843int snd_mixer_selem_set_capture_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int value)
844{
845	CHECK_BASIC(elem);
846	CHECK_DIR_CHN(elem, SM_CAP_CSWITCH, SM_CAP_CSWITCH_JOIN, channel);
847	return sm_selem_ops(elem)->set_switch(elem, SM_CAPT, channel, value);
848}
849
850/**
851 * \brief Set value of capture switch control for all channels of a mixer simple element
852 * \param elem Mixer simple element handle
853 * \param value control value
854 * \return 0 on success otherwise a negative error code
855 */
856int snd_mixer_selem_set_capture_switch_all(snd_mixer_elem_t *elem, int value)
857{
858	snd_mixer_selem_channel_id_t chn;
859	int err;
860
861	for (chn = 0; chn < 32; chn++) {
862		if (!snd_mixer_selem_has_capture_channel(elem, chn))
863			continue;
864		err = snd_mixer_selem_set_capture_switch(elem, chn, value);
865		if (err < 0)
866			return err;
867		if (chn == 0 && snd_mixer_selem_has_capture_switch_joined(elem))
868			return 0;
869	}
870	return 0;
871}
872
873/**
874 * \brief Return true if mixer simple element is an enumerated control
875 * \param elem Mixer simple element handle
876 * \return 0 normal volume/switch control, 1 enumerated control
877 */
878int snd_mixer_selem_is_enumerated(snd_mixer_elem_t *elem)
879{
880	CHECK_BASIC(elem);
881	return sm_selem_ops(elem)->is(elem, SM_PLAY, SM_OPS_IS_ENUMERATED, 0);
882}
883
884/**
885 * \brief Return true if mixer simple enumerated element belongs to the playback direction
886 * \param elem Mixer simple element handle
887 * \return 0 no playback direction, 1 playback direction
888 */
889int snd_mixer_selem_is_enum_playback(snd_mixer_elem_t *elem)
890{
891	CHECK_BASIC(elem);
892	return sm_selem_ops(elem)->is(elem, SM_PLAY, SM_OPS_IS_ENUMERATED, 1);
893}
894
895/**
896 * \brief Return true if mixer simple enumerated element belongs to the capture direction
897 * \param elem Mixer simple element handle
898 * \return 0 no capture direction, 1 capture direction
899 */
900int snd_mixer_selem_is_enum_capture(snd_mixer_elem_t *elem)
901{
902	CHECK_BASIC(elem);
903	return sm_selem_ops(elem)->is(elem, SM_CAPT, SM_OPS_IS_ENUMERATED, 1);
904}
905
906/**
907 * \brief Return the number of enumerated items of the given mixer simple element
908 * \param elem Mixer simple element handle
909 * \return the number of enumerated items, otherwise a negative error code
910 */
911int snd_mixer_selem_get_enum_items(snd_mixer_elem_t *elem)
912{
913	CHECK_BASIC(elem);
914	CHECK_ENUM(elem);
915	return sm_selem_ops(elem)->is(elem, SM_PLAY, SM_OPS_IS_ENUMCNT, 0);
916}
917
918/**
919 * \brief get the enumerated item string for the given mixer simple element
920 * \param elem Mixer simple element handle
921 * \param item the index of the enumerated item to query
922 * \param maxlen the maximal length to be stored
923 * \param buf the buffer to store the name string
924 * \return 0 if successful, otherwise a negative error code
925 */
926int snd_mixer_selem_get_enum_item_name(snd_mixer_elem_t *elem,
927				       unsigned int item,
928				       size_t maxlen, char *buf)
929{
930	CHECK_BASIC(elem);
931	CHECK_ENUM(elem);
932	return sm_selem_ops(elem)->enum_item_name(elem, item, maxlen, buf);
933}
934
935/**
936 * \brief get the current selected enumerated item for the given mixer simple element
937 * \param elem Mixer simple element handle
938 * \param channel mixer simple element channel identifier
939 * \param itemp the pointer to store the index of the enumerated item
940 * \return 0 if successful, otherwise a negative error code
941 */
942int snd_mixer_selem_get_enum_item(snd_mixer_elem_t *elem,
943				  snd_mixer_selem_channel_id_t channel,
944				  unsigned int *itemp)
945{
946	CHECK_BASIC(elem);
947	CHECK_ENUM(elem);
948	return sm_selem_ops(elem)->get_enum_item(elem, channel, itemp);
949}
950
951/**
952 * \brief set the current selected enumerated item for the given mixer simple element
953 * \param elem Mixer simple element handle
954 * \param channel mixer simple element channel identifier
955 * \param item the enumerated item index
956 * \return 0 if successful, otherwise a negative error code
957 */
958int snd_mixer_selem_set_enum_item(snd_mixer_elem_t *elem,
959				  snd_mixer_selem_channel_id_t channel,
960				  unsigned int item)
961{
962	CHECK_BASIC(elem);
963	CHECK_ENUM(elem);
964	return sm_selem_ops(elem)->set_enum_item(elem, channel, item);
965}
966
967/**
968 * \brief get size of #snd_mixer_selem_id_t
969 * \return size in bytes
970 */
971size_t snd_mixer_selem_id_sizeof()
972{
973	return sizeof(snd_mixer_selem_id_t);
974}
975
976/**
977 * \brief allocate an invalid #snd_mixer_selem_id_t using standard malloc
978 * \param ptr returned pointer
979 * \return 0 on success otherwise negative error code
980 */
981int snd_mixer_selem_id_malloc(snd_mixer_selem_id_t **ptr)
982{
983	assert(ptr);
984	*ptr = calloc(1, sizeof(snd_mixer_selem_id_t));
985	if (!*ptr)
986		return -ENOMEM;
987	return 0;
988}
989
990/**
991 * \brief frees a previously allocated #snd_mixer_selem_id_t
992 * \param obj pointer to object to free
993 */
994void snd_mixer_selem_id_free(snd_mixer_selem_id_t *obj)
995{
996	free(obj);
997}
998
999/**
1000 * \brief copy one #snd_mixer_selem_id_t to another
1001 * \param dst pointer to destination
1002 * \param src pointer to source
1003 */
1004void snd_mixer_selem_id_copy(snd_mixer_selem_id_t *dst, const snd_mixer_selem_id_t *src)
1005{
1006	assert(dst && src);
1007	*dst = *src;
1008}
1009
1010/**
1011 * \brief Get name part of a mixer simple element identifier
1012 * \param obj Mixer simple element identifier
1013 * \return name part
1014 */
1015const char *snd_mixer_selem_id_get_name(const snd_mixer_selem_id_t *obj)
1016{
1017	assert(obj);
1018	return obj->name;
1019}
1020
1021/**
1022 * \brief Get index part of a mixer simple element identifier
1023 * \param obj Mixer simple element identifier
1024 * \return index part
1025 */
1026unsigned int snd_mixer_selem_id_get_index(const snd_mixer_selem_id_t *obj)
1027{
1028	assert(obj);
1029	return obj->index;
1030}
1031
1032/**
1033 * \brief Set name part of a mixer simple element identifier
1034 * \param obj Mixer simple element identifier
1035 * \param val name part
1036 */
1037void snd_mixer_selem_id_set_name(snd_mixer_selem_id_t *obj, const char *val)
1038{
1039	assert(obj);
1040	strncpy(obj->name, val, sizeof(obj->name));
1041	obj->name[sizeof(obj->name)-1] = '\0';
1042}
1043
1044/**
1045 * \brief Set index part of a mixer simple element identifier
1046 * \param obj Mixer simple element identifier
1047 * \param val index part
1048 */
1049void snd_mixer_selem_id_set_index(snd_mixer_selem_id_t *obj, unsigned int val)
1050{
1051	assert(obj);
1052	obj->index = val;
1053}
1054