diff options
author | Abramo Bagnara <abramo@alsa-project.org> | 2001-03-30 09:43:29 +0000 |
---|---|---|
committer | Abramo Bagnara <abramo@alsa-project.org> | 2001-03-30 09:43:29 +0000 |
commit | b4ac62f3dd2eddb2aed9ab0d2a901653c8e77a38 (patch) | |
tree | 02ce2d05b9c44333ee6a382aaaa92f2fed8196ed /src/mixer | |
parent | 5b50ec848a65396d5e8be32290c4431485001ed5 (diff) |
More documentation. Tiny change for simple mixer element API (get_range)
Diffstat (limited to 'src/mixer')
-rw-r--r-- | src/mixer/Makefile.am | 2 | ||||
-rw-r--r-- | src/mixer/mixer.c | 262 | ||||
-rw-r--r-- | src/mixer/mixer_local.h | 1 | ||||
-rw-r--r-- | src/mixer/mixer_m4.c | 120 | ||||
-rw-r--r-- | src/mixer/simple.c | 750 |
5 files changed, 779 insertions, 356 deletions
diff --git a/src/mixer/Makefile.am b/src/mixer/Makefile.am index bcdb109e..115c4077 100644 --- a/src/mixer/Makefile.am +++ b/src/mixer/Makefile.am @@ -1,6 +1,6 @@ EXTRA_LTLIBRARIES=libmixer.la -libmixer_la_SOURCES = bag.c mixer.c mixer_m4.c simple.c +libmixer_la_SOURCES = bag.c mixer.c simple.c noinst_HEADERS = mixer_local.h diff --git a/src/mixer/mixer.c b/src/mixer/mixer.c index 471911e4..9efbaa49 100644 --- a/src/mixer/mixer.c +++ b/src/mixer/mixer.c @@ -1,3 +1,12 @@ +/** + * \file mixer/mixer.c + * \author Jaroslav Kysela <perex@suse.cz> + * \author Abramo Bagnara <abramo@alsa-project.org> + * \date 2001 + * + * Mixer interface is designed to access mixer elements. + * Callbacks may be used for event handling. + */ /* * Mixer Interface - main file * Copyright (c) 1998/1999/2000 by Jaroslav Kysela <perex@suse.cz> @@ -20,6 +29,7 @@ * */ +#ifndef DOC_HIDDEN #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -33,16 +43,18 @@ typedef struct _snd_mixer_slave { struct list_head list; } snd_mixer_slave_t; - -typedef struct _snd_mixer_elem_bag { - -} snd_mixer_elem_bag_t; - +#endif static int snd_mixer_compare_default(const snd_mixer_elem_t *c1, const snd_mixer_elem_t *c2); +/** + * \brief Opens an empty mixer + * \param mixerp Returned mixer handle + * \param mode Open mode + * \return 0 on success otherwise a negative error code + */ int snd_mixer_open(snd_mixer_t **mixerp, int mode ATTRIBUTE_UNUSED) { snd_mixer_t *mixer; @@ -58,6 +70,14 @@ int snd_mixer_open(snd_mixer_t **mixerp, int mode ATTRIBUTE_UNUSED) return 0; } +/** + * \brief Attach an HCTL element to a mixer element + * \param melem Mixer element + * \param helem HCTL element + * \return 0 on success otherwise a negative error code + * + * For use by mixer element class specific code. + */ int snd_mixer_elem_attach(snd_mixer_elem_t *melem, snd_hctl_elem_t *helem) { @@ -69,6 +89,14 @@ int snd_mixer_elem_attach(snd_mixer_elem_t *melem, return bag_add(&melem->helems, helem); } +/** + * \brief Detach an HCTL element from a mixer element + * \param melem Mixer element + * \param helem HCTL element + * \return 0 on success otherwise a negative error code + * + * For use by mixer element class specific code. + */ int snd_mixer_elem_detach(snd_mixer_elem_t *melem, snd_hctl_elem_t *helem) { @@ -81,6 +109,13 @@ int snd_mixer_elem_detach(snd_mixer_elem_t *melem, return 0; } +/** + * \brief Return true if a mixer element does not contain any HCTL elements + * \param melem Mixer element + * \return 0 if not empty, 1 if empty + * + * For use by mixer element class specific code. + */ int snd_mixer_elem_empty(snd_mixer_elem_t *melem) { return bag_empty(&melem->helems); @@ -144,6 +179,12 @@ static int hctl_event_handler(snd_hctl_t *hctl, unsigned int mask, } +/** + * \brief Attach an HCTL to an opened mixer + * \param mixer Mixer handle + * \param name HCTL name (see #snd_hctl_open) + * \return 0 on success otherwise a negative error code + */ int snd_mixer_attach(snd_mixer_t *mixer, const char *name) { snd_mixer_slave_t *slave; @@ -170,6 +211,12 @@ int snd_mixer_attach(snd_mixer_t *mixer, const char *name) return 0; } +/** + * \brief Detach a previously attached HCTL to an opened mixer freeing all related resources + * \param mixer Mixer handle + * \param name HCTL previously attached + * \return 0 on success otherwise a negative error code + */ int snd_mixer_detach(snd_mixer_t *mixer, const char *name) { struct list_head *pos; @@ -195,7 +242,7 @@ static int snd_mixer_throw_event(snd_mixer_t *mixer, unsigned int mask, return 0; } -int snd_mixer_elem_throw_event(snd_mixer_elem_t *elem, unsigned int mask) +static int snd_mixer_elem_throw_event(snd_mixer_elem_t *elem, unsigned int mask) { elem->class->mixer->events++; if (elem->callback) @@ -226,6 +273,14 @@ static int _snd_mixer_find_elem(snd_mixer_t *mixer, snd_mixer_elem_t *elem, int return idx; } +/** + * \brief Add an element for a registered mixer element class + * \param elem Mixer element + * \param class Mixer element class + * \return 0 on success otherwise a negative error code + * + * For use by mixer element class specific code. + */ int snd_mixer_elem_add(snd_mixer_elem_t *elem, snd_mixer_class_t *class) { int dir, idx; @@ -263,6 +318,13 @@ int snd_mixer_elem_add(snd_mixer_elem_t *elem, snd_mixer_class_t *class) return snd_mixer_throw_event(mixer, SND_CTL_EVENT_MASK_ADD, elem); } +/** + * \brief Remove a mixer element + * \param elem Mixer element + * \return 0 on success otherwise a negative error code + * + * For use by mixer element class specific code. + */ int snd_mixer_elem_remove(snd_mixer_elem_t *elem) { snd_mixer_t *mixer = elem->class->mixer; @@ -292,16 +354,38 @@ int snd_mixer_elem_remove(snd_mixer_elem_t *elem) return err; } +/** + * \brief Mixer element informations are changed + * \param elem Mixer element + * \return 0 on success otherwise a negative error code + * + * For use by mixer element class specific code. + */ int snd_mixer_elem_info(snd_mixer_elem_t *elem) { return snd_mixer_elem_throw_event(elem, SND_CTL_EVENT_MASK_INFO); } +/** + * \brief Mixer element values is changed + * \param elem Mixer element + * \return 0 on success otherwise a negative error code + * + * For use by mixer element class specific code. + */ int snd_mixer_elem_value(snd_mixer_elem_t *elem) { return snd_mixer_elem_throw_event(elem, SND_CTL_EVENT_MASK_VALUE); } +/** + * \brief Register mixer element class + * \param class Mixer element class + * \param mixer Mixer handle + * \return 0 on success otherwise a negative error code + * + * For use by mixer element class specific code. + */ int snd_mixer_class_register(snd_mixer_class_t *class, snd_mixer_t *mixer) { struct list_head *pos; @@ -325,6 +409,11 @@ int snd_mixer_class_register(snd_mixer_class_t *class, snd_mixer_t *mixer) return 0; } +/** + * \brief Unregister mixer element class and remove all its elements + * \param class Mixer element class + * \return 0 on success otherwise a negative error code + */ int snd_mixer_class_unregister(snd_mixer_class_t *class) { unsigned int k; @@ -342,6 +431,11 @@ int snd_mixer_class_unregister(snd_mixer_class_t *class) return 0; } +/** + * \brief Load a mixer elements + * \param mixer Mixer handle + * \return 0 on success otherwise a negative error code + */ int snd_mixer_load(snd_mixer_t *mixer) { struct list_head *pos; @@ -356,6 +450,10 @@ int snd_mixer_load(snd_mixer_t *mixer) return 0; } +/** + * \brief Unload all mixer elements and free all related resources + * \param mixer Mixer handle + */ void snd_mixer_free(snd_mixer_t *mixer) { struct list_head *pos; @@ -366,6 +464,11 @@ void snd_mixer_free(snd_mixer_t *mixer) } } +/** + * \brief Close a mixer and free all related resources + * \param mixer Mixer handle + * \return 0 on success otherwise a negative error code + */ int snd_mixer_close(snd_mixer_t *mixer) { int res = 0; @@ -423,21 +526,32 @@ static int snd_mixer_sort(snd_mixer_t *mixer) return 0; } -int snd_mixer_set_compare(snd_mixer_t *mixer, snd_mixer_compare_t msort) +/** + * \brief Change mixer compare function and reorder elements + * \param mixer Mixer handle + * \param compare Element compare function + * \return 0 on success otherwise a negative error code + */ +int snd_mixer_set_compare(snd_mixer_t *mixer, snd_mixer_compare_t compare) { - snd_mixer_compare_t msort_old; + snd_mixer_compare_t compare_old; int err; assert(mixer); - msort_old = mixer->compare; - mixer->compare = msort == NULL ? snd_mixer_compare_default : msort; + compare_old = mixer->compare; + mixer->compare = compare == NULL ? snd_mixer_compare_default : compare; if ((err = snd_mixer_sort(mixer)) < 0) { - mixer->compare = msort_old; + mixer->compare = compare_old; return err; } return 0; } +/** + * \brief get count of poll descriptors for mixer handle + * \param mixer Mixer handle + * \return count of poll descriptors + */ int snd_mixer_poll_descriptors_count(snd_mixer_t *mixer) { struct list_head *pos; @@ -455,6 +569,13 @@ int snd_mixer_poll_descriptors_count(snd_mixer_t *mixer) return c; } +/** + * \brief get poll descriptors + * \param mixer Mixer handle + * \param pfds array of poll descriptors + * \param space space in the poll descriptor array + * \return count of filled descriptors + */ int snd_mixer_poll_descriptors(snd_mixer_t *mixer, struct pollfd *pfds, unsigned int space) { struct list_head *pos; @@ -477,6 +598,12 @@ int snd_mixer_poll_descriptors(snd_mixer_t *mixer, struct pollfd *pfds, unsigned return count; } +/** + * \brief Wait for a mixer to become ready (i.e. at least one event pending) + * \param mixer Mixer handle + * \param timeout maximum time in milliseconds to wait + * \return 0 otherwise a negative error code on failure + */ int snd_mixer_wait(snd_mixer_t *mixer, int timeout) { struct pollfd spfds[16]; @@ -500,6 +627,11 @@ int snd_mixer_wait(snd_mixer_t *mixer, int timeout) return 0; } +/** + * \brief get first element for a mixer + * \param mixer Mixer handle + * \return pointer to first element + */ snd_mixer_elem_t *snd_mixer_first_elem(snd_mixer_t *mixer) { assert(mixer); @@ -508,6 +640,11 @@ snd_mixer_elem_t *snd_mixer_first_elem(snd_mixer_t *mixer) return list_entry(mixer->elems.next, snd_mixer_elem_t, list); } +/** + * \brief get last element for a mixer + * \param mixer Mixer handle + * \return pointer to last element + */ snd_mixer_elem_t *snd_mixer_last_elem(snd_mixer_t *mixer) { assert(mixer); @@ -516,6 +653,11 @@ snd_mixer_elem_t *snd_mixer_last_elem(snd_mixer_t *mixer) return list_entry(mixer->elems.prev, snd_mixer_elem_t, list); } +/** + * \brief get next mixer element + * \param elem mixer element + * \return pointer to next element + */ snd_mixer_elem_t *snd_mixer_elem_next(snd_mixer_elem_t *elem) { assert(elem); @@ -524,6 +666,11 @@ snd_mixer_elem_t *snd_mixer_elem_next(snd_mixer_elem_t *elem) return list_entry(elem->list.next, snd_mixer_elem_t, list); } +/** + * \brief get previous mixer element + * \param elem mixer element + * \return pointer to previous element + */ snd_mixer_elem_t *snd_mixer_elem_prev(snd_mixer_elem_t *elem) { assert(elem); @@ -532,6 +679,11 @@ snd_mixer_elem_t *snd_mixer_elem_prev(snd_mixer_elem_t *elem) return list_entry(elem->list.prev, snd_mixer_elem_t, list); } +/** + * \brief Handle pending mixer events invoking callbacks + * \param mixer Mixer handle + * \return 0 otherwise a negative error code on failure + */ int snd_mixer_handle_events(snd_mixer_t *mixer) { struct list_head *pos; @@ -548,3 +700,91 @@ int snd_mixer_handle_events(snd_mixer_t *mixer) return mixer->events; } +/** + * \brief Set callback function for a mixer + * \param mixer mixer handle + * \param callback callback function + */ +void snd_mixer_set_callback(snd_mixer_t *obj, snd_mixer_callback_t val) +{ + assert(obj); + obj->callback = val; +} + +/** + * \brief Set callback private value for a mixer + * \param mixer mixer handle + * \param callback_private callback private value + */ +void snd_mixer_set_callback_private(snd_mixer_t *obj, void * val) +{ + assert(obj); + obj->callback_private = val; +} + +/** + * \brief Get callback private value for a mixer + * \param mixer mixer handle + * \return callback private value + */ +void * snd_mixer_get_callback_private(const snd_mixer_t *obj) +{ + assert(obj); + return obj->callback_private; +} + +/** + * \brief Get elements count for a mixer + * \param mixer mixer handle + * \return elements count + */ +unsigned int snd_mixer_get_count(const snd_mixer_t *obj) +{ + assert(obj); + return obj->count; +} + +/** + * \brief Set callback function for a mixer element + * \param obj mixer element + * \param val callback function + */ +void snd_mixer_elem_set_callback(snd_mixer_elem_t *obj, snd_mixer_elem_callback_t val) +{ + assert(obj); + obj->callback = val; +} + +/** + * \brief Set callback private value for a mixer element + * \param obj mixer element + * \param val callback private value + */ +void snd_mixer_elem_set_callback_private(snd_mixer_elem_t *obj, void * val) +{ + assert(obj); + obj->callback_private = val; +} + +/** + * \brief Get callback private value for a mixer element + * \param obj mixer element + * \return callback private value + */ +void * snd_mixer_elem_get_callback_private(const snd_mixer_elem_t *obj) +{ + assert(obj); + return obj->callback_private; +} + +/** + * \brief Get type for a mixer element + * \param obj mixer element + * \return mixer element type + */ +snd_mixer_elem_type_t snd_mixer_elem_get_type(const snd_mixer_elem_t *obj) +{ + assert(obj); + return obj->type; +} + diff --git a/src/mixer/mixer_local.h b/src/mixer/mixer_local.h index e41b6a0c..266b11fc 100644 --- a/src/mixer/mixer_local.h +++ b/src/mixer/mixer_local.h @@ -90,7 +90,6 @@ struct _snd_mixer_selem_id { int snd_mixer_class_register(snd_mixer_class_t *class, snd_mixer_t *mixer); int snd_mixer_add_elem(snd_mixer_t *mixer, snd_mixer_elem_t *elem); int snd_mixer_remove_elem(snd_mixer_t *mixer, snd_mixer_elem_t *elem); -int snd_mixer_elem_throw_event(snd_mixer_elem_t *elem, unsigned int mask); int snd_mixer_elem_add(snd_mixer_elem_t *elem, snd_mixer_class_t *class); int snd_mixer_elem_remove(snd_mixer_elem_t *elem); int snd_mixer_elem_info(snd_mixer_elem_t *elem); diff --git a/src/mixer/mixer_m4.c b/src/mixer/mixer_m4.c deleted file mode 100644 index 73148818..00000000 --- a/src/mixer/mixer_m4.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Mixer - Automatically generated functions - * Copyright (c) 2001 by Abramo Bagnara <abramo@alsa-project.org> - * - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include "mixer_local.h" - -size_t snd_mixer_selem_id_sizeof() -{ - return sizeof(snd_mixer_selem_id_t); -} - -int snd_mixer_selem_id_malloc(snd_mixer_selem_id_t **ptr) -{ - assert(ptr); - *ptr = calloc(1, sizeof(snd_mixer_selem_id_t)); - if (!*ptr) - return -ENOMEM; - return 0; -} - -void snd_mixer_selem_id_free(snd_mixer_selem_id_t *obj) -{ - free(obj); -} - -void snd_mixer_selem_id_copy(snd_mixer_selem_id_t *dst, const snd_mixer_selem_id_t *src) -{ - assert(dst && src); - *dst = *src; -} - -const char *snd_mixer_selem_id_get_name(const snd_mixer_selem_id_t *obj) -{ - assert(obj); - return obj->name; -} - -unsigned int snd_mixer_selem_id_get_index(const snd_mixer_selem_id_t *obj) -{ - assert(obj); - return obj->index; -} - -void snd_mixer_selem_id_set_name(snd_mixer_selem_id_t *obj, const char *val) -{ - assert(obj); - strncpy(obj->name, val, sizeof(obj->name)); -} - -void snd_mixer_selem_id_set_index(snd_mixer_selem_id_t *obj, unsigned int val) -{ - assert(obj); - obj->index = val; -} - -void snd_mixer_set_callback(snd_mixer_t *obj, snd_mixer_callback_t val) -{ - assert(obj); - obj->callback = val; -} - -void * snd_mixer_get_callback_private(const snd_mixer_t *obj) -{ - assert(obj); - return obj->callback_private; -} - -void snd_mixer_set_callback_private(snd_mixer_t *obj, void * val) -{ - assert(obj); - obj->callback_private = val; -} - -unsigned int snd_mixer_get_count(const snd_mixer_t *obj) -{ - assert(obj); - return obj->count; -} - -void snd_mixer_elem_set_callback(snd_mixer_elem_t *obj, snd_mixer_elem_callback_t val) -{ - assert(obj); - obj->callback = val; -} - -void * snd_mixer_elem_get_callback_private(const snd_mixer_elem_t *obj) -{ - assert(obj); - return obj->callback_private; -} - -void snd_mixer_elem_set_callback_private(snd_mixer_elem_t *obj, void * val) -{ - assert(obj); - obj->callback_private = val; -} - -snd_mixer_elem_type_t snd_mixer_elem_get_type(const snd_mixer_elem_t *obj) -{ - assert(obj); - return obj->type; -} - diff --git a/src/mixer/simple.c b/src/mixer/simple.c index 34888eda..d3e3f932 100644 --- a/src/mixer/simple.c +++ b/src/mixer/simple.c @@ -1,3 +1,11 @@ +/** + * \file mixer/simple.c + * \author Jaroslav Kysela <perex@suse.cz> + * \author Abramo Bagnara <abramo@alsa-project.org> + * \date 2001 + * + * Mixer simple elements class interface. + */ /* * Mixer Interface - simple controls * Copyright (c) 2000 by Jaroslav Kysela <perex@suse.cz> @@ -20,6 +28,7 @@ * */ +#ifndef DOC_HIDDEN #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -83,6 +92,8 @@ typedef struct _selem { } str[2]; } selem_t; +#endif + static struct mixer_name_table { const char *longname; const char *shortname; @@ -869,7 +880,15 @@ static int simple_compare(const snd_mixer_elem_t *c1, const snd_mixer_elem_t *c2 return s1->id.index - s2->id.index; } -int snd_mixer_selem_register(snd_mixer_t *mixer, void *arg ATTRIBUTE_UNUSED, + +/** + * \brief Register mixer simple element class + * \param mixer Mixer handle + * \param options Options container (not used now) + * \param classp Pointer to returned mixer simple element class handle (or NULL) + * \return 0 on success otherwise a negative error code + */ +int snd_mixer_selem_register(snd_mixer_t *mixer, void *options ATTRIBUTE_UNUSED, snd_mixer_class_t **classp) { snd_mixer_class_t *class = calloc(1, sizeof(*class)); @@ -888,6 +907,12 @@ int snd_mixer_selem_register(snd_mixer_t *mixer, void *arg ATTRIBUTE_UNUSED, return 0; } +/** + * \brief Find a mixer simple element + * \param mixer Mixer handle + * \param id Mixer simple element identificator + * \return mixer simple element handle or NULL if not found + */ snd_mixer_elem_t *snd_mixer_find_selem(snd_mixer_t *mixer, const snd_mixer_selem_id_t *id) { @@ -905,6 +930,11 @@ snd_mixer_elem_t *snd_mixer_find_selem(snd_mixer_t *mixer, return NULL; } +/** + * \brief Get mixer simple element identificator + * \param elem Mixer simple element handle + * \param id returned mixer simple element identificator + */ void snd_mixer_selem_get_id(snd_mixer_elem_t *elem, snd_mixer_selem_id_t *id) { @@ -915,6 +945,11 @@ void snd_mixer_selem_get_id(snd_mixer_elem_t *elem, *id = s->id; } +/** + * \brief Get name part of mixer simple element identificator + * \param elem Mixer simple element handle + * \return name part of simple element identificator + */ const char *snd_mixer_selem_get_name(snd_mixer_elem_t *elem) { selem_t *s; @@ -924,6 +959,11 @@ const char *snd_mixer_selem_get_name(snd_mixer_elem_t *elem) return s->id.name; } +/** + * \brief Get index part of mixer simple element identificator + * \param elem Mixer simple element handle + * \return index part of simple element identificator + */ unsigned int snd_mixer_selem_get_index(snd_mixer_elem_t *elem) { selem_t *s; @@ -933,6 +973,130 @@ unsigned int snd_mixer_selem_get_index(snd_mixer_elem_t *elem) return s->id.index; } +/** + * \brief Return true if mixer simple element has only one volume control for both playback and capture + * \param elem Mixer simple element handle + * \return 0 separated control, 1 common control + */ +int snd_mixer_selem_has_common_volume(snd_mixer_elem_t *elem) +{ + selem_t *s; + assert(elem); + assert(elem->type == SND_MIXER_ELEM_SIMPLE); + s = elem->private_data; + return !!(s->caps & CAP_GVOLUME); +} + +/** + * \brief Return true if mixer simple element has only one switch control for both playback and capture + * \param elem Mixer simple element handle + * \return 0 separated control, 1 common control + */ +int snd_mixer_selem_has_common_switch(snd_mixer_elem_t *elem) +{ + selem_t *s; + assert(elem); + assert(elem->type == SND_MIXER_ELEM_SIMPLE); + s = elem->private_data; + return !!(s->caps & CAP_GSWITCH); +} + +static int _snd_mixer_selem_set_volume(snd_mixer_elem_t *elem, int dir, snd_mixer_selem_channel_id_t channel, long value) +{ + selem_t *s = elem->private_data; + assert((unsigned int) channel < s->str[dir].channels); + assert(value >= s->str[dir].min && value <= s->str[dir].max); + if (s->caps & + (dir == PLAY ? CAP_PVOLUME_JOIN : CAP_CVOLUME_JOIN)) + channel = 0; + if (value != s->str[dir].vol[channel]) { + s->str[dir].vol[channel] = value; + return 1; + } + return 0; +} + +static int _snd_mixer_selem_set_volume_all(snd_mixer_elem_t *elem, int dir, long value) +{ + int changed = 0; + snd_mixer_selem_channel_id_t channel; + selem_t *s = elem->private_data; + assert(value >= s->str[dir].min && value <= s->str[dir].max); + for (channel = 0; (unsigned int) channel < s->str[dir].channels; channel++) { + if (value != s->str[dir].vol[channel]) { + s->str[dir].vol[channel] = value; + changed = 1; + } + } + return changed; +} + +static int _snd_mixer_selem_set_switch(snd_mixer_elem_t *elem, int dir, snd_mixer_selem_channel_id_t channel, int value) +{ + selem_t *s = elem->private_data; + assert((unsigned int) channel < s->str[dir].channels); + if (s->caps & + (dir == PLAY ? CAP_PSWITCH_JOIN : CAP_CSWITCH_JOIN)) + channel = 0; + if (value) { + if (!(s->str[dir].sw & (1 << channel))) { + s->str[dir].sw |= 1 << channel; + return 1; + } + } else { + if (s->str[dir].sw & (1 << channel)) { + s->str[dir].sw &= ~(1 << channel); + return 1; + } + } + return 0; +} + +static int _snd_mixer_selem_set_switch_all(snd_mixer_elem_t *elem, int dir, int value) +{ + selem_t *s = elem->private_data; + if (value) { + if (s->str[dir].sw != ~0U) { + s->str[dir].sw = ~0U; + return 1; + } + } else { + if (s->str[dir].sw != 0U) { + s->str[dir].sw = 0U; + return 1; + } + } + return 0; +} + +/** + * \brief Return name of mixer simple element channel + * \param channel mixer simple element channel identificator + * \return channel name + */ +const char *snd_mixer_selem_channel_name(snd_mixer_selem_channel_id_t channel) +{ + static const char *array[snd_enum_to_int(SND_MIXER_SCHN_LAST) + 1] = { + [SND_MIXER_SCHN_FRONT_LEFT] = "Front Left", + [SND_MIXER_SCHN_FRONT_RIGHT] = "Front Right", + [SND_MIXER_SCHN_FRONT_CENTER] = "Front Center", + [SND_MIXER_SCHN_REAR_LEFT] = "Rear Left", + [SND_MIXER_SCHN_REAR_RIGHT] = "Rear Right", + [SND_MIXER_SCHN_WOOFER] = "Woofer" + }; + const char *p; + assert(channel <= SND_MIXER_SCHN_LAST); + p = array[snd_enum_to_int(channel)]; + if (!p) + return "?"; + return p; +} + +/** + * \brief Get info about channels of playback stream of a mixer simple element + * \param elem Mixer simple element handle + * \return 0 if not mono, 1 if mono + */ int snd_mixer_selem_is_playback_mono(snd_mixer_elem_t *elem) { selem_t *s; @@ -942,6 +1106,12 @@ int snd_mixer_selem_is_playback_mono(snd_mixer_elem_t *elem) return s->str[PLAY].channels == 1; } +/** + * \brief Get info about channels of playback stream of a mixer simple element + * \param elem Mixer simple element handle + * \param channel Mixer simple element channel identificator + * \return 0 if channel is not present, 1 if present + */ int snd_mixer_selem_has_playback_channel(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel) { selem_t *s; @@ -951,142 +1121,336 @@ int snd_mixer_selem_has_playback_channel(snd_mixer_elem_t *elem, snd_mixer_selem return (unsigned int) channel < s->str[PLAY].channels; } -int snd_mixer_selem_get_playback_min(snd_mixer_elem_t *elem) +/** + * \brief Get range for playback volume of a mixer simple element + * \param elem Mixer simple element handle + * \param min Pointer to returned minimum + * \param max Pointer to returned maximum + */ +void snd_mixer_selem_get_playback_volume_range(snd_mixer_elem_t *elem, + long *min, long *max) { selem_t *s; assert(elem); assert(elem->type == SND_MIXER_ELEM_SIMPLE); s = elem->private_data; - return s->str[PLAY].min; + *min = s->str[PLAY].min; + *max = s->str[PLAY].max; } -int snd_mixer_selem_get_playback_max(snd_mixer_elem_t *elem) +/** + * \brief Set range for playback volume of a mixer simple element + * \param elem Mixer simple element handle + * \param min minimum volume value + * \param max maximum volume value + */ +void snd_mixer_selem_set_playback_volume_range(snd_mixer_elem_t *elem, + long min, long max) { selem_t *s; assert(elem); assert(elem->type == SND_MIXER_ELEM_SIMPLE); s = elem->private_data; - return s->str[PLAY].max; + assert(min != max); + s->str[PLAY].range = 1; + s->str[PLAY].min = min; + s->str[PLAY].max = max; } -int snd_mixer_selem_is_capture_mono(snd_mixer_elem_t *elem) +/** + * \brief Return info about playback volume control of a mixer simple element + * \param elem Mixer simple element handle + * \return 0 if no control is present, 1 if it's present + */ +int snd_mixer_selem_has_playback_volume(snd_mixer_elem_t *elem) { selem_t *s; assert(elem); assert(elem->type == SND_MIXER_ELEM_SIMPLE); s = elem->private_data; - return s->str[CAPT].channels == 1; + return !!(s->caps & CAP_PVOLUME); } -int snd_mixer_selem_has_capture_channel(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel) +/** + * \brief Return info about playback volume control of a mixer simple element + * \param elem Mixer simple element handle + * \return 0 if control is separated per channel, 1 if control acts on all channels together + */ +int snd_mixer_selem_has_playback_volume_joined(snd_mixer_elem_t *elem) { selem_t *s; assert(elem); assert(elem->type == SND_MIXER_ELEM_SIMPLE); s = elem->private_data; - return (unsigned int) channel < s->str[CAPT].channels; + return !!(s->caps & CAP_PVOLUME_JOIN); } -int snd_mixer_selem_get_capture_min(snd_mixer_elem_t *elem) +/** + * \brief Return info about playback switch control existence of a mixer simple element + * \param elem Mixer simple element handle + * \return 0 if no control is present, 1 if it's present + */ +int snd_mixer_selem_has_playback_switch(snd_mixer_elem_t *elem) { selem_t *s; assert(elem); assert(elem->type == SND_MIXER_ELEM_SIMPLE); s = elem->private_data; - return s->str[CAPT].min; + return !!(s->caps & CAP_PSWITCH); } -int snd_mixer_selem_get_capture_max(snd_mixer_elem_t *elem) +/** + * \brief Return info about playback switch control of a mixer simple element + * \param elem Mixer simple element handle + * \return 0 if control is separated per channel, 1 if control acts on all channels together + */ +int snd_mixer_selem_has_playback_switch_joined(snd_mixer_elem_t *elem) { selem_t *s; assert(elem); assert(elem->type == SND_MIXER_ELEM_SIMPLE); s = elem->private_data; - return s->str[CAPT].max; + return !!(s->caps & CAP_PSWITCH_JOIN); } -int snd_mixer_selem_get_capture_group(snd_mixer_elem_t *elem) +/** + * \brief Return value of playback volume control of a mixer simple element + * \param elem Mixer simple element handle + * \param channel mixer simple element channel identificator + * \param value pointer to returned value + * \return 0 on success otherwise a negative error code + */ +int snd_mixer_selem_get_playback_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value) { + int err; selem_t *s; assert(elem); assert(elem->type == SND_MIXER_ELEM_SIMPLE); s = elem->private_data; - assert(s->caps & CAP_CSWITCH_EXCL); - return s->capture_group; + assert((unsigned int) channel < s->str[PLAY].channels); + assert(s->caps & CAP_PVOLUME); + err = snd_mixer_handle_events(elem->class->mixer); + if (err < 0) + return err; + if (s->caps & CAP_PVOLUME_JOIN) + channel = 0; + *value = s->str[PLAY].vol[channel]; + return 0; } -int snd_mixer_selem_has_common_volume(snd_mixer_elem_t *elem) +/** + * \brief Return value of playback switch control of a mixer simple element + * \param elem Mixer simple element handle + * \param channel mixer simple element channel identificator + * \param value pointer to returned value + * \return 0 on success otherwise a negative error code + */ +int snd_mixer_selem_get_playback_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int *value) { + int err; selem_t *s; assert(elem); assert(elem->type == SND_MIXER_ELEM_SIMPLE); s = elem->private_data; - return !!(s->caps & CAP_GVOLUME); + assert((unsigned int) channel < s->str[PLAY].channels); + assert(s->caps & CAP_PSWITCH); + err = snd_mixer_handle_events(elem->class->mixer); + if (err < 0) + return err; + if (s->caps & CAP_PSWITCH_JOIN) + channel = 0; + *value = !!(s->str[PLAY].sw & (1 << channel)); + return 0; } -int snd_mixer_selem_has_playback_volume(snd_mixer_elem_t *elem) +/** + * \brief Set value of playback volume control of a mixer simple element + * \param elem Mixer simple element handle + * \param channel mixer simple element channel identificator + * \param value control value + * \return 0 on success otherwise a negative error code + */ +int snd_mixer_selem_set_playback_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value) { + int changed; selem_t *s; assert(elem); assert(elem->type == SND_MIXER_ELEM_SIMPLE); s = elem->private_data; - return !!(s->caps & CAP_PVOLUME); + assert(s->caps & CAP_PVOLUME); + changed = _snd_mixer_selem_set_volume(elem, PLAY, channel, value); + if (changed < 0) + return changed; + if (changed) + return selem_write(elem); + return 0; } -int snd_mixer_selem_has_playback_volume_joined(snd_mixer_elem_t *elem) +/** + * \brief Set value of playback volume control for all channels of a mixer simple element + * \param elem Mixer simple element handle + * \param value control value + * \return 0 on success otherwise a negative error code + */ +int snd_mixer_selem_set_playback_volume_all(snd_mixer_elem_t *elem, long value) { + int changed; selem_t *s; assert(elem); assert(elem->type == SND_MIXER_ELEM_SIMPLE); s = elem->private_data; - return !!(s->caps & CAP_PVOLUME_JOIN); + assert(s->caps & CAP_PVOLUME); + changed = _snd_mixer_selem_set_volume_all(elem, PLAY, value); + if (changed < 0) + return changed; + if (changed) + return selem_write(elem); + return 0; } -int snd_mixer_selem_has_capture_volume(snd_mixer_elem_t *elem) +/** + * \brief Set value of playback switch control of a mixer simple element + * \param elem Mixer simple element handle + * \param channel mixer simple element channel identificator + * \param value control value + * \return 0 on success otherwise a negative error code + */ +int snd_mixer_selem_set_playback_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int value) { + int changed; selem_t *s; assert(elem); assert(elem->type == SND_MIXER_ELEM_SIMPLE); s = elem->private_data; - return !!(s->caps & CAP_CVOLUME); + assert(s->caps & CAP_PSWITCH); + changed = _snd_mixer_selem_set_switch(elem, PLAY, channel, value); + if (changed < 0) + return changed; + if (changed) + return selem_write(elem); + return 0; } -int snd_mixer_selem_has_capture_volume_joined(snd_mixer_elem_t *elem) +/** + * \brief Set value of playback switch control for all channels of a mixer simple element + * \param elem Mixer simple element handle + * \param value control value + * \return 0 on success otherwise a negative error code + */ +int snd_mixer_selem_set_playback_switch_all(snd_mixer_elem_t *elem, int value) { + int changed; selem_t *s; assert(elem); assert(elem->type == SND_MIXER_ELEM_SIMPLE); s = elem->private_data; - return !!(s->caps & CAP_CVOLUME_JOIN); + assert(s->caps & CAP_PSWITCH); + changed = _snd_mixer_selem_set_switch_all(elem, PLAY, value); + if (changed < 0) + return changed; + if (changed) + return selem_write(elem); + return 0; } -int snd_mixer_selem_has_common_switch(snd_mixer_elem_t *elem) +/** + * \brief Get info about channels of capture stream of a mixer simple element + * \param elem Mixer simple element handle + * \return 0 if not mono, 1 if mono + */ +int snd_mixer_selem_is_capture_mono(snd_mixer_elem_t *elem) { selem_t *s; assert(elem); assert(elem->type == SND_MIXER_ELEM_SIMPLE); s = elem->private_data; - return !!(s->caps & CAP_GSWITCH); + return s->str[CAPT].channels == 1; } -int snd_mixer_selem_has_playback_switch(snd_mixer_elem_t *elem) +/** + * \brief Get info about channels of capture stream of a mixer simple element + * \param elem Mixer simple element handle + * \param channel Mixer simple element channel identificator + * \return 0 if channel is not present, 1 if present + */ +int snd_mixer_selem_has_capture_channel(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel) { selem_t *s; assert(elem); assert(elem->type == SND_MIXER_ELEM_SIMPLE); s = elem->private_data; - return !!(s->caps & CAP_PSWITCH); + return (unsigned int) channel < s->str[CAPT].channels; } -int snd_mixer_selem_has_playback_switch_joined(snd_mixer_elem_t *elem) +/** + * \brief Get range for capture volume of a mixer simple element + * \param elem Mixer simple element handle + * \param min Pointer to returned minimum + * \param max Pointer to returned maximum + */ +void snd_mixer_selem_get_capture_volume_range(snd_mixer_elem_t *elem, + long *min, long *max) { selem_t *s; assert(elem); assert(elem->type == SND_MIXER_ELEM_SIMPLE); s = elem->private_data; - return !!(s->caps & CAP_PSWITCH_JOIN); + *min = s->str[CAPT].min; + *max = s->str[CAPT].max; +} + +/** + * \brief Set range for capture volume of a mixer simple element + * \param elem Mixer simple element handle + * \param min minimum volume value + * \param max maximum volume value + */ +void snd_mixer_selem_set_capture_volume_range(snd_mixer_elem_t *elem, + long min, long max) +{ + selem_t *s; + assert(elem); + assert(elem->type == SND_MIXER_ELEM_SIMPLE); + s = elem->private_data; + assert(min != max); + s->str[CAPT].range = 1; + s->str[CAPT].min = min; + s->str[CAPT].max = max; +} + +/** + * \brief Return info about capture volume control of a mixer simple element + * \param elem Mixer simple element handle + * \return 0 if no control is present, 1 if it's present + */ +int snd_mixer_selem_has_capture_volume(snd_mixer_elem_t *elem) +{ + selem_t *s; + assert(elem); + assert(elem->type == SND_MIXER_ELEM_SIMPLE); + s = elem->private_data; + return !!(s->caps & CAP_CVOLUME); } +/** + * \brief Return info about capture volume control of a mixer simple element + * \param elem Mixer simple element handle + * \return 0 if control is separated per channel, 1 if control acts on all channels together + */ +int snd_mixer_selem_has_capture_volume_joined(snd_mixer_elem_t *elem) +{ + selem_t *s; + assert(elem); + assert(elem->type == SND_MIXER_ELEM_SIMPLE); + s = elem->private_data; + return !!(s->caps & CAP_CVOLUME_JOIN); +} + +/** + * \brief Return info about capture switch control existence of a mixer simple element + * \param elem Mixer simple element handle + * \return 0 if no control is present, 1 if it's present + */ int snd_mixer_selem_has_capture_switch(snd_mixer_elem_t *elem) { selem_t *s; @@ -1096,6 +1460,11 @@ int snd_mixer_selem_has_capture_switch(snd_mixer_elem_t *elem) return !!(s->caps & CAP_CSWITCH); } +/** + * \brief Return info about capture switch control of a mixer simple element + * \param elem Mixer simple element handle + * \return 0 if control is separated per channel, 1 if control acts on all channels together + */ int snd_mixer_selem_has_capture_switch_joined(snd_mixer_elem_t *elem) { selem_t *s; @@ -1105,6 +1474,11 @@ int snd_mixer_selem_has_capture_switch_joined(snd_mixer_elem_t *elem) return !!(s->caps & CAP_CSWITCH_JOIN); } +/** + * \brief Return info about capture switch control of a mixer simple element + * \param elem Mixer simple element handle + * \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) + */ int snd_mixer_selem_has_capture_switch_exclusive(snd_mixer_elem_t *elem) { selem_t *s; @@ -1114,24 +1488,28 @@ int snd_mixer_selem_has_capture_switch_exclusive(snd_mixer_elem_t *elem) return !!(s->caps & CAP_CSWITCH_EXCL); } -int snd_mixer_selem_get_playback_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value) +/** + * \brief Return info about capture switch control of a mixer simple element + * \param elem Mixer simple element handle + * \return group for switch exclusivity (see #snd_mixer_selem_has_capture_switch_exclusive) + */ +int snd_mixer_selem_get_capture_group(snd_mixer_elem_t *elem) { - int err; selem_t *s; assert(elem); assert(elem->type == SND_MIXER_ELEM_SIMPLE); s = elem->private_data; - assert((unsigned int) channel < s->str[PLAY].channels); - assert(s->caps & CAP_PVOLUME); - err = snd_mixer_handle_events(elem->class->mixer); - if (err < 0) - return err; - if (s->caps & CAP_PVOLUME_JOIN) - channel = 0; - *value = s->str[PLAY].vol[channel]; - return 0; + assert(s->caps & CAP_CSWITCH_EXCL); + return s->capture_group; } +/** + * \brief Return value of capture volume control of a mixer simple element + * \param elem Mixer simple element handle + * \param channel mixer simple element channel identificator + * \param value pointer to returned value + * \return 0 on success otherwise a negative error code + */ int snd_mixer_selem_get_capture_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value) { int err; @@ -1150,24 +1528,13 @@ int snd_mixer_selem_get_capture_volume(snd_mixer_elem_t *elem, snd_mixer_selem_c return 0; } -int snd_mixer_selem_get_playback_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int *value) -{ - int err; - selem_t *s; - assert(elem); - assert(elem->type == SND_MIXER_ELEM_SIMPLE); - s = elem->private_data; - assert((unsigned int) channel < s->str[PLAY].channels); - assert(s->caps & CAP_PSWITCH); - err = snd_mixer_handle_events(elem->class->mixer); - if (err < 0) - return err; - if (s->caps & CAP_PSWITCH_JOIN) - channel = 0; - *value = !!(s->str[PLAY].sw & (1 << channel)); - return 0; -} - +/** + * \brief Return value of capture switch control of a mixer simple element + * \param elem Mixer simple element handle + * \param channel mixer simple element channel identificator + * \param value pointer to returned value + * \return 0 on success otherwise a negative error code + */ int snd_mixer_selem_get_capture_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int *value) { int err; @@ -1186,37 +1553,13 @@ int snd_mixer_selem_get_capture_switch(snd_mixer_elem_t *elem, snd_mixer_selem_c return 0; } -static int _snd_mixer_selem_set_volume(snd_mixer_elem_t *elem, int dir, snd_mixer_selem_channel_id_t channel, long value) -{ - selem_t *s = elem->private_data; - assert((unsigned int) channel < s->str[dir].channels); - assert(value >= s->str[dir].min && value <= s->str[dir].max); - if (s->caps & - (dir == PLAY ? CAP_PVOLUME_JOIN : CAP_CVOLUME_JOIN)) - channel = 0; - if (value != s->str[dir].vol[channel]) { - s->str[dir].vol[channel] = value; - return 1; - } - return 0; -} - -int snd_mixer_selem_set_playback_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value) -{ - int changed; - selem_t *s; - assert(elem); - assert(elem->type == SND_MIXER_ELEM_SIMPLE); - s = elem->private_data; - assert(s->caps & CAP_PVOLUME); - changed = _snd_mixer_selem_set_volume(elem, PLAY, channel, value); - if (changed < 0) - return changed; - if (changed) - return selem_write(elem); - return 0; -} - +/** + * \brief Set value of capture volume control of a mixer simple element + * \param elem Mixer simple element handle + * \param channel mixer simple element channel identificator + * \param value control value + * \return 0 on success otherwise a negative error code + */ int snd_mixer_selem_set_capture_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value) { int changed; @@ -1233,37 +1576,12 @@ int snd_mixer_selem_set_capture_volume(snd_mixer_elem_t *elem, snd_mixer_selem_c return 0; } -static int _snd_mixer_selem_set_volume_all(snd_mixer_elem_t *elem, int dir, long value) -{ - int changed = 0; - snd_mixer_selem_channel_id_t channel; - selem_t *s = elem->private_data; - assert(value >= s->str[dir].min && value <= s->str[dir].max); - for (channel = 0; (unsigned int) channel < s->str[dir].channels; channel++) { - if (value != s->str[dir].vol[channel]) { - s->str[dir].vol[channel] = value; - changed = 1; - } - } - return changed; -} - -int snd_mixer_selem_set_playback_volume_all(snd_mixer_elem_t *elem, long value) -{ - int changed; - selem_t *s; - assert(elem); - assert(elem->type == SND_MIXER_ELEM_SIMPLE); - s = elem->private_data; - assert(s->caps & CAP_PVOLUME); - changed = _snd_mixer_selem_set_volume_all(elem, PLAY, value); - if (changed < 0) - return changed; - if (changed) - return selem_write(elem); - return 0; -} - +/** + * \brief Set value of capture volume control for all channels of a mixer simple element + * \param elem Mixer simple element handle + * \param value control value + * \return 0 on success otherwise a negative error code + */ int snd_mixer_selem_set_capture_volume_all(snd_mixer_elem_t *elem, long value) { int changed; @@ -1280,36 +1598,22 @@ int snd_mixer_selem_set_capture_volume_all(snd_mixer_elem_t *elem, long value) return 0; } -static int _snd_mixer_selem_set_switch(snd_mixer_elem_t *elem, int dir, snd_mixer_selem_channel_id_t channel, int value) -{ - selem_t *s = elem->private_data; - assert((unsigned int) channel < s->str[dir].channels); - if (s->caps & - (dir == PLAY ? CAP_PSWITCH_JOIN : CAP_CSWITCH_JOIN)) - channel = 0; - if (value) { - if (!(s->str[dir].sw & (1 << channel))) { - s->str[dir].sw |= 1 << channel; - return 1; - } - } else { - if (s->str[dir].sw & (1 << channel)) { - s->str[dir].sw &= ~(1 << channel); - return 1; - } - } - return 0; -} - -int snd_mixer_selem_set_playback_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int value) +/** + * \brief Set value of capture switch control of a mixer simple element + * \param elem Mixer simple element handle + * \param channel mixer simple element channel identificator + * \param value control value + * \return 0 on success otherwise a negative error code + */ +int snd_mixer_selem_set_capture_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int value) { int changed; selem_t *s; assert(elem); assert(elem->type == SND_MIXER_ELEM_SIMPLE); s = elem->private_data; - assert(s->caps & CAP_PSWITCH); - changed = _snd_mixer_selem_set_switch(elem, PLAY, channel, value); + assert(s->caps & CAP_CSWITCH); + changed = _snd_mixer_selem_set_switch(elem, CAPT, channel, value); if (changed < 0) return changed; if (changed) @@ -1317,7 +1621,13 @@ int snd_mixer_selem_set_playback_switch(snd_mixer_elem_t *elem, snd_mixer_selem_ return 0; } -int snd_mixer_selem_set_capture_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int value) +/** + * \brief Set value of capture switch control for all channels of a mixer simple element + * \param elem Mixer simple element handle + * \param value control value + * \return 0 on success otherwise a negative error code + */ +int snd_mixer_selem_set_capture_switch_all(snd_mixer_elem_t *elem, int value) { int changed; selem_t *s; @@ -1325,7 +1635,7 @@ int snd_mixer_selem_set_capture_switch(snd_mixer_elem_t *elem, snd_mixer_selem_c assert(elem->type == SND_MIXER_ELEM_SIMPLE); s = elem->private_data; assert(s->caps & CAP_CSWITCH); - changed = _snd_mixer_selem_set_switch(elem, CAPT, channel, value); + changed = _snd_mixer_selem_set_switch_all(elem, CAPT, value); if (changed < 0) return changed; if (changed) @@ -1333,96 +1643,90 @@ int snd_mixer_selem_set_capture_switch(snd_mixer_elem_t *elem, snd_mixer_selem_c return 0; } -static int _snd_mixer_selem_set_switch_all(snd_mixer_elem_t *elem, int dir, int value) +/** + * \brief get size of #snd_mixer_selem_id_t + * \return size in bytes + */ +size_t snd_mixer_selem_id_sizeof() { - selem_t *s = elem->private_data; - if (value) { - if (s->str[dir].sw != ~0U) { - s->str[dir].sw = ~0U; - return 1; - } - } else { - if (s->str[dir].sw != 0U) { - s->str[dir].sw = 0U; - return 1; - } - } - return 0; + return sizeof(snd_mixer_selem_id_t); } -int snd_mixer_selem_set_playback_switch_all(snd_mixer_elem_t *elem, int value) +/** + * \brief allocate an invalid #snd_mixer_selem_id_t using standard malloc + * \param ptr returned pointer + * \return 0 on success otherwise negative error code + */ +int snd_mixer_selem_id_malloc(snd_mixer_selem_id_t **ptr) { - int changed; - selem_t *s; - assert(elem); - assert(elem->type == SND_MIXER_ELEM_SIMPLE); - s = elem->private_data; - assert(s->caps & CAP_PSWITCH); - changed = _snd_mixer_selem_set_switch_all(elem, PLAY, value); - if (changed < 0) - return changed; - if (changed) - return selem_write(elem); + assert(ptr); + *ptr = calloc(1, sizeof(snd_mixer_selem_id_t)); + if (!*ptr) + return -ENOMEM; return 0; } -int snd_mixer_selem_set_capture_switch_all(snd_mixer_elem_t *elem, int value) +/** + * \brief frees a previously allocated #snd_mixer_selem_id_t + * \param pointer to object to free + */ +void snd_mixer_selem_id_free(snd_mixer_selem_id_t *obj) { - int changed; - selem_t *s; - assert(elem); - assert(elem->type == SND_MIXER_ELEM_SIMPLE); - s = elem->private_data; - assert(s->caps & CAP_CSWITCH); - changed = _snd_mixer_selem_set_switch_all(elem, CAPT, value); - if (changed < 0) - return changed; - if (changed) - return selem_write(elem); - return 0; + free(obj); } -const char *snd_mixer_selem_channel_name(snd_mixer_selem_channel_id_t channel) +/** + * \brief copy one #snd_mixer_selem_id_t to another + * \param dst pointer to destination + * \param src pointer to source + */ +void snd_mixer_selem_id_copy(snd_mixer_selem_id_t *dst, const snd_mixer_selem_id_t *src) { - static const char *array[snd_enum_to_int(SND_MIXER_SCHN_LAST) + 1] = { - [SND_MIXER_SCHN_FRONT_LEFT] = "Front Left", - [SND_MIXER_SCHN_FRONT_RIGHT] = "Front Right", - [SND_MIXER_SCHN_FRONT_CENTER] = "Front Center", - [SND_MIXER_SCHN_REAR_LEFT] = "Rear Left", - [SND_MIXER_SCHN_REAR_RIGHT] = "Rear Right", - [SND_MIXER_SCHN_WOOFER] = "Woofer" - }; - const char *p; - assert(channel <= SND_MIXER_SCHN_LAST); - p = array[snd_enum_to_int(channel)]; - if (!p) - return "?"; - return p; + assert(dst && src); + *dst = *src; } -void snd_mixer_selem_set_playback_volume_range(snd_mixer_elem_t *elem, - long min, long max) +/** + * \brief Get name part of a mixer simple element identificator + * \param obj Mixer simple element identificator + * \return name part + */ +const char *snd_mixer_selem_id_get_name(const snd_mixer_selem_id_t *obj) { - selem_t *s; - assert(elem); - assert(elem->type == SND_MIXER_ELEM_SIMPLE); - s = elem->private_data; - assert(min != max); - s->str[PLAY].range = 1; - s->str[PLAY].min = min; - s->str[PLAY].max = max; + assert(obj); + return obj->name; } -void snd_mixer_selem_set_capture_volume_range(snd_mixer_elem_t *elem, - long min, long max) +/** + * \brief Get index part of a mixer simple element identificator + * \param obj Mixer simple element identificator + * \return index part + */ +unsigned int snd_mixer_selem_id_get_index(const snd_mixer_selem_id_t *obj) { - selem_t *s; - assert(elem); - assert(elem->type == SND_MIXER_ELEM_SIMPLE); - s = elem->private_data; - assert(min != max); - s->str[CAPT].range = 1; - s->str[CAPT].min = min; - s->str[CAPT].max = max; + assert(obj); + return obj->index; +} + +/** + * \brief Set name part of a mixer simple element identificator + * \param obj Mixer simple element identificator + * \param val name part + */ +void snd_mixer_selem_id_set_name(snd_mixer_selem_id_t *obj, const char *val) +{ + assert(obj); + strncpy(obj->name, val, sizeof(obj->name)); +} + +/** + * \brief Set index part of a mixer simple element identificator + * \param obj Mixer simple element identificator + * \param val index part + */ +void snd_mixer_selem_id_set_index(snd_mixer_selem_id_t *obj, unsigned int val) +{ + assert(obj); + obj->index = val; } |