cleanup specfile for packaging
[profile/ivi/alsa-lib.git] / src / mixer / simple.c
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  */
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         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  */
889 int snd_mixer_selem_is_enum_playback(snd_mixer_elem_t *elem)
890 {
891         CHECK_BASIC(elem);
892         CHECK_ENUM(elem);
893         return sm_selem_ops(elem)->is(elem, SM_PLAY, SM_OPS_IS_ENUMERATED, 1);
894 }
895
896 /**
897  * \brief Return true if mixer simple enumerated element belongs to the capture direction
898  * \param elem Mixer simple element handle
899  * \return 0 no capture direction, 1 capture direction
900  */
901 int snd_mixer_selem_is_enum_capture(snd_mixer_elem_t *elem)
902 {
903         CHECK_BASIC(elem);
904         CHECK_ENUM(elem);
905         return sm_selem_ops(elem)->is(elem, SM_CAPT, SM_OPS_IS_ENUMERATED, 1);
906 }
907
908 /**
909  * \brief Return the number of enumerated items of the given mixer simple element
910  * \param elem Mixer simple element handle
911  * \return the number of enumerated items, otherwise a negative error code
912  */
913 int snd_mixer_selem_get_enum_items(snd_mixer_elem_t *elem)
914 {
915         CHECK_BASIC(elem);
916         CHECK_ENUM(elem);
917         return sm_selem_ops(elem)->is(elem, SM_PLAY, SM_OPS_IS_ENUMCNT, 0);
918 }
919
920 /**
921  * \brief get the enumerated item string for the given mixer simple element
922  * \param elem Mixer simple element handle
923  * \param item the index of the enumerated item to query
924  * \param maxlen the maximal length to be stored
925  * \param buf the buffer to store the name string
926  * \return 0 if successful, otherwise a negative error code
927  */
928 int snd_mixer_selem_get_enum_item_name(snd_mixer_elem_t *elem,
929                                        unsigned int item,
930                                        size_t maxlen, char *buf)
931 {
932         CHECK_BASIC(elem);
933         CHECK_ENUM(elem);
934         return sm_selem_ops(elem)->enum_item_name(elem, item, maxlen, buf);
935 }
936
937 /**
938  * \brief get the current selected enumerated item for the given mixer simple element
939  * \param elem Mixer simple element handle
940  * \param channel mixer simple element channel identifier
941  * \param itemp the pointer to store the index of the enumerated item
942  * \return 0 if successful, otherwise a negative error code
943  */
944 int snd_mixer_selem_get_enum_item(snd_mixer_elem_t *elem,
945                                   snd_mixer_selem_channel_id_t channel,
946                                   unsigned int *itemp)
947 {
948         CHECK_BASIC(elem);
949         CHECK_ENUM(elem);
950         return sm_selem_ops(elem)->get_enum_item(elem, channel, itemp);
951 }
952
953 /**
954  * \brief set the current selected enumerated item for the given mixer simple element
955  * \param elem Mixer simple element handle
956  * \param channel mixer simple element channel identifier
957  * \param item the enumerated item index
958  * \return 0 if successful, otherwise a negative error code
959  */
960 int snd_mixer_selem_set_enum_item(snd_mixer_elem_t *elem,
961                                   snd_mixer_selem_channel_id_t channel,
962                                   unsigned int item)
963 {
964         CHECK_BASIC(elem);
965         CHECK_ENUM(elem);
966         return sm_selem_ops(elem)->set_enum_item(elem, channel, item);
967 }
968
969 /**
970  * \brief get size of #snd_mixer_selem_id_t
971  * \return size in bytes
972  */
973 size_t snd_mixer_selem_id_sizeof()
974 {
975         return sizeof(snd_mixer_selem_id_t);
976 }
977
978 /**
979  * \brief allocate an invalid #snd_mixer_selem_id_t using standard malloc
980  * \param ptr returned pointer
981  * \return 0 on success otherwise negative error code
982  */
983 int snd_mixer_selem_id_malloc(snd_mixer_selem_id_t **ptr)
984 {
985         assert(ptr);
986         *ptr = calloc(1, sizeof(snd_mixer_selem_id_t));
987         if (!*ptr)
988                 return -ENOMEM;
989         return 0;
990 }
991
992 /**
993  * \brief frees a previously allocated #snd_mixer_selem_id_t
994  * \param obj pointer to object to free
995  */
996 void snd_mixer_selem_id_free(snd_mixer_selem_id_t *obj)
997 {
998         free(obj);
999 }
1000
1001 /**
1002  * \brief copy one #snd_mixer_selem_id_t to another
1003  * \param dst pointer to destination
1004  * \param src pointer to source
1005  */
1006 void snd_mixer_selem_id_copy(snd_mixer_selem_id_t *dst, const snd_mixer_selem_id_t *src)
1007 {
1008         assert(dst && src);
1009         *dst = *src;
1010 }
1011
1012 /**
1013  * \brief Get name part of a mixer simple element identifier
1014  * \param obj Mixer simple element identifier
1015  * \return name part
1016  */
1017 const char *snd_mixer_selem_id_get_name(const snd_mixer_selem_id_t *obj)
1018 {
1019         assert(obj);
1020         return obj->name;
1021 }
1022
1023 /**
1024  * \brief Get index part of a mixer simple element identifier
1025  * \param obj Mixer simple element identifier
1026  * \return index part
1027  */
1028 unsigned int snd_mixer_selem_id_get_index(const snd_mixer_selem_id_t *obj)
1029 {
1030         assert(obj);
1031         return obj->index;
1032 }
1033
1034 /**
1035  * \brief Set name part of a mixer simple element identifier
1036  * \param obj Mixer simple element identifier
1037  * \param val name part
1038  */
1039 void snd_mixer_selem_id_set_name(snd_mixer_selem_id_t *obj, const char *val)
1040 {
1041         assert(obj);
1042         strncpy(obj->name, val, sizeof(obj->name));
1043         obj->name[sizeof(obj->name)-1] = '\0';
1044 }
1045
1046 /**
1047  * \brief Set index part of a mixer simple element identifier
1048  * \param obj Mixer simple element identifier
1049  * \param val index part
1050  */
1051 void snd_mixer_selem_id_set_index(snd_mixer_selem_id_t *obj, unsigned int val)
1052 {
1053         assert(obj);
1054         obj->index = val;
1055 }