Home | History | Annotate | Download | only in mixer
      1 /**
      2  * \file mixer/simple.c
      3  * \brief Mixer Simple Element Class Interface
      4  * \author Jaroslav Kysela <perex (at) perex.cz>
      5  * \author Abramo Bagnara <abramo (at) 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 (at) perex.cz>
     13  *  Copyright (c) 2001 by Abramo Bagnara <abramo (at) 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  */
     49 int 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
    115 int 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  */
    132 snd_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  */
    155 void 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  */
    170 const 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  */
    183 unsigned 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  */
    196 int 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  */
    207 int 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  */
    218 const 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  */
    244 int 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  */
    255 int 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  */
    267 int 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  */
    279 int 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  */
    293 int 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  */
    307 int 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  */
    321 int 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  */
    332 int 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  */
    343 int 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  */
    354 int 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  */
    367 int 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  */
    382 int 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  */
    396 int 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  */
    410 int 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  */
    430 int 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  */
    444 int 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  */
    459 int 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  */
    472 int 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  */
    496 int 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  */
    520 int 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  */
    533 int 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  */
    556 int 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  */
    569 int 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  */
    582 int 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  */
    596 int 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  */
    610 int 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  */
    624 int 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  */
    635 int 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  */
    646 int 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  */
    657 int 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  */
    668 int 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  */
    679 int 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  */
    696 int 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  */
    711 int 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  */
    725 int 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  */
    739 int 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  */
    753 int 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  */
    767 int 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  */
    782 int 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  */
    795 int 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  */
    819 int 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  */
    843 int 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  */
    856 int 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  */
    878 int snd_mixer_selem_is_enumerated(snd_mixer_elem_t *elem)
    879 {
    880 	CHECK_BASIC(elem);
    881 	CHECK_ENUM(elem);
    882 	return sm_selem_ops(elem)->is(elem, SM_PLAY, SM_OPS_IS_ENUMERATED, 0);
    883 }
    884 
    885 /**
    886  * \brief Return true if mixer simple enumerated element belongs to the playback direction
    887  * \param elem Mixer simple element handle
    888  * \return 0 no playback direction, 1 playback direction
    889  */
    890 int snd_mixer_selem_is_enum_playback(snd_mixer_elem_t *elem)
    891 {
    892 	CHECK_BASIC(elem);
    893 	CHECK_ENUM(elem);
    894 	return sm_selem_ops(elem)->is(elem, SM_PLAY, SM_OPS_IS_ENUMERATED, 1);
    895 }
    896 
    897 /**
    898  * \brief Return true if mixer simple enumerated element belongs to the capture direction
    899  * \param elem Mixer simple element handle
    900  * \return 0 no capture direction, 1 capture direction
    901  */
    902 int snd_mixer_selem_is_enum_capture(snd_mixer_elem_t *elem)
    903 {
    904 	CHECK_BASIC(elem);
    905 	CHECK_ENUM(elem);
    906 	return sm_selem_ops(elem)->is(elem, SM_CAPT, SM_OPS_IS_ENUMERATED, 1);
    907 }
    908 
    909 /**
    910  * \brief Return the number of enumerated items of the given mixer simple element
    911  * \param elem Mixer simple element handle
    912  * \return the number of enumerated items, otherwise a negative error code
    913  */
    914 int snd_mixer_selem_get_enum_items(snd_mixer_elem_t *elem)
    915 {
    916 	CHECK_BASIC(elem);
    917 	CHECK_ENUM(elem);
    918 	return sm_selem_ops(elem)->is(elem, SM_PLAY, SM_OPS_IS_ENUMCNT, 0);
    919 }
    920 
    921 /**
    922  * \brief get the enumerated item string for the given mixer simple element
    923  * \param elem Mixer simple element handle
    924  * \param item the index of the enumerated item to query
    925  * \param maxlen the maximal length to be stored
    926  * \param buf the buffer to store the name string
    927  * \return 0 if successful, otherwise a negative error code
    928  */
    929 int snd_mixer_selem_get_enum_item_name(snd_mixer_elem_t *elem,
    930 				       unsigned int item,
    931 				       size_t maxlen, char *buf)
    932 {
    933 	CHECK_BASIC(elem);
    934 	CHECK_ENUM(elem);
    935 	return sm_selem_ops(elem)->enum_item_name(elem, item, maxlen, buf);
    936 }
    937 
    938 /**
    939  * \brief get the current selected enumerated item for the given mixer simple element
    940  * \param elem Mixer simple element handle
    941  * \param channel mixer simple element channel identifier
    942  * \param itemp the pointer to store the index of the enumerated item
    943  * \return 0 if successful, otherwise a negative error code
    944  */
    945 int snd_mixer_selem_get_enum_item(snd_mixer_elem_t *elem,
    946 				  snd_mixer_selem_channel_id_t channel,
    947 				  unsigned int *itemp)
    948 {
    949 	CHECK_BASIC(elem);
    950 	CHECK_ENUM(elem);
    951 	return sm_selem_ops(elem)->get_enum_item(elem, channel, itemp);
    952 }
    953 
    954 /**
    955  * \brief set the current selected enumerated item for the given mixer simple element
    956  * \param elem Mixer simple element handle
    957  * \param channel mixer simple element channel identifier
    958  * \param item the enumerated item index
    959  * \return 0 if successful, otherwise a negative error code
    960  */
    961 int snd_mixer_selem_set_enum_item(snd_mixer_elem_t *elem,
    962 				  snd_mixer_selem_channel_id_t channel,
    963 				  unsigned int item)
    964 {
    965 	CHECK_BASIC(elem);
    966 	CHECK_ENUM(elem);
    967 	return sm_selem_ops(elem)->set_enum_item(elem, channel, item);
    968 }
    969 
    970 /**
    971  * \brief get size of #snd_mixer_selem_id_t
    972  * \return size in bytes
    973  */
    974 size_t snd_mixer_selem_id_sizeof()
    975 {
    976 	return sizeof(snd_mixer_selem_id_t);
    977 }
    978 
    979 /**
    980  * \brief allocate an invalid #snd_mixer_selem_id_t using standard malloc
    981  * \param ptr returned pointer
    982  * \return 0 on success otherwise negative error code
    983  */
    984 int snd_mixer_selem_id_malloc(snd_mixer_selem_id_t **ptr)
    985 {
    986 	assert(ptr);
    987 	*ptr = calloc(1, sizeof(snd_mixer_selem_id_t));
    988 	if (!*ptr)
    989 		return -ENOMEM;
    990 	return 0;
    991 }
    992 
    993 /**
    994  * \brief frees a previously allocated #snd_mixer_selem_id_t
    995  * \param obj pointer to object to free
    996  */
    997 void snd_mixer_selem_id_free(snd_mixer_selem_id_t *obj)
    998 {
    999 	free(obj);
   1000 }
   1001 
   1002 /**
   1003  * \brief copy one #snd_mixer_selem_id_t to another
   1004  * \param dst pointer to destination
   1005  * \param src pointer to source
   1006  */
   1007 void snd_mixer_selem_id_copy(snd_mixer_selem_id_t *dst, const snd_mixer_selem_id_t *src)
   1008 {
   1009 	assert(dst && src);
   1010 	*dst = *src;
   1011 }
   1012 
   1013 /**
   1014  * \brief Get name part of a mixer simple element identifier
   1015  * \param obj Mixer simple element identifier
   1016  * \return name part
   1017  */
   1018 const char *snd_mixer_selem_id_get_name(const snd_mixer_selem_id_t *obj)
   1019 {
   1020 	assert(obj);
   1021 	return obj->name;
   1022 }
   1023 
   1024 /**
   1025  * \brief Get index part of a mixer simple element identifier
   1026  * \param obj Mixer simple element identifier
   1027  * \return index part
   1028  */
   1029 unsigned int snd_mixer_selem_id_get_index(const snd_mixer_selem_id_t *obj)
   1030 {
   1031 	assert(obj);
   1032 	return obj->index;
   1033 }
   1034 
   1035 /**
   1036  * \brief Set name part of a mixer simple element identifier
   1037  * \param obj Mixer simple element identifier
   1038  * \param val name part
   1039  */
   1040 void snd_mixer_selem_id_set_name(snd_mixer_selem_id_t *obj, const char *val)
   1041 {
   1042 	assert(obj);
   1043 	strncpy(obj->name, val, sizeof(obj->name));
   1044 	obj->name[sizeof(obj->name)-1] = '\0';
   1045 }
   1046 
   1047 /**
   1048  * \brief Set index part of a mixer simple element identifier
   1049  * \param obj Mixer simple element identifier
   1050  * \param val index part
   1051  */
   1052 void snd_mixer_selem_id_set_index(snd_mixer_selem_id_t *obj, unsigned int val)
   1053 {
   1054 	assert(obj);
   1055 	obj->index = val;
   1056 }
   1057