OSDN Git Service

Changed Jaroslav Kysela's e-mail from perex@suse.cz to perex@perex.cz
[android-x86/external-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 *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 value of playback volume control of a mixer simple element
362  * \param elem Mixer simple element handle
363  * \param channel mixer simple element channel identifier
364  * \param value pointer to returned value
365  * \return 0 on success otherwise a negative error code
366  */
367 int snd_mixer_selem_get_playback_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value)
368 {
369         CHECK_BASIC(elem);
370         CHECK_DIR_CHN(elem, SM_CAP_PVOLUME, SM_CAP_PVOLUME_JOIN, channel);
371         return sm_selem_ops(elem)->get_volume(elem, SM_PLAY, channel, value);
372 }
373
374 /**
375  * \brief Return value of playback volume in dB control of a mixer simple element
376  * \param elem Mixer simple element handle
377  * \param channel mixer simple element channel identifier
378  * \param value pointer to returned value (dB * 100)
379  * \return 0 on success otherwise a negative error code
380  */
381 int snd_mixer_selem_get_playback_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value)
382 {
383         unsigned int caps;
384
385         CHECK_BASIC(elem);
386         caps = ((sm_selem_t *)elem->private_data)->caps;
387         if (!(caps & SM_CAP_PVOLUME))
388                 return -EINVAL;
389         if (caps & SM_CAP_PVOLUME_JOIN)
390                 channel = 0;
391         return sm_selem_ops(elem)->get_dB(elem, SM_PLAY, channel, value);
392 }
393
394 /**
395  * \brief Return value of playback switch control of a mixer simple element
396  * \param elem Mixer simple element handle
397  * \param channel mixer simple element channel identifier
398  * \param value pointer to returned value
399  * \return 0 on success otherwise a negative error code
400  */
401 int snd_mixer_selem_get_playback_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int *value)
402 {
403         CHECK_BASIC(elem);
404         CHECK_DIR_CHN(elem, SM_CAP_PSWITCH, SM_CAP_PSWITCH_JOIN, channel);
405         return sm_selem_ops(elem)->get_switch(elem, SM_PLAY, channel, value);
406 }
407
408 /**
409  * \brief Set value of playback volume control of a mixer simple element
410  * \param elem Mixer simple element handle
411  * \param channel mixer simple element channel identifier
412  * \param value control value
413  * \return 0 on success otherwise a negative error code
414  */
415 int snd_mixer_selem_set_playback_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value)
416 {
417         CHECK_BASIC(elem);
418         CHECK_DIR_CHN(elem, SM_CAP_PVOLUME, SM_CAP_PVOLUME_JOIN, channel);
419         return sm_selem_ops(elem)->set_volume(elem, SM_PLAY, channel, value);
420 }
421
422 /**
423  * \brief Set value in dB of playback volume control of a mixer simple element
424  * \param elem Mixer simple element handle
425  * \param channel mixer simple element channel identifier
426  * \param value control value in dB * 100
427  * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
428  * \return 0 on success otherwise a negative error code
429  */
430 int snd_mixer_selem_set_playback_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value, int dir)
431 {
432         CHECK_BASIC(elem);
433         CHECK_DIR_CHN(elem, SM_CAP_PVOLUME, SM_CAP_PVOLUME_JOIN, channel);
434         return sm_selem_ops(elem)->set_dB(elem, SM_PLAY, channel, value, dir);
435 }
436
437 /**
438  * \brief Set value of playback volume control for all channels of a mixer simple element
439  * \param elem Mixer simple element handle
440  * \param value control value
441  * \return 0 on success otherwise a negative error code
442  */
443 int snd_mixer_selem_set_playback_volume_all(snd_mixer_elem_t *elem, long value)
444 {
445         snd_mixer_selem_channel_id_t chn;
446         int err;
447
448         for (chn = 0; chn < 32; chn++) {
449                 if (!snd_mixer_selem_has_playback_channel(elem, chn))
450                         continue;
451                 err = snd_mixer_selem_set_playback_volume(elem, chn, value);
452                 if (err < 0)
453                         return err;
454                 if (chn == 0 && snd_mixer_selem_has_playback_volume_joined(elem))
455                         return 0;
456         }
457         return 0;
458 }
459
460 /**
461  * \brief Set value in dB of playback volume control for all channels of a mixer simple element
462  * \param elem Mixer simple element handle
463  * \param value control value in dB * 100
464  * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
465  * \return 0 on success otherwise a negative error code
466  */
467 int snd_mixer_selem_set_playback_dB_all(snd_mixer_elem_t *elem, long value, int dir)
468 {
469         snd_mixer_selem_channel_id_t chn;
470         int err;
471
472         for (chn = 0; chn < 32; chn++) {
473                 if (!snd_mixer_selem_has_playback_channel(elem, chn))
474                         continue;
475                 err = snd_mixer_selem_set_playback_dB(elem, chn, value, dir);
476                 if (err < 0)
477                         return err;
478                 if (chn == 0 && snd_mixer_selem_has_playback_volume_joined(elem))
479                         return 0;
480         }
481         return 0;
482 }
483
484 /**
485  * \brief Set value of playback switch control of a mixer simple element
486  * \param elem Mixer simple element handle
487  * \param channel mixer simple element channel identifier
488  * \param value control value
489  * \return 0 on success otherwise a negative error code
490  */
491 int snd_mixer_selem_set_playback_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int value)
492 {
493         CHECK_BASIC(elem);
494         CHECK_DIR_CHN(elem, SM_CAP_PSWITCH, SM_CAP_PSWITCH_JOIN, channel);
495         return sm_selem_ops(elem)->set_switch(elem, SM_PLAY, channel, value);
496 }
497
498 /**
499  * \brief Set value of playback switch control for all channels of a mixer simple element
500  * \param elem Mixer simple element handle
501  * \param value control value
502  * \return 0 on success otherwise a negative error code
503  */
504 int snd_mixer_selem_set_playback_switch_all(snd_mixer_elem_t *elem, int value)
505 {
506         snd_mixer_selem_channel_id_t chn;
507         int err;
508
509         CHECK_BASIC(elem);
510         for (chn = 0; chn < 32; chn++) {
511                 if (!snd_mixer_selem_has_playback_channel(elem, chn))
512                         continue;
513                 err = snd_mixer_selem_set_playback_switch(elem, chn, value);
514                 if (err < 0)
515                         return err;
516                 if (chn == 0 && snd_mixer_selem_has_playback_switch_joined(elem))
517                         return 0;
518         }
519         return 0;
520 }
521
522 /**
523  * \brief Get info about channels of capture stream of a mixer simple element
524  * \param elem Mixer simple element handle
525  * \return 0 if not mono, 1 if mono
526  */
527 int snd_mixer_selem_is_capture_mono(snd_mixer_elem_t *elem)
528 {
529         CHECK_BASIC(elem);
530         CHECK_DIR(elem, SM_CAP_CVOLUME|SM_CAP_CSWITCH);
531         return sm_selem_ops(elem)->is(elem, SM_CAPT, SM_OPS_IS_MONO, 0);
532 }
533
534 /**
535  * \brief Get info about channels of capture stream of a mixer simple element
536  * \param elem Mixer simple element handle
537  * \param channel Mixer simple element channel identifier
538  * \return 0 if channel is not present, 1 if present
539  */
540 int snd_mixer_selem_has_capture_channel(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel)
541 {
542         CHECK_BASIC(elem);
543         CHECK_DIR(elem, SM_CAP_CVOLUME|SM_CAP_CSWITCH);
544         return sm_selem_ops(elem)->is(elem, SM_CAPT, SM_OPS_IS_CHANNEL, channel);
545 }
546
547 /**
548  * \brief Get range for capture volume of a mixer simple element
549  * \param elem Mixer simple element handle
550  * \param min Pointer to returned minimum
551  * \param max Pointer to returned maximum
552  */
553 int snd_mixer_selem_get_capture_volume_range(snd_mixer_elem_t *elem,
554                                              long *min, long *max)
555 {
556         CHECK_BASIC(elem);
557         CHECK_DIR(elem, SM_CAP_CVOLUME);
558         return sm_selem_ops(elem)->get_range(elem, SM_CAPT, min, max);
559 }
560
561 /**
562  * \brief Get range in dB for capture volume of a mixer simple element
563  * \param elem Mixer simple element handle
564  * \param min Pointer to returned minimum (dB * 100)
565  * \param max Pointer to returned maximum (dB * 100)
566  */
567 int snd_mixer_selem_get_capture_dB_range(snd_mixer_elem_t *elem,
568                                          long *min, long *max)
569 {
570         CHECK_BASIC(elem);
571         CHECK_DIR(elem, SM_CAP_CVOLUME);
572         return sm_selem_ops(elem)->get_dB_range(elem, SM_CAPT, min, max);
573 }
574
575 /**
576  * \brief Set range for capture volume of a mixer simple element
577  * \param elem Mixer simple element handle
578  * \param min minimum volume value
579  * \param max maximum volume value
580  */
581 int snd_mixer_selem_set_capture_volume_range(snd_mixer_elem_t *elem, 
582                                              long min, long max)
583 {
584         CHECK_BASIC(elem);
585         assert(min < max);
586         CHECK_DIR(elem, SM_CAP_CVOLUME);
587         return sm_selem_ops(elem)->set_range(elem, SM_CAPT, min, max);
588 }
589
590 /**
591  * \brief Return info about capture volume control of a mixer simple element
592  * \param elem Mixer simple element handle
593  * \return 0 if no control is present, 1 if it's present
594  */
595 int snd_mixer_selem_has_capture_volume(snd_mixer_elem_t *elem)
596 {
597         CHECK_BASIC(elem);
598         return COND_CAPS(elem, SM_CAP_CVOLUME);
599 }
600
601 /**
602  * \brief Return info about capture volume control of a mixer simple element
603  * \param elem Mixer simple element handle
604  * \return 0 if control is separated per channel, 1 if control acts on all channels together
605  */
606 int snd_mixer_selem_has_capture_volume_joined(snd_mixer_elem_t *elem)
607 {
608         CHECK_BASIC(elem);
609         return COND_CAPS(elem, SM_CAP_CVOLUME_JOIN);
610 }
611
612 /**
613  * \brief Return info about capture switch control existence of a mixer simple element
614  * \param elem Mixer simple element handle
615  * \return 0 if no control is present, 1 if it's present
616  */
617 int snd_mixer_selem_has_capture_switch(snd_mixer_elem_t *elem)
618 {
619         CHECK_BASIC(elem);
620         return COND_CAPS(elem, SM_CAP_CSWITCH);
621 }
622
623 /**
624  * \brief Return info about capture switch control of a mixer simple element
625  * \param elem Mixer simple element handle
626  * \return 0 if control is separated per channel, 1 if control acts on all channels together
627  */
628 int snd_mixer_selem_has_capture_switch_joined(snd_mixer_elem_t *elem)
629 {
630         CHECK_BASIC(elem);
631         return COND_CAPS(elem, SM_CAP_CSWITCH_JOIN);
632 }
633
634 /**
635  * \brief Return info about capture switch control of a mixer simple element
636  * \param elem Mixer simple element handle
637  * \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)
638  */
639 int snd_mixer_selem_has_capture_switch_exclusive(snd_mixer_elem_t *elem)
640 {
641         CHECK_BASIC(elem);
642         return COND_CAPS(elem, SM_CAP_CSWITCH_EXCL);
643 }
644
645 /**
646  * \brief Return info about capture switch control of a mixer simple element
647  * \param elem Mixer simple element handle
648  * \return group for switch exclusivity (see #snd_mixer_selem_has_capture_switch_exclusive)
649  */
650 int snd_mixer_selem_get_capture_group(snd_mixer_elem_t *elem)
651 {
652         sm_selem_t *s;
653         CHECK_BASIC(elem);
654         s = elem->private_data;
655         if (! (s->caps & SM_CAP_CSWITCH_EXCL))
656                 return -EINVAL;
657         return s->capture_group;
658 }
659
660 /**
661  * \brief Return value of capture volume control of a mixer simple element
662  * \param elem Mixer simple element handle
663  * \param channel mixer simple element channel identifier
664  * \param value pointer to returned value
665  * \return 0 on success otherwise a negative error code
666  */
667 int snd_mixer_selem_get_capture_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value)
668 {
669         CHECK_BASIC(elem);
670         CHECK_DIR_CHN(elem, SM_CAP_CVOLUME, SM_CAP_CVOLUME_JOIN, channel);
671         return sm_selem_ops(elem)->get_volume(elem, SM_CAPT, channel, value);
672 }
673
674 /**
675  * \brief Return value of capture volume in dB control of a mixer simple element
676  * \param elem Mixer simple element handle
677  * \param channel mixer simple element channel identifier
678  * \param value pointer to returned value (dB * 100)
679  * \return 0 on success otherwise a negative error code
680  */
681 int snd_mixer_selem_get_capture_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value)
682 {
683         CHECK_BASIC(elem);
684         CHECK_DIR_CHN(elem, SM_CAP_CVOLUME, SM_CAP_CVOLUME_JOIN, channel);
685         return sm_selem_ops(elem)->get_dB(elem, SM_CAPT, channel, value);
686 }
687
688 /**
689  * \brief Return value of capture switch control of a mixer simple element
690  * \param elem Mixer simple element handle
691  * \param channel mixer simple element channel identifier
692  * \param value pointer to returned value
693  * \return 0 on success otherwise a negative error code
694  */
695 int snd_mixer_selem_get_capture_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int *value)
696 {
697         CHECK_BASIC(elem);
698         CHECK_DIR_CHN(elem, SM_CAP_CSWITCH, SM_CAP_CSWITCH_JOIN, channel);
699         return sm_selem_ops(elem)->get_switch(elem, SM_CAPT, channel, value);
700 }
701
702 /**
703  * \brief Set value of capture volume control of a mixer simple element
704  * \param elem Mixer simple element handle
705  * \param channel mixer simple element channel identifier
706  * \param value control value
707  * \return 0 on success otherwise a negative error code
708  */
709 int snd_mixer_selem_set_capture_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value)
710 {
711         CHECK_BASIC(elem);
712         CHECK_DIR_CHN(elem, SM_CAP_CVOLUME, SM_CAP_CVOLUME_JOIN, channel);
713         return sm_selem_ops(elem)->set_volume(elem, SM_CAPT, channel, value);
714 }
715
716 /**
717  * \brief Set value in dB of capture volume control of a mixer simple element
718  * \param elem Mixer simple element handle
719  * \param channel mixer simple element channel identifier
720  * \param value control value in dB * 100
721  * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
722  * \return 0 on success otherwise a negative error code
723  */
724 int snd_mixer_selem_set_capture_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value, int dir)
725 {
726         CHECK_BASIC(elem);
727         CHECK_DIR_CHN(elem, SM_CAP_CVOLUME, SM_CAP_CVOLUME_JOIN, channel);
728         return sm_selem_ops(elem)->set_dB(elem, SM_CAPT, channel, value, dir);
729 }
730
731 /**
732  * \brief Set value of capture volume control for all channels of a mixer simple element
733  * \param elem Mixer simple element handle
734  * \param value control value
735  * \return 0 on success otherwise a negative error code
736  */
737 int snd_mixer_selem_set_capture_volume_all(snd_mixer_elem_t *elem, long value)
738 {
739         snd_mixer_selem_channel_id_t chn;
740         int err;
741
742         for (chn = 0; chn < 32; chn++) {
743                 if (!snd_mixer_selem_has_capture_channel(elem, chn))
744                         continue;
745                 err = snd_mixer_selem_set_capture_volume(elem, chn, value);
746                 if (err < 0)
747                         return err;
748                 if (chn == 0 && snd_mixer_selem_has_capture_volume_joined(elem))
749                         return 0;
750         }
751         return 0;
752 }
753
754 /**
755  * \brief Set value in dB of capture volume control for all channels of a mixer simple element
756  * \param elem Mixer simple element handle
757  * \param value control value in dB * 100
758  * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
759  * \return 0 on success otherwise a negative error code
760  */
761 int snd_mixer_selem_set_capture_dB_all(snd_mixer_elem_t *elem, long value, int dir)
762 {
763         snd_mixer_selem_channel_id_t chn;
764         int err;
765
766         for (chn = 0; chn < 32; chn++) {
767                 if (!snd_mixer_selem_has_capture_channel(elem, chn))
768                         continue;
769                 err = snd_mixer_selem_set_capture_dB(elem, chn, value, dir);
770                 if (err < 0)
771                         return err;
772                 if (chn == 0 && snd_mixer_selem_has_capture_volume_joined(elem))
773                         return 0;
774         }
775         return 0;
776 }
777
778 /**
779  * \brief Set value of capture switch control of a mixer simple element
780  * \param elem Mixer simple element handle
781  * \param channel mixer simple element channel identifier
782  * \param value control value
783  * \return 0 on success otherwise a negative error code
784  */
785 int snd_mixer_selem_set_capture_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int value)
786 {
787         CHECK_BASIC(elem);
788         CHECK_DIR_CHN(elem, SM_CAP_CSWITCH, SM_CAP_CSWITCH_JOIN, channel);
789         return sm_selem_ops(elem)->set_switch(elem, SM_CAPT, channel, value);
790 }
791
792 /**
793  * \brief Set value of capture switch control for all channels of a mixer simple element
794  * \param elem Mixer simple element handle
795  * \param value control value
796  * \return 0 on success otherwise a negative error code
797  */
798 int snd_mixer_selem_set_capture_switch_all(snd_mixer_elem_t *elem, int value)
799 {
800         snd_mixer_selem_channel_id_t chn;
801         int err;
802
803         for (chn = 0; chn < 32; chn++) {
804                 if (!snd_mixer_selem_has_capture_channel(elem, chn))
805                         continue;
806                 err = snd_mixer_selem_set_capture_switch(elem, chn, value);
807                 if (err < 0)
808                         return err;
809                 if (chn == 0 && snd_mixer_selem_has_capture_switch_joined(elem))
810                         return 0;
811         }
812         return 0;
813 }
814
815 /**
816  * \brief Return true if mixer simple element is an enumerated control
817  * \param elem Mixer simple element handle
818  * \return 0 normal volume/switch control, 1 enumerated control
819  */
820 int snd_mixer_selem_is_enumerated(snd_mixer_elem_t *elem)
821 {
822         CHECK_BASIC(elem);
823         CHECK_ENUM(elem);
824         return sm_selem_ops(elem)->is(elem, SM_PLAY, SM_OPS_IS_ENUMERATED, 0);
825 }
826
827 /**
828  * \brief Return true if mixer simple enumerated element belongs to the playback direction
829  * \param elem Mixer simple element handle
830  * \return 0 no playback direction, 1 playback direction
831  */
832 int snd_mixer_selem_is_enum_playback(snd_mixer_elem_t *elem)
833 {
834         CHECK_BASIC(elem);
835         CHECK_ENUM(elem);
836         return sm_selem_ops(elem)->is(elem, SM_PLAY, SM_OPS_IS_ENUMERATED, 1);
837 }
838
839 /**
840  * \brief Return true if mixer simple enumerated element belongs to the capture direction
841  * \param elem Mixer simple element handle
842  * \return 0 no capture direction, 1 capture direction
843  */
844 int snd_mixer_selem_is_enum_capture(snd_mixer_elem_t *elem)
845 {
846         CHECK_BASIC(elem);
847         CHECK_ENUM(elem);
848         return sm_selem_ops(elem)->is(elem, SM_CAPT, SM_OPS_IS_ENUMERATED, 1);
849 }
850
851 /**
852  * \brief Return the number of enumerated items of the given mixer simple element
853  * \param elem Mixer simple element handle
854  * \return the number of enumerated items, otherwise a negative error code
855  */
856 int snd_mixer_selem_get_enum_items(snd_mixer_elem_t *elem)
857 {
858         CHECK_BASIC(elem);
859         CHECK_ENUM(elem);
860         return sm_selem_ops(elem)->is(elem, SM_PLAY, SM_OPS_IS_ENUMCNT, 0);
861 }
862
863 /**
864  * \brief get the enumerated item string for the given mixer simple element
865  * \param elem Mixer simple element handle
866  * \param item the index of the enumerated item to query
867  * \param maxlen the maximal length to be stored
868  * \param buf the buffer to store the name string
869  * \return 0 if successful, otherwise a negative error code
870  */
871 int snd_mixer_selem_get_enum_item_name(snd_mixer_elem_t *elem,
872                                        unsigned int item,
873                                        size_t maxlen, char *buf)
874 {
875         CHECK_BASIC(elem);
876         CHECK_ENUM(elem);
877         return sm_selem_ops(elem)->enum_item_name(elem, item, maxlen, buf);
878 }
879
880 /**
881  * \brief get the current selected enumerated item for the given mixer simple element
882  * \param elem Mixer simple element handle
883  * \param channel mixer simple element channel identifier
884  * \param itemp the pointer to store the index of the enumerated item
885  * \return 0 if successful, otherwise a negative error code
886  */
887 int snd_mixer_selem_get_enum_item(snd_mixer_elem_t *elem,
888                                   snd_mixer_selem_channel_id_t channel,
889                                   unsigned int *itemp)
890 {
891         CHECK_BASIC(elem);
892         CHECK_ENUM(elem);
893         return sm_selem_ops(elem)->get_enum_item(elem, channel, itemp);
894 }
895
896 /**
897  * \brief set the current selected enumerated item for the given mixer simple element
898  * \param elem Mixer simple element handle
899  * \param channel mixer simple element channel identifier
900  * \param item the enumerated item index
901  * \return 0 if successful, otherwise a negative error code
902  */
903 int snd_mixer_selem_set_enum_item(snd_mixer_elem_t *elem,
904                                   snd_mixer_selem_channel_id_t channel,
905                                   unsigned int item)
906 {
907         CHECK_BASIC(elem);
908         CHECK_ENUM(elem);
909         return sm_selem_ops(elem)->set_enum_item(elem, channel, item);
910 }
911
912 /**
913  * \brief get size of #snd_mixer_selem_id_t
914  * \return size in bytes
915  */
916 size_t snd_mixer_selem_id_sizeof()
917 {
918         return sizeof(snd_mixer_selem_id_t);
919 }
920
921 /**
922  * \brief allocate an invalid #snd_mixer_selem_id_t using standard malloc
923  * \param ptr returned pointer
924  * \return 0 on success otherwise negative error code
925  */
926 int snd_mixer_selem_id_malloc(snd_mixer_selem_id_t **ptr)
927 {
928         assert(ptr);
929         *ptr = calloc(1, sizeof(snd_mixer_selem_id_t));
930         if (!*ptr)
931                 return -ENOMEM;
932         return 0;
933 }
934
935 /**
936  * \brief frees a previously allocated #snd_mixer_selem_id_t
937  * \param obj pointer to object to free
938  */
939 void snd_mixer_selem_id_free(snd_mixer_selem_id_t *obj)
940 {
941         free(obj);
942 }
943
944 /**
945  * \brief copy one #snd_mixer_selem_id_t to another
946  * \param dst pointer to destination
947  * \param src pointer to source
948  */
949 void snd_mixer_selem_id_copy(snd_mixer_selem_id_t *dst, const snd_mixer_selem_id_t *src)
950 {
951         assert(dst && src);
952         *dst = *src;
953 }
954
955 /**
956  * \brief Get name part of a mixer simple element identifier
957  * \param obj Mixer simple element identifier
958  * \return name part
959  */
960 const char *snd_mixer_selem_id_get_name(const snd_mixer_selem_id_t *obj)
961 {
962         assert(obj);
963         return obj->name;
964 }
965
966 /**
967  * \brief Get index part of a mixer simple element identifier
968  * \param obj Mixer simple element identifier
969  * \return index part
970  */
971 unsigned int snd_mixer_selem_id_get_index(const snd_mixer_selem_id_t *obj)
972 {
973         assert(obj);
974         return obj->index;
975 }
976
977 /**
978  * \brief Set name part of a mixer simple element identifier
979  * \param obj Mixer simple element identifier
980  * \param val name part
981  */
982 void snd_mixer_selem_id_set_name(snd_mixer_selem_id_t *obj, const char *val)
983 {
984         assert(obj);
985         strncpy(obj->name, val, sizeof(obj->name));
986         obj->name[sizeof(obj->name)-1] = '\0';
987 }
988
989 /**
990  * \brief Set index part of a mixer simple element identifier
991  * \param obj Mixer simple element identifier
992  * \param val index part
993  */
994 void snd_mixer_selem_id_set_index(snd_mixer_selem_id_t *obj, unsigned int val)
995 {
996         assert(obj);
997         obj->index = val;
998 }