summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaroslav Kysela <perex@perex.cz>2009-05-12 08:05:50 +0200
committerJaroslav Kysela <perex@perex.cz>2009-05-15 14:18:15 +0200
commitecd6846c88d24f2a03895115b8ebf50679af69f3 (patch)
tree6880963798e200e7dcc3ef962e0149434bf709b1
parent3e30007a19a0904ad7c8965b0883322639e52b82 (diff)
downloadalsa-lib-amixer.tar.gz
Initial amixer implementation + ctl & hctl API mergingamixer
This patch adds new mixer API which simplifies the previous mixer API (removed mixer class). The control and hcontrol APIs were merged into one. Signed-off-by: Jaroslav Kysela <perex@perex.cz>
-rw-r--r--Makefile.am2
-rw-r--r--include/control.h134
-rw-r--r--include/mixer.h408
-rw-r--r--include/mixer_abst.h77
-rw-r--r--include/mixer_old.h331
-rw-r--r--modules/mixer/Makefile.am2
-rw-r--r--modules/mixer/simple/sbase.c66
-rw-r--r--modules/mixer/simple/sbase.h27
-rw-r--r--modules/mixer/simple/sbasedl.c2
-rw-r--r--src/Makefile.am4
-rw-r--r--src/conf/alsa.conf25
-rw-r--r--src/control/Makefile.am3
-rw-r--r--src/control/control.c13
-rw-r--r--src/control/control_ext.c2
-rw-r--r--src/control/control_hw.c2
-rw-r--r--src/control/control_local.h34
-rw-r--r--src/control/control_shm.c9
-rw-r--r--src/control/hcontrol.c657
-rw-r--r--src/control/hcontrol_old.c512
-rw-r--r--src/mixer/Makefile.am5
-rw-r--r--src/mixer/mixer.c1215
-rw-r--r--src/mixer/mixer_local.h50
-rw-r--r--src/mixer/mixer_old.c375
-rw-r--r--src/mixer/mixer_old_local.h (renamed from src/mixer/mixer_simple.h)21
-rw-r--r--src/mixer/mixer_symbols.c36
-rw-r--r--src/mixer/simple.c885
-rw-r--r--src/mixer/simple_abst.c420
-rw-r--r--src/mixer/simple_none.c539
-rw-r--r--src/mixer/simple_old.c805
29 files changed, 3852 insertions, 2809 deletions
diff --git a/Makefile.am b/Makefile.am
index f0c39c1d..924ae5e6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -9,7 +9,7 @@ SUBDIRS += aserver
endif
if BUILD_MIXER
if BUILD_ALISP
-SUBDIRS += alsalisp
+#SUBDIRS += alsalisp
endif
endif
SUBDIRS += test utils
diff --git a/include/control.h b/include/control.h
index 2361dc3a..d2076f04 100644
--- a/include/control.h
+++ b/include/control.h
@@ -4,7 +4,7 @@
* \author Jaroslav Kysela <perex@perex.cz>
* \author Abramo Bagnara <abramo@alsa-project.org>
* \author Takashi Iwai <tiwai@suse.de>
- * \date 1998-2001
+ * \date 1998-2008
*
* Application interface library for the ALSA driver
*/
@@ -199,14 +199,13 @@ typedef enum _snd_ctl_type {
/** Read only (flag for open mode) \hideinitializer */
#define SND_CTL_READONLY 0x0004
+/** Cache (extended) mode (flag for open mode) \hideinitializer */
+#define SND_CTL_CACHE 0x0008
+
/** CTL handle */
typedef struct _snd_ctl snd_ctl_t;
-
-/** Don't destroy the ctl handle when close */
-#define SND_SCTL_NOFREE 0x0001
-
-/** SCTL type */
-typedef struct _snd_sctl snd_sctl_t;
+/** CTL element handle */
+typedef struct _snd_ctl_elem snd_ctl_elem_t;
int snd_card_load(int card);
int snd_card_next(int *card);
@@ -466,89 +465,72 @@ int snd_ctl_convert_from_dB(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id,
/**
* \defgroup HControl High level Control Interface
* \ingroup Control
- * The high level control interface.
+ * The high level control interface. The #SND_CTL_CACHE flag must be
+ * set to enable this interface.
* See \ref hcontrol page for more details.
* \{
*/
-/** HCTL element handle */
-typedef struct _snd_hctl_elem snd_hctl_elem_t;
-
-/** HCTL handle */
-typedef struct _snd_hctl snd_hctl_t;
-
/**
- * \brief Compare function for sorting HCTL elements
+ * \brief Compare function for sorting CTL elements
* \param e1 First element
* \param e2 Second element
* \return -1 if e1 < e2, 0 if e1 == e2, 1 if e1 > e2
*/
-typedef int (*snd_hctl_compare_t)(const snd_hctl_elem_t *e1,
- const snd_hctl_elem_t *e2);
-int snd_hctl_compare_fast(const snd_hctl_elem_t *c1,
- const snd_hctl_elem_t *c2);
+typedef int (*snd_ctl_compare_t)(const snd_ctl_elem_t *e1,
+ const snd_ctl_elem_t *e2);
+int snd_ctl_compare_fast(const snd_ctl_elem_t *c1,
+ const snd_ctl_elem_t *c2);
/**
- * \brief HCTL callback function
- * \param hctl HCTL handle
+ * \brief CTL callback function
+ * \param ctl CTL handle
* \param mask event mask
- * \param elem related HCTL element (if any)
+ * \param elem related CTL element (if any)
* \return 0 on success otherwise a negative error code
*/
-typedef int (*snd_hctl_callback_t)(snd_hctl_t *hctl,
- unsigned int mask,
- snd_hctl_elem_t *elem);
+typedef int (*snd_ctl_callback_t)(snd_ctl_t *ctl,
+ unsigned int mask,
+ snd_ctl_elem_t *elem);
/**
- * \brief HCTL element callback function
- * \param elem HCTL element
+ * \brief CTL element callback function
+ * \param elem CTL element
* \param mask event mask
* \return 0 on success otherwise a negative error code
*/
-typedef int (*snd_hctl_elem_callback_t)(snd_hctl_elem_t *elem,
- unsigned int mask);
-
-int snd_hctl_open(snd_hctl_t **hctl, const char *name, int mode);
-int snd_hctl_open_ctl(snd_hctl_t **hctlp, snd_ctl_t *ctl);
-int snd_hctl_close(snd_hctl_t *hctl);
-int snd_hctl_nonblock(snd_hctl_t *hctl, int nonblock);
-int snd_hctl_poll_descriptors_count(snd_hctl_t *hctl);
-int snd_hctl_poll_descriptors(snd_hctl_t *hctl, struct pollfd *pfds, unsigned int space);
-int snd_hctl_poll_descriptors_revents(snd_hctl_t *ctl, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
-unsigned int snd_hctl_get_count(snd_hctl_t *hctl);
-int snd_hctl_set_compare(snd_hctl_t *hctl, snd_hctl_compare_t hsort);
-snd_hctl_elem_t *snd_hctl_first_elem(snd_hctl_t *hctl);
-snd_hctl_elem_t *snd_hctl_last_elem(snd_hctl_t *hctl);
-snd_hctl_elem_t *snd_hctl_find_elem(snd_hctl_t *hctl, const snd_ctl_elem_id_t *id);
-void snd_hctl_set_callback(snd_hctl_t *hctl, snd_hctl_callback_t callback);
-void snd_hctl_set_callback_private(snd_hctl_t *hctl, void *data);
-void *snd_hctl_get_callback_private(snd_hctl_t *hctl);
-int snd_hctl_load(snd_hctl_t *hctl);
-int snd_hctl_free(snd_hctl_t *hctl);
-int snd_hctl_handle_events(snd_hctl_t *hctl);
-const char *snd_hctl_name(snd_hctl_t *hctl);
-int snd_hctl_wait(snd_hctl_t *hctl, int timeout);
-snd_ctl_t *snd_hctl_ctl(snd_hctl_t *hctl);
-
-snd_hctl_elem_t *snd_hctl_elem_next(snd_hctl_elem_t *elem);
-snd_hctl_elem_t *snd_hctl_elem_prev(snd_hctl_elem_t *elem);
-int snd_hctl_elem_info(snd_hctl_elem_t *elem, snd_ctl_elem_info_t * info);
-int snd_hctl_elem_read(snd_hctl_elem_t *elem, snd_ctl_elem_value_t * value);
-int snd_hctl_elem_write(snd_hctl_elem_t *elem, snd_ctl_elem_value_t * value);
-int snd_hctl_elem_tlv_read(snd_hctl_elem_t *elem, unsigned int *tlv, unsigned int tlv_size);
-int snd_hctl_elem_tlv_write(snd_hctl_elem_t *elem, const unsigned int *tlv);
-int snd_hctl_elem_tlv_command(snd_hctl_elem_t *elem, const unsigned int *tlv);
-
-snd_hctl_t *snd_hctl_elem_get_hctl(snd_hctl_elem_t *elem);
-
-void snd_hctl_elem_get_id(const snd_hctl_elem_t *obj, snd_ctl_elem_id_t *ptr);
-unsigned int snd_hctl_elem_get_numid(const snd_hctl_elem_t *obj);
-snd_ctl_elem_iface_t snd_hctl_elem_get_interface(const snd_hctl_elem_t *obj);
-unsigned int snd_hctl_elem_get_device(const snd_hctl_elem_t *obj);
-unsigned int snd_hctl_elem_get_subdevice(const snd_hctl_elem_t *obj);
-const char *snd_hctl_elem_get_name(const snd_hctl_elem_t *obj);
-unsigned int snd_hctl_elem_get_index(const snd_hctl_elem_t *obj);
-void snd_hctl_elem_set_callback(snd_hctl_elem_t *obj, snd_hctl_elem_callback_t val);
-void * snd_hctl_elem_get_callback_private(const snd_hctl_elem_t *obj);
-void snd_hctl_elem_set_callback_private(snd_hctl_elem_t *obj, void * val);
+typedef int (*snd_ctl_elem_callback_t)(snd_ctl_elem_t *elem,
+ unsigned int mask);
+
+unsigned int snd_ctl_get_count(snd_ctl_t *ctl);
+int snd_ctl_set_compare(snd_ctl_t *ctl, snd_ctl_compare_t hsort);
+snd_ctl_elem_t *snd_ctl_first_elem(snd_ctl_t *ctl);
+snd_ctl_elem_t *snd_ctl_last_elem(snd_ctl_t *ctl);
+snd_ctl_elem_t *snd_ctl_find_elem(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id);
+void snd_ctl_set_callback(snd_ctl_t *ctl, snd_ctl_callback_t callback);
+void snd_ctl_set_callback_private(snd_ctl_t *ctl, void *data);
+void *snd_ctl_get_callback_private(snd_ctl_t *ctl);
+int snd_ctl_handle_events(snd_ctl_t *ctl);
+
+snd_ctl_elem_t *snd_ctl_elem_next(snd_ctl_elem_t *elem);
+snd_ctl_elem_t *snd_ctl_elem_prev(snd_ctl_elem_t *elem);
+int snd_ctl_celem_info(snd_ctl_elem_t *elem, snd_ctl_elem_info_t * info);
+int snd_ctl_celem_read(snd_ctl_elem_t *elem, snd_ctl_elem_value_t * value);
+int snd_ctl_celem_write(snd_ctl_elem_t *elem, snd_ctl_elem_value_t * value);
+int snd_ctl_celem_tlv_read(snd_ctl_elem_t *elem, unsigned int *tlv, unsigned int tlv_size);
+int snd_ctl_celem_tlv_write(snd_ctl_elem_t *elem, const unsigned int *tlv);
+int snd_ctl_celem_tlv_command(snd_ctl_elem_t *elem, const unsigned int *tlv);
+
+snd_ctl_t *snd_ctl_elem_get_ctl(snd_ctl_elem_t *elem);
+
+void snd_ctl_elem_get_id(const snd_ctl_elem_t *obj, snd_ctl_elem_id_t *ptr);
+unsigned int snd_ctl_elem_get_numid(const snd_ctl_elem_t *obj);
+snd_ctl_elem_iface_t snd_ctl_elem_get_interface(const snd_ctl_elem_t *obj);
+unsigned int snd_ctl_elem_get_device(const snd_ctl_elem_t *obj);
+unsigned int snd_ctl_elem_get_subdevice(const snd_ctl_elem_t *obj);
+const char *snd_ctl_elem_get_name(const snd_ctl_elem_t *obj);
+unsigned int snd_ctl_elem_get_index(const snd_ctl_elem_t *obj);
+void snd_ctl_elem_set_callback(snd_ctl_elem_t *obj, snd_ctl_elem_callback_t val);
+void * snd_ctl_elem_get_callback_private(const snd_ctl_elem_t *obj);
+void snd_ctl_elem_set_callback_private(snd_ctl_elem_t *obj, void * val);
/** \} */
@@ -561,6 +543,12 @@ void snd_hctl_elem_set_callback_private(snd_hctl_elem_t *obj, void * val);
* \{
*/
+/** Don't destroy the ctl handle when close */
+#define SND_SCTL_NOFREE 0x0001
+
+/** SCTL type */
+typedef struct _snd_sctl snd_sctl_t;
+
int snd_sctl_build(snd_sctl_t **ctl, snd_ctl_t *handle, snd_config_t *config,
snd_config_t *private_data, int mode);
int snd_sctl_free(snd_sctl_t *handle);
diff --git a/include/mixer.h b/include/mixer.h
index df921642..dd79fef8 100644
--- a/include/mixer.h
+++ b/include/mixer.h
@@ -1,10 +1,10 @@
-/**
+/*
* \file include/mixer.h
* \brief Application interface library for the ALSA driver
* \author Jaroslav Kysela <perex@perex.cz>
* \author Abramo Bagnara <abramo@alsa-project.org>
* \author Takashi Iwai <tiwai@suse.de>
- * \date 1998-2001
+ * \date 1998-2009
*
* Application interface library for the ALSA driver
*/
@@ -34,142 +34,27 @@ extern "C" {
/**
* \defgroup Mixer Mixer Interface
- * The mixer interface.
+ * The amixer interface.
* \{
*/
-/** Mixer handle */
-typedef struct _snd_mixer snd_mixer_t;
-/** Mixer elements class handle */
-typedef struct _snd_mixer_class snd_mixer_class_t;
-/** Mixer element handle */
-typedef struct _snd_mixer_elem snd_mixer_elem_t;
-
-/**
- * \brief Mixer callback function
- * \param mixer Mixer handle
- * \param mask event mask
- * \param elem related mixer element (if any)
- * \return 0 on success otherwise a negative error code
- */
-typedef int (*snd_mixer_callback_t)(snd_mixer_t *ctl,
- unsigned int mask,
- snd_mixer_elem_t *elem);
-
-/**
- * \brief Mixer element callback function
- * \param elem Mixer element
- * \param mask event mask
- * \return 0 on success otherwise a negative error code
- */
-typedef int (*snd_mixer_elem_callback_t)(snd_mixer_elem_t *elem,
- unsigned int mask);
-
-/**
- * \brief Compare function for sorting mixer elements
- * \param e1 First element
- * \param e2 Second element
- * \return -1 if e1 < e2, 0 if e1 == e2, 1 if e1 > e2
- */
-typedef int (*snd_mixer_compare_t)(const snd_mixer_elem_t *e1,
- const snd_mixer_elem_t *e2);
-
-/**
- * \brief Event callback for the mixer class
- * \param class_ Mixer class
- * \param mask Event mask (SND_CTL_EVENT_*)
- * \param helem HCTL element which invoked the event
- * \param melem Mixer element associated to HCTL element
- * \return zero if success, otherwise a negative error value
- */
-typedef int (*snd_mixer_event_t)(snd_mixer_class_t *class_, unsigned int mask,
- snd_hctl_elem_t *helem, snd_mixer_elem_t *melem);
-
-
-/** Mixer element type */
-typedef enum _snd_mixer_elem_type {
- /* Simple mixer elements */
- SND_MIXER_ELEM_SIMPLE,
- SND_MIXER_ELEM_LAST = SND_MIXER_ELEM_SIMPLE
-} snd_mixer_elem_type_t;
-
-int snd_mixer_open(snd_mixer_t **mixer, int mode);
-int snd_mixer_close(snd_mixer_t *mixer);
-snd_mixer_elem_t *snd_mixer_first_elem(snd_mixer_t *mixer);
-snd_mixer_elem_t *snd_mixer_last_elem(snd_mixer_t *mixer);
-int snd_mixer_handle_events(snd_mixer_t *mixer);
-int snd_mixer_attach(snd_mixer_t *mixer, const char *name);
-int snd_mixer_attach_hctl(snd_mixer_t *mixer, snd_hctl_t *hctl);
-int snd_mixer_detach(snd_mixer_t *mixer, const char *name);
-int snd_mixer_detach_hctl(snd_mixer_t *mixer, snd_hctl_t *hctl);
-int snd_mixer_get_hctl(snd_mixer_t *mixer, const char *name, snd_hctl_t **hctl);
-int snd_mixer_poll_descriptors_count(snd_mixer_t *mixer);
-int snd_mixer_poll_descriptors(snd_mixer_t *mixer, struct pollfd *pfds, unsigned int space);
-int snd_mixer_poll_descriptors_revents(snd_mixer_t *mixer, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
-int snd_mixer_load(snd_mixer_t *mixer);
-void snd_mixer_free(snd_mixer_t *mixer);
-int snd_mixer_wait(snd_mixer_t *mixer, int timeout);
-int snd_mixer_set_compare(snd_mixer_t *mixer, snd_mixer_compare_t msort);
-void snd_mixer_set_callback(snd_mixer_t *obj, snd_mixer_callback_t val);
-void * snd_mixer_get_callback_private(const snd_mixer_t *obj);
-void snd_mixer_set_callback_private(snd_mixer_t *obj, void * val);
-unsigned int snd_mixer_get_count(const snd_mixer_t *obj);
-int snd_mixer_class_unregister(snd_mixer_class_t *clss);
-
-snd_mixer_elem_t *snd_mixer_elem_next(snd_mixer_elem_t *elem);
-snd_mixer_elem_t *snd_mixer_elem_prev(snd_mixer_elem_t *elem);
-void snd_mixer_elem_set_callback(snd_mixer_elem_t *obj, snd_mixer_elem_callback_t val);
-void * snd_mixer_elem_get_callback_private(const snd_mixer_elem_t *obj);
-void snd_mixer_elem_set_callback_private(snd_mixer_elem_t *obj, void * val);
-snd_mixer_elem_type_t snd_mixer_elem_get_type(const snd_mixer_elem_t *obj);
-
-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_new(snd_mixer_elem_t **elem,
- snd_mixer_elem_type_t type,
- int compare_weight,
- void *private_data,
- void (*private_free)(snd_mixer_elem_t *elem));
-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);
-void snd_mixer_elem_free(snd_mixer_elem_t *elem);
-int snd_mixer_elem_info(snd_mixer_elem_t *elem);
-int snd_mixer_elem_value(snd_mixer_elem_t *elem);
-int snd_mixer_elem_attach(snd_mixer_elem_t *melem, snd_hctl_elem_t *helem);
-int snd_mixer_elem_detach(snd_mixer_elem_t *melem, snd_hctl_elem_t *helem);
-int snd_mixer_elem_empty(snd_mixer_elem_t *melem);
-void *snd_mixer_elem_get_private(const snd_mixer_elem_t *melem);
-
-size_t snd_mixer_class_sizeof(void);
-/** \hideinitializer
- * \brief allocate an invalid #snd_mixer_class_t using standard alloca
- * \param ptr returned pointer
- */
-#define snd_mixer_class_alloca(ptr) __snd_alloca(ptr, snd_mixer_class)
-int snd_mixer_class_malloc(snd_mixer_class_t **ptr);
-void snd_mixer_class_free(snd_mixer_class_t *obj);
-void snd_mixer_class_copy(snd_mixer_class_t *dst, const snd_mixer_class_t *src);
-snd_mixer_t *snd_mixer_class_get_mixer(const snd_mixer_class_t *class_);
-snd_mixer_event_t snd_mixer_class_get_event(const snd_mixer_class_t *class_);
-void *snd_mixer_class_get_private(const snd_mixer_class_t *class_);
-snd_mixer_compare_t snd_mixer_class_get_compare(const snd_mixer_class_t *class_);
-int snd_mixer_class_set_event(snd_mixer_class_t *class_, snd_mixer_event_t event);
-int snd_mixer_class_set_private(snd_mixer_class_t *class_, void *private_data);
-int snd_mixer_class_set_private_free(snd_mixer_class_t *class_, void (*private_free)(snd_mixer_class_t *class_));
-int snd_mixer_class_set_compare(snd_mixer_class_t *class_, snd_mixer_compare_t compare);
+/* AMixer elements API */
-/**
- * \defgroup SimpleMixer Simple Mixer Interface
- * \ingroup Mixer
- * The simple mixer interface.
- * \{
- */
+/** dlsym version for interface entry callback */
+#define SND_AMIXER_DLSYM_VERSION _dlsym_amixer_001
-/* Simple mixer elements API */
+/** AMixer element operation identifier */
+typedef enum _snd_amixer_elem_type {
+ /** Playback */
+ SND_MIXER_DIR_PLAYBACK = 0,
+ /** Capture */
+ SND_MIXER_DIR_CAPTURE = 1,
+ /** Common - playback and capture directions are identical */
+ SND_MIXER_DIR_COMMON = 2,
+} snd_amixer_dir_t;
-/** Mixer simple element channel identifier */
-typedef enum _snd_mixer_selem_channel_id {
+/** AMixer element channel identifier */
+typedef enum _snd_amixer_elem_channel_id {
/** Unknown */
SND_MIXER_SCHN_UNKNOWN = -1,
/** Front left */
@@ -193,121 +78,168 @@ typedef enum _snd_mixer_selem_channel_id {
SND_MIXER_SCHN_LAST = 31,
/** Mono (Front left alias) */
SND_MIXER_SCHN_MONO = SND_MIXER_SCHN_FRONT_LEFT
-} snd_mixer_selem_channel_id_t;
-
-/** Mixer simple element - register options - abstraction level */
-enum snd_mixer_selem_regopt_abstract {
- /** no abstraction - try use all universal controls from driver */
- SND_MIXER_SABSTRACT_NONE = 0,
- /** basic abstraction - Master,PCM,CD,Aux,Record-Gain etc. */
- SND_MIXER_SABSTRACT_BASIC,
-};
-
-/** Mixer simple element - register options */
-struct snd_mixer_selem_regopt {
- /** structure version */
- int ver;
- /** v1: abstract layer selection */
- enum snd_mixer_selem_regopt_abstract abstract;
- /** v1: device name (must be NULL when playback_pcm or capture_pcm != NULL) */
- const char *device;
- /** v1: playback PCM connected to mixer device (NULL == none) */
- snd_pcm_t *playback_pcm;
- /** v1: capture PCM connected to mixer device (NULL == none) */
- snd_pcm_t *capture_pcm;
-};
+} snd_amixer_elem_channel_id_t;
+/** Mixer handle */
+typedef struct _snd_amixer snd_amixer_t;
+/** Mixer element handle */
+typedef struct _snd_amixer_elem snd_amixer_elem_t;
/** Mixer simple element identifier */
-typedef struct _snd_mixer_selem_id snd_mixer_selem_id_t;
-
-const char *snd_mixer_selem_channel_name(snd_mixer_selem_channel_id_t channel);
-
-int snd_mixer_selem_register(snd_mixer_t *mixer,
- struct snd_mixer_selem_regopt *options,
- snd_mixer_class_t **classp);
-void snd_mixer_selem_get_id(snd_mixer_elem_t *element,
- snd_mixer_selem_id_t *id);
-const char *snd_mixer_selem_get_name(snd_mixer_elem_t *elem);
-unsigned int snd_mixer_selem_get_index(snd_mixer_elem_t *elem);
-snd_mixer_elem_t *snd_mixer_find_selem(snd_mixer_t *mixer,
- const snd_mixer_selem_id_t *id);
+typedef struct _snd_amixer_elem_id {
+ char name[60];
+ unsigned int index;
+} snd_amixer_elem_id_t;
-int snd_mixer_selem_is_active(snd_mixer_elem_t *elem);
-int snd_mixer_selem_is_playback_mono(snd_mixer_elem_t *elem);
-int snd_mixer_selem_has_playback_channel(snd_mixer_elem_t *obj, snd_mixer_selem_channel_id_t channel);
-int snd_mixer_selem_is_capture_mono(snd_mixer_elem_t *elem);
-int snd_mixer_selem_has_capture_channel(snd_mixer_elem_t *obj, snd_mixer_selem_channel_id_t channel);
-int snd_mixer_selem_get_capture_group(snd_mixer_elem_t *elem);
-int snd_mixer_selem_has_common_volume(snd_mixer_elem_t *elem);
-int snd_mixer_selem_has_playback_volume(snd_mixer_elem_t *elem);
-int snd_mixer_selem_has_playback_volume_joined(snd_mixer_elem_t *elem);
-int snd_mixer_selem_has_capture_volume(snd_mixer_elem_t *elem);
-int snd_mixer_selem_has_capture_volume_joined(snd_mixer_elem_t *elem);
-int snd_mixer_selem_has_common_switch(snd_mixer_elem_t *elem);
-int snd_mixer_selem_has_playback_switch(snd_mixer_elem_t *elem);
-int snd_mixer_selem_has_playback_switch_joined(snd_mixer_elem_t *elem);
-int snd_mixer_selem_has_capture_switch(snd_mixer_elem_t *elem);
-int snd_mixer_selem_has_capture_switch_joined(snd_mixer_elem_t *elem);
-int snd_mixer_selem_has_capture_switch_exclusive(snd_mixer_elem_t *elem);
+/**
+ * \brief Mixer callback function
+ * \param amixer Mixer handle
+ * \param mask event mask
+ * \param elem related amixer element (if any)
+ * \return 0 on success otherwise a negative error code
+ */
+typedef int (*snd_amixer_callback_t)(snd_amixer_t *ctl,
+ unsigned int mask,
+ snd_amixer_elem_t *elem);
-int snd_mixer_selem_ask_playback_vol_dB(snd_mixer_elem_t *elem, long value, long *dBvalue);
-int snd_mixer_selem_ask_capture_vol_dB(snd_mixer_elem_t *elem, long value, long *dBvalue);
-int snd_mixer_selem_ask_playback_dB_vol(snd_mixer_elem_t *elem, long dBvalue, int dir, long *value);
-int snd_mixer_selem_ask_capture_dB_vol(snd_mixer_elem_t *elem, long dBvalue, int dir, long *value);
-int snd_mixer_selem_get_playback_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value);
-int snd_mixer_selem_get_capture_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value);
-int snd_mixer_selem_get_playback_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value);
-int snd_mixer_selem_get_capture_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value);
-int snd_mixer_selem_get_playback_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int *value);
-int snd_mixer_selem_get_capture_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int *value);
-int snd_mixer_selem_set_playback_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value);
-int snd_mixer_selem_set_capture_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value);
-int snd_mixer_selem_set_playback_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value, int dir);
-int snd_mixer_selem_set_capture_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value, int dir);
-int snd_mixer_selem_set_playback_volume_all(snd_mixer_elem_t *elem, long value);
-int snd_mixer_selem_set_capture_volume_all(snd_mixer_elem_t *elem, long value);
-int snd_mixer_selem_set_playback_dB_all(snd_mixer_elem_t *elem, long value, int dir);
-int snd_mixer_selem_set_capture_dB_all(snd_mixer_elem_t *elem, long value, int dir);
-int snd_mixer_selem_set_playback_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int value);
-int snd_mixer_selem_set_capture_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int value);
-int snd_mixer_selem_set_playback_switch_all(snd_mixer_elem_t *elem, int value);
-int snd_mixer_selem_set_capture_switch_all(snd_mixer_elem_t *elem, int value);
-int snd_mixer_selem_get_playback_volume_range(snd_mixer_elem_t *elem,
- long *min, long *max);
-int snd_mixer_selem_get_playback_dB_range(snd_mixer_elem_t *elem,
- long *min, long *max);
-int snd_mixer_selem_set_playback_volume_range(snd_mixer_elem_t *elem,
- long min, long max);
-int snd_mixer_selem_get_capture_volume_range(snd_mixer_elem_t *elem,
- long *min, long *max);
-int snd_mixer_selem_get_capture_dB_range(snd_mixer_elem_t *elem,
- long *min, long *max);
-int snd_mixer_selem_set_capture_volume_range(snd_mixer_elem_t *elem,
- long min, long max);
+/**
+ * \brief Mixer element callback function
+ * \param elem Mixer element
+ * \param mask event mask
+ * \return 0 on success otherwise a negative error code
+ */
+typedef int (*snd_amixer_elem_callback_t)(snd_amixer_elem_t *elem,
+ unsigned int mask);
-int snd_mixer_selem_is_enumerated(snd_mixer_elem_t *elem);
-int snd_mixer_selem_is_enum_playback(snd_mixer_elem_t *elem);
-int snd_mixer_selem_is_enum_capture(snd_mixer_elem_t *elem);
-int snd_mixer_selem_get_enum_items(snd_mixer_elem_t *elem);
-int snd_mixer_selem_get_enum_item_name(snd_mixer_elem_t *elem, unsigned int idx, size_t maxlen, char *str);
-int snd_mixer_selem_get_enum_item(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, unsigned int *idxp);
-int snd_mixer_selem_set_enum_item(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, unsigned int idx);
+/**
+ * \brief Compare function for sorting amixer elements
+ * \param e1 First element
+ * \param e2 Second element
+ * \return -1 if e1 < e2, 0 if e1 == e2, 1 if e1 > e2
+ */
+typedef int (*snd_amixer_compare_t)(const snd_amixer_elem_t *e1,
+ const snd_amixer_elem_t *e2);
-size_t snd_mixer_selem_id_sizeof(void);
+/**
+ * \brief Event callback for the amixer class
+ * \param amixer mixer handle
+ * \param mask Event mask (SND_CTL_EVENT_*)
+ * \param celem CTL element which invoked the event
+ * \param melem Mixer element associated to CTL element
+ * \return zero if success, otherwise a negative error value
+ */
+typedef int (*snd_amixer_event_t)(snd_amixer_t *amixer,
+ unsigned int mask,
+ snd_ctl_elem_t *celem,
+ snd_amixer_elem_t *melem);
+
+/** Expose all mixer controls (flag for open mode) \hideinitializer */
+#define SND_AMIXER_ALL 0x00000002
+/** Compatibility mode for older selem API (flag for open mode) \hideinitializer */
+#define SND_AMIXER_COMPAT1 0x40000000
+
+int snd_amixer_open(snd_amixer_t **amixer, const char *name,
+ snd_pcm_t *playback_pcm, snd_pcm_t *capture_pcm,
+ int mode);
+int snd_amixer_close(snd_amixer_t *amixer);
+int snd_amixer_handle_events(snd_amixer_t *amixer);
+int snd_amixer_poll_descriptors_count(snd_amixer_t *amixer);
+int snd_amixer_poll_descriptors(snd_amixer_t *amixer, struct pollfd *pfds, unsigned int space);
+int snd_amixer_poll_descriptors_revents(snd_amixer_t *amixer, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
+int snd_amixer_wait(snd_amixer_t *amixer, int timeout);
+int snd_amixer_set_compare(snd_amixer_t *amixer, snd_amixer_compare_t msort);
+void snd_amixer_set_callback(snd_amixer_t *obj, snd_amixer_callback_t val);
+void *snd_amixer_get_callback_private(const snd_amixer_t *obj);
+void snd_amixer_set_callback_private(snd_amixer_t *obj, void *val);
+void snd_amixer_set_event(snd_amixer_t *amixer, snd_amixer_event_t event);
+snd_amixer_event_t snd_amixer_get_event(const snd_amixer_t *amixer);
+unsigned int snd_amixer_get_count(const snd_amixer_t *obj);
+void snd_amixer_set_private(const snd_amixer_t *amixer, void *private_data);
+void snd_amixer_set_private_free(const snd_amixer_t *amixer, void (*private_free)(snd_amixer_t *amixer));
+void *snd_amixer_get_private(const snd_amixer_t *amixer);
+int snd_amixer_conf_generic_id(const char *id);
+
+int snd_amixer_compare_default(const snd_amixer_elem_t *c1, const snd_amixer_elem_t *c2);
+
+snd_amixer_elem_t *snd_amixer_first_elem(snd_amixer_t *amixer);
+snd_amixer_elem_t *snd_amixer_last_elem(snd_amixer_t *amixer);
+snd_amixer_elem_t *snd_amixer_elem_next(snd_amixer_elem_t *elem);
+snd_amixer_elem_t *snd_amixer_elem_prev(snd_amixer_elem_t *elem);
+void snd_amixer_elem_set_callback(snd_amixer_elem_t *obj, snd_amixer_elem_callback_t val);
+void * snd_amixer_elem_get_callback_private(const snd_amixer_elem_t *obj);
+void snd_amixer_elem_set_callback_private(snd_amixer_elem_t *obj, void * val);
+
+int snd_amixer_add_elem(snd_amixer_t *amixer, snd_amixer_elem_t *elem);
+int snd_amixer_remove_elem(snd_amixer_t *amixer, snd_amixer_elem_t *elem);
+int snd_amixer_elem_new(snd_amixer_t *amixer,
+ snd_amixer_elem_t **elem,
+ snd_amixer_elem_id_t *id,
+ int compare_weight,
+ void *private_data,
+ void (*private_free)(snd_amixer_elem_t *elem));
+int snd_amixer_elem_add(snd_amixer_t *amixer, snd_amixer_elem_t *elem);
+int snd_amixer_elem_remove(snd_amixer_elem_t *elem);
+void snd_amixer_elem_free(snd_amixer_elem_t *elem);
+int snd_amixer_elem_info(snd_amixer_elem_t *elem);
+int snd_amixer_elem_value(snd_amixer_elem_t *elem);
+int snd_amixer_elem_attach(snd_amixer_elem_t *melem, snd_ctl_elem_t *helem);
+int snd_amixer_elem_detach(snd_amixer_elem_t *melem, snd_ctl_elem_t *helem);
+int snd_amixer_elem_is_empty(snd_amixer_elem_t *melem);
+void *snd_amixer_elem_get_private(const snd_amixer_elem_t *melem);
+
+const char *snd_amixer_elem_channel_name(snd_amixer_elem_channel_id_t channel);
+
+void snd_amixer_elem_get_id(snd_amixer_elem_t *element,
+ snd_amixer_elem_id_t *id);
+const char *snd_amixer_elem_get_name(snd_amixer_elem_t *elem);
+unsigned int snd_amixer_elem_get_index(snd_amixer_elem_t *elem);
+snd_amixer_elem_t *snd_amixer_find_elem(snd_amixer_t *amixer,
+ const snd_amixer_elem_id_t *id);
+
+int snd_amixer_elem_is_active(snd_amixer_elem_t *elem);
+int snd_amixer_elem_has_channel(snd_amixer_elem_t *obj, snd_amixer_dir_t dir, snd_amixer_elem_channel_id_t channel);
+int snd_amixer_elem_has_volume(snd_amixer_elem_t *elem, snd_amixer_dir_t dir);
+int snd_amixer_elem_has_volume_joined(snd_amixer_elem_t *elem, snd_amixer_dir_t dir);
+int snd_amixer_elem_has_switch(snd_amixer_elem_t *elem, snd_amixer_dir_t dir);
+int snd_amixer_elem_has_switch_joined(snd_amixer_elem_t *elem, snd_amixer_dir_t dir);
+
+int snd_amixer_elem_get_group(snd_amixer_elem_t *elem, snd_amixer_dir_t dir);
+int snd_amixer_elem_has_switch_exclusive(snd_amixer_elem_t *elem, snd_amixer_dir_t dir);
+
+int snd_amixer_elem_ask_vol_dB(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, long value, long *dBvalue);
+int snd_amixer_elem_ask_dB_vol(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, long dBvalue, int xdir, long *value);
+int snd_amixer_elem_get_channels(snd_amixer_elem_t *elem, snd_amixer_dir_t dir);
+int snd_amixer_elem_get_volume(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, snd_amixer_elem_channel_id_t channel, long *value);
+int snd_amixer_elem_get_dB(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, snd_amixer_elem_channel_id_t channel, long *value);
+int snd_amixer_elem_get_switch(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, snd_amixer_elem_channel_id_t channel, int *value);
+int snd_amixer_elem_get_volume_range(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, long *min, long *max);
+int snd_amixer_elem_get_dB_range(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, long *min, long *max);
+int snd_amixer_elem_set_volume(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, snd_amixer_elem_channel_id_t channel, long value);
+int snd_amixer_elem_set_dB(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, snd_amixer_elem_channel_id_t channel, long value, int xdir);
+int snd_amixer_elem_set_volume_all(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, long value);
+int snd_amixer_elem_set_dB_all(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, long value, int xdir);
+int snd_amixer_elem_set_switch(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, snd_amixer_elem_channel_id_t channel, int value);
+int snd_amixer_elem_set_switch_all(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, int value);
+int snd_amixer_elem_set_volume_range(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, long min, long max);
+
+int snd_amixer_elem_is_enum(snd_amixer_elem_t *elem, snd_amixer_dir_t dir);
+int snd_amixer_elem_get_enum_items(snd_amixer_elem_t *elem);
+int snd_amixer_elem_get_enum_item_name(snd_amixer_elem_t *elem, unsigned int idx, size_t maxlen, char *str);
+int snd_amixer_elem_get_enum_item(snd_amixer_elem_t *elem, snd_amixer_elem_channel_id_t channel, unsigned int *idxp);
+int snd_amixer_elem_set_enum_item(snd_amixer_elem_t *elem, snd_amixer_elem_channel_id_t channel, unsigned int idx);
+
+size_t snd_amixer_elem_id_sizeof(void);
/** \hideinitializer
- * \brief allocate an invalid #snd_mixer_selem_id_t using standard alloca
+ * \brief allocate an invalid #snd_amixer_elem_id_t using standard alloca
* \param ptr returned pointer
*/
-#define snd_mixer_selem_id_alloca(ptr) __snd_alloca(ptr, snd_mixer_selem_id)
-int snd_mixer_selem_id_malloc(snd_mixer_selem_id_t **ptr);
-void snd_mixer_selem_id_free(snd_mixer_selem_id_t *obj);
-void snd_mixer_selem_id_copy(snd_mixer_selem_id_t *dst, const snd_mixer_selem_id_t *src);
-const char *snd_mixer_selem_id_get_name(const snd_mixer_selem_id_t *obj);
-unsigned int snd_mixer_selem_id_get_index(const snd_mixer_selem_id_t *obj);
-void snd_mixer_selem_id_set_name(snd_mixer_selem_id_t *obj, const char *val);
-void snd_mixer_selem_id_set_index(snd_mixer_selem_id_t *obj, unsigned int val);
-
-/** \} */
+#define snd_amixer_elem_id_alloca(ptr) __snd_alloca(ptr, snd_amixer_elem_id)
+int snd_amixer_elem_id_malloc(snd_amixer_elem_id_t **ptr);
+void snd_amixer_elem_id_free(snd_amixer_elem_id_t *obj);
+void snd_amixer_elem_id_copy(snd_amixer_elem_id_t *dst, const snd_amixer_elem_id_t *src);
+const char *snd_amixer_elem_id_get_name(const snd_amixer_elem_id_t *obj);
+unsigned int snd_amixer_elem_id_get_index(const snd_amixer_elem_id_t *obj);
+void snd_amixer_elem_id_set_name(snd_amixer_elem_id_t *obj, const char *val);
+void snd_amixer_elem_id_set_index(snd_amixer_elem_id_t *obj, unsigned int val);
/** \} */
diff --git a/include/mixer_abst.h b/include/mixer_abst.h
index 7844b191..781e9e30 100644
--- a/include/mixer_abst.h
+++ b/include/mixer_abst.h
@@ -2,7 +2,7 @@
* \file include/mixer_abst.h
* \brief Mixer abstract implementation interface library for the ALSA library
* \author Jaroslav Kysela <perex@perex.cz>
- * \date 2005
+ * \date 2005-2008
*
* Mixer abstact implementation interface library for the ALSA library
*/
@@ -36,8 +36,11 @@ extern "C" {
* \{
*/
-#define SM_PLAY 0
-#define SM_CAPT 1
+#define SM_CTL_COUNT 8
+
+#define SM_PLAY SND_MIXER_DIR_PLAYBACK
+#define SM_CAPT SND_MIXER_DIR_CAPTURE
+#define SM_COMM SND_MIXER_DIR_COMMON
#define SM_CAP_GVOLUME (1<<1)
#define SM_CAP_GSWITCH (1<<2)
@@ -55,52 +58,45 @@ extern "C" {
/* SM_CAP_* 24-31 => private for module use */
#define SM_OPS_IS_ACTIVE 0
-#define SM_OPS_IS_MONO 1
-#define SM_OPS_IS_CHANNEL 2
-#define SM_OPS_IS_ENUMERATED 3
-#define SM_OPS_IS_ENUMCNT 4
-
-#define sm_selem(x) ((sm_selem_t *)((x)->private_data))
-#define sm_selem_ops(x) ((sm_selem_t *)((x)->private_data))->ops
+#define SM_OPS_IS_CHANNEL 1
+#define SM_OPS_IS_ENUMERATED 2
+#define SM_OPS_IS_ENUMCNT 3
-typedef struct _sm_selem {
- snd_mixer_selem_id_t *id;
+typedef struct _sm_elem {
+ snd_amixer_elem_id_t id;
struct sm_elem_ops *ops;
unsigned int caps;
unsigned int capture_group;
-} sm_selem_t;
-
-typedef struct _sm_class_basic {
- char *device;
- snd_ctl_t *ctl;
- snd_hctl_t *hctl;
- snd_ctl_card_info_t *info;
-} sm_class_basic_t;
+} sm_elem_t;
struct sm_elem_ops {
- int (*is)(snd_mixer_elem_t *elem, int dir, int cmd, int val);
- int (*get_range)(snd_mixer_elem_t *elem, int dir, long *min, long *max);
- int (*set_range)(snd_mixer_elem_t *elem, int dir, long min, long max);
- int (*get_dB_range)(snd_mixer_elem_t *elem, int dir, long *min, long *max);
- int (*ask_vol_dB)(snd_mixer_elem_t *elem, int dir, long value, long *dbValue);
- int (*ask_dB_vol)(snd_mixer_elem_t *elem, int dir, long dbValue, long *value, int xdir);
- int (*get_volume)(snd_mixer_elem_t *elem, int dir, snd_mixer_selem_channel_id_t channel, long *value);
- int (*get_dB)(snd_mixer_elem_t *elem, int dir, snd_mixer_selem_channel_id_t channel, long *value);
- int (*set_volume)(snd_mixer_elem_t *elem, int dir, snd_mixer_selem_channel_id_t channel, long value);
- int (*set_dB)(snd_mixer_elem_t *elem, int dir, snd_mixer_selem_channel_id_t channel, long value, int xdir);
- int (*get_switch)(snd_mixer_elem_t *elem, int dir, snd_mixer_selem_channel_id_t channel, int *value);
- int (*set_switch)(snd_mixer_elem_t *elem, int dir, snd_mixer_selem_channel_id_t channel, int value);
- int (*enum_item_name)(snd_mixer_elem_t *elem, unsigned int item, size_t maxlen, char *buf);
- int (*get_enum_item)(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, unsigned int *itemp);
- int (*set_enum_item)(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, unsigned int item);
+ int (*is)(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, int cmd, int val);
+ int (*get_channels)(snd_amixer_elem_t *elem, snd_amixer_dir_t dir);
+ int (*get_range)(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, long *min, long *max);
+ int (*set_range)(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, long min, long max);
+ int (*get_dB_range)(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, long *min, long *max);
+ int (*ask_vol_dB)(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, long value, long *dbValue);
+ int (*ask_dB_vol)(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, long dbValue, long *value, int xdir);
+ int (*get_volume)(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, snd_amixer_elem_channel_id_t channel, long *value);
+ int (*get_dB)(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, snd_amixer_elem_channel_id_t channel, long *value);
+ int (*set_volume)(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, snd_amixer_elem_channel_id_t channel, long value);
+ int (*set_dB)(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, snd_amixer_elem_channel_id_t channel, long value, int xdir);
+ int (*get_switch)(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, snd_amixer_elem_channel_id_t channel, int *value);
+ int (*set_switch)(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, snd_amixer_elem_channel_id_t channel, int value);
+ int (*enum_item_name)(snd_amixer_elem_t *elem, unsigned int item, size_t maxlen, char *buf);
+ int (*get_enum_item)(snd_amixer_elem_t *elem, snd_amixer_elem_channel_id_t channel, unsigned int *itemp);
+ int (*set_enum_item)(snd_amixer_elem_t *elem, snd_amixer_elem_channel_id_t channel, unsigned int item);
};
-int snd_mixer_selem_compare(const snd_mixer_elem_t *c1, const snd_mixer_elem_t *c2);
+struct sm_open {
+ const char *name;
+ snd_pcm_t *pcm_playback;
+ snd_pcm_t *pcm_capture;
+ int mode;
+ snd_ctl_t *ctl[SM_CTL_COUNT];
+};
-int snd_mixer_sbasic_info(const snd_mixer_class_t *class, sm_class_basic_t *info);
-void *snd_mixer_sbasic_get_private(const snd_mixer_class_t *class);
-void snd_mixer_sbasic_set_private(const snd_mixer_class_t *class, void *private_data);
-void snd_mixer_sbasic_set_private_free(const snd_mixer_class_t *class, void (*private_free)(snd_mixer_class_t *class));
+sm_elem_t *snd_amixer_elem_get_sm(snd_amixer_elem_t *elem);
/** \} */
@@ -109,4 +105,3 @@ void snd_mixer_sbasic_set_private_free(const snd_mixer_class_t *class, void (*pr
#endif
#endif /* __ALSA_MIXER_ABST_H */
-
diff --git a/include/mixer_old.h b/include/mixer_old.h
new file mode 100644
index 00000000..fc38d346
--- /dev/null
+++ b/include/mixer_old.h
@@ -0,0 +1,331 @@
+/**
+ * \file include/mixer_old.h
+ * \brief Application interface library for the ALSA driver
+ * \author Jaroslav Kysela <perex@perex.cz>
+ * \author Abramo Bagnara <abramo@alsa-project.org>
+ * \author Takashi Iwai <tiwai@suse.de>
+ * \date 1998-2009
+ *
+ * Application interface library for the ALSA driver
+ */
+/*
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef __ALSA_MIXER_OLD_H
+#define __ALSA_MIXER_OLD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \defgroup HControl High level Control Interface
+ * \ingroup Control
+ * The high level control interface.
+ * See \ref hcontrol page for more details.
+ * \{
+ */
+
+/** HCTL element handle */
+#define snd_hctl_elem_t snd_ctl_elem_t
+
+/** HCTL handle */
+#define snd_hctl_t snd_ctl_t
+
+/**
+ * \brief Compare function for sorting HCTL elements
+ * \param e1 First element
+ * \param e2 Second element
+ * \return -1 if e1 < e2, 0 if e1 == e2, 1 if e1 > e2
+ */
+#define snd_hctl_compare_t snd_ctl_compare_t
+#define snd_hctl_compare_fast snd_ctl_compare_fast
+
+/**
+ * \brief HCTL callback function
+ * \param hctl HCTL handle
+ * \param mask event mask
+ * \param elem related HCTL element (if any)
+ * \return 0 on success otherwise a negative error code
+ */
+#define snd_hctl_callback_t snd_ctl_callback_t
+
+/**
+ * \brief HCTL element callback function
+ * \param elem HCTL element
+ * \param mask event mask
+ * \return 0 on success otherwise a negative error code
+ */
+#define snd_hctl_elem_callback_t snd_ctl_elem_callback_t
+
+int snd_hctl_open(snd_hctl_t **hctl, const char *name, int mode);
+int snd_hctl_open_ctl(snd_hctl_t **hctlp, snd_ctl_t *ctl);
+int snd_hctl_close(snd_hctl_t *hctl);
+int snd_hctl_nonblock(snd_hctl_t *hctl, int nonblock);
+int snd_hctl_poll_descriptors_count(snd_hctl_t *hctl);
+int snd_hctl_poll_descriptors(snd_hctl_t *hctl, struct pollfd *pfds, unsigned int space);
+int snd_hctl_poll_descriptors_revents(snd_hctl_t *ctl, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
+unsigned int snd_hctl_get_count(snd_hctl_t *hctl);
+int snd_hctl_set_compare(snd_hctl_t *hctl, snd_hctl_compare_t hsort);
+snd_hctl_elem_t *snd_hctl_first_elem(snd_hctl_t *hctl);
+snd_hctl_elem_t *snd_hctl_last_elem(snd_hctl_t *hctl);
+snd_hctl_elem_t *snd_hctl_find_elem(snd_hctl_t *hctl, const snd_ctl_elem_id_t *id);
+void snd_hctl_set_callback(snd_hctl_t *hctl, snd_hctl_callback_t callback);
+void snd_hctl_set_callback_private(snd_hctl_t *hctl, void *data);
+void *snd_hctl_get_callback_private(snd_hctl_t *hctl);
+int snd_hctl_load(snd_hctl_t *hctl);
+int snd_hctl_free(snd_hctl_t *hctl);
+int snd_hctl_handle_events(snd_hctl_t *hctl);
+const char *snd_hctl_name(snd_hctl_t *hctl);
+int snd_hctl_wait(snd_hctl_t *hctl, int timeout);
+snd_ctl_t *snd_hctl_ctl(snd_hctl_t *hctl);
+
+snd_hctl_elem_t *snd_hctl_elem_next(snd_hctl_elem_t *elem);
+snd_hctl_elem_t *snd_hctl_elem_prev(snd_hctl_elem_t *elem);
+int snd_hctl_elem_info(snd_hctl_elem_t *elem, snd_ctl_elem_info_t * info);
+int snd_hctl_elem_read(snd_hctl_elem_t *elem, snd_ctl_elem_value_t * value);
+int snd_hctl_elem_write(snd_hctl_elem_t *elem, snd_ctl_elem_value_t * value);
+int snd_hctl_elem_tlv_read(snd_hctl_elem_t *elem, unsigned int *tlv, unsigned int tlv_size);
+int snd_hctl_elem_tlv_write(snd_hctl_elem_t *elem, const unsigned int *tlv);
+int snd_hctl_elem_tlv_command(snd_hctl_elem_t *elem, const unsigned int *tlv);
+
+snd_hctl_t *snd_hctl_elem_get_hctl(snd_hctl_elem_t *elem);
+
+void snd_hctl_elem_get_id(const snd_hctl_elem_t *obj, snd_ctl_elem_id_t *ptr);
+unsigned int snd_hctl_elem_get_numid(const snd_hctl_elem_t *obj);
+snd_ctl_elem_iface_t snd_hctl_elem_get_interface(const snd_hctl_elem_t *obj);
+unsigned int snd_hctl_elem_get_device(const snd_hctl_elem_t *obj);
+unsigned int snd_hctl_elem_get_subdevice(const snd_hctl_elem_t *obj);
+const char *snd_hctl_elem_get_name(const snd_hctl_elem_t *obj);
+unsigned int snd_hctl_elem_get_index(const snd_hctl_elem_t *obj);
+void snd_hctl_elem_set_callback(snd_hctl_elem_t *obj, snd_hctl_elem_callback_t val);
+void * snd_hctl_elem_get_callback_private(const snd_hctl_elem_t *obj);
+void snd_hctl_elem_set_callback_private(snd_hctl_elem_t *obj, void * val);
+
+/** \} */
+
+/** \} */
+
+/**
+ * \defgroup MixerOld Mixer Interface
+ * The mixer interface.
+ * \{
+ */
+
+/** Mixer handle */
+typedef struct _snd_mixer snd_mixer_t;
+/** Mixer element handle */
+#define snd_mixer_elem_t snd_amixer_elem_t
+
+/**
+ * \brief Mixer callback function
+ * \param mixer Mixer handle
+ * \param mask event mask
+ * \param elem related mixer element (if any)
+ * \return 0 on success otherwise a negative error code
+ */
+typedef int (*snd_mixer_callback_t)(snd_mixer_t *ctl,
+ unsigned int mask,
+ snd_mixer_elem_t *elem);
+
+/**
+ * \brief Mixer element callback function
+ * \param elem Mixer element
+ * \param mask event mask
+ * \return 0 on success otherwise a negative error code
+ */
+typedef int (*snd_mixer_elem_callback_t)(snd_mixer_elem_t *elem,
+ unsigned int mask);
+
+/**
+ * \brief Compare function for sorting mixer elements
+ * \param e1 First element
+ * \param e2 Second element
+ * \return -1 if e1 < e2, 0 if e1 == e2, 1 if e1 > e2
+ */
+typedef int (*snd_mixer_compare_t)(const snd_mixer_elem_t *e1,
+ const snd_mixer_elem_t *e2);
+
+/** Mixer element type */
+typedef enum _snd_mixer_elem_type {
+ /* Simple mixer elements */
+ SND_MIXER_ELEM_SIMPLE,
+ SND_MIXER_ELEM_LAST = SND_MIXER_ELEM_SIMPLE
+} snd_mixer_elem_type_t;
+
+int snd_mixer_open(snd_mixer_t **mixer, int mode);
+int snd_mixer_close(snd_mixer_t *mixer);
+snd_mixer_elem_t *snd_mixer_first_elem(snd_mixer_t *mixer);
+snd_mixer_elem_t *snd_mixer_last_elem(snd_mixer_t *mixer);
+int snd_mixer_handle_events(snd_mixer_t *mixer);
+int snd_mixer_attach(snd_mixer_t *mixer, const char *name);
+int snd_mixer_attach_hctl(snd_mixer_t *mixer, snd_hctl_t *hctl);
+int snd_mixer_detach(snd_mixer_t *mixer, const char *name);
+int snd_mixer_detach_hctl(snd_mixer_t *mixer, snd_hctl_t *hctl);
+int snd_mixer_get_hctl(snd_mixer_t *mixer, const char *name, snd_hctl_t **hctl);
+int snd_mixer_poll_descriptors_count(snd_mixer_t *mixer);
+int snd_mixer_poll_descriptors(snd_mixer_t *mixer, struct pollfd *pfds, unsigned int space);
+int snd_mixer_poll_descriptors_revents(snd_mixer_t *mixer, struct pollfd *pfds, unsigned int nfds, unsigned short *revents);
+int snd_mixer_load(snd_mixer_t *mixer);
+void snd_mixer_free(snd_mixer_t *mixer);
+int snd_mixer_wait(snd_mixer_t *mixer, int timeout);
+int snd_mixer_set_compare(snd_mixer_t *mixer, snd_mixer_compare_t msort);
+void snd_mixer_set_callback(snd_mixer_t *obj, snd_mixer_callback_t val);
+void * snd_mixer_get_callback_private(const snd_mixer_t *obj);
+void snd_mixer_set_callback_private(snd_mixer_t *obj, void * val);
+unsigned int snd_mixer_get_count(const snd_mixer_t *obj);
+
+snd_mixer_elem_t *snd_mixer_elem_next(snd_mixer_elem_t *elem);
+snd_mixer_elem_t *snd_mixer_elem_prev(snd_mixer_elem_t *elem);
+void snd_mixer_elem_set_callback(snd_mixer_elem_t *obj, snd_mixer_elem_callback_t val);
+void * snd_mixer_elem_get_callback_private(const snd_mixer_elem_t *obj);
+void snd_mixer_elem_set_callback_private(snd_mixer_elem_t *obj, void * val);
+snd_mixer_elem_type_t snd_mixer_elem_get_type(const snd_mixer_elem_t *obj);
+
+/**
+ * \defgroup SimpleMixer Simple Mixer Interface
+ * \ingroup Mixer
+ * The simple mixer interface.
+ * \{
+ */
+
+/* Simple mixer elements API */
+
+/** Mixer simple element channel identifier */
+#define snd_mixer_selem_channel_id_t snd_amixer_elem_channel_id_t
+
+/** Mixer simple element - register options - abstraction level */
+enum snd_mixer_selem_regopt_abstract {
+ /** no abstraction - try use all universal controls from driver */
+ SND_MIXER_SABSTRACT_NONE = 0,
+ /** basic abstraction - Master,PCM,CD,Aux,Record-Gain etc. */
+ SND_MIXER_SABSTRACT_BASIC,
+};
+
+/** Mixer simple element - register options */
+struct snd_mixer_selem_regopt {
+ /** structure version */
+ int ver;
+ /** v1: abstract layer selection */
+ enum snd_mixer_selem_regopt_abstract abstract;
+ /** v1: device name (must be NULL when playback_pcm or capture_pcm != NULL) */
+ const char *device;
+ /** v1: playback PCM connected to mixer device (NULL == none) */
+ snd_pcm_t *playback_pcm;
+ /** v1: capture PCM connected to mixer device (NULL == none) */
+ snd_pcm_t *capture_pcm;
+};
+
+/** Mixer simple element identifier */
+#define snd_mixer_selem_id_t snd_amixer_elem_id_t
+
+const char *snd_mixer_selem_channel_name(snd_mixer_selem_channel_id_t channel);
+
+int snd_mixer_selem_register(snd_mixer_t *mixer,
+ struct snd_mixer_selem_regopt *options,
+ void **nothing);
+void snd_mixer_selem_get_id(snd_mixer_elem_t *element,
+ snd_mixer_selem_id_t *id);
+const char *snd_mixer_selem_get_name(snd_mixer_elem_t *elem);
+unsigned int snd_mixer_selem_get_index(snd_mixer_elem_t *elem);
+snd_mixer_elem_t *snd_mixer_find_selem(snd_mixer_t *mixer,
+ const snd_mixer_selem_id_t *id);
+
+int snd_mixer_selem_is_active(snd_mixer_elem_t *elem);
+int snd_mixer_selem_is_playback_mono(snd_mixer_elem_t *elem);
+int snd_mixer_selem_has_playback_channel(snd_mixer_elem_t *obj, snd_mixer_selem_channel_id_t channel);
+int snd_mixer_selem_is_capture_mono(snd_mixer_elem_t *elem);
+int snd_mixer_selem_has_capture_channel(snd_mixer_elem_t *obj, snd_mixer_selem_channel_id_t channel);
+int snd_mixer_selem_get_capture_group(snd_mixer_elem_t *elem);
+int snd_mixer_selem_has_common_volume(snd_mixer_elem_t *elem);
+int snd_mixer_selem_has_playback_volume(snd_mixer_elem_t *elem);
+int snd_mixer_selem_has_playback_volume_joined(snd_mixer_elem_t *elem);
+int snd_mixer_selem_has_capture_volume(snd_mixer_elem_t *elem);
+int snd_mixer_selem_has_capture_volume_joined(snd_mixer_elem_t *elem);
+int snd_mixer_selem_has_common_switch(snd_mixer_elem_t *elem);
+int snd_mixer_selem_has_playback_switch(snd_mixer_elem_t *elem);
+int snd_mixer_selem_has_playback_switch_joined(snd_mixer_elem_t *elem);
+int snd_mixer_selem_has_capture_switch(snd_mixer_elem_t *elem);
+int snd_mixer_selem_has_capture_switch_joined(snd_mixer_elem_t *elem);
+int snd_mixer_selem_has_capture_switch_exclusive(snd_mixer_elem_t *elem);
+
+int snd_mixer_selem_ask_playback_vol_dB(snd_mixer_elem_t *elem, long value, long *dBvalue);
+int snd_mixer_selem_ask_capture_vol_dB(snd_mixer_elem_t *elem, long value, long *dBvalue);
+int snd_mixer_selem_ask_playback_dB_vol(snd_mixer_elem_t *elem, long dBvalue, int dir, long *value);
+int snd_mixer_selem_ask_capture_dB_vol(snd_mixer_elem_t *elem, long dBvalue, int dir, long *value);
+int snd_mixer_selem_get_playback_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value);
+int snd_mixer_selem_get_capture_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value);
+int snd_mixer_selem_get_playback_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value);
+int snd_mixer_selem_get_capture_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value);
+int snd_mixer_selem_get_playback_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int *value);
+int snd_mixer_selem_get_capture_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int *value);
+int snd_mixer_selem_set_playback_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value);
+int snd_mixer_selem_set_capture_volume(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value);
+int snd_mixer_selem_set_playback_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value, int dir);
+int snd_mixer_selem_set_capture_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value, int dir);
+int snd_mixer_selem_set_playback_volume_all(snd_mixer_elem_t *elem, long value);
+int snd_mixer_selem_set_capture_volume_all(snd_mixer_elem_t *elem, long value);
+int snd_mixer_selem_set_playback_dB_all(snd_mixer_elem_t *elem, long value, int dir);
+int snd_mixer_selem_set_capture_dB_all(snd_mixer_elem_t *elem, long value, int dir);
+int snd_mixer_selem_set_playback_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int value);
+int snd_mixer_selem_set_capture_switch(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, int value);
+int snd_mixer_selem_set_playback_switch_all(snd_mixer_elem_t *elem, int value);
+int snd_mixer_selem_set_capture_switch_all(snd_mixer_elem_t *elem, int value);
+int snd_mixer_selem_get_playback_volume_range(snd_mixer_elem_t *elem,
+ long *min, long *max);
+int snd_mixer_selem_get_playback_dB_range(snd_mixer_elem_t *elem,
+ long *min, long *max);
+int snd_mixer_selem_set_playback_volume_range(snd_mixer_elem_t *elem,
+ long min, long max);
+int snd_mixer_selem_get_capture_volume_range(snd_mixer_elem_t *elem,
+ long *min, long *max);
+int snd_mixer_selem_get_capture_dB_range(snd_mixer_elem_t *elem,
+ long *min, long *max);
+int snd_mixer_selem_set_capture_volume_range(snd_mixer_elem_t *elem,
+ long min, long max);
+
+int snd_mixer_selem_is_enumerated(snd_mixer_elem_t *elem);
+int snd_mixer_selem_is_enum_playback(snd_mixer_elem_t *elem);
+int snd_mixer_selem_is_enum_capture(snd_mixer_elem_t *elem);
+int snd_mixer_selem_get_enum_items(snd_mixer_elem_t *elem);
+int snd_mixer_selem_get_enum_item_name(snd_mixer_elem_t *elem, unsigned int idx, size_t maxlen, char *str);
+int snd_mixer_selem_get_enum_item(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, unsigned int *idxp);
+int snd_mixer_selem_set_enum_item(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, unsigned int idx);
+
+size_t snd_mixer_selem_id_sizeof(void);
+/** \hideinitializer
+ * \brief allocate an invalid #snd_mixer_selem_id_t using standard alloca
+ * \param ptr returned pointer
+ */
+#define snd_mixer_selem_id_alloca(ptr) __snd_alloca(ptr, snd_mixer_selem_id)
+int snd_mixer_selem_id_malloc(snd_mixer_selem_id_t **ptr);
+void snd_mixer_selem_id_free(snd_mixer_selem_id_t *obj);
+void snd_mixer_selem_id_copy(snd_mixer_selem_id_t *dst, const snd_mixer_selem_id_t *src);
+const char *snd_mixer_selem_id_get_name(const snd_mixer_selem_id_t *obj);
+unsigned int snd_mixer_selem_id_get_index(const snd_mixer_selem_id_t *obj);
+void snd_mixer_selem_id_set_name(snd_mixer_selem_id_t *obj, const char *val);
+void snd_mixer_selem_id_set_index(snd_mixer_selem_id_t *obj, unsigned int val);
+
+/** \} */
+
+/** \} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ALSA_MIXER_OLD_H */
diff --git a/modules/mixer/Makefile.am b/modules/mixer/Makefile.am
index 9f5917fe..61272edf 100644
--- a/modules/mixer/Makefile.am
+++ b/modules/mixer/Makefile.am
@@ -1 +1 @@
-SUBDIRS=simple
+#SUBDIRS=simple
diff --git a/modules/mixer/simple/sbase.c b/modules/mixer/simple/sbase.c
index 97feee89..1aab535a 100644
--- a/modules/mixer/simple/sbase.c
+++ b/modules/mixer/simple/sbase.c
@@ -34,7 +34,7 @@
* Prototypes
*/
-static int selem_read(snd_mixer_elem_t *elem);
+static int selem_read(snd_amixer_elem_t *elem);
/*
* Helpers
@@ -313,11 +313,11 @@ static void selem_free(snd_mixer_elem_t *elem)
free(simple);
}
-static int simple_event_add1(snd_mixer_class_t *class,
+static int simple_event_add1(snd_amixer_t *amixer,
snd_hctl_elem_t *helem,
struct helem_selector *sel)
{
- struct bclass_private *priv = snd_mixer_sbasic_get_private(class);
+ struct bmixer_private *priv = snd_amixer_sbasic_get_private(class);
snd_mixer_elem_t *melem;
snd_mixer_selem_id_t *id;
snd_ctl_elem_info_t *info;
@@ -328,12 +328,12 @@ static int simple_event_add1(snd_mixer_class_t *class,
long min, max;
int err, new = 0;
struct list_head *pos;
- struct bclass_sid *bsid;
+ struct bmixer_sid *bsid;
struct melem_sids *sid;
unsigned int ui;
list_for_each(pos, &priv->sids) {
- bsid = list_entry(pos, struct bclass_sid, list);
+ bsid = list_entry(pos, struct bmixer_sid, list);
for (ui = 0; ui < bsid->count; ui++) {
if (bsid->sids[ui].sid == sel->sid) {
sid = &bsid->sids[ui];
@@ -391,7 +391,7 @@ static int simple_event_add1(snd_mixer_class_t *class,
hsimple->max = max;
snd_mixer_selem_id_set_name(id, sid->sname);
snd_mixer_selem_id_set_index(id, sid->sindex);
- melem = snd_mixer_find_selem(snd_mixer_class_get_mixer(class), id);
+ melem = snd_mixer_find_selem(amixer, id);
if (!melem) {
simple = calloc(1, sizeof(*simple));
if (!simple) {
@@ -435,7 +435,7 @@ static int simple_event_add1(snd_mixer_class_t *class,
}
#endif
if (new)
- err = snd_mixer_elem_add(melem, class);
+ err = snd_mixer_elem_add(melem, amixer);
else
err = snd_mixer_elem_info(melem);
if (err < 0)
@@ -452,10 +452,10 @@ static int simple_event_add1(snd_mixer_class_t *class,
return -EINVAL;
}
-static int simple_event_add(snd_mixer_class_t *class, snd_hctl_elem_t *helem)
+static int simple_event_add(snd__amixer_t *amixer, snd_hctl_elem_t *helem)
{
- struct bclass_private *priv = snd_mixer_sbasic_get_private(class);
- struct bclass_selector *sel;
+ struct bmixer_private *priv = snd_mixer_sbasic_get_private(amixer);
+ struct bmixer_selector *sel;
struct helem_selector *hsel;
struct list_head *pos;
snd_ctl_elem_iface_t iface = snd_hctl_elem_get_interface(helem);
@@ -465,11 +465,11 @@ static int simple_event_add(snd_mixer_class_t *class, snd_hctl_elem_t *helem)
int err;
list_for_each(pos, &priv->selectors) {
- sel = list_entry(pos, struct bclass_selector, list);
+ sel = list_entry(pos, struct bmixer_selector, list);
for (ui = 0; ui < sel->count; ui++) {
hsel = &sel->selectors[ui];
if (hsel->iface == iface && !strcmp(hsel->name, name) && hsel->index == index) {
- err = simple_event_add1(class, helem, hsel);
+ err = simple_event_add1(amixer, helem, hsel);
if (err < 0)
return err; /* early exit? */
}
@@ -478,14 +478,14 @@ static int simple_event_add(snd_mixer_class_t *class, snd_hctl_elem_t *helem)
return 0;
}
-int alsa_mixer_sbasic_event(snd_mixer_class_t *class, unsigned int mask,
+int alsa_mixer_sbasic_event(snd_amixer_t *amixer, unsigned int mask,
snd_hctl_elem_t *helem, snd_mixer_elem_t *melem)
{
int err;
if (mask == SND_CTL_EVENT_MASK_REMOVE)
return simple_event_remove(helem, melem);
if (mask & SND_CTL_EVENT_MASK_ADD) {
- err = simple_event_add(class, helem);
+ err = simple_event_add(amixer, helem);
if (err < 0)
return err;
}
@@ -493,7 +493,7 @@ int alsa_mixer_sbasic_event(snd_mixer_class_t *class, unsigned int mask,
err = simple_event_remove(helem, melem);
if (err < 0)
return err;
- err = simple_event_add(class, helem);
+ err = simple_event_add(amixer, helem);
if (err < 0)
return err;
return 0;
@@ -511,39 +511,39 @@ int alsa_mixer_sbasic_event(snd_mixer_class_t *class, unsigned int mask,
return 0;
}
-static void sbasic_cpriv_free(snd_mixer_class_t *class)
+static void sbasic_cpriv_free(snd_amixer_t *amixer)
{
- struct bclass_private *priv = snd_mixer_sbasic_get_private(class);
- struct bclass_selector *sel;
- struct bclass_sid *sid;
+ struct bmixer_private *priv = snd_amixer_sbasic_get_private(amixer);
+ struct bmixer_selector *sel;
+ struct bmixer_sid *sid;
struct list_head *pos, *pos1;
list_for_each_safe(pos, pos1, &priv->selectors) {
- sel = list_entry(pos, struct bclass_selector, list);
+ sel = list_entry(pos, struct bmixer_selector, list);
free(sel);
}
list_for_each_safe(pos, pos1, &priv->sids) {
- sid = list_entry(pos, struct bclass_sid, list);
+ sid = list_entry(pos, struct bmixer_sid, list);
free(sid);
}
free(priv);
}
-void alsa_mixer_sbasic_initpriv(snd_mixer_class_t *class,
- struct bclass_private *priv)
+void alsa_mixer_sbasic_initpriv(snd_amixer_t *amixer,
+ struct bmixer_private *priv)
{
INIT_LIST_HEAD(&priv->selectors);
INIT_LIST_HEAD(&priv->sids);
- snd_mixer_sbasic_set_private(class, priv);
- snd_mixer_sbasic_set_private_free(class, sbasic_cpriv_free);
+ snd_mixer_sbasic_set_private(amixer, priv);
+ snd_mixer_sbasic_set_private_free(amixer, sbasic_cpriv_free);
}
-int alsa_mixer_sbasic_selreg(snd_mixer_class_t *class,
+int alsa_mixer_sbasic_selreg(snd_amixer_t *amixer,
struct helem_selector *selectors,
unsigned int count)
{
- struct bclass_private *priv = snd_mixer_sbasic_get_private(class);
- struct bclass_selector *sel = calloc(1, sizeof(*sel));
+ struct bmixer_private *priv = snd_mixer_sbasic_get_private(amixer);
+ struct bmixer_selector *sel = calloc(1, sizeof(*sel));
if (sel == NULL)
return -ENOMEM;
@@ -560,12 +560,12 @@ int alsa_mixer_sbasic_selreg(snd_mixer_class_t *class,
return 0;
}
-int alsa_mixer_sbasic_sidreg(snd_mixer_class_t *class,
+int alsa_mixer_sbasic_sidreg(snd_amixer_t *amixer,
struct melem_sids *sids,
unsigned int count)
{
- struct bclass_private *priv = snd_mixer_sbasic_get_private(class);
- struct bclass_sid *sid = calloc(1, sizeof(*sid));
+ struct bmixer_private *priv = snd_mixer_sbasic_get_private(amixer);
+ struct bmixer_sid *sid = calloc(1, sizeof(*sid));
if (sid == NULL)
return -ENOMEM;
@@ -577,8 +577,8 @@ int alsa_mixer_sbasic_sidreg(snd_mixer_class_t *class,
}
INIT_LIST_HEAD(&priv->selectors);
INIT_LIST_HEAD(&priv->sids);
- snd_mixer_sbasic_set_private(class, priv);
- snd_mixer_sbasic_set_private_free(class, sbasic_cpriv_free);
+ snd_mixer_sbasic_set_private(amixer, priv);
+ snd_mixer_sbasic_set_private_free(amixer, sbasic_cpriv_free);
}
sid->sids = sids;
sid->count = count;
diff --git a/modules/mixer/simple/sbase.h b/modules/mixer/simple/sbase.h
index ee5fe03c..7feedc58 100644
--- a/modules/mixer/simple/sbase.h
+++ b/modules/mixer/simple/sbase.h
@@ -55,7 +55,7 @@ struct helem_selector {
struct helem_base {
struct list_head list;
- snd_hctl_elem_t *helem;
+ snd_ctl_elem_t *helem;
unsigned short purpose;
unsigned int caps;
unsigned int inactive: 1;
@@ -64,7 +64,6 @@ struct helem_base {
};
struct selem_base {
- sm_selem_t selem;
struct list_head helems;
unsigned short sid;
struct {
@@ -75,37 +74,37 @@ struct selem_base {
} dir[2];
};
-struct bclass_selector {
+struct bmixer_selector {
struct list_head list;
struct helem_selector *selectors;
unsigned int count;
};
-struct bclass_sid {
+struct bmixer_sid {
struct list_head list;
struct melem_sids *sids;
unsigned int count;
};
-typedef struct bclass_base_ops {
- int (*event)(snd_mixer_class_t *class, unsigned int mask,
- snd_hctl_elem_t *helem, snd_mixer_elem_t *melem);
- int (*selreg)(snd_mixer_class_t *class,
+typedef struct bmixer_base_ops {
+ int (*event)(snd_amixer_t *amixer, unsigned int mask,
+ snd_ctl_elem_t *helem, snd_amixer_elem_t *melem);
+ int (*selreg)(snd_amixer_t *amixer,
struct helem_selector *selectors,
unsigned int count);
- int (*sidreg)(snd_mixer_class_t *class,
+ int (*sidreg)(snd_amixer_t *amixer,
struct melem_sids *sids,
unsigned int count);
-} bclass_base_ops_t;
+} bmixer_base_ops_t;
-struct bclass_private {
+struct bmixer_private {
struct list_head selectors;
struct list_head sids;
void *dl_sbase;
- bclass_base_ops_t ops;
+ bmixer_base_ops_t ops;
};
-int mixer_simple_basic_dlopen(snd_mixer_class_t *class,
- bclass_base_ops_t **ops);
+int mixer_simple_basic_dlopen(snd_amixer_t *amixer,
+ bmixer_base_ops_t **ops);
#endif /* __SMIXER_BASE_H */
diff --git a/modules/mixer/simple/sbasedl.c b/modules/mixer/simple/sbasedl.c
index 0137586a..d03ca3ef 100644
--- a/modules/mixer/simple/sbasedl.c
+++ b/modules/mixer/simple/sbasedl.c
@@ -1,6 +1,6 @@
/*
* Mixer Interface - simple abstact module - base library (dlopen function)
- * Copyright (c) 2005 by Jaroslav Kysela <perex@perex.cz>
+ * Copyright (c) 2005-2008 by Jaroslav Kysela <perex@perex.cz>
*
*
* This library is free software; you can redistribute it and/or modify
diff --git a/src/Makefile.am b/src/Makefile.am
index 3204fe46..d3e3a714 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -39,8 +39,8 @@ SUBDIRS += seq
libasound_la_LIBADD += seq/libseq.la
endif
if BUILD_ALISP
-SUBDIRS += alisp
-libasound_la_LIBADD += alisp/libalisp.la
+#SUBDIRS += alisp
+#libasound_la_LIBADD += alisp/libalisp.la
endif
SUBDIRS += compat conf
libasound_la_LIBADD += compat/libcompat.la @ALSA_DEPLIBS@
diff --git a/src/conf/alsa.conf b/src/conf/alsa.conf
index db642597..8d0d4a29 100644
--- a/src/conf/alsa.conf
+++ b/src/conf/alsa.conf
@@ -98,6 +98,7 @@ defaults.pcm.modem.device defaults.pcm.device
# truncate files via file or tee PCM
defaults.pcm.file_format "raw"
defaults.pcm.file_truncate true
+defaults.amixer.card 0
defaults.rawmidi.card 0
defaults.rawmidi.device 0
defaults.rawmidi.subdevice -1
@@ -368,6 +369,30 @@ ctl.shm {
}
#
+# Mixer interface
+#
+
+amixer.default {
+ type none
+ @args [ CARD ]
+ @args.CARD {
+ type string
+ default {
+ @func getenv
+ vars [
+ ALSA_AMIXER_CARD
+ ALSA_CARD
+ ]
+ default {
+ @func refer
+ name defaults.amixer.card
+ }
+ }
+ }
+ card $CARD
+}
+
+#
# RawMidi interface
#
diff --git a/src/control/Makefile.am b/src/control/Makefile.am
index d4c50c01..eaf6f917 100644
--- a/src/control/Makefile.am
+++ b/src/control/Makefile.am
@@ -1,7 +1,8 @@
EXTRA_LTLIBRARIES = libcontrol.la
libcontrol_la_SOURCES = cards.c tlv.c namehint.c hcontrol.c \
- control.c control_hw.c setup.c control_symbols.c
+ control.c control_hw.c hcontrol_old.c \
+ setup.c control_symbols.c
if BUILD_CTL_PLUGIN_SHM
libcontrol_la_SOURCES += control_shm.c
endif
diff --git a/src/control/control.c b/src/control/control.c
index c0907973..0537ad2a 100644
--- a/src/control/control.c
+++ b/src/control/control.c
@@ -88,6 +88,8 @@ snd_ctl_type_t snd_ctl_type(snd_ctl_t *ctl)
int snd_ctl_close(snd_ctl_t *ctl)
{
int err;
+
+ snd_ctl_cache_free(ctl);
while (!list_empty(&ctl->async_handlers)) {
snd_async_handler_t *h = list_entry(&ctl->async_handlers.next, snd_async_handler_t, hlist);
snd_async_del_handler(h);
@@ -118,16 +120,18 @@ int snd_ctl_nonblock(snd_ctl_t *ctl, int nonblock)
}
#ifndef DOC_HIDDEN
-int snd_ctl_new(snd_ctl_t **ctlp, snd_ctl_type_t type, const char *name)
+int snd_ctl_new(snd_ctl_t **ctlp, snd_ctl_type_t type, const char *name, int mode)
{
snd_ctl_t *ctl;
ctl = calloc(1, sizeof(*ctl));
if (!ctl)
return -ENOMEM;
ctl->type = type;
+ ctl->mode = mode;
if (name)
ctl->name = strdup(name);
INIT_LIST_HEAD(&ctl->async_handlers);
+ INIT_LIST_HEAD(&ctl->elems);
*ctlp = ctl;
return 0;
}
@@ -218,7 +222,14 @@ int snd_ctl_poll_descriptors_revents(snd_ctl_t *ctl, struct pollfd *pfds, unsign
*/
int snd_ctl_subscribe_events(snd_ctl_t *ctl, int subscribe)
{
+ int err;
+
assert(ctl);
+ if (ctl->mode & SND_CTL_CACHE) {
+ err = snd_ctl_cache_load(ctl);
+ if (err < 0)
+ return err;
+ }
return ctl->ops->subscribe_events(ctl, subscribe);
}
diff --git a/src/control/control_ext.c b/src/control/control_ext.c
index d1fe8eaa..1f46f6ee 100644
--- a/src/control/control_ext.c
+++ b/src/control/control_ext.c
@@ -665,7 +665,7 @@ int snd_ctl_ext_create(snd_ctl_ext_t *ext, const char *name, int mode)
return -ENXIO;
}
- err = snd_ctl_new(&ctl, SND_CTL_TYPE_EXT, name);
+ err = snd_ctl_new(&ctl, SND_CTL_TYPE_EXT, name, mode);
if (err < 0)
return err;
diff --git a/src/control/control_hw.c b/src/control/control_hw.c
index e9a6be27..c33d8ca9 100644
--- a/src/control/control_hw.c
+++ b/src/control/control_hw.c
@@ -421,7 +421,7 @@ int snd_ctl_hw_open(snd_ctl_t **handle, const char *name, int card, int mode)
hw->fd = fd;
hw->protocol = ver;
- err = snd_ctl_new(&ctl, SND_CTL_TYPE_HW, name);
+ err = snd_ctl_new(&ctl, SND_CTL_TYPE_HW, name, mode);
if (err < 0) {
close(fd);
free(hw);
diff --git a/src/control/control_local.h b/src/control/control_local.h
index fd9f9418..b7518397 100644
--- a/src/control/control_local.h
+++ b/src/control/control_local.h
@@ -59,42 +59,44 @@ struct _snd_ctl {
void *dl_handle;
char *name;
snd_ctl_type_t type;
+ int mode;
const snd_ctl_ops_t *ops;
void *private_data;
int nonblock;
int poll_fd;
struct list_head async_handlers;
+ struct list_head elems; /* list of all controls */
+ unsigned int alloc;
+ unsigned int count;
+ snd_ctl_elem_t **pelems;
+ snd_ctl_compare_t compare;
+ snd_ctl_callback_t callback;
+ void *callback_private;
};
-struct _snd_hctl_elem {
+struct _snd_ctl_elem {
snd_ctl_elem_id_t id; /* must be always on top */
struct list_head list; /* links for list of all helems */
int compare_weight; /* compare weight (reversed) */
/* event callback */
- snd_hctl_elem_callback_t callback;
+ snd_ctl_elem_callback_t callback;
void *callback_private;
/* links */
- snd_hctl_t *hctl; /* associated handle */
-};
-
-struct _snd_hctl {
- snd_ctl_t *ctl;
- struct list_head elems; /* list of all controls */
- unsigned int alloc;
- unsigned int count;
- snd_hctl_elem_t **pelems;
- snd_hctl_compare_t compare;
- snd_hctl_callback_t callback;
- void *callback_private;
+ snd_ctl_t *ctl; /* associated handle */
};
/* make local functions really local */
-#define snd_ctl_new snd1_ctl_new
+#define snd_ctl_new snd1_ctl_new
+#define snd_ctl_cache_load snd1_ctl_cache_load
+#define snd_ctl_cache_free snd1_ctl_cache_free
-int snd_ctl_new(snd_ctl_t **ctlp, snd_ctl_type_t type, const char *name);
+int snd_ctl_new(snd_ctl_t **ctlp, snd_ctl_type_t type, const char *name, int mode);
int _snd_ctl_poll_descriptor(snd_ctl_t *ctl);
#define _snd_ctl_async_descriptor _snd_ctl_poll_descriptor
int snd_ctl_hw_open(snd_ctl_t **handle, const char *name, int card, int mode);
int snd_ctl_shm_open(snd_ctl_t **handlep, const char *name, const char *sockname, const char *sname, int mode);
int snd_ctl_async(snd_ctl_t *ctl, int sig, pid_t pid);
+
+int snd_ctl_cache_load(snd_ctl_t *ctl);
+int snd_ctl_cache_free(snd_ctl_t *ctl);
diff --git a/src/control/control_shm.c b/src/control/control_shm.c
index abab3983..721ee69e 100644
--- a/src/control/control_shm.c
+++ b/src/control/control_shm.c
@@ -535,7 +535,7 @@ int snd_ctl_shm_open(snd_ctl_t **handlep, const char *name, const char *sockname
shm->socket = sock;
shm->ctrl = ctrl;
- err = snd_ctl_new(&ctl, SND_CTL_TYPE_SHM, name);
+ err = snd_ctl_new(&ctl, SND_CTL_TYPE_SHM, name, mode);
if (err < 0) {
result = err;
goto _err;
@@ -548,6 +548,13 @@ int snd_ctl_shm_open(snd_ctl_t **handlep, const char *name, const char *sockname
return err;
}
ctl->poll_fd = err;
+ if (mode & SND_CTL_CACHE) {
+ err = snd_ctl_cache_load(ctl);
+ if (err < 0) {
+ snd_ctl_close(ctl);
+ return err;
+ }
+ }
*handlep = ctl;
return 0;
diff --git a/src/control/hcontrol.c b/src/control/hcontrol.c
index 181e7672..7128616d 100644
--- a/src/control/hcontrol.c
+++ b/src/control/hcontrol.c
@@ -1,11 +1,11 @@
/**
* \file control/hcontrol.c
- * \brief HCTL Interface - High Level CTL
+ * \brief CTL Interface - High Level Cached Control Elements
* \author Jaroslav Kysela <perex@perex.cz>
* \author Abramo Bagnara <abramo@alsa-project.org>
* \date 2000
*
- * HCTL interface is designed to access preloaded and sorted primitive controls.
+ * CTL interface is designed to access preloaded and sorted primitive controls.
* Callbacks may be used for event handling.
* See \ref hcontrol page for more details.
*/
@@ -31,7 +31,7 @@
*
*/
-/*! \page hcontrol High level control interface
+/*! \page hcontrol High level cached control interface
<P> High level control interface is designed to access preloaded and sorted primitive controls.
@@ -60,164 +60,26 @@ to reduce overhead accessing the real controls in kernel drivers.
#define NOT_FOUND 1000000000
#endif
-static int snd_hctl_compare_default(const snd_hctl_elem_t *c1,
- const snd_hctl_elem_t *c2);
+static int snd_ctl_compare_default(const snd_ctl_elem_t *c1,
+ const snd_ctl_elem_t *c2);
-/**
- * \brief Opens an HCTL
- * \param hctlp Returned HCTL handle
- * \param name ASCII identifier of the underlying CTL handle
- * \param mode Open mode (see #SND_CTL_NONBLOCK, #SND_CTL_ASYNC)
- * \return 0 on success otherwise a negative error code
- */
-int snd_hctl_open(snd_hctl_t **hctlp, const char *name, int mode)
-{
- snd_ctl_t *ctl;
- int err;
-
- if ((err = snd_ctl_open(&ctl, name, mode)) < 0)
- return err;
- err = snd_hctl_open_ctl(hctlp, ctl);
- if (err < 0)
- snd_ctl_close(ctl);
- return err;
-}
-
-/**
- * \brief Opens an HCTL
- * \param hctlp Returned HCTL handle
- * \param ctl underlying CTL handle
- * \return 0 on success otherwise a negative error code
- */
-int snd_hctl_open_ctl(snd_hctl_t **hctlp, snd_ctl_t *ctl)
-{
- snd_hctl_t *hctl;
-
- assert(hctlp);
- *hctlp = NULL;
- if ((hctl = (snd_hctl_t *)calloc(1, sizeof(snd_hctl_t))) == NULL)
- return -ENOMEM;
- INIT_LIST_HEAD(&hctl->elems);
- hctl->ctl = ctl;
- *hctlp = hctl;
- return 0;
-}
-
-/**
- * \brief close HCTL handle
- * \param hctl HCTL handle
- * \return 0 on success otherwise a negative error code
- *
- * Closes the specified HCTL handle and frees all associated
- * resources.
- */
-int snd_hctl_close(snd_hctl_t *hctl)
-{
- int err;
-
- assert(hctl);
- err = snd_ctl_close(hctl->ctl);
- snd_hctl_free(hctl);
- free(hctl);
- return err;
-}
-
-/**
- * \brief get identifier of HCTL handle
- * \param hctl HCTL handle
- * \return ascii identifier of HCTL handle
- *
- * Returns the ASCII identifier of given HCTL handle. It's the same
- * identifier specified in snd_hctl_open().
- */
-const char *snd_hctl_name(snd_hctl_t *hctl)
-{
- assert(hctl);
- return snd_ctl_name(hctl->ctl);
-}
-
-/**
- * \brief set nonblock mode
- * \param hctl HCTL handle
- * \param nonblock 0 = block, 1 = nonblock mode
- * \return 0 on success otherwise a negative error code
- */
-int snd_hctl_nonblock(snd_hctl_t *hctl, int nonblock)
-{
- assert(hctl);
- return snd_ctl_nonblock(hctl->ctl, nonblock);
-}
-
-/**
- * \brief set async mode
- * \param hctl HCTL handle
- * \param sig Signal to raise: < 0 disable, 0 default (SIGIO)
- * \param pid Process ID to signal: 0 current
- * \return 0 on success otherwise a negative error code
- *
- * A signal is raised when a change happens.
- */
-int snd_hctl_async(snd_hctl_t *hctl, int sig, pid_t pid)
-{
- assert(hctl);
- return snd_ctl_async(hctl->ctl, sig, pid);
-}
-
-/**
- * \brief get count of poll descriptors for HCTL handle
- * \param hctl HCTL handle
- * \return count of poll descriptors
- */
-int snd_hctl_poll_descriptors_count(snd_hctl_t *hctl)
-{
- assert(hctl);
- return snd_ctl_poll_descriptors_count(hctl->ctl);
-}
-
-/**
- * \brief get poll descriptors
- * \param hctl HCTL handle
- * \param pfds array of poll descriptors
- * \param space space in the poll descriptor array
- * \return count of filled descriptors
- */
-int snd_hctl_poll_descriptors(snd_hctl_t *hctl, struct pollfd *pfds, unsigned int space)
-{
- assert(hctl);
- return snd_ctl_poll_descriptors(hctl->ctl, pfds, space);
-}
-
-/**
- * \brief get returned events from poll descriptors
- * \param hctl HCTL handle
- * \param pfds array of poll descriptors
- * \param nfds count of poll descriptors
- * \param revents returned events
- * \return zero if success, otherwise a negative error code
- */
-int snd_hctl_poll_descriptors_revents(snd_hctl_t *hctl, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
+static int snd_ctl_throw_event(snd_ctl_t *ctl, unsigned int mask,
+ snd_ctl_elem_t *elem)
{
- assert(hctl);
- return snd_ctl_poll_descriptors_revents(hctl->ctl, pfds, nfds, revents);
-}
-
-static int snd_hctl_throw_event(snd_hctl_t *hctl, unsigned int mask,
- snd_hctl_elem_t *elem)
-{
- if (hctl->callback)
- return hctl->callback(hctl, mask, elem);
+ if (ctl->callback)
+ return ctl->callback(ctl, mask, elem);
return 0;
}
-static int snd_hctl_elem_throw_event(snd_hctl_elem_t *elem,
- unsigned int mask)
+static int snd_ctl_elem_throw_event(snd_ctl_elem_t *elem,
+ unsigned int mask)
{
if (elem->callback)
return elem->callback(elem, mask);
return 0;
}
-static int snd_hctl_compare_mixer_priority_lookup(const char **name, const char * const *names, int coef)
+static int snd_ctl_compare_mixer_priority_lookup(const char **name, const char * const *names, int coef)
{
int res;
@@ -298,7 +160,7 @@ static int get_compare_weight(const snd_ctl_elem_id_t *id)
const char *name = (char *)id->name, *name1;
int res, res1;
- if ((res = snd_hctl_compare_mixer_priority_lookup((const char **)&name, names, 1000000)) == NOT_FOUND)
+ if ((res = snd_ctl_compare_mixer_priority_lookup((const char **)&name, names, 1000000)) == NOT_FOUND)
return NOT_FOUND;
if (*name == '\0')
return res;
@@ -309,32 +171,32 @@ static int get_compare_weight(const snd_ctl_elem_id_t *id)
if (name1 != name) {
for (; name1 != name && *name1 != ' '; name1--);
name = name1;
- if ((res1 = snd_hctl_compare_mixer_priority_lookup((const char **)&name, names1, 1000)) == NOT_FOUND)
+ if ((res1 = snd_ctl_compare_mixer_priority_lookup((const char **)&name, names1, 1000)) == NOT_FOUND)
return res;
res += res1;
} else {
name = name1;
}
- if ((res1 = snd_hctl_compare_mixer_priority_lookup((const char **)&name, names2, 1)) == NOT_FOUND)
+ if ((res1 = snd_ctl_compare_mixer_priority_lookup((const char **)&name, names2, 1)) == NOT_FOUND)
return res;
return res + res1;
}
-static int _snd_hctl_find_elem(snd_hctl_t *hctl, const snd_ctl_elem_id_t *id, int *dir)
+static int _snd_ctl_find_elem(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id, int *dir)
{
unsigned int l, u;
- snd_hctl_elem_t el;
+ snd_ctl_elem_t el;
int c = 0;
int idx = -1;
- assert(hctl && id);
- assert(hctl->compare);
+ assert(ctl && id);
+ assert(ctl->compare);
el.id = *id;
el.compare_weight = get_compare_weight(id);
l = 0;
- u = hctl->count;
+ u = ctl->count;
while (l < u) {
idx = (l + u) / 2;
- c = hctl->compare(&el, hctl->pelems[idx]);
+ c = ctl->compare(&el, ctl->pelems[idx]);
if (c < 0)
u = idx;
else if (c > 0)
@@ -346,130 +208,133 @@ static int _snd_hctl_find_elem(snd_hctl_t *hctl, const snd_ctl_elem_id_t *id, in
return idx;
}
-static int snd_hctl_elem_add(snd_hctl_t *hctl, snd_hctl_elem_t *elem)
+static int snd_ctl_elem_add(snd_ctl_t *ctl, snd_ctl_elem_t *elem)
{
int dir;
int idx;
elem->compare_weight = get_compare_weight(&elem->id);
- if (hctl->count == hctl->alloc) {
- snd_hctl_elem_t **h;
- hctl->alloc += 32;
- h = realloc(hctl->pelems, sizeof(*h) * hctl->alloc);
+ if (ctl->count == ctl->alloc) {
+ snd_ctl_elem_t **h;
+ ctl->alloc += 32;
+ h = realloc(ctl->pelems, sizeof(*h) * ctl->alloc);
if (!h) {
- hctl->alloc -= 32;
+ ctl->alloc -= 32;
return -ENOMEM;
}
- hctl->pelems = h;
+ ctl->pelems = h;
}
- if (hctl->count == 0) {
- list_add_tail(&elem->list, &hctl->elems);
- hctl->pelems[0] = elem;
+ if (ctl->count == 0) {
+ list_add_tail(&elem->list, &ctl->elems);
+ ctl->pelems[0] = elem;
} else {
- idx = _snd_hctl_find_elem(hctl, &elem->id, &dir);
+ idx = _snd_ctl_find_elem(ctl, &elem->id, &dir);
assert(dir != 0);
if (dir > 0) {
- list_add(&elem->list, &hctl->pelems[idx]->list);
+ list_add(&elem->list, &ctl->pelems[idx]->list);
idx++;
} else {
- list_add_tail(&elem->list, &hctl->pelems[idx]->list);
+ list_add_tail(&elem->list, &ctl->pelems[idx]->list);
}
- memmove(hctl->pelems + idx + 1,
- hctl->pelems + idx,
- (hctl->count - idx) * sizeof(snd_hctl_elem_t *));
- hctl->pelems[idx] = elem;
+ memmove(ctl->pelems + idx + 1,
+ ctl->pelems + idx,
+ (ctl->count - idx) * sizeof(snd_ctl_elem_t *));
+ ctl->pelems[idx] = elem;
}
- hctl->count++;
- return snd_hctl_throw_event(hctl, SNDRV_CTL_EVENT_MASK_ADD, elem);
+ ctl->count++;
+ return snd_ctl_throw_event(ctl, SNDRV_CTL_EVENT_MASK_ADD, elem);
}
-static void snd_hctl_elem_remove(snd_hctl_t *hctl, unsigned int idx)
+static void snd_ctl_celem_remove(snd_ctl_t *ctl, unsigned int idx)
{
- snd_hctl_elem_t *elem = hctl->pelems[idx];
+ snd_ctl_elem_t *elem = ctl->pelems[idx];
unsigned int m;
- snd_hctl_elem_throw_event(elem, SNDRV_CTL_EVENT_MASK_REMOVE);
+ snd_ctl_elem_throw_event(elem, SNDRV_CTL_EVENT_MASK_REMOVE);
list_del(&elem->list);
free(elem);
- hctl->count--;
- m = hctl->count - idx;
+ ctl->count--;
+ m = ctl->count - idx;
if (m > 0)
- memmove(hctl->pelems + idx,
- hctl->pelems + idx + 1,
- m * sizeof(snd_hctl_elem_t *));
+ memmove(ctl->pelems + idx,
+ ctl->pelems + idx + 1,
+ m * sizeof(snd_ctl_elem_t *));
}
+#ifndef DOC_HIDDEN
/**
- * \brief free HCTL loaded elements
- * \param hctl HCTL handle
+ * \brief free cached elements
+ * \param ctl CTL handle
* \return 0 on success otherwise a negative error code
*/
-int snd_hctl_free(snd_hctl_t *hctl)
+int snd_ctl_cache_free(snd_ctl_t *ctl)
{
- while (hctl->count > 0)
- snd_hctl_elem_remove(hctl, hctl->count - 1);
- free(hctl->pelems);
- hctl->pelems = 0;
- hctl->alloc = 0;
- INIT_LIST_HEAD(&hctl->elems);
+ while (ctl->count > 0)
+ snd_ctl_celem_remove(ctl, ctl->count - 1);
+ if (ctl->pelems)
+ free(ctl->pelems);
+ ctl->pelems = 0;
+ ctl->alloc = 0;
+ INIT_LIST_HEAD(&ctl->elems);
return 0;
}
+#endif
-static snd_hctl_t *compare_hctl;
-static int hctl_compare(const void *a, const void *b) {
- return compare_hctl->compare(*(const snd_hctl_elem_t * const *) a,
- *(const snd_hctl_elem_t * const *) b);
+static snd_ctl_t *compare_ctl;
+static int ctl_compare(const void *a, const void *b) {
+ return compare_ctl->compare(*(const snd_ctl_elem_t * const *) a,
+ *(const snd_ctl_elem_t * const *) b);
}
-static void snd_hctl_sort(snd_hctl_t *hctl)
+static void snd_ctl_sort(snd_ctl_t *ctl)
{
unsigned int k;
#ifdef HAVE_LIBPTHREAD
static pthread_mutex_t sync_lock = PTHREAD_MUTEX_INITIALIZER;
#endif
- assert(hctl);
- assert(hctl->compare);
- INIT_LIST_HEAD(&hctl->elems);
+ assert(ctl);
+ assert(ctl->compare);
+ INIT_LIST_HEAD(&ctl->elems);
#ifdef HAVE_LIBPTHREAD
pthread_mutex_lock(&sync_lock);
#endif
- compare_hctl = hctl;
- qsort(hctl->pelems, hctl->count, sizeof(*hctl->pelems), hctl_compare);
+ compare_ctl = ctl;
+ qsort(ctl->pelems, ctl->count, sizeof(*ctl->pelems), ctl_compare);
#ifdef HAVE_LIBPTHREAD
pthread_mutex_unlock(&sync_lock);
#endif
- for (k = 0; k < hctl->count; k++)
- list_add_tail(&hctl->pelems[k]->list, &hctl->elems);
+ for (k = 0; k < ctl->count; k++)
+ list_add_tail(&ctl->pelems[k]->list, &ctl->elems);
}
/**
- * \brief Change HCTL compare function and reorder elements
- * \param hctl HCTL handle
+ * \brief Change CTL compare function and reorder elements
+ * \param ctl CTL handle
* \param compare Element compare function
* \return 0 on success otherwise a negative error code
*/
-int snd_hctl_set_compare(snd_hctl_t *hctl, snd_hctl_compare_t compare)
+int snd_ctl_set_compare(snd_ctl_t *ctl, snd_ctl_compare_t compare)
{
- assert(hctl);
- hctl->compare = compare == NULL ? snd_hctl_compare_default : compare;
- snd_hctl_sort(hctl);
+ assert(ctl);
+ ctl->compare = compare == NULL ? snd_ctl_compare_default : compare;
+ snd_ctl_sort(ctl);
return 0;
}
/**
- * \brief A "don't care" fast compare functions that may be used with #snd_hctl_set_compare
- * \param c1 First HCTL element
- * \param c2 Second HCTL element
+ * \brief A "don't care" fast compare functions that may be used with #snd_ctl_set_compare
+ * \param c1 First CTL element
+ * \param c2 Second CTL element
* \return -1 if c1 < c2, 0 if c1 == c2, 1 if c1 > c2
*/
-int snd_hctl_compare_fast(const snd_hctl_elem_t *c1,
- const snd_hctl_elem_t *c2)
+int snd_ctl_compare_fast(const snd_ctl_elem_t *c1,
+ const snd_ctl_elem_t *c2)
{
return c1->id.numid - c2->id.numid;
}
-static int snd_hctl_compare_default(const snd_hctl_elem_t *c1,
- const snd_hctl_elem_t *c2)
+static int snd_ctl_compare_default(const snd_ctl_elem_t *c1,
+ const snd_ctl_elem_t *c2)
{
int res;
int d = c1->id.iface - c2->id.iface;
@@ -488,248 +353,187 @@ static int snd_hctl_compare_default(const snd_hctl_elem_t *c1,
}
/**
- * \brief get first element for an HCTL
- * \param hctl HCTL handle
+ * \brief get first element for an CTL
+ * \param ctl CTL handle
* \return pointer to first element
*/
-snd_hctl_elem_t *snd_hctl_first_elem(snd_hctl_t *hctl)
+snd_ctl_elem_t *snd_ctl_first_elem(snd_ctl_t *ctl)
{
- assert(hctl);
- if (list_empty(&hctl->elems))
+ assert(ctl);
+ if (list_empty(&ctl->elems))
return NULL;
- return list_entry(hctl->elems.next, snd_hctl_elem_t, list);
+ return list_entry(ctl->elems.next, snd_ctl_elem_t, list);
}
/**
- * \brief get last element for an HCTL
- * \param hctl HCTL handle
+ * \brief get last element for an CTL
+ * \param ctl CTL handle
* \return pointer to last element
*/
-snd_hctl_elem_t *snd_hctl_last_elem(snd_hctl_t *hctl)
+snd_ctl_elem_t *snd_ctl_last_elem(snd_ctl_t *ctl)
{
- assert(hctl);
- if (list_empty(&hctl->elems))
+ assert(ctl);
+ if (list_empty(&ctl->elems))
return NULL;
- return list_entry(hctl->elems.prev, snd_hctl_elem_t, list);
+ return list_entry(ctl->elems.prev, snd_ctl_elem_t, list);
}
/**
- * \brief get next HCTL element
- * \param elem HCTL element
+ * \brief get next CTL element
+ * \param elem CTL element
* \return pointer to next element
*/
-snd_hctl_elem_t *snd_hctl_elem_next(snd_hctl_elem_t *elem)
+snd_ctl_elem_t *snd_ctl_elem_next(snd_ctl_elem_t *elem)
{
assert(elem);
- if (elem->list.next == &elem->hctl->elems)
+ if (elem->list.next == &elem->ctl->elems)
return NULL;
- return list_entry(elem->list.next, snd_hctl_elem_t, list);
+ return list_entry(elem->list.next, snd_ctl_elem_t, list);
}
/**
- * \brief get previous HCTL element
- * \param elem HCTL element
+ * \brief get previous CTL element
+ * \param elem CTL element
* \return pointer to previous element
*/
-snd_hctl_elem_t *snd_hctl_elem_prev(snd_hctl_elem_t *elem)
+snd_ctl_elem_t *snd_ctl_elem_prev(snd_ctl_elem_t *elem)
{
assert(elem);
- if (elem->list.prev == &elem->hctl->elems)
+ if (elem->list.prev == &elem->ctl->elems)
return NULL;
- return list_entry(elem->list.prev, snd_hctl_elem_t, list);
+ return list_entry(elem->list.prev, snd_ctl_elem_t, list);
}
/**
- * \brief Search an HCTL element
- * \param hctl HCTL handle
+ * \brief Search an CTL element
+ * \param ctl CTL handle
* \param id Element identifier
- * \return pointer to found HCTL element or NULL if it does not exists
+ * \return pointer to found CTL element or NULL if it does not exists
*/
-snd_hctl_elem_t *snd_hctl_find_elem(snd_hctl_t *hctl, const snd_ctl_elem_id_t *id)
+snd_ctl_elem_t *snd_ctl_find_elem(snd_ctl_t *ctl, const snd_ctl_elem_id_t *id)
{
int dir;
- int res = _snd_hctl_find_elem(hctl, id, &dir);
+ int res = _snd_ctl_find_elem(ctl, id, &dir);
if (res < 0 || dir != 0)
return NULL;
- return hctl->pelems[res];
+ return ctl->pelems[res];
}
+#ifndef DOC_HIDDEN
/**
- * \brief Load an HCTL with all elements and sort them
- * \param hctl HCTL handle
+ * \brief Load an CTL with all elements and sort them
+ * \param ctl CTL handle
* \return 0 on success otherwise a negative error code
*/
-int snd_hctl_load(snd_hctl_t *hctl)
+int snd_ctl_cache_load(snd_ctl_t *ctl)
{
snd_ctl_elem_list_t list;
int err = 0;
unsigned int idx;
- assert(hctl);
- assert(hctl->ctl);
- assert(hctl->count == 0);
- assert(list_empty(&hctl->elems));
+ assert(ctl);
+ assert(ctl->count == 0);
+ assert(list_empty(&ctl->elems));
memset(&list, 0, sizeof(list));
- if ((err = snd_ctl_elem_list(hctl->ctl, &list)) < 0)
+ if ((err = snd_ctl_elem_list(ctl, &list)) < 0)
goto _end;
while (list.count != list.used) {
+ if (list.space)
+ snd_ctl_elem_list_free_space(&list);
err = snd_ctl_elem_list_alloc_space(&list, list.count);
if (err < 0)
goto _end;
- if ((err = snd_ctl_elem_list(hctl->ctl, &list)) < 0)
+ if ((err = snd_ctl_elem_list(ctl, &list)) < 0)
goto _end;
}
- if (hctl->alloc < list.count) {
- hctl->alloc = list.count;
- free(hctl->pelems);
- hctl->pelems = malloc(hctl->alloc * sizeof(*hctl->pelems));
- if (!hctl->pelems) {
+ if (ctl->alloc < list.count) {
+ ctl->alloc = list.count;
+ free(ctl->pelems);
+ ctl->pelems = malloc(ctl->alloc * sizeof(*ctl->pelems));
+ if (!ctl->pelems) {
err = -ENOMEM;
goto _end;
}
}
for (idx = 0; idx < list.count; idx++) {
- snd_hctl_elem_t *elem;
- elem = calloc(1, sizeof(snd_hctl_elem_t));
+ snd_ctl_elem_t *elem;
+ elem = calloc(1, sizeof(snd_ctl_elem_t));
if (elem == NULL) {
- snd_hctl_free(hctl);
+ snd_ctl_cache_free(ctl);
err = -ENOMEM;
goto _end;
}
elem->id = list.pids[idx];
- elem->hctl = hctl;
+ elem->ctl = ctl;
elem->compare_weight = get_compare_weight(&elem->id);
- hctl->pelems[idx] = elem;
- list_add_tail(&elem->list, &hctl->elems);
- hctl->count++;
+ ctl->pelems[idx] = elem;
+ list_add_tail(&elem->list, &ctl->elems);
+ ctl->count++;
}
- if (!hctl->compare)
- hctl->compare = snd_hctl_compare_default;
- snd_hctl_sort(hctl);
- for (idx = 0; idx < hctl->count; idx++) {
- int res = snd_hctl_throw_event(hctl, SNDRV_CTL_EVENT_MASK_ADD,
- hctl->pelems[idx]);
+ if (!ctl->compare)
+ ctl->compare = snd_ctl_compare_default;
+ snd_ctl_sort(ctl);
+ for (idx = 0; idx < ctl->count; idx++) {
+ int res = snd_ctl_throw_event(ctl, SNDRV_CTL_EVENT_MASK_ADD,
+ ctl->pelems[idx]);
if (res < 0)
return res;
}
- err = snd_ctl_subscribe_events(hctl->ctl, 1);
_end:
- free(list.pids);
+ snd_ctl_elem_list_free_space(&list);
return err;
}
+#endif
/**
- * \brief Set callback function for an HCTL
- * \param hctl HCTL handle
+ * \brief Set callback function for an CTL
+ * \param ctl CTL handle
* \param callback callback function
*/
-void snd_hctl_set_callback(snd_hctl_t *hctl, snd_hctl_callback_t callback)
+void snd_ctl_set_callback(snd_ctl_t *ctl, snd_ctl_callback_t callback)
{
- assert(hctl);
- hctl->callback = callback;
+ assert(ctl);
+ ctl->callback = callback;
}
/**
- * \brief Set callback private value for an HCTL
- * \param hctl HCTL handle
+ * \brief Set callback private value for an CTL
+ * \param ctl CTL handle
* \param callback_private callback private value
*/
-void snd_hctl_set_callback_private(snd_hctl_t *hctl, void *callback_private)
+void snd_ctl_set_callback_private(snd_ctl_t *ctl, void *callback_private)
{
- assert(hctl);
- hctl->callback_private = callback_private;
+ assert(ctl);
+ ctl->callback_private = callback_private;
}
/**
- * \brief Get callback private value for an HCTL
- * \param hctl HCTL handle
+ * \brief Get callback private value for an CTL
+ * \param ctl CTL handle
* \return callback private value
*/
-void *snd_hctl_get_callback_private(snd_hctl_t *hctl)
+void *snd_ctl_get_callback_private(snd_ctl_t *ctl)
{
- assert(hctl);
- return hctl->callback_private;
+ assert(ctl);
+ return ctl->callback_private;
}
/**
- * \brief Get number of loaded elements for an HCTL
- * \param hctl HCTL handle
+ * \brief Get number of loaded elements for an CTL
+ * \param ctl CTL handle
* \return elements count
*/
-unsigned int snd_hctl_get_count(snd_hctl_t *hctl)
-{
- return hctl->count;
-}
-
-/**
- * \brief Wait for a HCTL to become ready (i.e. at least one event pending)
- * \param hctl HCTL handle
- * \param timeout maximum time in milliseconds to wait
- * \return a positive value on success otherwise a negative error code
- * \retval 0 timeout occurred
- * \retval 1 an event is pending
- */
-int snd_hctl_wait(snd_hctl_t *hctl, int timeout)
-{
- struct pollfd *pfd;
- unsigned short *revents;
- int i, npfds, pollio, err, err_poll;
-
- npfds = snd_hctl_poll_descriptors_count(hctl);
- if (npfds <= 0 || npfds >= 16) {
- SNDERR("Invalid poll_fds %d\n", npfds);
- return -EIO;
- }
- pfd = alloca(sizeof(*pfd) * npfds);
- revents = alloca(sizeof(*revents) * npfds);
- err = snd_hctl_poll_descriptors(hctl, pfd, npfds);
- if (err < 0)
- return err;
- if (err != npfds) {
- SNDMSG("invalid poll descriptors %d\n", err);
- return -EIO;
- }
- do {
- pollio = 0;
- err_poll = poll(pfd, npfds, timeout);
- if (err_poll < 0) {
- if (errno == EINTR)
- continue;
- return -errno;
- }
- if (! err_poll)
- break;
- err = snd_hctl_poll_descriptors_revents(hctl, pfd, npfds, revents);
- if (err < 0)
- return err;
- for (i = 0; i < npfds; i++) {
- if (revents[i] & (POLLERR | POLLNVAL))
- return -EIO;
- if ((revents[i] & (POLLIN | POLLOUT)) == 0)
- continue;
- pollio++;
- }
- } while (! pollio);
- return err_poll > 0 ? 1 : 0;
-}
-
-/**
- * \brief Get a ctl handle associated to the given hctl handle
- * \param hctl HCTL handle
- * \return a ctl handle otherwise NULL
- */
-snd_ctl_t *snd_hctl_ctl(snd_hctl_t *hctl)
+unsigned int snd_ctl_get_count(snd_ctl_t *ctl)
{
- return hctl->ctl;
+ return ctl->count;
}
-static int snd_hctl_handle_event(snd_hctl_t *hctl, snd_ctl_event_t *event)
+static int snd_ctl_handle_event(snd_ctl_t *ctl, snd_ctl_event_t *event)
{
- snd_hctl_elem_t *elem;
+ snd_ctl_elem_t *elem;
int res;
- assert(hctl);
- assert(hctl->ctl);
+ assert(ctl);
switch (event->type) {
case SND_CTL_EVENT_ELEM:
break;
@@ -738,30 +542,30 @@ static int snd_hctl_handle_event(snd_hctl_t *hctl, snd_ctl_event_t *event)
}
if (event->data.elem.mask == SNDRV_CTL_EVENT_MASK_REMOVE) {
int dir;
- res = _snd_hctl_find_elem(hctl, &event->data.elem.id, &dir);
+ res = _snd_ctl_find_elem(ctl, &event->data.elem.id, &dir);
assert(res >= 0 && dir == 0);
if (res < 0 || dir != 0)
return -ENOENT;
- snd_hctl_elem_remove(hctl, (unsigned int) res);
+ snd_ctl_celem_remove(ctl, (unsigned int) res);
return 0;
}
if (event->data.elem.mask & SNDRV_CTL_EVENT_MASK_ADD) {
- elem = calloc(1, sizeof(snd_hctl_elem_t));
+ elem = calloc(1, sizeof(snd_ctl_elem_t));
if (elem == NULL)
return -ENOMEM;
elem->id = event->data.elem.id;
- elem->hctl = hctl;
- res = snd_hctl_elem_add(hctl, elem);
+ elem->ctl = ctl;
+ res = snd_ctl_elem_add(ctl, elem);
if (res < 0)
return res;
}
if (event->data.elem.mask & (SNDRV_CTL_EVENT_MASK_VALUE |
SNDRV_CTL_EVENT_MASK_INFO)) {
- elem = snd_hctl_find_elem(hctl, &event->data.elem.id);
+ elem = snd_ctl_find_elem(ctl, &event->data.elem.id);
assert(elem);
if (!elem)
return -ENOENT;
- res = snd_hctl_elem_throw_event(elem, event->data.elem.mask &
+ res = snd_ctl_elem_throw_event(elem, event->data.elem.mask &
(SNDRV_CTL_EVENT_MASK_VALUE |
SNDRV_CTL_EVENT_MASK_INFO));
if (res < 0)
@@ -771,23 +575,22 @@ static int snd_hctl_handle_event(snd_hctl_t *hctl, snd_ctl_event_t *event)
}
/**
- * \brief Handle pending HCTL events invoking callbacks
- * \param hctl HCTL handle
+ * \brief Handle pending CTL events invoking callbacks
+ * \param ctl CTL handle
* \return 0 otherwise a negative error code on failure
*/
-int snd_hctl_handle_events(snd_hctl_t *hctl)
+int snd_ctl_handle_events(snd_ctl_t *ctl)
{
snd_ctl_event_t event;
int res;
unsigned int count = 0;
- assert(hctl);
- assert(hctl->ctl);
- while ((res = snd_ctl_read(hctl->ctl, &event)) != 0 &&
+ assert(ctl);
+ while ((res = snd_ctl_read(ctl, &event)) != 0 &&
res != -EAGAIN) {
if (res < 0)
return res;
- res = snd_hctl_handle_event(hctl, &event);
+ res = snd_ctl_handle_event(ctl, &event);
if (res < 0)
return res;
count++;
@@ -796,108 +599,108 @@ int snd_hctl_handle_events(snd_hctl_t *hctl)
}
/**
- * \brief Get information for an HCTL element
- * \param elem HCTL element
- * \param info HCTL element information
+ * \brief Get information for an CTL element
+ * \param elem CTL element
+ * \param info CTL element information
* \return 0 otherwise a negative error code on failure
*/
-int snd_hctl_elem_info(snd_hctl_elem_t *elem, snd_ctl_elem_info_t *info)
+int snd_ctl_celem_info(snd_ctl_elem_t *elem, snd_ctl_elem_info_t *info)
{
assert(elem);
- assert(elem->hctl);
+ assert(elem->ctl);
assert(info);
info->id = elem->id;
- return snd_ctl_elem_info(elem->hctl->ctl, info);
+ return snd_ctl_elem_info(elem->ctl, info);
}
/**
- * \brief Get value for an HCTL element
- * \param elem HCTL element
- * \param value HCTL element value
+ * \brief Get value for an CTL element
+ * \param elem CTL element
+ * \param value CTL element value
* \return 0 otherwise a negative error code on failure
*/
-int snd_hctl_elem_read(snd_hctl_elem_t *elem, snd_ctl_elem_value_t * value)
+int snd_ctl_celem_read(snd_ctl_elem_t *elem, snd_ctl_elem_value_t * value)
{
assert(elem);
- assert(elem->hctl);
+ assert(elem->ctl);
assert(value);
value->id = elem->id;
- return snd_ctl_elem_read(elem->hctl->ctl, value);
+ return snd_ctl_elem_read(elem->ctl, value);
}
/**
- * \brief Set value for an HCTL element
- * \param elem HCTL element
- * \param value HCTL element value
+ * \brief Set value for an CTL element
+ * \param elem CTL element
+ * \param value CTL element value
* \retval 0 on success
* \retval >1 on success when value was changed
* \retval <0 a negative error code on failure
*/
-int snd_hctl_elem_write(snd_hctl_elem_t *elem, snd_ctl_elem_value_t * value)
+int snd_ctl_celem_write(snd_ctl_elem_t *elem, snd_ctl_elem_value_t * value)
{
assert(elem);
- assert(elem->hctl);
+ assert(elem->ctl);
assert(value);
value->id = elem->id;
- return snd_ctl_elem_write(elem->hctl->ctl, value);
+ return snd_ctl_elem_write(elem->ctl, value);
}
/**
- * \brief Get TLV value for an HCTL element
- * \param elem HCTL element
+ * \brief Get TLV value for an CTL element
+ * \param elem CTL element
* \param tlv TLV array for value
* \param tlv_size size of TLV array in bytes
* \return 0 otherwise a negative error code on failure
*/
-int snd_hctl_elem_tlv_read(snd_hctl_elem_t *elem, unsigned int *tlv, unsigned int tlv_size)
+int snd_ctl_celem_tlv_read(snd_ctl_elem_t *elem, unsigned int *tlv, unsigned int tlv_size)
{
assert(elem);
assert(tlv);
assert(tlv_size >= 12);
- return snd_ctl_elem_tlv_read(elem->hctl->ctl, &elem->id, tlv, tlv_size);
+ return snd_ctl_elem_tlv_read(elem->ctl, &elem->id, tlv, tlv_size);
}
/**
- * \brief Set TLV value for an HCTL element
- * \param elem HCTL element
+ * \brief Set TLV value for an CTL element
+ * \param elem CTL element
* \param tlv TLV array for value
* \retval 0 on success
* \retval >1 on success when value was changed
* \retval <0 a negative error code on failure
*/
-int snd_hctl_elem_tlv_write(snd_hctl_elem_t *elem, const unsigned int *tlv)
+int snd_ctl_celem_tlv_write(snd_ctl_elem_t *elem, const unsigned int *tlv)
{
assert(elem);
assert(tlv);
assert(tlv[1] >= 4);
- return snd_ctl_elem_tlv_write(elem->hctl->ctl, &elem->id, tlv);
+ return snd_ctl_elem_tlv_write(elem->ctl, &elem->id, tlv);
}
/**
- * \brief Set TLV value for an HCTL element
- * \param elem HCTL element
+ * \brief Set TLV value for an CTL element
+ * \param elem CTL element
* \param tlv TLV array for value
* \retval 0 on success
* \retval >1 on success when value was changed
* \retval <0 a negative error code on failure
*/
-int snd_hctl_elem_tlv_command(snd_hctl_elem_t *elem, const unsigned int *tlv)
+int snd_ctl_celem_tlv_command(snd_ctl_elem_t *elem, const unsigned int *tlv)
{
assert(elem);
assert(tlv);
assert(tlv[1] >= 4);
- return snd_ctl_elem_tlv_command(elem->hctl->ctl, &elem->id, tlv);
+ return snd_ctl_elem_tlv_command(elem->ctl, &elem->id, tlv);
}
/**
- * \brief Get HCTL handle for an HCTL element
- * \param elem HCTL element
- * \return HCTL handle
+ * \brief Get CTL handle for an CTL element
+ * \param elem CTL element
+ * \return CTL handle
*/
-snd_hctl_t *snd_hctl_elem_get_hctl(snd_hctl_elem_t *elem)
+snd_ctl_t *snd_ctl_elem_get_ctl(snd_ctl_elem_t *elem)
{
assert(elem);
- return elem->hctl;
+ return elem->ctl;
}
/**
@@ -905,7 +708,7 @@ snd_hctl_t *snd_hctl_elem_get_hctl(snd_hctl_elem_t *elem)
* \param obj CTL element id/value
* \param ptr Pointer to returned CTL element identifier
*/
-void snd_hctl_elem_get_id(const snd_hctl_elem_t *obj, snd_ctl_elem_id_t *ptr)
+void snd_ctl_elem_get_id(const snd_ctl_elem_t *obj, snd_ctl_elem_id_t *ptr)
{
assert(obj && ptr);
*ptr = obj->id;
@@ -916,7 +719,7 @@ void snd_hctl_elem_get_id(const snd_hctl_elem_t *obj, snd_ctl_elem_id_t *ptr)
* \param obj CTL element id/value
* \return element numeric identifier
*/
-unsigned int snd_hctl_elem_get_numid(const snd_hctl_elem_t *obj)
+unsigned int snd_ctl_elem_get_numid(const snd_ctl_elem_t *obj)
{
assert(obj);
return obj->id.numid;
@@ -927,7 +730,7 @@ unsigned int snd_hctl_elem_get_numid(const snd_hctl_elem_t *obj)
* \param obj CTL element id/value
* \return interface part of element identifier
*/
-snd_ctl_elem_iface_t snd_hctl_elem_get_interface(const snd_hctl_elem_t *obj)
+snd_ctl_elem_iface_t snd_ctl_elem_get_interface(const snd_ctl_elem_t *obj)
{
assert(obj);
return obj->id.iface;
@@ -938,7 +741,7 @@ snd_ctl_elem_iface_t snd_hctl_elem_get_interface(const snd_hctl_elem_t *obj)
* \param obj CTL element id/value
* \return device part of element identifier
*/
-unsigned int snd_hctl_elem_get_device(const snd_hctl_elem_t *obj)
+unsigned int snd_ctl_elem_get_device(const snd_ctl_elem_t *obj)
{
assert(obj);
return obj->id.device;
@@ -949,7 +752,7 @@ unsigned int snd_hctl_elem_get_device(const snd_hctl_elem_t *obj)
* \param obj CTL element id/value
* \return subdevice part of element identifier
*/
-unsigned int snd_hctl_elem_get_subdevice(const snd_hctl_elem_t *obj)
+unsigned int snd_ctl_elem_get_subdevice(const snd_ctl_elem_t *obj)
{
assert(obj);
return obj->id.subdevice;
@@ -960,7 +763,7 @@ unsigned int snd_hctl_elem_get_subdevice(const snd_hctl_elem_t *obj)
* \param obj CTL element id/value
* \return name part of element identifier
*/
-const char *snd_hctl_elem_get_name(const snd_hctl_elem_t *obj)
+const char *snd_ctl_elem_get_name(const snd_ctl_elem_t *obj)
{
assert(obj);
return (const char *)obj->id.name;
@@ -971,40 +774,40 @@ const char *snd_hctl_elem_get_name(const snd_hctl_elem_t *obj)
* \param obj CTL element id/value
* \return index part of element identifier
*/
-unsigned int snd_hctl_elem_get_index(const snd_hctl_elem_t *obj)
+unsigned int snd_ctl_elem_get_index(const snd_ctl_elem_t *obj)
{
assert(obj);
return obj->id.index;
}
/**
- * \brief Set callback function for an HCTL element
- * \param obj HCTL element
+ * \brief Set callback function for an CTL element
+ * \param obj CTL element
* \param val callback function
*/
-void snd_hctl_elem_set_callback(snd_hctl_elem_t *obj, snd_hctl_elem_callback_t val)
+void snd_ctl_elem_set_callback(snd_ctl_elem_t *obj, snd_ctl_elem_callback_t val)
{
assert(obj);
obj->callback = val;
}
/**
- * \brief Set callback private value for an HCTL element
- * \param obj HCTL element
+ * \brief Set callback private value for an CTL element
+ * \param obj CTL element
* \param val callback private value
*/
-void snd_hctl_elem_set_callback_private(snd_hctl_elem_t *obj, void * val)
+void snd_ctl_elem_set_callback_private(snd_ctl_elem_t *obj, void * val)
{
assert(obj);
obj->callback_private = val;
}
/**
- * \brief Get callback private value for an HCTL element
- * \param obj HCTL element
+ * \brief Get callback private value for an CTL element
+ * \param obj CTL element
* \return callback private value
*/
-void * snd_hctl_elem_get_callback_private(const snd_hctl_elem_t *obj)
+void * snd_ctl_elem_get_callback_private(const snd_ctl_elem_t *obj)
{
assert(obj);
return obj->callback_private;
diff --git a/src/control/hcontrol_old.c b/src/control/hcontrol_old.c
new file mode 100644
index 00000000..a084f1a2
--- /dev/null
+++ b/src/control/hcontrol_old.c
@@ -0,0 +1,512 @@
+/**
+ * \file control/hcontrol_old.c
+ * \brief HCTL Interface - High Level CTL
+ * \author Jaroslav Kysela <perex@perex.cz>
+ * \author Abramo Bagnara <abramo@alsa-project.org>
+ * \date 2000
+ *
+ * HCTL interface is designed to access preloaded and sorted primitive controls.
+ * Callbacks may be used for event handling.
+ * See \ref hcontrol page for more details.
+ */
+/*
+ * Control Interface - high level API
+ * Copyright (c) 2000 by Jaroslav Kysela <perex@perex.cz>
+ * 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 Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/*! \page hcontrol High level control interface
+
+<P> High level control interface is designed to access preloaded and sorted primitive controls.
+
+\section hcontrol_general_overview General overview
+
+<P> High level control interface caches the accesses to primitive controls
+to reduce overhead accessing the real controls in kernel drivers.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/poll.h>
+#include "control_local.h"
+#include "mixer_old.h"
+
+/**
+ * \brief Opens an HCTL
+ * \param hctlp Returned HCTL handle
+ * \param name ASCII identifier of the underlying CTL handle
+ * \param mode Open mode (see #SND_CTL_NONBLOCK, #SND_CTL_ASYNC)
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_hctl_open(snd_hctl_t **hctlp, const char *name, int mode ATTRIBUTE_UNUSED)
+{
+ return snd_ctl_open(hctlp, name, SND_CTL_CACHE);
+}
+
+/**
+ * \brief Opens an HCTL
+ * \param hctlp Returned HCTL handle
+ * \param ctl underlying CTL handle
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_hctl_open_ctl(snd_hctl_t **hctlp, snd_ctl_t *ctl)
+{
+ assert(hctlp);
+ assert(ctl);
+ *hctlp = ctl;
+ ctl->mode = SND_CTL_CACHE;
+ return 0;
+}
+
+/**
+ * \brief close HCTL handle
+ * \param hctl HCTL handle
+ * \return 0 on success otherwise a negative error code
+ *
+ * Closes the specified HCTL handle and frees all associated
+ * resources.
+ */
+int snd_hctl_close(snd_hctl_t *hctl)
+{
+ return snd_ctl_close(hctl);
+}
+
+/**
+ * \brief get identifier of HCTL handle
+ * \param hctl HCTL handle
+ * \return ascii identifier of HCTL handle
+ *
+ * Returns the ASCII identifier of given HCTL handle. It's the same
+ * identifier specified in snd_hctl_open().
+ */
+const char *snd_hctl_name(snd_hctl_t *hctl)
+{
+ assert(hctl);
+ return snd_ctl_name(hctl);
+}
+
+/**
+ * \brief set nonblock mode
+ * \param hctl HCTL handle
+ * \param nonblock 0 = block, 1 = nonblock mode
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_hctl_nonblock(snd_hctl_t *hctl, int nonblock)
+{
+ assert(hctl);
+ return snd_ctl_nonblock(hctl, nonblock);
+}
+
+/**
+ * \brief set async mode
+ * \param hctl HCTL handle
+ * \param sig Signal to raise: < 0 disable, 0 default (SIGIO)
+ * \param pid Process ID to signal: 0 current
+ * \return 0 on success otherwise a negative error code
+ *
+ * A signal is raised when a change happens.
+ */
+int snd_hctl_async(snd_hctl_t *hctl, int sig, pid_t pid)
+{
+ assert(hctl);
+ return snd_ctl_async(hctl, sig, pid);
+}
+
+/**
+ * \brief get count of poll descriptors for HCTL handle
+ * \param hctl HCTL handle
+ * \return count of poll descriptors
+ */
+int snd_hctl_poll_descriptors_count(snd_hctl_t *hctl)
+{
+ assert(hctl);
+ return snd_ctl_poll_descriptors_count(hctl);
+}
+
+/**
+ * \brief get poll descriptors
+ * \param hctl HCTL handle
+ * \param pfds array of poll descriptors
+ * \param space space in the poll descriptor array
+ * \return count of filled descriptors
+ */
+int snd_hctl_poll_descriptors(snd_hctl_t *hctl, struct pollfd *pfds, unsigned int space)
+{
+ assert(hctl);
+ return snd_ctl_poll_descriptors(hctl, pfds, space);
+}
+
+/**
+ * \brief get returned events from poll descriptors
+ * \param hctl HCTL handle
+ * \param pfds array of poll descriptors
+ * \param nfds count of poll descriptors
+ * \param revents returned events
+ * \return zero if success, otherwise a negative error code
+ */
+int snd_hctl_poll_descriptors_revents(snd_hctl_t *hctl, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
+{
+ assert(hctl);
+ return snd_ctl_poll_descriptors_revents(hctl, pfds, nfds, revents);
+}
+
+/**
+ * \brief free HCTL loaded elements
+ * \param hctl HCTL handle
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_hctl_free(snd_hctl_t *hctl)
+{
+ return snd_ctl_cache_free(hctl);
+}
+
+/**
+ * \brief Change HCTL compare function and reorder elements
+ * \param hctl HCTL handle
+ * \param compare Element compare function
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_hctl_set_compare(snd_hctl_t *hctl, snd_hctl_compare_t compare)
+{
+ return snd_ctl_set_compare(hctl, compare);
+}
+
+/**
+ * \brief get first element for an HCTL
+ * \param hctl HCTL handle
+ * \return pointer to first element
+ */
+snd_hctl_elem_t *snd_hctl_first_elem(snd_hctl_t *hctl)
+{
+ return snd_ctl_first_elem(hctl);
+}
+
+/**
+ * \brief get last element for an HCTL
+ * \param hctl HCTL handle
+ * \return pointer to last element
+ */
+snd_hctl_elem_t *snd_hctl_last_elem(snd_hctl_t *hctl)
+{
+ return snd_ctl_last_elem(hctl);
+}
+
+/**
+ * \brief get next HCTL element
+ * \param elem HCTL element
+ * \return pointer to next element
+ */
+snd_hctl_elem_t *snd_hctl_elem_next(snd_hctl_elem_t *elem)
+{
+ return snd_ctl_elem_next(elem);
+}
+
+/**
+ * \brief get previous HCTL element
+ * \param elem HCTL element
+ * \return pointer to previous element
+ */
+snd_hctl_elem_t *snd_hctl_elem_prev(snd_hctl_elem_t *elem)
+{
+ return snd_ctl_elem_prev(elem);
+}
+
+/**
+ * \brief Search an HCTL element
+ * \param hctl HCTL handle
+ * \param id Element identifier
+ * \return pointer to found HCTL element or NULL if it does not exists
+ */
+snd_hctl_elem_t *snd_hctl_find_elem(snd_hctl_t *hctl, const snd_ctl_elem_id_t *id)
+{
+ return snd_ctl_find_elem(hctl, id);
+}
+
+/**
+ * \brief Load an HCTL with all elements and sort them
+ * \param hctl HCTL handle
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_hctl_load(snd_hctl_t *hctl)
+{
+ return snd_ctl_subscribe_events(hctl, 1);
+}
+
+/**
+ * \brief Set callback function for an HCTL
+ * \param hctl HCTL handle
+ * \param callback callback function
+ */
+void snd_hctl_set_callback(snd_hctl_t *hctl, snd_hctl_callback_t callback)
+{
+ snd_ctl_set_callback(hctl, callback);
+}
+
+/**
+ * \brief Set callback private value for an HCTL
+ * \param hctl HCTL handle
+ * \param callback_private callback private value
+ */
+void snd_hctl_set_callback_private(snd_hctl_t *hctl, void *callback_private)
+{
+ snd_ctl_set_callback_private(hctl, callback_private);
+}
+
+/**
+ * \brief Get callback private value for an HCTL
+ * \param hctl HCTL handle
+ * \return callback private value
+ */
+void *snd_hctl_get_callback_private(snd_hctl_t *hctl)
+{
+ return snd_ctl_get_callback_private(hctl);
+}
+
+/**
+ * \brief Get number of loaded elements for an HCTL
+ * \param hctl HCTL handle
+ * \return elements count
+ */
+unsigned int snd_hctl_get_count(snd_hctl_t *hctl)
+{
+ return snd_ctl_get_count(hctl);
+}
+
+/**
+ * \brief Wait for a HCTL to become ready (i.e. at least one event pending)
+ * \param hctl HCTL handle
+ * \param timeout maximum time in milliseconds to wait
+ * \return a positive value on success otherwise a negative error code
+ * \retval 0 timeout occurred
+ * \retval 1 an event is pending
+ */
+int snd_hctl_wait(snd_hctl_t *hctl, int timeout)
+{
+ return snd_ctl_wait(hctl, timeout);
+}
+
+/**
+ * \brief Get a ctl handle associated to the given hctl handle
+ * \param hctl HCTL handle
+ * \return a ctl handle otherwise NULL
+ */
+snd_ctl_t *snd_hctl_ctl(snd_hctl_t *hctl)
+{
+ return hctl;
+}
+
+/**
+ * \brief Handle pending HCTL events invoking callbacks
+ * \param hctl HCTL handle
+ * \return 0 otherwise a negative error code on failure
+ */
+int snd_hctl_handle_events(snd_hctl_t *hctl)
+{
+ return snd_ctl_handle_events(hctl);
+}
+
+/**
+ * \brief Get information for an HCTL element
+ * \param elem HCTL element
+ * \param info HCTL element information
+ * \return 0 otherwise a negative error code on failure
+ */
+int snd_hctl_elem_info(snd_hctl_elem_t *elem, snd_ctl_elem_info_t *info)
+{
+ return snd_ctl_celem_info(elem, info);
+}
+
+/**
+ * \brief Get value for an HCTL element
+ * \param elem HCTL element
+ * \param value HCTL element value
+ * \return 0 otherwise a negative error code on failure
+ */
+int snd_hctl_elem_read(snd_hctl_elem_t *elem, snd_ctl_elem_value_t * value)
+{
+ return snd_ctl_celem_read(elem, value);
+}
+
+/**
+ * \brief Set value for an HCTL element
+ * \param elem HCTL element
+ * \param value HCTL element value
+ * \retval 0 on success
+ * \retval >1 on success when value was changed
+ * \retval <0 a negative error code on failure
+ */
+int snd_hctl_elem_write(snd_hctl_elem_t *elem, snd_ctl_elem_value_t * value)
+{
+ return snd_ctl_celem_write(elem, value);
+}
+
+/**
+ * \brief Get TLV value for an HCTL element
+ * \param elem HCTL element
+ * \param tlv TLV array for value
+ * \param tlv_size size of TLV array in bytes
+ * \return 0 otherwise a negative error code on failure
+ */
+int snd_hctl_elem_tlv_read(snd_hctl_elem_t *elem, unsigned int *tlv, unsigned int tlv_size)
+{
+ return snd_ctl_celem_tlv_read(elem, tlv, tlv_size);
+}
+
+/**
+ * \brief Set TLV value for an HCTL element
+ * \param elem HCTL element
+ * \param tlv TLV array for value
+ * \retval 0 on success
+ * \retval >1 on success when value was changed
+ * \retval <0 a negative error code on failure
+ */
+int snd_hctl_elem_tlv_write(snd_hctl_elem_t *elem, const unsigned int *tlv)
+{
+ return snd_ctl_celem_tlv_write(elem, tlv);
+}
+
+/**
+ * \brief Set TLV value for an HCTL element
+ * \param elem HCTL element
+ * \param tlv TLV array for value
+ * \retval 0 on success
+ * \retval >1 on success when value was changed
+ * \retval <0 a negative error code on failure
+ */
+int snd_hctl_elem_tlv_command(snd_hctl_elem_t *elem, const unsigned int *tlv)
+{
+ return snd_ctl_celem_tlv_command(elem, tlv);
+}
+
+/**
+ * \brief Get HCTL handle for an HCTL element
+ * \param elem HCTL element
+ * \return HCTL handle
+ */
+snd_hctl_t *snd_hctl_elem_get_hctl(snd_hctl_elem_t *elem)
+{
+ return snd_ctl_elem_get_ctl(elem);
+}
+
+/**
+ * \brief Get CTL element identifier of a CTL element id/value
+ * \param obj CTL element id/value
+ * \param ptr Pointer to returned CTL element identifier
+ */
+void snd_hctl_elem_get_id(const snd_hctl_elem_t *obj, snd_ctl_elem_id_t *ptr)
+{
+ snd_ctl_elem_get_id(obj, ptr);
+}
+
+/**
+ * \brief Get element numeric identifier of a CTL element id/value
+ * \param obj CTL element id/value
+ * \return element numeric identifier
+ */
+unsigned int snd_hctl_elem_get_numid(const snd_hctl_elem_t *obj)
+{
+ return snd_ctl_elem_get_numid(obj);
+}
+
+/**
+ * \brief Get interface part of CTL element identifier of a CTL element id/value
+ * \param obj CTL element id/value
+ * \return interface part of element identifier
+ */
+snd_ctl_elem_iface_t snd_hctl_elem_get_interface(const snd_hctl_elem_t *obj)
+{
+return snd_ctl_elem_get_interface(obj);
+}
+
+/**
+ * \brief Get device part of CTL element identifier of a CTL element id/value
+ * \param obj CTL element id/value
+ * \return device part of element identifier
+ */
+unsigned int snd_hctl_elem_get_device(const snd_hctl_elem_t *obj)
+{
+ return snd_ctl_elem_get_device(obj);
+}
+
+/**
+ * \brief Get subdevice part of CTL element identifier of a CTL element id/value
+ * \param obj CTL element id/value
+ * \return subdevice part of element identifier
+ */
+unsigned int snd_hctl_elem_get_subdevice(const snd_hctl_elem_t *obj)
+{
+ return snd_ctl_elem_get_subdevice(obj);
+}
+
+/**
+ * \brief Get name part of CTL element identifier of a CTL element id/value
+ * \param obj CTL element id/value
+ * \return name part of element identifier
+ */
+const char *snd_hctl_elem_get_name(const snd_hctl_elem_t *obj)
+{
+ return snd_ctl_elem_get_name(obj);
+}
+
+/**
+ * \brief Get index part of CTL element identifier of a CTL element id/value
+ * \param obj CTL element id/value
+ * \return index part of element identifier
+ */
+unsigned int snd_hctl_elem_get_index(const snd_hctl_elem_t *obj)
+{
+ return snd_ctl_elem_get_index(obj);
+}
+
+/**
+ * \brief Set callback function for an HCTL element
+ * \param obj HCTL element
+ * \param val callback function
+ */
+void snd_hctl_elem_set_callback(snd_hctl_elem_t *obj, snd_hctl_elem_callback_t val)
+{
+ return snd_ctl_elem_set_callback(obj, val);
+}
+
+/**
+ * \brief Set callback private value for an HCTL element
+ * \param obj HCTL element
+ * \param val callback private value
+ */
+void snd_hctl_elem_set_callback_private(snd_hctl_elem_t *obj, void * val)
+{
+ return snd_ctl_elem_set_callback_private(obj, val);
+}
+
+/**
+ * \brief Get callback private value for an HCTL element
+ * \param obj HCTL element
+ * \return callback private value
+ */
+void * snd_hctl_elem_get_callback_private(const snd_hctl_elem_t *obj)
+{
+ return snd_ctl_elem_get_callback_private(obj);
+}
+
diff --git a/src/mixer/Makefile.am b/src/mixer/Makefile.am
index bb466ed7..84272ada 100644
--- a/src/mixer/Makefile.am
+++ b/src/mixer/Makefile.am
@@ -1,8 +1,9 @@
EXTRA_LTLIBRARIES=libmixer.la
-libmixer_la_SOURCES = bag.c mixer.c simple.c simple_none.c simple_abst.c
+libmixer_la_SOURCES = bag.c mixer.c simple.c simple_none.c mixer_symbols.c \
+ mixer_old.c simple_old.c
-noinst_HEADERS = mixer_local.h mixer_simple.h
+noinst_HEADERS = mixer_local.h mixer_old_local.h
all: libmixer.la
diff --git a/src/mixer/mixer.c b/src/mixer/mixer.c
index 85d843fc..cece6541 100644
--- a/src/mixer/mixer.c
+++ b/src/mixer/mixer.c
@@ -3,7 +3,7 @@
* \brief Mixer Interface
* \author Jaroslav Kysela <perex@perex.cz>
* \author Abramo Bagnara <abramo@alsa-project.org>
- * \date 2001
+ * \date 2001-2009
*
* Mixer interface is designed to access mixer elements.
* Callbacks may be used for event handling.
@@ -30,12 +30,49 @@
*
*/
-/*! \page mixer Mixer interface
+/*! \page amixer Mixer interface
-<P>Mixer interface is designed to access the abstracted mixer controls.
-This is an abstraction layer over the hcontrol layer.
+<P>Mixer interface is designed to access the abstracted amixer controls.
-\section mixer_general_overview General overview
+\section amixer_general_overview General overview
+
+\section amixer_global Global mixer
+
+The global mixer exposes basic or all (#SND_AMIXER_ALL) mixer related
+controls to application.
+
+\par Master
+This control element defines playback master volume control for
+whole card.
+
+\section amixer_pcm PCM related mixer
+
+This mixer works with PCM related controls with predefined abstractions.
+
+\subsection amixer_pcm_playback Playback direction
+
+Bellow mixer controls are available for playback PCM.
+
+\par Master
+Playback master volume control.
+
+\par PCM
+Playback PCM stream related volume control.
+
+\subsection amixer_pcm_capture Capture direction
+
+Note that none or any combination of controls might be present, but
+at least Capture control should be implemented in alsa-lib.
+
+\par Capture
+Capture PCM stream related volume control.
+
+\par Source
+Capture Source (enum like Mic,CD,Line etc.).
+
+\par [other] - like CD, Aux, Front Line etc.
+These sources are mixed to PCM input. Both volume and switch might be
+available.
*/
@@ -46,103 +83,342 @@ This is an abstraction layer over the hcontrol layer.
#include <fcntl.h>
#include <sys/ioctl.h>
#include "mixer_local.h"
-
-#ifndef DOC_HIDDEN
-typedef struct _snd_mixer_slave {
- snd_hctl_t *hctl;
- struct list_head list;
-} snd_mixer_slave_t;
-
+#include "mixer_abst.h"
+
+static int ctl_event_handler(snd_ctl_t *ctl,
+ unsigned int mask,
+ snd_ctl_elem_t *elem);
+
+static const char *const build_in_mixers[] = {
+ "none", NULL
+};
+
+static int snd_amixer_open_conf(snd_amixer_t **amixerp,
+ const char *name,
+ snd_config_t *mixer_root,
+ snd_config_t *mixer_conf,
+ snd_pcm_t *pcm_playback,
+ snd_pcm_t *pcm_capture,
+ int mode)
+{
+ const char *str;
+ char *buf = NULL, *buf1 = NULL;
+ int err, idx;
+ snd_config_t *conf, *type_conf = NULL;
+ snd_config_iterator_t i, next;
+ const char *id;
+ const char *lib = NULL, *open_name = NULL;
+ int (*open_func)(snd_amixer_t *amixer,
+ snd_config_t *root,
+ snd_config_t *conf,
+ struct sm_open *sm_open) = NULL;
+#ifndef PIC
+ extern void *snd_amixer_open_symbols(void);
+#endif
+ void *h = NULL;
+ snd_amixer_t *amixer;
+ if (snd_config_get_type(mixer_conf) != SND_CONFIG_TYPE_COMPOUND) {
+ char *val;
+ id = NULL;
+ snd_config_get_id(mixer_conf, &id);
+ val = NULL;
+ snd_config_get_ascii(mixer_conf, &val);
+ SNDERR("Invalid type for mixer %s%sdefinition (id: %s, value: %s)", name ? name : "", name ? " " : "", id, val);
+ free(val);
+ return -EINVAL;
+ }
+ err = snd_config_search(mixer_conf, "type", &conf);
+ if (err < 0) {
+ SNDERR("type is not defined");
+ return err;
+ }
+ err = snd_config_get_id(conf, &id);
+ if (err < 0) {
+ SNDERR("unable to get id");
+ return err;
+ }
+ err = snd_config_get_string(conf, &str);
+ if (err < 0) {
+ SNDERR("Invalid type for %s", id);
+ return err;
+ }
+ err = snd_config_search_definition(mixer_root, "amixer_type", str, &type_conf);
+ if (err >= 0) {
+ if (snd_config_get_type(type_conf) != SND_CONFIG_TYPE_COMPOUND) {
+ SNDERR("Invalid type for amixer type %s definition", str);
+ goto _err;
+ }
+ snd_config_for_each(i, next, type_conf) {
+ snd_config_t *n = snd_config_iterator_entry(i);
+ const char *id;
+ if (snd_config_get_id(n, &id) < 0)
+ continue;
+ if (strcmp(id, "comment") == 0)
+ continue;
+ if (strcmp(id, "lib") == 0) {
+ err = snd_config_get_string(n, &lib);
+ if (err < 0) {
+ SNDERR("Invalid type for %s", id);
+ goto _err;
+ }
+ continue;
+ }
+ if (strcmp(id, "open") == 0) {
+ err = snd_config_get_string(n, &open_name);
+ if (err < 0) {
+ SNDERR("Invalid type for %s", id);
+ goto _err;
+ }
+ continue;
+ }
+ SNDERR("Unknown field %s", id);
+ err = -EINVAL;
+ goto _err;
+ }
+ }
+ if (!open_name) {
+ buf = malloc(strlen(str) + 32);
+ if (buf == NULL) {
+ err = -ENOMEM;
+ goto _err;
+ }
+ open_name = buf;
+ sprintf(buf, "_snd_amixer_%s_open", str);
+ }
+ if (!lib) {
+ const char *const *build_in = build_in_mixers;
+ while (*build_in) {
+ if (!strcmp(*build_in, str))
+ break;
+ build_in++;
+ }
+ if (*build_in == NULL) {
+ buf1 = malloc(strlen(str) + sizeof(ALSA_PLUGIN_DIR) + 32);
+ if (buf1 == NULL) {
+ err = -ENOMEM;
+ goto _err;
+ }
+ lib = buf1;
+ sprintf(buf1, "%s/libasound_module_mixer_%s.so", ALSA_PLUGIN_DIR, str);
+ }
+ }
+#ifndef PIC
+ snd_mixer_open_symbols(); /* this call is for static linking only */
#endif
+ open_func = snd_dlobj_cache_lookup(open_name);
+ if (open_func) {
+ err = 0;
+ goto _err;
+ }
+ h = snd_dlopen(lib, RTLD_NOW);
+ if (h)
+ open_func = snd_dlsym(h, open_name, SND_DLSYM_VERSION(SND_AMIXER_DLSYM_VERSION));
+ err = 0;
+ if (!h) {
+ SNDERR("Cannot open shared library %s",
+ lib ? lib : "[builtin]");
+ err = -ENOENT;
+ } else if (!open_func) {
+ SNDERR("symbol %s is not defined inside %s", open_name,
+ lib ? lib : "[builtin]");
+ snd_dlclose(h);
+ err = -ENXIO;
+ }
+ _err:
+ if (err >= 0) {
+ amixer = calloc(1, sizeof(*amixer));
+ if (amixer == NULL) {
+ err = -ENOMEM;
+ goto _err1;
+ }
+ INIT_LIST_HEAD(&amixer->elems);
+ amixer->compare = snd_amixer_compare_default;
+ amixer->sm_open.name = name;
+ amixer->sm_open.pcm_playback = pcm_playback;
+ amixer->sm_open.pcm_capture = pcm_capture;
+ amixer->sm_open.mode = mode;
+ err = open_func(amixer, mixer_root, mixer_conf, &amixer->sm_open);
+ if (err < 0) {
+ snd_amixer_close(amixer);
+ goto _err1;
+ }
+ for (idx = 0; idx < SM_CTL_COUNT; idx++) {
+ snd_ctl_t *ctl = amixer->sm_open.ctl[idx];
+ if (ctl == NULL)
+ continue;
+ snd_ctl_set_callback(ctl, ctl_event_handler);
+ snd_ctl_set_callback_private(ctl, amixer);
+ err = snd_hctl_nonblock(ctl, 1);
+ if (err >= 0)
+ err = snd_ctl_subscribe_events(ctl, 1);
+ if (err < 0) {
+ snd_amixer_close(amixer);
+ goto _err1;
+ }
+ }
+ *amixerp = amixer;
+ _err1:
+ if (err >= 0) {
+ if (h /*&& (mode & SND_PCM_KEEP_ALIVE)*/) {
+ snd_dlobj_cache_add(open_name, h, open_func);
+ h = NULL;
+ }
+ amixer->dl_handle = h;
+ err = 0;
+ } else {
+ if (h)
+ snd_dlclose(h);
+ }
+ }
+ if (type_conf)
+ snd_config_delete(type_conf);
+ free(buf);
+ free(buf1);
+ return err;
+}
+
+static int snd_amixer_open_noupdate(snd_amixer_t **amixerp,
+ snd_config_t *root,
+ const char *name,
+ snd_pcm_t *pcm_playback,
+ snd_pcm_t *pcm_capture,
+ int mode,
+ int hop)
+{
+ int err, pcm = pcm_playback || pcm_capture;
+ snd_config_t *mixer_conf;
+ const char *str;
-static int snd_mixer_compare_default(const snd_mixer_elem_t *c1,
- const snd_mixer_elem_t *c2);
+ err = snd_config_search_definition(root, pcm ? "amixer_pcm" : "amixer", name, &mixer_conf);
+ if (err < 0) {
+ SNDERR("Uknown amixer %s", name);
+ return err;
+ }
+ if (snd_config_get_string(mixer_conf, &str) >= 0) {
+ err = snd_amixer_open_noupdate(amixerp, root, name, pcm_playback, pcm_capture, mode, hop);
+ } else {
+ snd_config_set_hop(mixer_conf, hop);
+ err = snd_amixer_open_conf(amixerp, name, root, mixer_conf, pcm_playback, pcm_capture, mode);
+ }
+ snd_config_delete(mixer_conf);
+ return err;
+}
+/**
+ * \brief Opens the global or PCM related mixer
+ * \param amixerp Returned amixer handle
+ * \param name ASCII identifier of the mixer handle
+ * \param pcm_playback Playback PCM
+ * \param pcm_capture Capture PCM
+ * \param mode Open mode
+ * \return 0 on success otherwise a negative error code
+ *
+ * If both pcm_playback and pcm_capture parameters are NULL, the global
+ * mixer is opened.
+ */
+int snd_amixer_open(snd_amixer_t **amixerp,
+ const char *name,
+ snd_pcm_t *pcm_playback,
+ snd_pcm_t *pcm_capture,
+ int mode)
+{
+ int err;
+ assert(amixerp);
+ assert(name);
+ err = snd_config_update();
+ if (err < 0)
+ return err;
+ return snd_amixer_open_noupdate(amixerp, snd_config, name, pcm_playback, pcm_capture, mode, 0);
+}
/**
- * \brief Opens an empty mixer
- * \param mixerp Returned mixer handle
+ * \brief Opens the global or PCM related mixer using local configuration
+ * \param amixerp Returned amixer handle
+ * \param name ASCII identifier of the mixer handle
+ * \param pcm_playback Playback PCM
+ * \param pcm_capture Capture PCM
* \param mode Open mode
+ * \param lconf Local configuration
* \return 0 on success otherwise a negative error code
+ *
+ * If both pcm_playback and pcm_capture parameters are NULL, the global
+ * mixer is opened.
*/
-int snd_mixer_open(snd_mixer_t **mixerp, int mode ATTRIBUTE_UNUSED)
+int snd_amixer_open_lconf(snd_amixer_t **amixerp,
+ const char *name,
+ snd_pcm_t *pcm_playback,
+ snd_pcm_t *pcm_capture,
+ int mode,
+ snd_config_t *lconf)
{
- snd_mixer_t *mixer;
- assert(mixerp);
- mixer = calloc(1, sizeof(*mixer));
- if (mixer == NULL)
- return -ENOMEM;
- INIT_LIST_HEAD(&mixer->slaves);
- INIT_LIST_HEAD(&mixer->classes);
- INIT_LIST_HEAD(&mixer->elems);
- mixer->compare = snd_mixer_compare_default;
- *mixerp = mixer;
- return 0;
+ assert(amixerp);
+ assert(name);
+ assert(lconf);
+ return snd_amixer_open_noupdate(amixerp, lconf, name, pcm_playback, pcm_capture, mode, 0);
}
/**
- * \brief Attach an HCTL element to a mixer element
+ * \brief Attach an CTL element to a amixer element
* \param melem Mixer element
- * \param helem HCTL element
+ * \param elem CTL element
* \return 0 on success otherwise a negative error code
*
- * For use by mixer element class specific code.
+ * For use by amixer element class specific code.
*/
-int snd_mixer_elem_attach(snd_mixer_elem_t *melem,
- snd_hctl_elem_t *helem)
+int snd_amixer_elem_attach(snd_amixer_elem_t *melem,
+ snd_ctl_elem_t *elem)
{
- bag_t *bag = snd_hctl_elem_get_callback_private(helem);
+ bag_t *bag = snd_ctl_elem_get_callback_private(elem);
int err;
err = bag_add(bag, melem);
if (err < 0)
return err;
- return bag_add(&melem->helems, helem);
+ return bag_add(&melem->helems, elem);
}
/**
- * \brief Detach an HCTL element from a mixer element
+ * \brief Detach an CTL element from a amixer element
* \param melem Mixer element
- * \param helem HCTL element
+ * \param elem CTL element
* \return 0 on success otherwise a negative error code
*
- * For use by mixer element class specific code.
+ * For use by amixer element class specific code.
*/
-int snd_mixer_elem_detach(snd_mixer_elem_t *melem,
- snd_hctl_elem_t *helem)
+int snd_amixer_elem_detach(snd_amixer_elem_t *melem,
+ snd_ctl_elem_t *elem)
{
- bag_t *bag = snd_hctl_elem_get_callback_private(helem);
+ bag_t *bag = snd_ctl_elem_get_callback_private(elem);
int err;
err = bag_del(bag, melem);
assert(err >= 0);
- err = bag_del(&melem->helems, helem);
+ err = bag_del(&melem->helems, elem);
assert(err >= 0);
return 0;
}
/**
- * \brief Return true if a mixer element does not contain any HCTL elements
+ * \brief Return true if a amixer element does not contain any CTL elements
* \param melem Mixer element
* \return 0 if not empty, 1 if empty
*
- * For use by mixer element class specific code.
+ * For use by amixer element class specific code.
*/
-int snd_mixer_elem_empty(snd_mixer_elem_t *melem)
+int snd_amixer_elem_is_empty(snd_amixer_elem_t *melem)
{
return bag_empty(&melem->helems);
}
-static int hctl_elem_event_handler(snd_hctl_elem_t *helem,
- unsigned int mask)
+static int ctl_elem_event_handler(snd_ctl_elem_t *elem,
+ unsigned int mask)
{
- bag_t *bag = snd_hctl_elem_get_callback_private(helem);
+ bag_t *bag = snd_ctl_elem_get_callback_private(elem);
if (mask == SND_CTL_EVENT_MASK_REMOVE) {
int res = 0;
int err;
bag_iterator_t i, n;
bag_for_each_safe(i, n, bag) {
- snd_mixer_elem_t *melem = bag_iterator_entry(i);
- snd_mixer_class_t *class = melem->class;
- err = class->event(class, mask, helem, melem);
+ snd_amixer_elem_t *melem = bag_iterator_entry(i);
+ err = melem->amixer->event(melem->amixer, mask, elem, melem);
if (err < 0)
res = err;
}
@@ -154,9 +430,8 @@ static int hctl_elem_event_handler(snd_hctl_elem_t *helem,
int err = 0;
bag_iterator_t i, n;
bag_for_each_safe(i, n, bag) {
- snd_mixer_elem_t *melem = bag_iterator_entry(i);
- snd_mixer_class_t *class = melem->class;
- err = class->event(class, mask, helem, melem);
+ snd_amixer_elem_t *melem = bag_iterator_entry(i);
+ err = melem->amixer->event(melem->amixer, mask, elem, melem);
if (err < 0)
return err;
}
@@ -164,176 +439,57 @@ static int hctl_elem_event_handler(snd_hctl_elem_t *helem,
return 0;
}
-static int hctl_event_handler(snd_hctl_t *hctl, unsigned int mask,
- snd_hctl_elem_t *elem)
+static int ctl_event_handler(snd_ctl_t *ctl,
+ unsigned int mask,
+ snd_ctl_elem_t *elem)
{
- snd_mixer_t *mixer = snd_hctl_get_callback_private(hctl);
+ snd_amixer_t *amixer = snd_ctl_get_callback_private(ctl);
int res = 0;
if (mask & SND_CTL_EVENT_MASK_ADD) {
- struct list_head *pos;
bag_t *bag;
int err = bag_new(&bag);
if (err < 0)
return err;
- snd_hctl_elem_set_callback(elem, hctl_elem_event_handler);
- snd_hctl_elem_set_callback_private(elem, bag);
- list_for_each(pos, &mixer->classes) {
- snd_mixer_class_t *c;
- c = list_entry(pos, snd_mixer_class_t, list);
- err = c->event(c, mask, elem, NULL);
- if (err < 0)
- res = err;
- }
+ snd_ctl_elem_set_callback(elem, ctl_elem_event_handler);
+ snd_ctl_elem_set_callback_private(elem, bag);
+ err = amixer->event(amixer, mask, elem, NULL);
+ if (err < 0)
+ return err;
}
return res;
}
-
-/**
- * \brief Attach an HCTL specified with the CTL device name 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_hctl_t *hctl;
- int err;
-
- err = snd_hctl_open(&hctl, name, 0);
- if (err < 0)
- return err;
- err = snd_mixer_attach_hctl(mixer, hctl);
- if (err < 0) {
- snd_hctl_close(hctl);
- return err;
- }
- return 0;
-}
-
-/**
- * \brief Attach an HCTL to an opened mixer
- * \param mixer Mixer handle
- * \param hctl the HCTL to be attached
- * \return 0 on success otherwise a negative error code
- */
-int snd_mixer_attach_hctl(snd_mixer_t *mixer, snd_hctl_t *hctl)
-{
- snd_mixer_slave_t *slave;
- int err;
-
- assert(hctl);
- slave = calloc(1, sizeof(*slave));
- if (slave == NULL)
- return -ENOMEM;
- err = snd_hctl_nonblock(hctl, 1);
- if (err < 0) {
- snd_hctl_close(hctl);
- free(slave);
- return err;
- }
- snd_hctl_set_callback(hctl, hctl_event_handler);
- snd_hctl_set_callback_private(hctl, mixer);
- slave->hctl = hctl;
- list_add_tail(&slave->list, &mixer->slaves);
- 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;
- list_for_each(pos, &mixer->slaves) {
- snd_mixer_slave_t *s;
- s = list_entry(pos, snd_mixer_slave_t, list);
- if (strcmp(name, snd_hctl_name(s->hctl)) == 0) {
- snd_hctl_close(s->hctl);
- list_del(pos);
- free(s);
- return 0;
- }
- }
- return -ENOENT;
-}
-
-/**
- * \brief Detach a previously attached HCTL to an opened mixer freeing all related resources
- * \param mixer Mixer handle
- * \param hctl HCTL previously attached
- * \return 0 on success otherwise a negative error code
- *
- * Note: The hctl handle is not closed!
- */
-int snd_mixer_detach_hctl(snd_mixer_t *mixer, snd_hctl_t *hctl)
-{
- struct list_head *pos;
- list_for_each(pos, &mixer->slaves) {
- snd_mixer_slave_t *s;
- s = list_entry(pos, snd_mixer_slave_t, list);
- if (hctl == s->hctl) {
- list_del(pos);
- free(s);
- return 0;
- }
- }
- return -ENOENT;
-}
-
-/**
- * \brief Obtain a HCTL pointer associated to given name
- * \param mixer Mixer handle
- * \param name HCTL previously attached
- * \param hctl HCTL pointer
- * \return 0 on success otherwise a negative error code
- */
-int snd_mixer_get_hctl(snd_mixer_t *mixer, const char *name, snd_hctl_t **hctl)
-{
- struct list_head *pos;
- list_for_each(pos, &mixer->slaves) {
- snd_mixer_slave_t *s;
- s = list_entry(pos, snd_mixer_slave_t, list);
- if (strcmp(name, snd_hctl_name(s->hctl)) == 0) {
- *hctl = s->hctl;
- return 0;
- }
- }
- return -ENOENT;
-}
-
-static int snd_mixer_throw_event(snd_mixer_t *mixer, unsigned int mask,
- snd_mixer_elem_t *elem)
+static int snd_amixer_throw_event(snd_amixer_t *amixer,
+ unsigned int mask,
+ snd_amixer_elem_t *elem)
{
- mixer->events++;
- if (mixer->callback)
- return mixer->callback(mixer, mask, elem);
+ amixer->events++;
+ if (amixer->callback)
+ return amixer->callback(amixer, mask, elem);
return 0;
}
-static int snd_mixer_elem_throw_event(snd_mixer_elem_t *elem, unsigned int mask)
+static int snd_amixer_elem_throw_event(snd_amixer_elem_t *elem,
+ unsigned int mask)
{
- elem->class->mixer->events++;
+ elem->amixer->events++;
if (elem->callback)
return elem->callback(elem, mask);
return 0;
}
-static int _snd_mixer_find_elem(snd_mixer_t *mixer, snd_mixer_elem_t *elem, int *dir)
+static int _snd_amixer_find_elem(snd_amixer_t *amixer, snd_amixer_elem_t *elem, int *dir)
{
unsigned int l, u;
int c = 0;
int idx = -1;
- assert(mixer && elem);
- assert(mixer->compare);
+ assert(amixer && elem);
+ assert(amixer->compare);
l = 0;
- u = mixer->count;
+ u = amixer->count;
while (l < u) {
idx = (l + u) / 2;
- c = mixer->compare(elem, mixer->pelems[idx]);
+ c = amixer->compare(elem, amixer->pelems[idx]);
if (c < 0)
u = idx;
else if (c > 0)
@@ -346,38 +502,37 @@ static int _snd_mixer_find_elem(snd_mixer_t *mixer, snd_mixer_elem_t *elem, int
}
/**
- * \brief Get private data associated to give mixer element
+ * \brief Get private data associated to give amixer element
* \param elem Mixer element
* \return private data
- *
- * For use by mixer element class specific code.
*/
-void *snd_mixer_elem_get_private(const snd_mixer_elem_t *elem)
+void *snd_amixer_elem_get_private(const snd_amixer_elem_t *elem)
{
return elem->private_data;
}
/**
- * \brief Allocate a new mixer element
- * \param elem Returned mixer element
- * \param type Mixer element type
+ * \brief Allocate a new amixer element
+ * \param amixer Mixer handle
+ * \param elem Returned amixer element
+ * \param id Element identificator
* \param compare_weight Mixer element compare weight
* \param private_data Private data
* \param private_free Private data free callback
* \return 0 on success otherwise a negative error code
- *
- * For use by mixer element class specific code.
*/
-int snd_mixer_elem_new(snd_mixer_elem_t **elem,
- snd_mixer_elem_type_t type,
- int compare_weight,
- void *private_data,
- void (*private_free)(snd_mixer_elem_t *elem))
+int snd_amixer_elem_new(snd_amixer_t *amixer,
+ snd_amixer_elem_t **elem,
+ snd_amixer_elem_id_t *id,
+ int compare_weight,
+ void *private_data,
+ void (*private_free)(snd_amixer_elem_t *elem))
{
- snd_mixer_elem_t *melem = calloc(1, sizeof(*melem));
+ snd_amixer_elem_t *melem = calloc(1, sizeof(*melem));
if (melem == NULL)
return -ENOMEM;
- melem->type = type;
+ melem->amixer = amixer;
+ melem->sm.id = *id;
melem->compare_weight = compare_weight;
melem->private_data = private_data;
melem->private_free = private_free;
@@ -387,92 +542,84 @@ int snd_mixer_elem_new(snd_mixer_elem_t **elem,
}
/**
- * \brief Add an element for a registered mixer element class
+ * \brief Add an element for an amixer handle
+ * \param amixer Mixer handle
* \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 snd_amixer_elem_add(snd_amixer_t *amixer, snd_amixer_elem_t *elem)
{
int dir, idx;
- snd_mixer_t *mixer = class->mixer;
- elem->class = class;
- if (mixer->count == mixer->alloc) {
- snd_mixer_elem_t **m;
- mixer->alloc += 32;
- m = realloc(mixer->pelems, sizeof(*m) * mixer->alloc);
+ if (amixer->count == amixer->alloc) {
+ snd_amixer_elem_t **m;
+ amixer->alloc += 32;
+ m = realloc(amixer->pelems, sizeof(*m) * amixer->alloc);
if (!m) {
- mixer->alloc -= 32;
+ amixer->alloc -= 32;
return -ENOMEM;
}
- mixer->pelems = m;
+ amixer->pelems = m;
}
- if (mixer->count == 0) {
- list_add_tail(&elem->list, &mixer->elems);
- mixer->pelems[0] = elem;
+ if (amixer->count == 0) {
+ list_add_tail(&elem->list, &amixer->elems);
+ amixer->pelems[0] = elem;
} else {
- idx = _snd_mixer_find_elem(mixer, elem, &dir);
+ idx = _snd_amixer_find_elem(amixer, elem, &dir);
assert(dir != 0);
if (dir > 0) {
- list_add(&elem->list, &mixer->pelems[idx]->list);
+ list_add(&elem->list, &amixer->pelems[idx]->list);
idx++;
} else {
- list_add_tail(&elem->list, &mixer->pelems[idx]->list);
+ list_add_tail(&elem->list, &amixer->pelems[idx]->list);
}
- memmove(mixer->pelems + idx + 1,
- mixer->pelems + idx,
- (mixer->count - idx) * sizeof(snd_mixer_elem_t *));
- mixer->pelems[idx] = elem;
+ memmove(amixer->pelems + idx + 1,
+ amixer->pelems + idx,
+ (amixer->count - idx) * sizeof(snd_amixer_elem_t *));
+ amixer->pelems[idx] = elem;
}
- mixer->count++;
- return snd_mixer_throw_event(mixer, SND_CTL_EVENT_MASK_ADD, elem);
+ amixer->count++;
+ return snd_amixer_throw_event(amixer, SND_CTL_EVENT_MASK_ADD, elem);
}
/**
- * \brief Remove a mixer element
+ * \brief Remove a amixer 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)
+int snd_amixer_elem_remove(snd_amixer_elem_t *elem)
{
- snd_mixer_t *mixer = elem->class->mixer;
+ snd_amixer_t *amixer = elem->amixer;
bag_iterator_t i, n;
int err, idx, dir;
unsigned int m;
assert(elem);
- assert(mixer->count);
- idx = _snd_mixer_find_elem(mixer, elem, &dir);
+ assert(amixer->count);
+ idx = _snd_amixer_find_elem(amixer, elem, &dir);
if (dir != 0)
return -EINVAL;
bag_for_each_safe(i, n, &elem->helems) {
- snd_hctl_elem_t *helem = bag_iterator_entry(i);
- snd_mixer_elem_detach(elem, helem);
+ snd_ctl_elem_t *helem = bag_iterator_entry(i);
+ snd_amixer_elem_detach(elem, helem);
}
- err = snd_mixer_elem_throw_event(elem, SND_CTL_EVENT_MASK_REMOVE);
+ err = snd_amixer_elem_throw_event(elem, SND_CTL_EVENT_MASK_REMOVE);
list_del(&elem->list);
- snd_mixer_elem_free(elem);
- mixer->count--;
- m = mixer->count - idx;
+ snd_amixer_elem_free(elem);
+ amixer->count--;
+ m = amixer->count - idx;
if (m > 0)
- memmove(mixer->pelems + idx,
- mixer->pelems + idx + 1,
- m * sizeof(snd_mixer_elem_t *));
+ memmove(amixer->pelems + idx,
+ amixer->pelems + idx + 1,
+ m * sizeof(snd_amixer_elem_t *));
return err;
}
/**
- * \brief Free a mixer element
+ * \brief Free a amixer element
* \param elem Mixer element
* \return 0 on success otherwise a negative error code
- *
- * For use by mixer element class specific code.
*/
-void snd_mixer_elem_free(snd_mixer_elem_t *elem)
+void snd_amixer_elem_free(snd_amixer_elem_t *elem)
{
if (elem->private_free)
elem->private_free(elem);
@@ -483,214 +630,100 @@ void snd_mixer_elem_free(snd_mixer_elem_t *elem)
* \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)
+int snd_amixer_elem_info(snd_amixer_elem_t *elem)
{
- return snd_mixer_elem_throw_event(elem, SND_CTL_EVENT_MASK_INFO);
+ return snd_amixer_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;
- class->mixer = mixer;
- list_add_tail(&class->list, &mixer->classes);
- if (!class->event)
- return 0;
- list_for_each(pos, &mixer->slaves) {
- int err;
- snd_mixer_slave_t *slave;
- snd_hctl_elem_t *elem;
- slave = list_entry(pos, snd_mixer_slave_t, list);
- elem = snd_hctl_first_elem(slave->hctl);
- while (elem) {
- err = class->event(class, SND_CTL_EVENT_MASK_ADD, elem, NULL);
- if (err < 0)
- return err;
- elem = snd_hctl_elem_next(elem);
- }
- }
- 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
- *
- * Note that the class structure is also deallocated!
*/
-int snd_mixer_class_unregister(snd_mixer_class_t *class)
+int snd_amixer_elem_value(snd_amixer_elem_t *elem)
{
- unsigned int k;
- snd_mixer_elem_t *e;
- snd_mixer_t *mixer = class->mixer;
- for (k = mixer->count; k > 0; k--) {
- e = mixer->pelems[k-1];
- if (e->class == class)
- snd_mixer_elem_remove(e);
- }
- if (class->private_free)
- class->private_free(class);
- list_del(&class->list);
- free(class);
- return 0;
+ return snd_amixer_elem_throw_event(elem, SND_CTL_EVENT_MASK_VALUE);
}
/**
- * \brief Load a mixer elements
- * \param mixer Mixer handle
+ * \brief Close a amixer and free all related resources
+ * \param amixer Mixer handle
* \return 0 on success otherwise a negative error code
*/
-int snd_mixer_load(snd_mixer_t *mixer)
+int snd_amixer_close(snd_amixer_t *amixer)
{
- struct list_head *pos;
- list_for_each(pos, &mixer->slaves) {
- int err;
- snd_mixer_slave_t *s;
- s = list_entry(pos, snd_mixer_slave_t, list);
- err = snd_hctl_load(s->hctl);
- if (err < 0)
- return err;
- }
- return 0;
-}
+ int res = 0, i;
-/**
- * \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;
- list_for_each(pos, &mixer->slaves) {
- snd_mixer_slave_t *s;
- s = list_entry(pos, snd_mixer_slave_t, list);
- snd_hctl_free(s->hctl);
- }
-}
-
-/**
- * \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;
- assert(mixer);
- while (!list_empty(&mixer->classes)) {
- snd_mixer_class_t *c;
- c = list_entry(mixer->classes.next, snd_mixer_class_t, list);
- snd_mixer_class_unregister(c);
+ assert(amixer);
+ for (i = 0; i < SM_CTL_COUNT; i++) {
+ if (amixer->sm_open.ctl[i])
+ res = snd_ctl_close(amixer->sm_open.ctl[i]);
+ amixer->sm_open.ctl[i] = NULL;
}
- assert(list_empty(&mixer->elems));
- assert(mixer->count == 0);
- free(mixer->pelems);
- mixer->pelems = NULL;
- while (!list_empty(&mixer->slaves)) {
- int err;
- snd_mixer_slave_t *s;
- s = list_entry(mixer->slaves.next, snd_mixer_slave_t, list);
- err = snd_hctl_close(s->hctl);
- if (err < 0)
- res = err;
- list_del(&s->list);
- free(s);
- }
- free(mixer);
+ assert(list_empty(&amixer->elems));
+ if (amixer->pelems)
+ free(amixer->pelems);
+ if (amixer->dl_handle)
+ snd_dlclose(amixer->dl_handle);
+ free(amixer);
return res;
}
-static int snd_mixer_compare_default(const snd_mixer_elem_t *c1,
- const snd_mixer_elem_t *c2)
-{
- int d = c1->compare_weight - c2->compare_weight;
- if (d)
- return d;
- assert(c1->class && c1->class->compare);
- assert(c2->class && c2->class->compare);
- assert(c1->class == c2->class);
- return c1->class->compare(c1, c2);
-}
-
-static int mixer_compare(const void *a, const void *b)
+static int amixer_compare(const void *a, const void *b)
{
- snd_mixer_t *mixer;
+ snd_amixer_t *amixer;
- mixer = (*((const snd_mixer_elem_t * const *)a))->class->mixer;
- return mixer->compare(*(const snd_mixer_elem_t * const *)a, *(const snd_mixer_elem_t * const *)b);
+ amixer = (*((const snd_amixer_elem_t * const *)a))->amixer;
+ return amixer->compare(*(const snd_amixer_elem_t * const *)a, *(const snd_amixer_elem_t * const *)b);
}
-static int snd_mixer_sort(snd_mixer_t *mixer)
+static int snd_amixer_sort(snd_amixer_t *amixer)
{
unsigned int k;
- assert(mixer);
- assert(mixer->compare);
- INIT_LIST_HEAD(&mixer->elems);
- qsort(mixer->pelems, mixer->count, sizeof(snd_mixer_elem_t *), mixer_compare);
- for (k = 0; k < mixer->count; k++)
- list_add_tail(&mixer->pelems[k]->list, &mixer->elems);
+ assert(amixer);
+ assert(amixer->compare);
+ INIT_LIST_HEAD(&amixer->elems);
+ qsort(amixer->pelems, amixer->count, sizeof(snd_amixer_elem_t *), amixer_compare);
+ for (k = 0; k < amixer->count; k++)
+ list_add_tail(&amixer->pelems[k]->list, &amixer->elems);
return 0;
}
/**
- * \brief Change mixer compare function and reorder elements
- * \param mixer Mixer handle
+ * \brief Change amixer compare function and reorder elements
+ * \param amixer 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)
+int snd_amixer_set_compare(snd_amixer_t *amixer, snd_amixer_compare_t compare)
{
- snd_mixer_compare_t compare_old;
+ snd_amixer_compare_t compare_old;
int err;
- assert(mixer);
- compare_old = mixer->compare;
- mixer->compare = compare == NULL ? snd_mixer_compare_default : compare;
- if ((err = snd_mixer_sort(mixer)) < 0) {
- mixer->compare = compare_old;
+ assert(amixer);
+ compare_old = amixer->compare;
+ amixer->compare = compare == NULL ? snd_amixer_compare_default : compare;
+ if ((err = snd_amixer_sort(amixer)) < 0) {
+ amixer->compare = compare_old;
return err;
}
return 0;
}
/**
- * \brief get count of poll descriptors for mixer handle
- * \param mixer Mixer handle
+ * \brief get count of poll descriptors for amixer handle
+ * \param amixer Mixer handle
* \return count of poll descriptors
*/
-int snd_mixer_poll_descriptors_count(snd_mixer_t *mixer)
+int snd_amixer_poll_descriptors_count(snd_amixer_t *amixer)
{
- struct list_head *pos;
- unsigned int c = 0;
- assert(mixer);
- list_for_each(pos, &mixer->slaves) {
- snd_mixer_slave_t *s;
- int n;
- s = list_entry(pos, snd_mixer_slave_t, list);
- n = snd_hctl_poll_descriptors_count(s->hctl);
+ assert(amixer);
+ int i, c = 0, n;
+ for (i = 0; i < SM_CTL_COUNT; i++) {
+ if (amixer->sm_open.ctl[i] == NULL)
+ continue;
+ n = snd_ctl_poll_descriptors_count(amixer->sm_open.ctl[i]);
if (n < 0)
return n;
c += n;
@@ -700,46 +733,46 @@ int snd_mixer_poll_descriptors_count(snd_mixer_t *mixer)
/**
* \brief get poll descriptors
- * \param mixer Mixer handle
+ * \param amixer 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)
+int snd_amixer_poll_descriptors(snd_amixer_t *amixer, struct pollfd *pfds, unsigned int space)
{
- struct list_head *pos;
- unsigned int count = 0;
- assert(mixer);
- list_for_each(pos, &mixer->slaves) {
- snd_mixer_slave_t *s;
- int n;
- s = list_entry(pos, snd_mixer_slave_t, list);
- n = snd_hctl_poll_descriptors(s->hctl, pfds, space);
+ int i, count = 0, n;
+
+ assert(amixer);
+ for (i = 0; i < SM_CTL_COUNT; i++) {
+ if (amixer->sm_open.ctl[i] == NULL)
+ continue;
+ n = snd_ctl_poll_descriptors(amixer->sm_open.ctl[i], pfds, space);
if (n < 0)
return n;
- if (space >= (unsigned int) n) {
+ if (space >= (unsigned int)n) {
count += n;
space -= n;
pfds += n;
- } else
+ } else {
space = 0;
+ }
}
return count;
}
/**
* \brief get returned events from poll descriptors
- * \param mixer Mixer handle
+ * \param amixer Mixer handle
* \param pfds array of poll descriptors
* \param nfds count of poll descriptors
* \param revents returned events
* \return zero if success, otherwise a negative error code
*/
-int snd_mixer_poll_descriptors_revents(snd_mixer_t *mixer, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
+int snd_amixer_poll_descriptors_revents(snd_amixer_t *amixer, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
{
unsigned int idx;
unsigned short res;
- assert(mixer && pfds && revents);
+ assert(amixer && pfds && revents);
if (nfds == 0)
return -EINVAL;
res = 0;
@@ -750,25 +783,25 @@ int snd_mixer_poll_descriptors_revents(snd_mixer_t *mixer, struct pollfd *pfds,
}
/**
- * \brief Wait for a mixer to become ready (i.e. at least one event pending)
- * \param mixer Mixer handle
+ * \brief Wait for a amixer to become ready (i.e. at least one event pending)
+ * \param amixer 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)
+int snd_amixer_wait(snd_amixer_t *amixer, int timeout)
{
struct pollfd spfds[16];
struct pollfd *pfds = spfds;
int err;
int count;
- count = snd_mixer_poll_descriptors(mixer, pfds, sizeof(spfds) / sizeof(spfds[0]));
+ count = snd_amixer_poll_descriptors(amixer, pfds, sizeof(spfds) / sizeof(spfds[0]));
if (count < 0)
return count;
if ((unsigned int) count > sizeof(spfds) / sizeof(spfds[0])) {
pfds = malloc(count * sizeof(*pfds));
if (!pfds)
return -ENOMEM;
- err = snd_mixer_poll_descriptors(mixer, pfds,
+ err = snd_amixer_poll_descriptors(amixer, pfds,
(unsigned int) count);
assert(err == count);
}
@@ -779,305 +812,181 @@ int snd_mixer_wait(snd_mixer_t *mixer, int timeout)
}
/**
- * \brief get first element for a mixer
- * \param mixer Mixer handle
+ * \brief get first element for a amixer
+ * \param amixer Mixer handle
* \return pointer to first element
*/
-snd_mixer_elem_t *snd_mixer_first_elem(snd_mixer_t *mixer)
+snd_amixer_elem_t *snd_amixer_first_elem(snd_amixer_t *amixer)
{
- assert(mixer);
- if (list_empty(&mixer->elems))
+ assert(amixer);
+ if (list_empty(&amixer->elems))
return NULL;
- return list_entry(mixer->elems.next, snd_mixer_elem_t, list);
+ return list_entry(amixer->elems.next, snd_amixer_elem_t, list);
}
/**
- * \brief get last element for a mixer
- * \param mixer Mixer handle
+ * \brief get last element for a amixer
+ * \param amixer Mixer handle
* \return pointer to last element
*/
-snd_mixer_elem_t *snd_mixer_last_elem(snd_mixer_t *mixer)
+snd_amixer_elem_t *snd_amixer_last_elem(snd_amixer_t *amixer)
{
- assert(mixer);
- if (list_empty(&mixer->elems))
+ assert(amixer);
+ if (list_empty(&amixer->elems))
return NULL;
- return list_entry(mixer->elems.prev, snd_mixer_elem_t, list);
+ return list_entry(amixer->elems.prev, snd_amixer_elem_t, list);
}
/**
- * \brief get next mixer element
- * \param elem mixer element
+ * \brief get next amixer element
+ * \param elem amixer element
* \return pointer to next element
*/
-snd_mixer_elem_t *snd_mixer_elem_next(snd_mixer_elem_t *elem)
+snd_amixer_elem_t *snd_amixer_elem_next(snd_amixer_elem_t *elem)
{
assert(elem);
- if (elem->list.next == &elem->class->mixer->elems)
+ if (elem->list.next == &elem->amixer->elems)
return NULL;
- return list_entry(elem->list.next, snd_mixer_elem_t, list);
+ return list_entry(elem->list.next, snd_amixer_elem_t, list);
}
/**
- * \brief get previous mixer element
- * \param elem mixer element
+ * \brief get previous amixer element
+ * \param elem amixer element
* \return pointer to previous element
*/
-snd_mixer_elem_t *snd_mixer_elem_prev(snd_mixer_elem_t *elem)
+snd_amixer_elem_t *snd_amixer_elem_prev(snd_amixer_elem_t *elem)
{
assert(elem);
- if (elem->list.prev == &elem->class->mixer->elems)
+ if (elem->list.prev == &elem->amixer->elems)
return NULL;
- return list_entry(elem->list.prev, snd_mixer_elem_t, list);
+ return list_entry(elem->list.prev, snd_amixer_elem_t, list);
}
/**
- * \brief Handle pending mixer events invoking callbacks
- * \param mixer Mixer handle
+ * \brief Handle pending amixer events invoking callbacks
+ * \param amixer Mixer handle
* \return Number of events that occured on success, otherwise a negative error code on failure
*/
-int snd_mixer_handle_events(snd_mixer_t *mixer)
+int snd_amixer_handle_events(snd_amixer_t *amixer)
{
- struct list_head *pos;
- assert(mixer);
- mixer->events = 0;
- list_for_each(pos, &mixer->slaves) {
- int err;
- snd_mixer_slave_t *s;
- s = list_entry(pos, snd_mixer_slave_t, list);
- err = snd_hctl_handle_events(s->hctl);
+ int err, i;
+
+ assert(amixer);
+ amixer->events = 0;
+ for (i = 0; i < SM_CTL_COUNT; i++) {
+ if (amixer->sm_open.ctl[i] == NULL)
+ continue;
+ err = snd_ctl_handle_events(amixer->sm_open.ctl[i]);
if (err < 0)
return err;
}
- return mixer->events;
+ return amixer->events;
}
/**
- * \brief Set callback function for a mixer
- * \param obj mixer handle
+ * \brief Set event callback function for a amixer
+ * \param obj amixer handle
* \param val callback function
+ *
+ * This function is used in the mixer implementation. Use callback
+ * functions to watch events.
*/
-void snd_mixer_set_callback(snd_mixer_t *obj, snd_mixer_callback_t val)
+void snd_amixer_set_event(snd_amixer_t *obj, snd_amixer_event_t val)
{
assert(obj);
- obj->callback = val;
-}
-
-/**
- * \brief Set callback private value for a mixer
- * \param mixer mixer handle
- * \param val callback private value
- */
-void snd_mixer_set_callback_private(snd_mixer_t *mixer, void * val)
-{
- assert(mixer);
- mixer->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 *mixer)
-{
- assert(mixer);
- return mixer->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 *mixer)
-{
- assert(mixer);
- return mixer->count;
+ obj->event = val;
}
/**
- * \brief Set callback function for a mixer element
- * \param mixer mixer element
+ * \brief Set callback function for a amixer
+ * \param obj amixer handle
* \param val callback function
*/
-void snd_mixer_elem_set_callback(snd_mixer_elem_t *mixer, snd_mixer_elem_callback_t val)
-{
- assert(mixer);
- mixer->callback = val;
-}
-
-/**
- * \brief Set callback private value for a mixer element
- * \param mixer mixer element
- * \param val callback private value
- */
-void snd_mixer_elem_set_callback_private(snd_mixer_elem_t *mixer, void * val)
-{
- assert(mixer);
- mixer->callback_private = val;
-}
-
-/**
- * \brief Get callback private value for a mixer element
- * \param mixer mixer element
- * \return callback private value
- */
-void * snd_mixer_elem_get_callback_private(const snd_mixer_elem_t *mixer)
-{
- assert(mixer);
- return mixer->callback_private;
-}
-
-/**
- * \brief Get type for a mixer element
- * \param mixer mixer element
- * \return mixer element type
- */
-snd_mixer_elem_type_t snd_mixer_elem_get_type(const snd_mixer_elem_t *mixer)
-{
- assert(mixer);
- return mixer->type;
-}
-
-
-/**
- * \brief get size of #snd_mixer_class_t
- * \return size in bytes
- */
-size_t snd_mixer_class_sizeof()
-{
- return sizeof(snd_mixer_class_t);
-}
-
-/**
- * \brief allocate an invalid #snd_mixer_class_t using standard malloc
- * \param ptr returned pointer
- * \return 0 on success otherwise negative error code
- */
-int snd_mixer_class_malloc(snd_mixer_class_t **ptr)
-{
- assert(ptr);
- *ptr = calloc(1, sizeof(snd_mixer_class_t));
- if (!*ptr)
- return -ENOMEM;
- return 0;
-}
-
-/**
- * \brief frees a previously allocated #snd_mixer_class_t
- * \param obj pointer to object to free
- */
-void snd_mixer_class_free(snd_mixer_class_t *obj)
-{
- if (obj->private_free)
- obj->private_free(obj);
- free(obj);
-}
-
-/**
- * \brief copy one #snd_mixer_class_t to another
- * \param dst pointer to destination
- * \param src pointer to source
- */
-void snd_mixer_class_copy(snd_mixer_class_t *dst, const snd_mixer_class_t *src)
-{
- assert(dst && src);
- *dst = *src;
-}
-
-/**
- * \brief Get a mixer associated to given mixer class
- * \param obj Mixer simple class identifier
- * \return mixer pointer
- */
-snd_mixer_t *snd_mixer_class_get_mixer(const snd_mixer_class_t *obj)
+void snd_amixer_set_callback(snd_amixer_t *obj, snd_amixer_callback_t val)
{
assert(obj);
- return obj->mixer;
+ obj->callback = val;
}
/**
- * \brief Get mixer event callback associated to given mixer class
- * \param obj Mixer simple class identifier
- * \return event callback pointer
+ * \brief Set callback private value for a amixer
+ * \param obj amixer handle
+ * \param val callback private value
*/
-snd_mixer_event_t snd_mixer_class_get_event(const snd_mixer_class_t *obj)
+void snd_amixer_set_callback_private(snd_amixer_t *obj, void * val)
{
assert(obj);
- return obj->event;
+ obj->callback_private = val;
}
/**
- * \brief Get mixer private data associated to given mixer class
- * \param obj Mixer simple class identifier
- * \return event callback pointer
+ * \brief Get callback private value for a amixer
+ * \param amixer amixer handle
+ * \return callback private value
*/
-void *snd_mixer_class_get_private(const snd_mixer_class_t *obj)
+void * snd_amixer_get_callback_private(const snd_amixer_t *amixer)
{
- assert(obj);
- return obj->private_data;
+ assert(amixer);
+ return amixer->callback_private;
}
-
/**
- * \brief Get mixer compare callback associated to given mixer class
- * \param obj Mixer simple class identifier
- * \return event callback pointer
+ * \brief Get elements count for a amixer
+ * \param amixer amixer handle
+ * \return elements count
*/
-snd_mixer_compare_t snd_mixer_class_get_compare(const snd_mixer_class_t *obj)
+unsigned int snd_amixer_get_count(const snd_amixer_t *amixer)
{
- assert(obj);
- return obj->compare;
+ assert(amixer);
+ return amixer->count;
}
/**
- * \brief Set mixer event callback to given mixer class
- * \param obj Mixer simple class identifier
- * \param event Event callback
- * \return zero if success, otherwise a negative error code
+ * \brief Set callback function for a amixer element
+ * \param amixer amixer element
+ * \param val callback function
*/
-int snd_mixer_class_set_event(snd_mixer_class_t *obj, snd_mixer_event_t event)
+void snd_amixer_elem_set_callback(snd_amixer_elem_t *amixer, snd_amixer_elem_callback_t val)
{
- assert(obj);
- obj->event = event;
- return 0;
+ assert(amixer);
+ amixer->callback = val;
}
/**
- * \brief Set mixer private data to given mixer class
- * \param obj Mixer simple class identifier
- * \param private_data class private data
- * \return zero if success, otherwise a negative error code
+ * \brief Set callback private value for a amixer element
+ * \param amixer amixer element
+ * \param val callback private value
*/
-int snd_mixer_class_set_private(snd_mixer_class_t *obj, void *private_data)
+void snd_amixer_elem_set_callback_private(snd_amixer_elem_t *amixer, void * val)
{
- assert(obj);
- obj->private_data = private_data;
- return 0;
+ assert(amixer);
+ amixer->callback_private = val;
}
/**
- * \brief Set mixer private data free callback to given mixer class
- * \param obj Mixer simple class identifier
- * \param private_free Mixer class private data free callback
- * \return zero if success, otherwise a negative error code
+ * \brief Get callback private value for a amixer element
+ * \param amixer amixer element
+ * \return callback private value
*/
-int snd_mixer_class_set_private_free(snd_mixer_class_t *obj, void (*private_free)(snd_mixer_class_t *class))
+void * snd_amixer_elem_get_callback_private(const snd_amixer_elem_t *amixer)
{
- assert(obj);
- obj->private_free = private_free;
- return 0;
+ assert(amixer);
+ return amixer->callback_private;
}
/**
- * \brief Set mixer compare callback to given mixer class
- * \param obj Mixer simple class identifier
- * \param compare the compare callback to be used
- * \return zero if success, otherwise a negative error code
+ * \brief Check if ID is generic
+ * \param id string
+ * \return 1 if success, otherwise 0
*/
-int snd_mixer_class_set_compare(snd_mixer_class_t *obj, snd_mixer_compare_t compare)
+int snd_amixer_conf_generic_id(const char *id)
{
- assert(obj);
- obj->compare = compare;
+ static const char ids[3][8] = { "comment", "type", "hint" };
+ unsigned int k;
+ for (k = 0; k < sizeof(ids) / sizeof(ids[0]); ++k) {
+ if (strcmp(id, ids[k]) == 0)
+ return 1;
+ }
return 0;
}
diff --git a/src/mixer/mixer_local.h b/src/mixer/mixer_local.h
index 27b4a3b1..cf68ffe3 100644
--- a/src/mixer/mixer_local.h
+++ b/src/mixer/mixer_local.h
@@ -21,6 +21,7 @@
*/
#include "local.h"
+#include "mixer_abst.h"
typedef struct _bag1 {
void *ptr;
@@ -42,41 +43,40 @@ typedef struct list_head *bag_iterator_t;
#define bag_for_each(pos, bag) list_for_each(pos, bag)
#define bag_for_each_safe(pos, next, bag) list_for_each_safe(pos, next, bag)
-struct _snd_mixer_class {
- struct list_head list;
- snd_mixer_t *mixer;
- snd_mixer_event_t event;
- void *private_data;
- void (*private_free)(snd_mixer_class_t *class);
- snd_mixer_compare_t compare;
-};
-
-struct _snd_mixer_elem {
- snd_mixer_elem_type_t type;
+struct _snd_amixer_elem {
struct list_head list; /* links for list of all elems */
- snd_mixer_class_t *class;
+ snd_amixer_t *amixer;
+ snd_ctl_t *ctl;
void *private_data;
- void (*private_free)(snd_mixer_elem_t *elem);
- snd_mixer_elem_callback_t callback;
+ void (*private_free)(snd_amixer_elem_t *elem);
+ snd_amixer_elem_callback_t callback;
void *callback_private;
bag_t helems;
int compare_weight; /* compare weight (reversed) */
+ sm_elem_t sm;
};
-struct _snd_mixer {
- struct list_head slaves; /* list of all slaves */
- struct list_head classes; /* list of all elem classes */
- struct list_head elems; /* list of all elems */
- snd_mixer_elem_t **pelems; /* array of all elems */
+struct _snd_amixer {
+ struct sm_open sm_open;
+ struct list_head elems; /* list of all elems */
+ snd_amixer_elem_t **pelems; /* array of all elems */
unsigned int count;
unsigned int alloc;
unsigned int events;
- snd_mixer_callback_t callback;
+ snd_amixer_callback_t callback;
void *callback_private;
- snd_mixer_compare_t compare;
+ snd_amixer_compare_t compare;
+ snd_amixer_event_t event;
+ void *dl_handle;
};
-struct _snd_mixer_selem_id {
- char name[60];
- unsigned int index;
-};
+/* make local functions really local */
+#define snd_amixer_simple_none_open \
+ snd1_amixer_simple_none_open
+#define snd_amixer_simple_basic_open \
+ snd1_amixer_simple_basic_open
+
+int snd_amixer_simple_none_open(snd_amixer_t *amixer,
+ struct sm_open *sm_open);
+int snd_amixer_simple_basic_open(snd_amixer_t *amixer,
+ struct sm_open *sm_open);
diff --git a/src/mixer/mixer_old.c b/src/mixer/mixer_old.c
new file mode 100644
index 00000000..37da864e
--- /dev/null
+++ b/src/mixer/mixer_old.c
@@ -0,0 +1,375 @@
+/**
+ * \file mixer/mixer.c
+ * \brief Mixer Interface
+ * \author Jaroslav Kysela <perex@perex.cz>
+ * \author Abramo Bagnara <abramo@alsa-project.org>
+ * \date 2001
+ *
+ * Old (v1) 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@perex.cz>
+ * 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 Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/*! \page mixer Mixer interface
+
+<P>Mixer interface is designed to access the abstracted mixer controls.
+This is an abstraction layer over the hcontrol layer.
+
+\section mixer_general_overview General overview
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include "mixer_old_local.h"
+
+/**
+ * \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;
+ assert(mixerp);
+ mixer = calloc(1, sizeof(*mixer));
+ if (mixer == NULL)
+ return -ENOMEM;
+ *mixerp = mixer;
+ return 0;
+}
+
+/**
+ * \brief Attach a HCTL to midxer
+ * \param mixer Mixer handle
+ * \param name the HCTL device name
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_mixer_attach(snd_mixer_t *mixer, const char *name)
+{
+ assert(mixer);
+ assert(name);
+ if (mixer->amixer)
+ return -EBUSY;
+ return snd_amixer_open(&mixer->amixer, name, NULL, NULL, SND_AMIXER_COMPAT1);
+}
+
+/**
+ * \brief Attach an HCTL to an opened mixer
+ * \param mixer Mixer handle
+ * \param hctl the HCTL to be attached
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_mixer_attach_hctl(snd_mixer_t *mixer, snd_hctl_t *hctl)
+{
+ return -ENXIO;
+}
+
+/**
+ * \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)
+{
+ return -ENXIO;
+}
+
+/**
+ * \brief Detach a previously attached HCTL to an opened mixer freeing all related resources
+ * \param mixer Mixer handle
+ * \param hctl HCTL previously attached
+ * \return 0 on success otherwise a negative error code
+ *
+ * Note: The hctl handle is not closed!
+ */
+int snd_mixer_detach_hctl(snd_mixer_t *mixer, snd_hctl_t *hctl)
+{
+ return -ENXIO;
+}
+
+/**
+ * \brief Obtain a HCTL pointer associated to given name
+ * \param mixer Mixer handle
+ * \param name HCTL previously attached
+ * \param hctl HCTL pointer
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_mixer_get_hctl(snd_mixer_t *mixer, const char *name, snd_hctl_t **hctl)
+{
+ return -ENXIO;
+}
+
+/**
+ * \brief Get private data associated to give mixer element
+ * \param elem Mixer element
+ * \return private data
+ *
+ * For use by mixer element class specific code.
+ */
+void *snd_mixer_elem_get_private(const snd_mixer_elem_t *elem)
+{
+ return snd_amixer_elem_get_private(elem);
+}
+
+/**
+ * \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)
+{
+ return 0;
+}
+
+/**
+ * \brief Unload all mixer elements and free all related resources
+ * \param mixer Mixer handle
+ */
+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;
+
+ if (mixer->amixer)
+ res = snd_amixer_close(mixer->amixer);
+ free(mixer);
+ return 0;
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_set_compare(mixer->amixer, compare);
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_poll_descriptors_count(mixer->amixer);
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_poll_descriptors(mixer->amixer, pfds, space);
+}
+
+/**
+ * \brief get returned events from poll descriptors
+ * \param mixer Mixer handle
+ * \param pfds array of poll descriptors
+ * \param nfds count of poll descriptors
+ * \param revents returned events
+ * \return zero if success, otherwise a negative error code
+ */
+int snd_mixer_poll_descriptors_revents(snd_mixer_t *mixer, struct pollfd *pfds, unsigned int nfds, unsigned short *revents)
+{
+ return snd_amixer_poll_descriptors_revents(mixer->amixer, pfds, nfds, revents);
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_wait(mixer->amixer, timeout);
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_first_elem(mixer->amixer);
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_last_elem(mixer->amixer);
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_elem_next(elem);
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_elem_prev(elem);
+}
+
+/**
+ * \brief Handle pending mixer events invoking callbacks
+ * \param mixer Mixer handle
+ * \return Number of events that occured on success, otherwise a negative error code on failure
+ */
+int snd_mixer_handle_events(snd_mixer_t *mixer)
+{
+ return snd_amixer_handle_events(mixer->amixer);
+}
+
+static int snd_mixer_default_callback(snd_amixer_t *mixer,
+ unsigned int mask,
+ snd_mixer_elem_t *elem)
+{
+ snd_mixer_t *old = snd_amixer_get_callback_private(mixer);
+ return old->callback(old, mask, elem);
+}
+
+/**
+ * \brief Set callback function for a mixer
+ * \param obj mixer handle
+ * \param val callback function
+ */
+void snd_mixer_set_callback(snd_mixer_t *obj, snd_mixer_callback_t val)
+{
+ assert(obj);
+ obj->callback = val;
+ snd_amixer_set_callback(obj->amixer, snd_mixer_default_callback);
+ snd_amixer_set_callback_private(obj->amixer, obj);
+}
+
+/**
+ * \brief Set callback private value for a mixer
+ * \param mixer mixer handle
+ * \param val callback private value
+ */
+void snd_mixer_set_callback_private(snd_mixer_t *mixer, void * val)
+{
+ assert(mixer);
+ mixer->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 *mixer)
+{
+ assert(mixer);
+ return mixer->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 *mixer)
+{
+ return snd_amixer_get_count(mixer->amixer);
+}
+
+/**
+ * \brief Set callback function for a mixer element
+ * \param mixer mixer element
+ * \param val callback function
+ */
+void snd_mixer_elem_set_callback(snd_mixer_elem_t *mixer, snd_mixer_elem_callback_t val)
+{
+ return snd_amixer_elem_set_callback(mixer, val);
+}
+
+/**
+ * \brief Set callback private value for a mixer element
+ * \param elem mixer element
+ * \param val callback private value
+ */
+void snd_mixer_elem_set_callback_private(snd_mixer_elem_t *elem, void * val)
+{
+ return snd_amixer_elem_set_callback_private(elem, val);
+}
+
+/**
+ * \brief Get callback private value for a mixer element
+ * \param elem mixer element
+ * \return callback private value
+ */
+void * snd_mixer_elem_get_callback_private(const snd_mixer_elem_t *elem)
+{
+ return snd_amixer_elem_get_callback_private(elem);
+}
+
+/**
+ * \brief Get type for a mixer element
+ * \param mixer mixer element
+ * \return mixer element type
+ */
+snd_mixer_elem_type_t snd_mixer_elem_get_type(const snd_mixer_elem_t *mixer)
+{
+ assert(mixer);
+ return SND_MIXER_ELEM_SIMPLE;
+}
+
+
diff --git a/src/mixer/mixer_simple.h b/src/mixer/mixer_old_local.h
index e88b0071..16d10c05 100644
--- a/src/mixer/mixer_simple.h
+++ b/src/mixer/mixer_old_local.h
@@ -1,6 +1,7 @@
/*
- * Mixer Simple Interface - local header file
- * Copyright (c) 2005 by Jaroslav Kysela <perex@perex.cz>
+ * Mixer Interface - local header file
+ * Copyright (c) 2000 by Jaroslav Kysela <perex@perex.cz>
+ * Copyright (c) 2001 by Abramo Bagnara <abramo@alsa-project.org>
*
*
* This library is free software; you can redistribute it and/or modify
@@ -19,13 +20,11 @@
*
*/
-#include "mixer_abst.h"
+#include "local.h"
+#include "mixer_old.h"
-/* make local functions really local */
-#define snd_mixer_simple_none_register \
- snd1_mixer_simple_none_register
-#define snd_mixer_simple_basic_register \
- snd1_mixer_simple_basic_register
-
-int snd_mixer_simple_none_register(snd_mixer_t *mixer, struct snd_mixer_selem_regopt *options, snd_mixer_class_t **classp);
-int snd_mixer_simple_basic_register(snd_mixer_t *mixer, struct snd_mixer_selem_regopt *options, snd_mixer_class_t **classp);
+struct _snd_mixer {
+ snd_amixer_t *amixer;
+ snd_mixer_callback_t callback;
+ void *callback_private;
+};
diff --git a/src/mixer/mixer_symbols.c b/src/mixer/mixer_symbols.c
new file mode 100644
index 00000000..29af4c0e
--- /dev/null
+++ b/src/mixer/mixer_symbols.c
@@ -0,0 +1,36 @@
+/*
+ * Mixer Symbols
+ * Copyright (c) 2009 by Jaroslav Kysela <perex@perex.cz>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef PIC
+
+#include "config.h"
+
+extern const char *_snd_module_mixer_none;
+
+static const char **snd_pcm_open_objects[] = {
+ &_snd_module_mixer_none,
+};
+
+void *snd_mixer_open_symbols(void)
+{
+ return snd_mixer_open_objects;
+}
+
+#endif /* !PIC */
diff --git a/src/mixer/simple.c b/src/mixer/simple.c
index 39790b2e..8cbe484d 100644
--- a/src/mixer/simple.c
+++ b/src/mixer/simple.c
@@ -3,7 +3,7 @@
* \brief Mixer Simple Element Class Interface
* \author Jaroslav Kysela <perex@perex.cz>
* \author Abramo Bagnara <abramo@alsa-project.org>
- * \date 2001-2004
+ * \date 2001-2008
*
* Mixer simple element class interface.
*/
@@ -37,89 +37,33 @@
#include <sys/ioctl.h>
#include <math.h>
#include "mixer_local.h"
-#include "mixer_simple.h"
-
-/**
- * \brief Register mixer simple element class
- * \param mixer Mixer handle
- * \param options Options container
- * \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,
- struct snd_mixer_selem_regopt *options,
- snd_mixer_class_t **classp)
-{
- if (options && options->ver == 1) {
- if (options->device != NULL &&
- (options->playback_pcm != NULL ||
- options->capture_pcm != NULL))
- return -EINVAL;
- if (options->device == NULL &&
- options->playback_pcm == NULL &&
- options->capture_pcm == NULL)
- return -EINVAL;
- }
- if (options == NULL ||
- (options->ver == 1 && options->abstract == SND_MIXER_SABSTRACT_NONE)) {
- int err = snd_mixer_simple_none_register(mixer, options, classp);
- if (err < 0)
- return err;
- if (options != NULL) {
- err = snd_mixer_attach(mixer, options->device);
- if (err < 0)
- return err;
- }
- return 0;
- } else if (options->ver == 1) {
- if (options->abstract == SND_MIXER_SABSTRACT_BASIC)
- return snd_mixer_simple_basic_register(mixer, options, classp);
- }
- return -ENXIO;
-}
#ifndef DOC_HIDDEN
-#define CHECK_BASIC(xelem) \
-{ \
- assert(xelem); \
- assert((xelem)->type == SND_MIXER_ELEM_SIMPLE); \
-}
-
-#define CHECK_DIR(xelem, xwhat) \
-{ \
- unsigned int xcaps = ((sm_selem_t *)(elem)->private_data)->caps; \
- if (! (xcaps & (xwhat))) \
- return -EINVAL; \
-}
-
-#define CHECK_DIR_CHN(xelem, xwhat, xjoin, xchannel) \
-{ \
- unsigned int xcaps = ((sm_selem_t *)(elem)->private_data)->caps; \
- if (! (xcaps & (xwhat))) \
- return -EINVAL; \
- if (xcaps & (xjoin)) \
- xchannel = 0; \
-}
-
#define CHECK_ENUM(xelem) \
- if (!((sm_selem_t *)(elem)->private_data)->caps & (SM_CAP_PENUM|SM_CAP_CENUM)) \
+ if (!(elem->sm.caps & (SM_CAP_PENUM|SM_CAP_CENUM))) \
return -EINVAL;
#define COND_CAPS(xelem, what) \
- !!(((sm_selem_t *)(elem)->private_data)->caps & (what))
+ !!(elem->sm.caps & (what))
+
+#define sm_elem(x) (&(x)->sm)
+#define sm_elem_ops(x) ((x)->sm.ops)
#endif /* !DOC_HIDDEN */
#ifndef DOC_HIDDEN
-int snd_mixer_selem_compare(const snd_mixer_elem_t *c1, const snd_mixer_elem_t *c2)
+int snd_amixer_compare_default(const snd_amixer_elem_t *c1, const snd_amixer_elem_t *c2)
{
- sm_selem_t *s1 = c1->private_data;
- sm_selem_t *s2 = c2->private_data;
- int res = strcmp(s1->id->name, s2->id->name);
- if (res)
- return res;
- return s1->id->index - s2->id->index;
+ int d;
+
+ d = c1->compare_weight - c2->compare_weight;
+ if (d)
+ return d;
+ d = strcmp(c1->sm.id.name, c2->sm.id.name);
+ if (d)
+ return d;
+ return c1->sm.id.index - c2->sm.id.index;
}
#endif
@@ -129,19 +73,15 @@ int snd_mixer_selem_compare(const snd_mixer_elem_t *c1, const snd_mixer_elem_t *
* \param id Mixer simple element identifier
* \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)
+snd_amixer_elem_t *snd_amixer_find_elem(snd_amixer_t *mixer,
+ const snd_amixer_elem_id_t *id)
{
struct list_head *list;
- snd_mixer_elem_t *e;
- sm_selem_t *s;
+ snd_amixer_elem_t *e;
list_for_each(list, &mixer->elems) {
- e = list_entry(list, snd_mixer_elem_t, list);
- if (e->type != SND_MIXER_ELEM_SIMPLE)
- continue;
- s = e->private_data;
- if (!strcmp(s->id->name, id->name) && s->id->index == id->index)
+ e = list_entry(list, snd_amixer_elem_t, list);
+ if (!strcmp(e->sm.id.name, id->name) && e->sm.id.index == id->index)
return e;
}
return NULL;
@@ -152,14 +92,11 @@ snd_mixer_elem_t *snd_mixer_find_selem(snd_mixer_t *mixer,
* \param elem Mixer simple element handle
* \param id returned mixer simple element identifier
*/
-void snd_mixer_selem_get_id(snd_mixer_elem_t *elem,
- snd_mixer_selem_id_t *id)
+void snd_amixer_elem_get_id(snd_amixer_elem_t *elem,
+ snd_amixer_elem_id_t *id)
{
- sm_selem_t *s;
assert(id);
- CHECK_BASIC(elem);
- s = elem->private_data;
- *id = *s->id;
+ *id = elem->sm.id;
}
/**
@@ -167,12 +104,9 @@ void snd_mixer_selem_get_id(snd_mixer_elem_t *elem,
* \param elem Mixer simple element handle
* \return name part of simple element identifier
*/
-const char *snd_mixer_selem_get_name(snd_mixer_elem_t *elem)
+const char *snd_amixer_elem_get_name(snd_amixer_elem_t *elem)
{
- sm_selem_t *s;
- CHECK_BASIC(elem);
- s = elem->private_data;
- return s->id->name;
+ return elem->sm.id.name;
}
/**
@@ -180,34 +114,73 @@ const char *snd_mixer_selem_get_name(snd_mixer_elem_t *elem)
* \param elem Mixer simple element handle
* \return index part of simple element identifier
*/
-unsigned int snd_mixer_selem_get_index(snd_mixer_elem_t *elem)
+unsigned int snd_amixer_elem_get_index(snd_amixer_elem_t *elem)
{
- sm_selem_t *s;
- CHECK_BASIC(elem);
- s = elem->private_data;
- return s->id->index;
+ return elem->sm.id.index;
}
/**
- * \brief Return true if mixer simple element has only one volume control for both playback and capture
+ * \brief Return true if mixer simple element has control for specified direction
* \param elem Mixer simple element handle
- * \return 0 separated control, 1 common control
+ * \param dir Mixer direction
+ * \return 0 false, 1 true
*/
-int snd_mixer_selem_has_common_volume(snd_mixer_elem_t *elem)
+int snd_amixer_elem_has_volume(snd_amixer_elem_t *elem, snd_amixer_dir_t dir)
{
- CHECK_BASIC(elem);
- return COND_CAPS(elem, SM_CAP_GVOLUME);
+ if (dir == SM_COMM)
+ return COND_CAPS(elem, SM_CAP_GVOLUME);
+ if (dir == SM_PLAY)
+ return COND_CAPS(elem, SM_CAP_PVOLUME);
+ if (dir == SM_CAPT)
+ return COND_CAPS(elem, SM_CAP_CVOLUME);
+ return 0;
}
/**
- * \brief Return true if mixer simple element has only one switch control for both playback and capture
+ * \brief Return info about volume control of a mixer simple element
* \param elem Mixer simple element handle
- * \return 0 separated control, 1 common control
+ * \param dir Mixer direction
+ * \return 0 if control is separated per channel, 1 if control acts on all channels together
*/
-int snd_mixer_selem_has_common_switch(snd_mixer_elem_t *elem)
+int snd_amixer_elem_has_volume_joined(snd_amixer_elem_t *elem, snd_amixer_dir_t dir)
{
- CHECK_BASIC(elem);
- return COND_CAPS(elem, SM_CAP_GSWITCH);
+ if (dir == SM_PLAY)
+ return COND_CAPS(elem, SM_CAP_PVOLUME_JOIN);
+ if (dir == SM_CAPT)
+ return COND_CAPS(elem, SM_CAP_CVOLUME_JOIN);
+ return 0;
+}
+
+/**
+ * \brief Return true if mixer simple element has control for specified direction
+ * \param elem Mixer simple element handle
+ * \param dir Mixer direction
+ * \return 0 false, 1 true
+ */
+int snd_amixer_elem_has_switch(snd_amixer_elem_t *elem, snd_amixer_dir_t dir)
+{
+ if (dir == SM_COMM)
+ return COND_CAPS(elem, SM_CAP_GSWITCH);
+ if (dir == SM_PLAY)
+ return COND_CAPS(elem, SM_CAP_PSWITCH);
+ if (dir == SM_CAPT)
+ return COND_CAPS(elem, SM_CAP_CSWITCH);
+ return 0;
+}
+
+/**
+ * \brief Return info about switch control of a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param dir Mixer direction
+ * \return 0 if control is separated per channel, 1 if control acts on all channels together
+ */
+int snd_amixer_elem_has_switch_joined(snd_amixer_elem_t *elem, snd_amixer_dir_t dir)
+{
+ if (dir == SM_PLAY)
+ return COND_CAPS(elem, SM_CAP_PSWITCH_JOIN);
+ if (dir == SM_CAPT)
+ return COND_CAPS(elem, SM_CAP_CSWITCH_JOIN);
+ return 0;
}
/**
@@ -215,7 +188,7 @@ int snd_mixer_selem_has_common_switch(snd_mixer_elem_t *elem)
* \param channel mixer simple element channel identifier
* \return channel name
*/
-const char *snd_mixer_selem_channel_name(snd_mixer_selem_channel_id_t channel)
+const char *snd_amixer_elem_channel_name(snd_amixer_elem_channel_id_t channel)
{
static const char *const array[SND_MIXER_SCHN_LAST + 1] = {
[SND_MIXER_SCHN_FRONT_LEFT] = "Front Left",
@@ -241,270 +214,262 @@ const char *snd_mixer_selem_channel_name(snd_mixer_selem_channel_id_t channel)
* \param elem Mixer simple element handle
* \return 0 if not active, 1 if active
*/
-int snd_mixer_selem_is_active(snd_mixer_elem_t *elem)
+int snd_amixer_elem_is_active(snd_amixer_elem_t *elem)
{
- CHECK_BASIC(elem);
- return sm_selem_ops(elem)->is(elem, SM_PLAY, SM_OPS_IS_ACTIVE, 0);
+ return sm_elem_ops(elem)->is(elem, SM_PLAY, SM_OPS_IS_ACTIVE, 0);
}
/**
- * \brief Get info about channels of playback stream of a mixer simple element
+ * \brief Get info about channels of a mixer simple element
* \param elem Mixer simple element handle
- * \return 0 if not mono, 1 if mono
+ * \param dir Mixer direction
+ * \param channel Mixer simple element channel identifier
+ * \return 0 if channel is not present, 1 if present
*/
-int snd_mixer_selem_is_playback_mono(snd_mixer_elem_t *elem)
+int snd_amixer_elem_has_channel(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, snd_amixer_elem_channel_id_t channel)
{
- CHECK_BASIC(elem);
- return sm_selem_ops(elem)->is(elem, SM_PLAY, SM_OPS_IS_MONO, 0);
+ return sm_elem_ops(elem)->is(elem, dir, SM_OPS_IS_CHANNEL, (int)channel);
}
/**
- * \brief Get info about channels of playback stream of a mixer simple element
+ * \brief Get count of valid channels
* \param elem Mixer simple element handle
- * \param channel Mixer simple element channel identifier
- * \return 0 if channel is not present, 1 if present
+ * \param dir Mixer direction
+ * \return 1 or more
*/
-int snd_mixer_selem_has_playback_channel(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel)
+int snd_amixer_elem_get_channels(snd_amixer_elem_t *elem, snd_amixer_dir_t dir)
{
- CHECK_BASIC(elem);
- return sm_selem_ops(elem)->is(elem, SM_PLAY, SM_OPS_IS_CHANNEL, (int)channel);
+ return sm_elem_ops(elem)->get_channels(elem, dir);
}
/**
- * \brief Get range for playback volume of a mixer simple element
+ * \brief Get range for volume of a mixer simple element
* \param elem Mixer simple element handle
+ * \param dir Mixer direction
* \param min Pointer to returned minimum
* \param max Pointer to returned maximum
*/
-int snd_mixer_selem_get_playback_volume_range(snd_mixer_elem_t *elem,
- long *min, long *max)
+int snd_amixer_elem_get_volume_range(snd_amixer_elem_t *elem,
+ snd_amixer_dir_t dir,
+ long *min, long *max)
{
- CHECK_BASIC(elem);
- CHECK_DIR(elem, SM_CAP_PVOLUME);
- return sm_selem_ops(elem)->get_range(elem, SM_PLAY, min, max);
+ if (!snd_amixer_elem_has_volume(elem, dir))
+ return -EINVAL;
+ return sm_elem_ops(elem)->get_range(elem, dir, min, max);
}
/**
- * \brief Get range in dB for playback volume of a mixer simple element
+ * \brief Get range in dB for volume of a mixer simple element
* \param elem Mixer simple element handle
+ * \param dir Mixer direction
* \param min Pointer to returned minimum (dB * 100)
* \param max Pointer to returned maximum (dB * 100)
*/
-int snd_mixer_selem_get_playback_dB_range(snd_mixer_elem_t *elem,
- long *min, long *max)
+int snd_amixer_elem_get_dB_range(snd_amixer_elem_t *elem,
+ snd_amixer_dir_t dir,
+ long *min, long *max)
{
- CHECK_BASIC(elem);
- CHECK_DIR(elem, SM_CAP_PVOLUME);
- return sm_selem_ops(elem)->get_dB_range(elem, SM_PLAY, min, max);
+ if (!snd_amixer_elem_has_volume(elem, dir))
+ return -EINVAL;
+ return sm_elem_ops(elem)->get_dB_range(elem, dir, min, max);
}
/**
- * \brief Set range for playback volume of a mixer simple element
+ * \brief Set range for volume of a mixer simple element
* \param elem Mixer simple element handle
+ * \param dir Mixer direction
* \param min minimum volume value
* \param max maximum volume value
*/
-int snd_mixer_selem_set_playback_volume_range(snd_mixer_elem_t *elem,
- long min, long max)
+int snd_amixer_elem_set_volume_range(snd_amixer_elem_t *elem,
+ snd_amixer_dir_t dir,
+ long min, long max)
{
- CHECK_BASIC(elem);
assert(min < max);
- CHECK_DIR(elem, SM_CAP_PVOLUME);
- return sm_selem_ops(elem)->set_range(elem, SM_PLAY, min, max);
-}
-
-/**
- * \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)
-{
- CHECK_BASIC(elem);
- return COND_CAPS(elem, SM_CAP_PVOLUME);
-}
-
-/**
- * \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)
-{
- CHECK_BASIC(elem);
- return COND_CAPS(elem, SM_CAP_PVOLUME_JOIN);
-}
-
-/**
- * \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)
-{
- CHECK_BASIC(elem);
- return COND_CAPS(elem, SM_CAP_PSWITCH);
-}
-
-/**
- * \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)
-{
- CHECK_BASIC(elem);
- return COND_CAPS(elem, SM_CAP_PSWITCH_JOIN);
+ if (!snd_amixer_elem_has_volume(elem, dir))
+ return -EINVAL;
+ return sm_elem_ops(elem)->set_range(elem, dir, min, max);
}
/**
- * \brief Return corresponding dB value to an integer playback volume for a mixer simple element
+ * \brief Return corresponding dB value to an integer volume for a mixer simple element
* \param elem Mixer simple element handle
+ * \param dir Mixer direction
* \param value value to be converted to dB range
* \param dBvalue pointer to returned dB value
* \return 0 on success otherwise a negative error code
*/
-int snd_mixer_selem_ask_playback_vol_dB(snd_mixer_elem_t *elem, long value, long *dBvalue)
+int snd_amixer_elem_ask_vol_dB(snd_amixer_elem_t *elem, snd_amixer_dir_t dir,
+ long value, long *dBvalue)
{
- CHECK_BASIC(elem);
- CHECK_DIR(elem, SM_CAP_PVOLUME);
- return sm_selem_ops(elem)->ask_vol_dB(elem, SM_PLAY, value, dBvalue);
+ if (!snd_amixer_elem_has_volume(elem, dir))
+ return -EINVAL;
+ return sm_elem_ops(elem)->ask_vol_dB(elem, dir, value, dBvalue);
}
/**
- * \brief Return corresponding integer playback volume for given dB value for a mixer simple element
+ * \brief Return corresponding integer volume for given dB value for a mixer simple element
* \param elem Mixer simple element handle
+ * \param dir Mixer direction
* \param value value to be converted to dB range
- * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
+ * \param xdir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
* \param dBvalue pointer to returned dB value
* \return 0 on success otherwise a negative error code
*/
-int snd_mixer_selem_ask_playback_dB_vol(snd_mixer_elem_t *elem, long dBvalue, int dir, long *value)
+int snd_amixer_elem_ask_dB_vol(snd_amixer_elem_t *elem,
+ snd_amixer_dir_t dir,
+ long dBvalue, int xdir, long *value)
{
- CHECK_BASIC(elem);
- CHECK_DIR(elem, SM_CAP_PVOLUME);
- return sm_selem_ops(elem)->ask_dB_vol(elem, SM_PLAY, dBvalue, value, dir);
+ if (!snd_amixer_elem_has_volume(elem, dir))
+ return -EINVAL;
+ return sm_elem_ops(elem)->ask_dB_vol(elem, dir, dBvalue, value, xdir);
}
/**
* \brief Return value of playback volume control of a mixer simple element
* \param elem Mixer simple element handle
+ * \param dir Mixer direction
* \param channel mixer simple element channel identifier
* \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 snd_amixer_elem_get_volume(snd_amixer_elem_t *elem, snd_amixer_dir_t dir,
+ snd_amixer_elem_channel_id_t channel,
+ long *value)
{
- CHECK_BASIC(elem);
- CHECK_DIR_CHN(elem, SM_CAP_PVOLUME, SM_CAP_PVOLUME_JOIN, channel);
- return sm_selem_ops(elem)->get_volume(elem, SM_PLAY, channel, value);
+ if (!snd_amixer_elem_has_volume(elem, dir))
+ return -EINVAL;
+ if (snd_amixer_elem_has_volume_joined(elem, dir))
+ channel = 0;
+ return sm_elem_ops(elem)->get_volume(elem, dir, channel, value);
}
/**
- * \brief Return value of playback volume in dB control of a mixer simple element
+ * \brief Return value of volume in dB control of a mixer simple element
* \param elem Mixer simple element handle
+ * \param dir Mixer direction
* \param channel mixer simple element channel identifier
* \param value pointer to returned value (dB * 100)
* \return 0 on success otherwise a negative error code
*/
-int snd_mixer_selem_get_playback_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value)
+int snd_amixer_elem_get_dB(snd_amixer_elem_t *elem,
+ snd_amixer_dir_t dir,
+ snd_amixer_elem_channel_id_t channel, long *value)
{
- unsigned int caps;
-
- CHECK_BASIC(elem);
- caps = ((sm_selem_t *)elem->private_data)->caps;
- if (!(caps & SM_CAP_PVOLUME))
+ if (!snd_amixer_elem_has_volume(elem, dir))
return -EINVAL;
- if (caps & SM_CAP_PVOLUME_JOIN)
+ if (snd_amixer_elem_has_volume_joined(elem, dir))
channel = 0;
- return sm_selem_ops(elem)->get_dB(elem, SM_PLAY, channel, value);
+ return sm_elem_ops(elem)->get_dB(elem, dir, channel, value);
}
/**
* \brief Return value of playback switch control of a mixer simple element
* \param elem Mixer simple element handle
+ * \param dir Mixer direction
* \param channel mixer simple element channel identifier
* \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 snd_amixer_elem_get_switch(snd_amixer_elem_t *elem,
+ snd_amixer_dir_t dir,
+ snd_amixer_elem_channel_id_t channel,
+ int *value)
{
- CHECK_BASIC(elem);
- CHECK_DIR_CHN(elem, SM_CAP_PSWITCH, SM_CAP_PSWITCH_JOIN, channel);
- return sm_selem_ops(elem)->get_switch(elem, SM_PLAY, channel, value);
+ if (!snd_amixer_elem_has_volume(elem, dir))
+ return -EINVAL;
+ if (snd_amixer_elem_has_volume_joined(elem, dir))
+ channel = 0;
+ return sm_elem_ops(elem)->get_switch(elem, dir, channel, value);
}
/**
- * \brief Set value of playback volume control of a mixer simple element
+ * \brief Set value of volume control of a mixer simple element
* \param elem Mixer simple element handle
+ * \param dir Mixer direction
* \param channel mixer simple element channel identifier
* \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 snd_amixer_elem_set_volume(snd_amixer_elem_t *elem,
+ snd_amixer_dir_t dir,
+ snd_amixer_elem_channel_id_t channel,
+ long value)
{
- CHECK_BASIC(elem);
- CHECK_DIR_CHN(elem, SM_CAP_PVOLUME, SM_CAP_PVOLUME_JOIN, channel);
- return sm_selem_ops(elem)->set_volume(elem, SM_PLAY, channel, value);
+ if (!snd_amixer_elem_has_volume(elem, dir))
+ return -EINVAL;
+ if (snd_amixer_elem_has_volume_joined(elem, dir))
+ channel = 0;
+ return sm_elem_ops(elem)->set_volume(elem, dir, channel, value);
}
/**
* \brief Set value in dB of playback volume control of a mixer simple element
* \param elem Mixer simple element handle
+ * \param dir Mixer direction
* \param channel mixer simple element channel identifier
* \param value control value in dB * 100
* \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
* \return 0 on success otherwise a negative error code
*/
-int snd_mixer_selem_set_playback_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value, int dir)
+int snd_amixer_elem_set_dB(snd_amixer_elem_t *elem,
+ snd_amixer_dir_t dir,
+ snd_amixer_elem_channel_id_t channel,
+ long value, int xdir)
{
- CHECK_BASIC(elem);
- CHECK_DIR_CHN(elem, SM_CAP_PVOLUME, SM_CAP_PVOLUME_JOIN, channel);
- return sm_selem_ops(elem)->set_dB(elem, SM_PLAY, channel, value, dir);
+ if (!snd_amixer_elem_has_volume(elem, dir))
+ return -EINVAL;
+ if (snd_amixer_elem_has_volume_joined(elem, dir))
+ channel = 0;
+ return sm_elem_ops(elem)->set_dB(elem, dir, channel, value, xdir);
}
/**
- * \brief Set value of playback volume control for all channels of a mixer simple element
+ * \brief Set value of volume control for all channels of a mixer simple element
* \param elem Mixer simple element handle
+ * \param dir Mixer direction
* \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 snd_amixer_elem_set_volume_all(snd_amixer_elem_t *elem,
+ snd_amixer_dir_t dir, long value)
{
- snd_mixer_selem_channel_id_t chn;
+ snd_amixer_elem_channel_id_t chn;
int err;
- for (chn = 0; chn < 32; chn++) {
- if (!snd_mixer_selem_has_playback_channel(elem, chn))
+ for (chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) {
+ if (!snd_amixer_elem_has_channel(elem, dir, chn))
continue;
- err = snd_mixer_selem_set_playback_volume(elem, chn, value);
+ err = snd_amixer_elem_set_volume(elem, dir, chn, value);
if (err < 0)
return err;
- if (chn == 0 && snd_mixer_selem_has_playback_volume_joined(elem))
+ if (chn == 0 && snd_amixer_elem_has_volume_joined(elem, dir))
return 0;
}
return 0;
}
/**
- * \brief Set value in dB of playback volume control for all channels of a mixer simple element
+ * \brief Set value in dB of volume control for all channels of a mixer simple element
* \param elem Mixer simple element handle
+ * \param dir Mixer direction
* \param value control value in dB * 100
* \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
* \return 0 on success otherwise a negative error code
*/
-int snd_mixer_selem_set_playback_dB_all(snd_mixer_elem_t *elem, long value, int dir)
+int snd_amixer_elem_set_dB_all(snd_amixer_elem_t *elem, snd_amixer_dir_t dir,
+ long value, int xdir)
{
- snd_mixer_selem_channel_id_t chn;
+ snd_amixer_elem_channel_id_t chn;
int err;
- for (chn = 0; chn < 32; chn++) {
- if (!snd_mixer_selem_has_playback_channel(elem, chn))
+ for (chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) {
+ if (!snd_amixer_elem_has_channel(elem, dir, chn))
continue;
- err = snd_mixer_selem_set_playback_dB(elem, chn, value, dir);
+ err = snd_amixer_elem_set_dB(elem, dir, chn, value, xdir);
if (err < 0)
return err;
- if (chn == 0 && snd_mixer_selem_has_playback_volume_joined(elem))
+ if (chn == 0 && snd_amixer_elem_has_volume_joined(elem, dir))
return 0;
}
return 0;
@@ -513,397 +478,91 @@ int snd_mixer_selem_set_playback_dB_all(snd_mixer_elem_t *elem, long value, int
/**
* \brief Set value of playback switch control of a mixer simple element
* \param elem Mixer simple element handle
+ * \param dir Mixer direction
* \param channel mixer simple element channel identifier
* \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 snd_amixer_elem_set_switch(snd_amixer_elem_t *elem,
+ snd_amixer_dir_t dir,
+ snd_amixer_elem_channel_id_t channel,
+ int value)
{
- CHECK_BASIC(elem);
- CHECK_DIR_CHN(elem, SM_CAP_PSWITCH, SM_CAP_PSWITCH_JOIN, channel);
- return sm_selem_ops(elem)->set_switch(elem, SM_PLAY, channel, value);
+ if (!snd_amixer_elem_has_switch(elem, dir))
+ return -EINVAL;
+ if (snd_amixer_elem_has_switch_joined(elem, dir))
+ channel = 0;
+ return sm_elem_ops(elem)->set_switch(elem, dir, channel, value);
}
/**
- * \brief Set value of playback switch control for all channels of a mixer simple element
+ * \brief Set value of switch control for all channels of a mixer simple element
* \param elem Mixer simple element handle
+ * \param dir Mixer direction
* \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 snd_amixer_elem_set_switch_all(snd_amixer_elem_t *elem,
+ snd_amixer_dir_t dir, int value)
{
- snd_mixer_selem_channel_id_t chn;
+ snd_amixer_elem_channel_id_t chn;
int err;
- CHECK_BASIC(elem);
- for (chn = 0; chn < 32; chn++) {
- if (!snd_mixer_selem_has_playback_channel(elem, chn))
+ for (chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) {
+ if (!snd_amixer_elem_has_channel(elem, dir, chn))
continue;
- err = snd_mixer_selem_set_playback_switch(elem, chn, value);
+ err = snd_amixer_elem_set_switch(elem, dir, chn, value);
if (err < 0)
return err;
- if (chn == 0 && snd_mixer_selem_has_playback_switch_joined(elem))
+ if (chn == 0 && snd_amixer_elem_has_switch_joined(elem, dir))
return 0;
}
return 0;
}
/**
- * \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)
-{
- CHECK_BASIC(elem);
- CHECK_DIR(elem, SM_CAP_CVOLUME|SM_CAP_CSWITCH);
- return sm_selem_ops(elem)->is(elem, SM_CAPT, SM_OPS_IS_MONO, 0);
-}
-
-/**
- * \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 identifier
- * \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)
-{
- CHECK_BASIC(elem);
- CHECK_DIR(elem, SM_CAP_CVOLUME|SM_CAP_CSWITCH);
- return sm_selem_ops(elem)->is(elem, SM_CAPT, SM_OPS_IS_CHANNEL, channel);
-}
-
-/**
- * \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
- */
-int snd_mixer_selem_get_capture_volume_range(snd_mixer_elem_t *elem,
- long *min, long *max)
-{
- CHECK_BASIC(elem);
- CHECK_DIR(elem, SM_CAP_CVOLUME);
- return sm_selem_ops(elem)->get_range(elem, SM_CAPT, min, max);
-}
-
-/**
- * \brief Get range in dB for capture volume of a mixer simple element
- * \param elem Mixer simple element handle
- * \param min Pointer to returned minimum (dB * 100)
- * \param max Pointer to returned maximum (dB * 100)
- */
-int snd_mixer_selem_get_capture_dB_range(snd_mixer_elem_t *elem,
- long *min, long *max)
-{
- CHECK_BASIC(elem);
- CHECK_DIR(elem, SM_CAP_CVOLUME);
- return sm_selem_ops(elem)->get_dB_range(elem, SM_CAPT, min, 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
- */
-int snd_mixer_selem_set_capture_volume_range(snd_mixer_elem_t *elem,
- long min, long max)
-{
- CHECK_BASIC(elem);
- assert(min < max);
- CHECK_DIR(elem, SM_CAP_CVOLUME);
- return sm_selem_ops(elem)->set_range(elem, SM_CAPT, min, 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)
-{
- CHECK_BASIC(elem);
- return COND_CAPS(elem, SM_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)
-{
- CHECK_BASIC(elem);
- return COND_CAPS(elem, SM_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)
-{
- CHECK_BASIC(elem);
- return COND_CAPS(elem, SM_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)
-{
- CHECK_BASIC(elem);
- return COND_CAPS(elem, SM_CAP_CSWITCH_JOIN);
-}
-
-/**
- * \brief Return info about capture switch control of a mixer simple element
+ * \brief Return info about switch control of a mixer simple element
* \param elem Mixer simple element handle
+ * \param dir Mixer direction (should be capture for now)
* \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)
+int snd_amixer_elem_has_switch_exclusive(snd_amixer_elem_t *elem, snd_amixer_dir_t dir)
{
- CHECK_BASIC(elem);
- return COND_CAPS(elem, SM_CAP_CSWITCH_EXCL);
+ if (dir == SM_CAPT)
+ return COND_CAPS(elem, SM_CAP_CSWITCH_EXCL);
+ return 0;
}
/**
- * \brief Return info about capture switch control of a mixer simple element
+ * \brief Return info about 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)
+ * \param dir Mixer direction
+ * \return group for switch exclusivity (see #snd_amixer_elem_has_switch_exclusive)
*/
-int snd_mixer_selem_get_capture_group(snd_mixer_elem_t *elem)
+int snd_amixer_elem_get_group(snd_amixer_elem_t *elem, snd_amixer_dir_t dir)
{
- sm_selem_t *s;
- CHECK_BASIC(elem);
- s = elem->private_data;
+ sm_elem_t *s;
+ if (dir != SM_CAPT)
+ return -EINVAL;
+ s = sm_elem(elem);
if (! (s->caps & SM_CAP_CSWITCH_EXCL))
return -EINVAL;
return s->capture_group;
}
/**
- * \brief Return corresponding dB value to an integer capture volume for a mixer simple element
- * \param elem Mixer simple element handle
- * \param value value to be converted to dB range
- * \param dBvalue pointer to returned dB value
- * \return 0 on success otherwise a negative error code
- */
-int snd_mixer_selem_ask_capture_vol_dB(snd_mixer_elem_t *elem, long value, long *dBvalue)
-{
- CHECK_BASIC(elem);
- CHECK_DIR(elem, SM_CAP_CVOLUME);
- return sm_selem_ops(elem)->ask_vol_dB(elem, SM_CAPT, value, dBvalue);
-}
-
-/**
- * \brief Return corresponding integer capture volume for given dB value for a mixer simple element
- * \param elem Mixer simple element handle
- * \param dBvalue dB value to be converted to integer range
- * \param value pointer to returned integer value
- * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
- * \return 0 on success otherwise a negative error code
- */
-int snd_mixer_selem_ask_capture_dB_vol(snd_mixer_elem_t *elem, long dBvalue, int dir, long *value)
-{
- CHECK_BASIC(elem);
- CHECK_DIR(elem, SM_CAP_CVOLUME);
- return sm_selem_ops(elem)->ask_dB_vol(elem, SM_CAPT, dBvalue, value, dir);
-}
-
-/**
- * \brief Return value of capture volume control of a mixer simple element
- * \param elem Mixer simple element handle
- * \param channel mixer simple element channel identifier
- * \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)
-{
- CHECK_BASIC(elem);
- CHECK_DIR_CHN(elem, SM_CAP_CVOLUME, SM_CAP_CVOLUME_JOIN, channel);
- return sm_selem_ops(elem)->get_volume(elem, SM_CAPT, channel, value);
-}
-
-/**
- * \brief Return value of capture volume in dB control of a mixer simple element
- * \param elem Mixer simple element handle
- * \param channel mixer simple element channel identifier
- * \param value pointer to returned value (dB * 100)
- * \return 0 on success otherwise a negative error code
- */
-int snd_mixer_selem_get_capture_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value)
-{
- CHECK_BASIC(elem);
- CHECK_DIR_CHN(elem, SM_CAP_CVOLUME, SM_CAP_CVOLUME_JOIN, channel);
- return sm_selem_ops(elem)->get_dB(elem, SM_CAPT, channel, value);
-}
-
-/**
- * \brief Return value of capture switch control of a mixer simple element
- * \param elem Mixer simple element handle
- * \param channel mixer simple element channel identifier
- * \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)
-{
- CHECK_BASIC(elem);
- CHECK_DIR_CHN(elem, SM_CAP_CSWITCH, SM_CAP_CSWITCH_JOIN, channel);
- return sm_selem_ops(elem)->get_switch(elem, SM_CAPT, channel, value);
-}
-
-/**
- * \brief Set value of capture volume control of a mixer simple element
- * \param elem Mixer simple element handle
- * \param channel mixer simple element channel identifier
- * \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)
-{
- CHECK_BASIC(elem);
- CHECK_DIR_CHN(elem, SM_CAP_CVOLUME, SM_CAP_CVOLUME_JOIN, channel);
- return sm_selem_ops(elem)->set_volume(elem, SM_CAPT, channel, value);
-}
-
-/**
- * \brief Set value in dB of capture volume control of a mixer simple element
- * \param elem Mixer simple element handle
- * \param channel mixer simple element channel identifier
- * \param value control value in dB * 100
- * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
- * \return 0 on success otherwise a negative error code
- */
-int snd_mixer_selem_set_capture_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value, int dir)
-{
- CHECK_BASIC(elem);
- CHECK_DIR_CHN(elem, SM_CAP_CVOLUME, SM_CAP_CVOLUME_JOIN, channel);
- return sm_selem_ops(elem)->set_dB(elem, SM_CAPT, channel, value, dir);
-}
-
-/**
- * \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)
-{
- snd_mixer_selem_channel_id_t chn;
- int err;
-
- for (chn = 0; chn < 32; chn++) {
- if (!snd_mixer_selem_has_capture_channel(elem, chn))
- continue;
- err = snd_mixer_selem_set_capture_volume(elem, chn, value);
- if (err < 0)
- return err;
- if (chn == 0 && snd_mixer_selem_has_capture_volume_joined(elem))
- return 0;
- }
- return 0;
-}
-
-/**
- * \brief Set value in dB of capture volume control for all channels of a mixer simple element
- * \param elem Mixer simple element handle
- * \param value control value in dB * 100
- * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
- * \return 0 on success otherwise a negative error code
- */
-int snd_mixer_selem_set_capture_dB_all(snd_mixer_elem_t *elem, long value, int dir)
-{
- snd_mixer_selem_channel_id_t chn;
- int err;
-
- for (chn = 0; chn < 32; chn++) {
- if (!snd_mixer_selem_has_capture_channel(elem, chn))
- continue;
- err = snd_mixer_selem_set_capture_dB(elem, chn, value, dir);
- if (err < 0)
- return err;
- if (chn == 0 && snd_mixer_selem_has_capture_volume_joined(elem))
- return 0;
- }
- return 0;
-}
-
-/**
- * \brief Set value of capture switch control of a mixer simple element
- * \param elem Mixer simple element handle
- * \param channel mixer simple element channel identifier
- * \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)
-{
- CHECK_BASIC(elem);
- CHECK_DIR_CHN(elem, SM_CAP_CSWITCH, SM_CAP_CSWITCH_JOIN, channel);
- return sm_selem_ops(elem)->set_switch(elem, SM_CAPT, channel, 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)
-{
- snd_mixer_selem_channel_id_t chn;
- int err;
-
- for (chn = 0; chn < 32; chn++) {
- if (!snd_mixer_selem_has_capture_channel(elem, chn))
- continue;
- err = snd_mixer_selem_set_capture_switch(elem, chn, value);
- if (err < 0)
- return err;
- if (chn == 0 && snd_mixer_selem_has_capture_switch_joined(elem))
- return 0;
- }
- return 0;
-}
-
-/**
- * \brief Return true if mixer simple element is an enumerated control
- * \param elem Mixer simple element handle
- * \return 0 normal volume/switch control, 1 enumerated control
- */
-int snd_mixer_selem_is_enumerated(snd_mixer_elem_t *elem)
-{
- CHECK_BASIC(elem);
- CHECK_ENUM(elem);
- return sm_selem_ops(elem)->is(elem, SM_PLAY, SM_OPS_IS_ENUMERATED, 0);
-}
-
-/**
- * \brief Return true if mixer simple enumerated element belongs to the playback direction
+ * \brief Return true if mixer simple enumerated element belongs to the direction
* \param elem Mixer simple element handle
+ * \param dir Mixer direction
* \return 0 no playback direction, 1 playback direction
*/
-int snd_mixer_selem_is_enum_playback(snd_mixer_elem_t *elem)
+int snd_amixer_elem_is_enum(snd_amixer_elem_t *elem, snd_amixer_dir_t dir)
{
- CHECK_BASIC(elem);
- CHECK_ENUM(elem);
- return sm_selem_ops(elem)->is(elem, SM_PLAY, SM_OPS_IS_ENUMERATED, 1);
-}
+ int res;
-/**
- * \brief Return true if mixer simple enumerated element belongs to the capture direction
- * \param elem Mixer simple element handle
- * \return 0 no capture direction, 1 capture direction
- */
-int snd_mixer_selem_is_enum_capture(snd_mixer_elem_t *elem)
-{
- CHECK_BASIC(elem);
- CHECK_ENUM(elem);
- return sm_selem_ops(elem)->is(elem, SM_CAPT, SM_OPS_IS_ENUMERATED, 1);
+ if (!(elem->sm.caps & (SM_CAP_PENUM|SM_CAP_CENUM)))
+ return 0;
+ return sm_elem_ops(elem)->is(elem, dir, SM_OPS_IS_ENUMERATED, 0);
}
/**
@@ -911,11 +570,10 @@ int snd_mixer_selem_is_enum_capture(snd_mixer_elem_t *elem)
* \param elem Mixer simple element handle
* \return the number of enumerated items, otherwise a negative error code
*/
-int snd_mixer_selem_get_enum_items(snd_mixer_elem_t *elem)
+int snd_amixer_elem_get_enum_items(snd_amixer_elem_t *elem)
{
- CHECK_BASIC(elem);
CHECK_ENUM(elem);
- return sm_selem_ops(elem)->is(elem, SM_PLAY, SM_OPS_IS_ENUMCNT, 0);
+ return sm_elem_ops(elem)->is(elem, SM_PLAY, SM_OPS_IS_ENUMCNT, 0);
}
/**
@@ -926,13 +584,12 @@ int snd_mixer_selem_get_enum_items(snd_mixer_elem_t *elem)
* \param buf the buffer to store the name string
* \return 0 if successful, otherwise a negative error code
*/
-int snd_mixer_selem_get_enum_item_name(snd_mixer_elem_t *elem,
+int snd_amixer_elem_get_enum_item_name(snd_amixer_elem_t *elem,
unsigned int item,
size_t maxlen, char *buf)
{
- CHECK_BASIC(elem);
CHECK_ENUM(elem);
- return sm_selem_ops(elem)->enum_item_name(elem, item, maxlen, buf);
+ return sm_elem_ops(elem)->enum_item_name(elem, item, maxlen, buf);
}
/**
@@ -942,13 +599,12 @@ int snd_mixer_selem_get_enum_item_name(snd_mixer_elem_t *elem,
* \param itemp the pointer to store the index of the enumerated item
* \return 0 if successful, otherwise a negative error code
*/
-int snd_mixer_selem_get_enum_item(snd_mixer_elem_t *elem,
- snd_mixer_selem_channel_id_t channel,
+int snd_amixer_elem_get_enum_item(snd_amixer_elem_t *elem,
+ snd_amixer_elem_channel_id_t channel,
unsigned int *itemp)
{
- CHECK_BASIC(elem);
CHECK_ENUM(elem);
- return sm_selem_ops(elem)->get_enum_item(elem, channel, itemp);
+ return sm_elem_ops(elem)->get_enum_item(elem, channel, itemp);
}
/**
@@ -958,53 +614,52 @@ int snd_mixer_selem_get_enum_item(snd_mixer_elem_t *elem,
* \param item the enumerated item index
* \return 0 if successful, otherwise a negative error code
*/
-int snd_mixer_selem_set_enum_item(snd_mixer_elem_t *elem,
- snd_mixer_selem_channel_id_t channel,
+int snd_amixer_elem_set_enum_item(snd_amixer_elem_t *elem,
+ snd_amixer_elem_channel_id_t channel,
unsigned int item)
{
- CHECK_BASIC(elem);
CHECK_ENUM(elem);
- return sm_selem_ops(elem)->set_enum_item(elem, channel, item);
+ return sm_elem_ops(elem)->set_enum_item(elem, channel, item);
}
/**
- * \brief get size of #snd_mixer_selem_id_t
+ * \brief get size of #snd_amixer_elem_id_t
* \return size in bytes
*/
-size_t snd_mixer_selem_id_sizeof()
+size_t snd_amixer_elem_id_sizeof()
{
- return sizeof(snd_mixer_selem_id_t);
+ return sizeof(snd_amixer_elem_id_t);
}
/**
- * \brief allocate an invalid #snd_mixer_selem_id_t using standard malloc
+ * \brief allocate an invalid #snd_amixer_elem_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 snd_amixer_elem_id_malloc(snd_amixer_elem_id_t **ptr)
{
assert(ptr);
- *ptr = calloc(1, sizeof(snd_mixer_selem_id_t));
+ *ptr = calloc(1, sizeof(snd_amixer_elem_id_t));
if (!*ptr)
return -ENOMEM;
return 0;
}
/**
- * \brief frees a previously allocated #snd_mixer_selem_id_t
+ * \brief frees a previously allocated #snd_amixer_elem_id_t
* \param obj pointer to object to free
*/
-void snd_mixer_selem_id_free(snd_mixer_selem_id_t *obj)
+void snd_amixer_elem_id_free(snd_amixer_elem_id_t *obj)
{
free(obj);
}
/**
- * \brief copy one #snd_mixer_selem_id_t to another
+ * \brief copy one #snd_amixer_elem_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)
+void snd_amixer_elem_id_copy(snd_amixer_elem_id_t *dst, const snd_amixer_elem_id_t *src)
{
assert(dst && src);
*dst = *src;
@@ -1015,7 +670,7 @@ void snd_mixer_selem_id_copy(snd_mixer_selem_id_t *dst, const snd_mixer_selem_id
* \param obj Mixer simple element identifier
* \return name part
*/
-const char *snd_mixer_selem_id_get_name(const snd_mixer_selem_id_t *obj)
+const char *snd_amixer_elem_id_get_name(const snd_amixer_elem_id_t *obj)
{
assert(obj);
return obj->name;
@@ -1026,7 +681,7 @@ const char *snd_mixer_selem_id_get_name(const snd_mixer_selem_id_t *obj)
* \param obj Mixer simple element identifier
* \return index part
*/
-unsigned int snd_mixer_selem_id_get_index(const snd_mixer_selem_id_t *obj)
+unsigned int snd_amixer_elem_id_get_index(const snd_amixer_elem_id_t *obj)
{
assert(obj);
return obj->index;
@@ -1037,7 +692,7 @@ unsigned int snd_mixer_selem_id_get_index(const snd_mixer_selem_id_t *obj)
* \param obj Mixer simple element identifier
* \param val name part
*/
-void snd_mixer_selem_id_set_name(snd_mixer_selem_id_t *obj, const char *val)
+void snd_amixer_elem_id_set_name(snd_amixer_elem_id_t *obj, const char *val)
{
assert(obj);
strncpy(obj->name, val, sizeof(obj->name));
@@ -1049,8 +704,20 @@ void snd_mixer_selem_id_set_name(snd_mixer_selem_id_t *obj, const char *val)
* \param obj Mixer simple element identifier
* \param val index part
*/
-void snd_mixer_selem_id_set_index(snd_mixer_selem_id_t *obj, unsigned int val)
+void snd_amixer_elem_id_set_index(snd_amixer_elem_id_t *obj, unsigned int val)
{
assert(obj);
obj->index = val;
}
+
+/**
+ * \brief Get simple mixer element abstraction structure
+ * \param obj Mixer simple element identifier
+ * \return sm_elem_t pointer
+ */
+sm_elem_t *snd_amixer_elem_get_sm(snd_amixer_elem_t *obj)
+{
+ assert(obj);
+ return &obj->sm;
+}
+
diff --git a/src/mixer/simple_abst.c b/src/mixer/simple_abst.c
deleted file mode 100644
index 9e9aaf55..00000000
--- a/src/mixer/simple_abst.c
+++ /dev/null
@@ -1,420 +0,0 @@
-/**
- * \file mixer/simple_abst.c
- * \brief Mixer Simple Element Class Interface - Module Abstraction
- * \author Jaroslav Kysela <perex@perex.cz>
- * \date 2005
- *
- * Mixer simple element class interface.
- */
-/*
- * Mixer Interface - simple controls - abstraction module
- * Copyright (c) 2005 by Jaroslav Kysela <perex@perex.cz>
- *
- *
- * This library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <math.h>
-#include <dlfcn.h>
-#include "config.h"
-#include "asoundlib.h"
-#include "mixer_simple.h"
-
-#ifndef DOC_HIDDEN
-
-#define SO_PATH ALSA_PLUGIN_DIR "/smixer"
-
-typedef struct _class_priv {
- char *device;
- snd_ctl_t *ctl;
- snd_hctl_t *hctl;
- int attach_flag;
- snd_ctl_card_info_t *info;
- void *dlhandle;
- void *private_data;
- void (*private_free)(snd_mixer_class_t *class);
-} class_priv_t;
-
-typedef int (*snd_mixer_sbasic_init_t)(snd_mixer_class_t *class);
-typedef int (*snd_mixer_sfbasic_init_t)(snd_mixer_class_t *class,
- snd_mixer_t *mixer,
- const char *device);
-
-#endif /* !DOC_HIDDEN */
-
-static int try_open(snd_mixer_class_t *class, const char *lib)
-{
- class_priv_t *priv = snd_mixer_class_get_private(class);
- snd_mixer_event_t event_func;
- snd_mixer_sbasic_init_t init_func = NULL;
- char *xlib, *path;
- void *h;
- int err = 0;
-
- path = getenv("ALSA_MIXER_SIMPLE_MODULES");
- if (!path)
- path = SO_PATH;
- xlib = malloc(strlen(lib) + strlen(path) + 1 + 1);
- if (xlib == NULL)
- return -ENOMEM;
- strcpy(xlib, path);
- strcat(xlib, "/");
- strcat(xlib, lib);
- h = snd_dlopen(xlib, RTLD_NOW);
- if (h == NULL) {
- SNDERR("Unable to open library '%s'", xlib);
- free(xlib);
- return -ENXIO;
- }
- priv->dlhandle = h;
- event_func = snd_dlsym(h, "alsa_mixer_simple_event", NULL);
- if (event_func == NULL) {
- SNDERR("Symbol 'alsa_mixer_simple_event' was not found in '%s'", xlib);
- err = -ENXIO;
- }
- if (err == 0) {
- init_func = snd_dlsym(h, "alsa_mixer_simple_init", NULL);
- if (init_func == NULL) {
- SNDERR("Symbol 'alsa_mixer_simple_init' was not found in '%s'", xlib);
- err = -ENXIO;
- }
- }
- free(xlib);
- err = err == 0 ? init_func(class) : err;
- if (err < 0)
- return err;
- snd_mixer_class_set_event(class, event_func);
- return 1;
-}
-
-static int try_open_full(snd_mixer_class_t *class, snd_mixer_t *mixer,
- const char *lib, const char *device)
-{
- class_priv_t *priv = snd_mixer_class_get_private(class);
- snd_mixer_event_t event_func;
- snd_mixer_sfbasic_init_t init_func = NULL;
- char *xlib, *path;
- void *h;
- int err = 0;
-
- path = getenv("ALSA_MIXER_SIMPLE_MODULES");
- if (!path)
- path = SO_PATH;
- xlib = malloc(strlen(lib) + strlen(path) + 1 + 1);
- if (xlib == NULL)
- return -ENOMEM;
- strcpy(xlib, path);
- strcat(xlib, "/");
- strcat(xlib, lib);
- /* note python modules requires RTLD_GLOBAL */
- h = snd_dlopen(xlib, RTLD_NOW|RTLD_GLOBAL);
- if (h == NULL) {
- SNDERR("Unable to open library '%s'", xlib);
- free(xlib);
- return -ENXIO;
- }
- priv->dlhandle = h;
- event_func = snd_dlsym(h, "alsa_mixer_simple_event", NULL);
- if (event_func == NULL) {
- SNDERR("Symbol 'alsa_mixer_simple_event' was not found in '%s'", xlib);
- err = -ENXIO;
- }
- if (err == 0) {
- init_func = snd_dlsym(h, "alsa_mixer_simple_finit", NULL);
- if (init_func == NULL) {
- SNDERR("Symbol 'alsa_mixer_simple_finit' was not found in '%s'", xlib);
- err = -ENXIO;
- }
- }
- free(xlib);
- err = err == 0 ? init_func(class, mixer, device) : err;
- if (err < 0)
- return err;
- snd_mixer_class_set_event(class, event_func);
- return 1;
-}
-
-static int match(snd_mixer_class_t *class, const char *lib, const char *searchl)
-{
- class_priv_t *priv = snd_mixer_class_get_private(class);
- const char *components;
-
- if (searchl == NULL)
- return try_open(class, lib);
- components = snd_ctl_card_info_get_components(priv->info);
- while (*components != '\0') {
- if (!strncmp(components, searchl, strlen(searchl)))
- return try_open(class, lib);
- while (*components != ' ' && *components != '\0')
- components++;
- while (*components == ' ' && *components != '\0')
- components++;
- }
- return 0;
-}
-
-static int find_full(snd_mixer_class_t *class, snd_mixer_t *mixer,
- snd_config_t *top, const char *device)
-{
- snd_config_iterator_t i, next;
- char *lib;
- const char *id;
- int err;
-
- snd_config_for_each(i, next, top) {
- snd_config_t *n = snd_config_iterator_entry(i);
- if (snd_config_get_id(n, &id) < 0)
- continue;
- if (strcmp(id, "_full"))
- continue;
- err = snd_config_get_string(n, (const char **)&lib);
- if (err < 0)
- return err;
- err = try_open_full(class, mixer, lib, device);
- if (err < 0)
- return err;
- return 0;
- }
- return -ENOENT;
-}
-
-static int find_module(snd_mixer_class_t *class, snd_config_t *top)
-{
- snd_config_iterator_t i, next;
- snd_config_iterator_t j, jnext;
- char *lib, *searchl;
- const char *id;
- int err;
-
- snd_config_for_each(i, next, top) {
- snd_config_t *n = snd_config_iterator_entry(i);
- if (snd_config_get_id(n, &id) < 0)
- continue;
- if (*id == '_')
- continue;
- searchl = NULL;
- lib = NULL;
- snd_config_for_each(j, jnext, n) {
- snd_config_t *m = snd_config_iterator_entry(j);
- if (snd_config_get_id(m, &id) < 0)
- continue;
- if (!strcmp(id, "searchl")) {
- err = snd_config_get_string(m, (const char **)&searchl);
- if (err < 0)
- return err;
- continue;
- }
- if (!strcmp(id, "lib")) {
- err = snd_config_get_string(m, (const char **)&lib);
- if (err < 0)
- return err;
- continue;
- }
- }
- err = match(class, lib, searchl);
- if (err == 1)
- return 0;
- if (err < 0)
- return err;
- }
- return -ENOENT;
-}
-
-static void private_free(snd_mixer_class_t *class)
-{
- class_priv_t *priv = snd_mixer_class_get_private(class);
-
- if (priv->private_free)
- priv->private_free(class);
- if (priv->dlhandle)
- snd_dlclose(priv->dlhandle);
- if (priv->info)
- snd_ctl_card_info_free(priv->info);
- if (priv->hctl) {
- if (priv->attach_flag)
- snd_mixer_detach_hctl(snd_mixer_class_get_mixer(class), priv->hctl);
- snd_hctl_close(priv->hctl);
- } else if (priv->ctl)
- snd_ctl_close(priv->ctl);
- free(priv->device);
- free(priv);
-}
-
-/**
- * \brief Register mixer simple element class - basic abstraction
- * \param mixer Mixer handle
- * \param options Options container
- * \param classp Pointer to returned mixer simple element class handle (or NULL
- * \return 0 on success otherwise a negative error code
- */
-int snd_mixer_simple_basic_register(snd_mixer_t *mixer,
- struct snd_mixer_selem_regopt *options,
- snd_mixer_class_t **classp)
-{
- snd_mixer_class_t *class;
- class_priv_t *priv = calloc(1, sizeof(*priv));
- const char *file;
- snd_input_t *input;
- snd_config_t *top = NULL;
- int err;
-
- if (priv == NULL)
- return -ENOMEM;
- if (options->device == NULL) {
- free(priv);
- return -EINVAL;
- }
- if (snd_mixer_class_malloc(&class)) {
- free(priv);
- return -ENOMEM;
- }
- priv->device = strdup(options->device);
- if (priv->device == NULL) {
- free(priv);
- snd_mixer_class_free(class);
- return -ENOMEM;
- }
- snd_mixer_class_set_compare(class, snd_mixer_selem_compare);
- snd_mixer_class_set_private(class, priv);
- snd_mixer_class_set_private_free(class, private_free);
- file = getenv("ALSA_MIXER_SIMPLE");
- if (!file)
- file = ALSA_CONFIG_DIR "/smixer.conf";
- err = snd_config_top(&top);
- if (err >= 0) {
- err = snd_input_stdio_open(&input, file, "r");
- if (err < 0) {
- SNDERR("unable to open simple mixer configuration file '%s'", file);
- goto __error;
- }
- err = snd_config_load(top, input);
- snd_input_close(input);
- if (err < 0) {
- SNDERR("%s may be old or corrupted: consider to remove or fix it", file);
- goto __error;
- }
- err = find_full(class, mixer, top, priv->device);
- if (err >= 0)
- goto __full;
- }
- if (err >= 0) {
- err = snd_ctl_open(&priv->ctl, priv->device, 0);
- if (err < 0) {
- SNDERR("unable to open control device '%s': %s", priv->device, snd_strerror(err));
- goto __error;
- }
- err = snd_hctl_open_ctl(&priv->hctl, priv->ctl);
- if (err < 0)
- goto __error;
- err = snd_ctl_card_info_malloc(&priv->info);
- if (err < 0)
- goto __error;
- err = snd_ctl_card_info(priv->ctl, priv->info);
- if (err < 0)
- goto __error;
- }
- if (err >= 0)
- err = find_module(class, top);
- if (err >= 0)
- err = snd_mixer_attach_hctl(mixer, priv->hctl);
- if (err >= 0) {
- priv->attach_flag = 1;
- err = snd_mixer_class_register(class, mixer);
- }
- __full:
- if (err < 0) {
- __error:
- if (top)
- snd_config_delete(top);
- if (class)
- snd_mixer_class_free(class);
- return err;
- }
- if (top)
- snd_config_delete(top);
- if (classp)
- *classp = class;
- return 0;
-}
-
-/**
- * \brief Basic Mixer Abstraction - Get information about device
- * \param class Mixer class
- * \param info Info structure
- * \return 0 on success otherwise a negative error code
- */
-int snd_mixer_sbasic_info(const snd_mixer_class_t *class, sm_class_basic_t *info)
-{
- class_priv_t *priv = snd_mixer_class_get_private(class);
-
- if (class == NULL || info == NULL)
- return -EINVAL;
- info->device = priv->device;
- info->ctl = priv->ctl;
- info->hctl = priv->hctl;
- info->info = priv->info;
- return 0;
-}
-
-/**
- * \brief Get private data for basic abstraction
- * \param class Mixer class
- * \return private data
- */
-void *snd_mixer_sbasic_get_private(const snd_mixer_class_t *class)
-{
- class_priv_t *priv = snd_mixer_class_get_private(class);
-
- if (class == NULL)
- return NULL;
- return priv->private_data;
-}
-
-/**
- * \brief Set private data for basic abstraction
- * \param class Mixer class
- * \param private_data Private data
- */
-void snd_mixer_sbasic_set_private(const snd_mixer_class_t *class, void *private_data)
-{
- class_priv_t *priv;
-
- if (class == NULL)
- return;
- priv = snd_mixer_class_get_private(class);
- priv->private_data = private_data;
-}
-
-/**
- * \brief Set private data free callback for basic abstraction
- * \param class Mixer class
- * \param private_free free callback for private data
- */
-void snd_mixer_sbasic_set_private_free(const snd_mixer_class_t *class, void (*private_free)(snd_mixer_class_t *class))
-{
- class_priv_t *priv;
-
- if (class == NULL)
- return;
- priv = snd_mixer_class_get_private(class);
- priv->private_free = private_free;
-}
diff --git a/src/mixer/simple_none.c b/src/mixer/simple_none.c
index 48022004..63442111 100644
--- a/src/mixer/simple_none.c
+++ b/src/mixer/simple_none.c
@@ -5,7 +5,7 @@
* \author Abramo Bagnara <abramo@alsa-project.org>
* \date 2001-2004
*
- * Mixer simple element class interface.
+ * Mixer simple element interface.
*/
/*
* Mixer Interface - simple controls
@@ -39,7 +39,12 @@
#include <math.h>
#include <limits.h>
#include <alsa/asoundlib.h>
-#include "mixer_simple.h"
+#include "mixer_abst.h"
+
+#ifndef PIC
+/* entry for static linking */
+const char *_snd_module_mixer_none = "";
+#endif
#ifndef DOC_HIDDEN
@@ -66,7 +71,7 @@ typedef enum _selem_ctl_type {
} selem_ctl_type_t;
typedef struct _selem_ctl {
- snd_hctl_elem_t *elem;
+ snd_ctl_elem_t *elem;
snd_ctl_elem_type_t type;
unsigned int inactive: 1;
unsigned int values;
@@ -74,7 +79,6 @@ typedef struct _selem_ctl {
} selem_ctl_t;
typedef struct _selem_none {
- sm_selem_t selem;
selem_ctl_t ctls[CTL_LAST + 1];
unsigned int capture_item;
struct selem_str {
@@ -211,7 +215,7 @@ static int get_compare_weight(const char *name, unsigned int idx)
return MIXER_COMPARE_WEIGHT_SIMPLE_BASE + res + idx;
}
-static long to_user(selem_none_t *s, int dir, selem_ctl_t *c, long value)
+static long to_user(selem_none_t *s, snd_amixer_dir_t dir, selem_ctl_t *c, long value)
{
int64_t n;
if (c->max == c->min)
@@ -220,7 +224,7 @@ static long to_user(selem_none_t *s, int dir, selem_ctl_t *c, long value)
return s->str[dir].min + (n + (c->max - c->min) / 2) / (c->max - c->min);
}
-static long from_user(selem_none_t *s, int dir, selem_ctl_t *c, long value)
+static long from_user(selem_none_t *s, snd_amixer_dir_t dir, selem_ctl_t *c, long value)
{
int64_t n;
if (s->str[dir].max == s->str[dir].min)
@@ -229,14 +233,15 @@ static long from_user(selem_none_t *s, int dir, selem_ctl_t *c, long value)
return c->min + (n + (s->str[dir].max - s->str[dir].min) / 2) / (s->str[dir].max - s->str[dir].min);
}
-static int elem_read_volume(selem_none_t *s, int dir, selem_ctl_type_t type)
+static int elem_read_volume(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, selem_ctl_type_t type)
{
+ selem_none_t *s = snd_amixer_elem_get_private(elem);
snd_ctl_elem_value_t *ctl;
unsigned int idx;
int err;
selem_ctl_t *c = &s->ctls[type];
snd_ctl_elem_value_alloca(&ctl);
- if ((err = snd_hctl_elem_read(c->elem, ctl)) < 0)
+ if ((err = snd_ctl_celem_read(c->elem, ctl)) < 0)
return err;
for (idx = 0; idx < s->str[dir].channels; idx++) {
unsigned int idx1 = idx;
@@ -247,14 +252,15 @@ static int elem_read_volume(selem_none_t *s, int dir, selem_ctl_type_t type)
return 0;
}
-static int elem_read_switch(selem_none_t *s, int dir, selem_ctl_type_t type)
+static int elem_read_switch(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, selem_ctl_type_t type)
{
+ selem_none_t *s = snd_amixer_elem_get_private(elem);
snd_ctl_elem_value_t *ctl;
unsigned int idx;
int err;
selem_ctl_t *c = &s->ctls[type];
snd_ctl_elem_value_alloca(&ctl);
- if ((err = snd_hctl_elem_read(c->elem, ctl)) < 0)
+ if ((err = snd_ctl_celem_read(c->elem, ctl)) < 0)
return err;
for (idx = 0; idx < s->str[dir].channels; idx++) {
unsigned int idx1 = idx;
@@ -266,14 +272,15 @@ static int elem_read_switch(selem_none_t *s, int dir, selem_ctl_type_t type)
return 0;
}
-static int elem_read_route(selem_none_t *s, int dir, selem_ctl_type_t type)
+static int elem_read_route(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, selem_ctl_type_t type)
{
+ selem_none_t *s = snd_amixer_elem_get_private(elem);
snd_ctl_elem_value_t *ctl;
unsigned int idx;
int err;
selem_ctl_t *c = &s->ctls[type];
snd_ctl_elem_value_alloca(&ctl);
- if ((err = snd_hctl_elem_read(c->elem, ctl)) < 0)
+ if ((err = snd_ctl_celem_read(c->elem, ctl)) < 0)
return err;
for (idx = 0; idx < s->str[dir].channels; idx++) {
unsigned int idx1 = idx;
@@ -285,23 +292,25 @@ static int elem_read_route(selem_none_t *s, int dir, selem_ctl_type_t type)
return 0;
}
-static int elem_read_enum(selem_none_t *s)
+static int elem_read_enum(snd_amixer_elem_t *elem)
{
+ selem_none_t *s = snd_amixer_elem_get_private(elem);
+ sm_elem_t *sm = snd_amixer_elem_get_sm(elem);
snd_ctl_elem_value_t *ctl;
unsigned int idx;
int err;
int type;
selem_ctl_t *c;
type = CTL_GLOBAL_ENUM;
- if ( (s->selem.caps & (SM_CAP_CENUM | SM_CAP_PENUM)) == (SM_CAP_CENUM | SM_CAP_PENUM) )
+ if ( (sm->caps & (SM_CAP_CENUM | SM_CAP_PENUM)) == (SM_CAP_CENUM | SM_CAP_PENUM) )
type = CTL_GLOBAL_ENUM;
- else if (s->selem.caps & SM_CAP_PENUM)
+ else if (sm->caps & SM_CAP_PENUM)
type = CTL_PLAYBACK_ENUM;
- else if (s->selem.caps & SM_CAP_CENUM)
+ else if (sm->caps & SM_CAP_CENUM)
type = CTL_CAPTURE_ENUM;
c = &s->ctls[type];
snd_ctl_elem_value_alloca(&ctl);
- if ((err = snd_hctl_elem_read(c->elem, ctl)) < 0)
+ if ((err = snd_ctl_celem_read(c->elem, ctl)) < 0)
return err;
for (idx = 0; idx < s->str[0].channels; idx++) {
unsigned int idx1 = idx;
@@ -312,17 +321,15 @@ static int elem_read_enum(selem_none_t *s)
return 0;
}
-static int selem_read(snd_mixer_elem_t *elem)
+static int selem_read(snd_amixer_elem_t *elem)
{
- selem_none_t *s;
+ selem_none_t *s = snd_amixer_elem_get_private(elem);
+ sm_elem_t *sm = snd_amixer_elem_get_sm(elem);
unsigned int idx;
int err = 0;
long pvol[32], cvol[32];
unsigned int psw, csw;
- assert(snd_mixer_elem_get_type(elem) == SND_MIXER_ELEM_SIMPLE);
- s = snd_mixer_elem_get_private(elem);
-
memcpy(pvol, s->str[SM_PLAY].vol, sizeof(pvol));
memset(&s->str[SM_PLAY].vol, 0, sizeof(s->str[SM_PLAY].vol));
psw = s->str[SM_PLAY].sw;
@@ -333,21 +340,21 @@ static int selem_read(snd_mixer_elem_t *elem)
s->str[SM_CAPT].sw = ~0U;
if (s->ctls[CTL_GLOBAL_ENUM].elem) {
- err = elem_read_enum(s);
+ err = elem_read_enum(elem);
if (err < 0)
return err;
goto __skip_cswitch;
}
if (s->ctls[CTL_CAPTURE_ENUM].elem) {
- err = elem_read_enum(s);
+ err = elem_read_enum(elem);
if (err < 0)
return err;
goto __skip_cswitch;
}
if (s->ctls[CTL_PLAYBACK_ENUM].elem) {
- err = elem_read_enum(s);
+ err = elem_read_enum(elem);
if (err < 0)
return err;
goto __skip_cswitch;
@@ -355,84 +362,84 @@ static int selem_read(snd_mixer_elem_t *elem)
if (s->ctls[CTL_PLAYBACK_VOLUME].elem)
- err = elem_read_volume(s, SM_PLAY, CTL_PLAYBACK_VOLUME);
+ err = elem_read_volume(elem, SM_PLAY, CTL_PLAYBACK_VOLUME);
else if (s->ctls[CTL_GLOBAL_VOLUME].elem)
- err = elem_read_volume(s, SM_PLAY, CTL_GLOBAL_VOLUME);
+ err = elem_read_volume(elem, SM_PLAY, CTL_GLOBAL_VOLUME);
else if (s->ctls[CTL_SINGLE].elem &&
s->ctls[CTL_SINGLE].type == SND_CTL_ELEM_TYPE_INTEGER)
- err = elem_read_volume(s, SM_PLAY, CTL_SINGLE);
+ err = elem_read_volume(elem, SM_PLAY, CTL_SINGLE);
if (err < 0)
return err;
- if ((s->selem.caps & (SM_CAP_GSWITCH|SM_CAP_PSWITCH)) == 0) {
+ if ((sm->caps & (SM_CAP_GSWITCH|SM_CAP_PSWITCH)) == 0) {
s->str[SM_PLAY].sw = 0;
goto __skip_pswitch;
}
if (s->ctls[CTL_PLAYBACK_SWITCH].elem) {
- err = elem_read_switch(s, SM_PLAY, CTL_PLAYBACK_SWITCH);
+ err = elem_read_switch(elem, SM_PLAY, CTL_PLAYBACK_SWITCH);
if (err < 0)
return err;
}
if (s->ctls[CTL_GLOBAL_SWITCH].elem) {
- err = elem_read_switch(s, SM_PLAY, CTL_GLOBAL_SWITCH);
+ err = elem_read_switch(elem, SM_PLAY, CTL_GLOBAL_SWITCH);
if (err < 0)
return err;
}
if (s->ctls[CTL_SINGLE].elem &&
s->ctls[CTL_SINGLE].type == SND_CTL_ELEM_TYPE_BOOLEAN) {
- err = elem_read_switch(s, SM_PLAY, CTL_SINGLE);
+ err = elem_read_switch(elem, SM_PLAY, CTL_SINGLE);
if (err < 0)
return err;
}
if (s->ctls[CTL_PLAYBACK_ROUTE].elem) {
- err = elem_read_route(s, SM_PLAY, CTL_PLAYBACK_ROUTE);
+ err = elem_read_route(elem, SM_PLAY, CTL_PLAYBACK_ROUTE);
if (err < 0)
return err;
}
if (s->ctls[CTL_GLOBAL_ROUTE].elem) {
- err = elem_read_route(s, SM_PLAY, CTL_GLOBAL_ROUTE);
+ err = elem_read_route(elem, SM_PLAY, CTL_GLOBAL_ROUTE);
if (err < 0)
return err;
}
__skip_pswitch:
if (s->ctls[CTL_CAPTURE_VOLUME].elem)
- err = elem_read_volume(s, SM_CAPT, CTL_CAPTURE_VOLUME);
+ err = elem_read_volume(elem, SM_CAPT, CTL_CAPTURE_VOLUME);
else if (s->ctls[CTL_GLOBAL_VOLUME].elem)
- err = elem_read_volume(s, SM_CAPT, CTL_GLOBAL_VOLUME);
+ err = elem_read_volume(elem, SM_CAPT, CTL_GLOBAL_VOLUME);
else if (s->ctls[CTL_SINGLE].elem &&
s->ctls[CTL_SINGLE].type == SND_CTL_ELEM_TYPE_INTEGER)
- err = elem_read_volume(s, SM_CAPT, CTL_SINGLE);
+ err = elem_read_volume(elem, SM_CAPT, CTL_SINGLE);
if (err < 0)
return err;
- if ((s->selem.caps & (SM_CAP_GSWITCH|SM_CAP_CSWITCH)) == 0) {
+ if ((sm->caps & (SM_CAP_GSWITCH|SM_CAP_CSWITCH)) == 0) {
s->str[SM_CAPT].sw = 0;
goto __skip_cswitch;
}
if (s->ctls[CTL_CAPTURE_SWITCH].elem) {
- err = elem_read_switch(s, SM_CAPT, CTL_CAPTURE_SWITCH);
+ err = elem_read_switch(elem, SM_CAPT, CTL_CAPTURE_SWITCH);
if (err < 0)
return err;
}
if (s->ctls[CTL_GLOBAL_SWITCH].elem) {
- err = elem_read_switch(s, SM_CAPT, CTL_GLOBAL_SWITCH);
+ err = elem_read_switch(elem, SM_CAPT, CTL_GLOBAL_SWITCH);
if (err < 0)
return err;
}
if (s->ctls[CTL_SINGLE].elem &&
s->ctls[CTL_SINGLE].type == SND_CTL_ELEM_TYPE_BOOLEAN) {
- err = elem_read_switch(s, SM_CAPT, CTL_SINGLE);
+ err = elem_read_switch(elem, SM_CAPT, CTL_SINGLE);
if (err < 0)
return err;
}
if (s->ctls[CTL_CAPTURE_ROUTE].elem) {
- err = elem_read_route(s, SM_CAPT, CTL_CAPTURE_ROUTE);
+ err = elem_read_route(elem, SM_CAPT, CTL_CAPTURE_ROUTE);
if (err < 0)
return err;
}
if (s->ctls[CTL_GLOBAL_ROUTE].elem) {
- err = elem_read_route(s, SM_CAPT, CTL_GLOBAL_ROUTE);
+ err = elem_read_route(elem, SM_CAPT, CTL_GLOBAL_ROUTE);
if (err < 0)
return err;
}
@@ -440,7 +447,7 @@ static int selem_read(snd_mixer_elem_t *elem)
snd_ctl_elem_value_t *ctl;
selem_ctl_t *c = &s->ctls[CTL_CAPTURE_SOURCE];
snd_ctl_elem_value_alloca(&ctl);
- err = snd_hctl_elem_read(c->elem, ctl);
+ err = snd_ctl_celem_read(c->elem, ctl);
if (err < 0)
return err;
for (idx = 0; idx < s->str[SM_CAPT].channels; idx++) {
@@ -461,34 +468,34 @@ static int selem_read(snd_mixer_elem_t *elem)
return 0;
}
-static int elem_write_volume(selem_none_t *s, int dir, selem_ctl_type_t type)
+static int elem_write_volume(selem_none_t *s, snd_amixer_dir_t dir, selem_ctl_type_t type)
{
snd_ctl_elem_value_t *ctl;
unsigned int idx;
int err;
selem_ctl_t *c = &s->ctls[type];
snd_ctl_elem_value_alloca(&ctl);
- if ((err = snd_hctl_elem_read(c->elem, ctl)) < 0)
+ if ((err = snd_ctl_celem_read(c->elem, ctl)) < 0)
return err;
for (idx = 0; idx < c->values; idx++)
snd_ctl_elem_value_set_integer(ctl, idx, from_user(s, dir, c, s->str[dir].vol[idx]));
- if ((err = snd_hctl_elem_write(c->elem, ctl)) < 0)
+ if ((err = snd_ctl_celem_write(c->elem, ctl)) < 0)
return err;
return 0;
}
-static int elem_write_switch(selem_none_t *s, int dir, selem_ctl_type_t type)
+static int elem_write_switch(selem_none_t *s, snd_amixer_dir_t dir, selem_ctl_type_t type)
{
snd_ctl_elem_value_t *ctl;
unsigned int idx;
int err;
selem_ctl_t *c = &s->ctls[type];
snd_ctl_elem_value_alloca(&ctl);
- if ((err = snd_hctl_elem_read(c->elem, ctl)) < 0)
+ if ((err = snd_ctl_celem_read(c->elem, ctl)) < 0)
return err;
for (idx = 0; idx < c->values; idx++)
snd_ctl_elem_value_set_integer(ctl, idx, !!(s->str[dir].sw & (1 << idx)));
- if ((err = snd_hctl_elem_write(c->elem, ctl)) < 0)
+ if ((err = snd_ctl_celem_write(c->elem, ctl)) < 0)
return err;
return 0;
}
@@ -500,75 +507,75 @@ static int elem_write_switch_constant(selem_none_t *s, selem_ctl_type_t type, in
int err;
selem_ctl_t *c = &s->ctls[type];
snd_ctl_elem_value_alloca(&ctl);
- if ((err = snd_hctl_elem_read(c->elem, ctl)) < 0)
+ if ((err = snd_ctl_celem_read(c->elem, ctl)) < 0)
return err;
for (idx = 0; idx < c->values; idx++)
snd_ctl_elem_value_set_integer(ctl, idx, !!val);
- if ((err = snd_hctl_elem_write(c->elem, ctl)) < 0)
+ if ((err = snd_ctl_celem_write(c->elem, ctl)) < 0)
return err;
return 0;
}
-static int elem_write_route(selem_none_t *s, int dir, selem_ctl_type_t type)
+static int elem_write_route(selem_none_t *s, snd_amixer_dir_t dir, selem_ctl_type_t type)
{
snd_ctl_elem_value_t *ctl;
unsigned int idx;
int err;
selem_ctl_t *c = &s->ctls[type];
snd_ctl_elem_value_alloca(&ctl);
- if ((err = snd_hctl_elem_read(c->elem, ctl)) < 0)
+ if ((err = snd_ctl_celem_read(c->elem, ctl)) < 0)
return err;
for (idx = 0; idx < c->values * c->values; idx++)
snd_ctl_elem_value_set_integer(ctl, idx, 0);
for (idx = 0; idx < c->values; idx++)
snd_ctl_elem_value_set_integer(ctl, idx * c->values + idx, !!(s->str[dir].sw & (1 << idx)));
- if ((err = snd_hctl_elem_write(c->elem, ctl)) < 0)
+ if ((err = snd_ctl_celem_write(c->elem, ctl)) < 0)
return err;
return 0;
}
-static int elem_write_enum(selem_none_t *s)
+static int elem_write_enum(snd_amixer_elem_t *elem)
{
+ selem_none_t *s = snd_amixer_elem_get_private(elem);
+ sm_elem_t *sm = snd_amixer_elem_get_sm(elem);
snd_ctl_elem_value_t *ctl;
+
unsigned int idx;
int err;
int type;
selem_ctl_t *c;
type = CTL_GLOBAL_ENUM;
- if ( (s->selem.caps & (SM_CAP_CENUM | SM_CAP_PENUM) ) == (SM_CAP_CENUM | SM_CAP_PENUM) )
+ if ( (sm->caps & (SM_CAP_CENUM | SM_CAP_PENUM) ) == (SM_CAP_CENUM | SM_CAP_PENUM) )
type = CTL_GLOBAL_ENUM;
- else if (s->selem.caps & SM_CAP_PENUM)
+ else if (sm->caps & SM_CAP_PENUM)
type = CTL_PLAYBACK_ENUM;
- else if (s->selem.caps & SM_CAP_CENUM)
+ else if (sm->caps & SM_CAP_CENUM)
type = CTL_CAPTURE_ENUM;
c = &s->ctls[type];
snd_ctl_elem_value_alloca(&ctl);
- if ((err = snd_hctl_elem_read(c->elem, ctl)) < 0)
+ if ((err = snd_ctl_celem_read(c->elem, ctl)) < 0)
return err;
for (idx = 0; idx < c->values; idx++)
snd_ctl_elem_value_set_enumerated(ctl, idx, (unsigned int)s->str[0].vol[idx]);
- if ((err = snd_hctl_elem_write(c->elem, ctl)) < 0)
+ if ((err = snd_ctl_celem_write(c->elem, ctl)) < 0)
return err;
return 0;
}
-static int selem_write_main(snd_mixer_elem_t *elem)
+static int selem_write_main(snd_amixer_elem_t *elem)
{
- selem_none_t *s;
+ selem_none_t *s = snd_amixer_elem_get_private(elem);
unsigned int idx;
int err;
- assert(snd_mixer_elem_get_type(elem) == SND_MIXER_ELEM_SIMPLE);
- s = snd_mixer_elem_get_private(elem);
-
if (s->ctls[CTL_GLOBAL_ENUM].elem)
- return elem_write_enum(s);
+ return elem_write_enum(elem);
if (s->ctls[CTL_PLAYBACK_ENUM].elem)
- return elem_write_enum(s);
+ return elem_write_enum(elem);
if (s->ctls[CTL_CAPTURE_ENUM].elem)
- return elem_write_enum(s);
+ return elem_write_enum(elem);
if (s->ctls[CTL_SINGLE].elem) {
if (s->ctls[CTL_SINGLE].type == SND_CTL_ELEM_TYPE_INTEGER)
@@ -625,13 +632,13 @@ static int selem_write_main(snd_mixer_elem_t *elem)
snd_ctl_elem_value_t *ctl;
selem_ctl_t *c = &s->ctls[CTL_CAPTURE_SOURCE];
snd_ctl_elem_value_alloca(&ctl);
- if ((err = snd_hctl_elem_read(c->elem, ctl)) < 0)
+ if ((err = snd_ctl_celem_read(c->elem, ctl)) < 0)
return err;
for (idx = 0; idx < c->values; idx++) {
if (s->str[SM_CAPT].sw & (1 << idx))
snd_ctl_elem_value_set_enumerated(ctl, idx, s->capture_item);
}
- if ((err = snd_hctl_elem_write(c->elem, ctl)) < 0)
+ if ((err = snd_ctl_celem_write(c->elem, ctl)) < 0)
return err;
/* update the element, don't remove */
err = selem_read(elem);
@@ -641,7 +648,7 @@ static int selem_write_main(snd_mixer_elem_t *elem)
return 0;
}
-static int selem_write(snd_mixer_elem_t *elem)
+static int selem_write(snd_amixer_elem_t *elem)
{
int err;
@@ -651,21 +658,19 @@ static int selem_write(snd_mixer_elem_t *elem)
return err;
}
-static void selem_free(snd_mixer_elem_t *elem)
+static void selem_free(snd_amixer_elem_t *elem)
{
- selem_none_t *simple = snd_mixer_elem_get_private(elem);
- assert(snd_mixer_elem_get_type(elem) == SND_MIXER_ELEM_SIMPLE);
- if (simple->selem.id)
- snd_mixer_selem_id_free(simple->selem.id);
+ selem_none_t *simple = snd_amixer_elem_get_private(elem);
/* free db range information */
free(simple->str[0].db_info);
free(simple->str[1].db_info);
free(simple);
}
-static int simple_update(snd_mixer_elem_t *melem)
+static int simple_update(snd_amixer_elem_t *melem)
{
selem_none_t *simple;
+ sm_elem_t *sm;
unsigned int caps, pchannels, cchannels;
long pmin, pmax, cmin, cmax;
selem_ctl_t *ctl;
@@ -678,9 +683,9 @@ static int simple_update(snd_mixer_elem_t *melem)
cchannels = 0;
cmin = LONG_MAX;
cmax = LONG_MIN;
- assert(snd_mixer_elem_get_type(melem) == SND_MIXER_ELEM_SIMPLE);
- simple = snd_mixer_elem_get_private(melem);
- name = snd_mixer_selem_get_name(melem);
+ simple = snd_amixer_elem_get_private(melem);
+ sm = snd_amixer_elem_get_sm(melem);
+ name = snd_amixer_elem_get_name(melem);
ctl = &simple->ctls[CTL_SINGLE];
if (ctl->elem) {
pchannels = cchannels = ctl->values;
@@ -868,7 +873,7 @@ static int simple_update(snd_mixer_elem_t *melem)
(caps & (SM_CAP_PVOLUME|SM_CAP_CVOLUME)) == 0)
caps |= SM_CAP_PVOLUME|SM_CAP_CVOLUME;
- simple->selem.caps = caps;
+ sm->caps = caps;
simple->str[SM_PLAY].channels = pchannels;
if (!simple->str[SM_PLAY].range) {
simple->str[SM_PLAY].min = pmin != LONG_MAX ? pmin : 0;
@@ -943,16 +948,17 @@ static int base_len(const char *name, selem_ctl_type_t *type)
* Simple Mixer Operations
*/
-static int _snd_mixer_selem_set_volume(snd_mixer_elem_t *elem, int dir, snd_mixer_selem_channel_id_t channel, long value)
+static int _snd_amixer_selem_set_volume(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, snd_amixer_elem_channel_id_t channel, long value)
{
- selem_none_t *s = snd_mixer_elem_get_private(elem);
- if (s->selem.caps & SM_CAP_GVOLUME)
+ selem_none_t *s = snd_amixer_elem_get_private(elem);
+ sm_elem_t *sm = snd_amixer_elem_get_sm(elem);
+ if (sm->caps & SM_CAP_GVOLUME)
dir = SM_PLAY;
if ((unsigned int) channel >= s->str[dir].channels)
return 0;
if (value < s->str[dir].min || value > s->str[dir].max)
return 0;
- if (s->selem.caps &
+ if (sm->caps &
(dir == SM_PLAY ? SM_CAP_PVOLUME_JOIN : SM_CAP_CVOLUME_JOIN))
channel = 0;
if (value != s->str[dir].vol[channel]) {
@@ -962,12 +968,14 @@ static int _snd_mixer_selem_set_volume(snd_mixer_elem_t *elem, int dir, snd_mixe
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)
+static int _snd_amixer_selem_set_switch(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, snd_amixer_elem_channel_id_t channel, int value)
{
- selem_none_t *s = snd_mixer_elem_get_private(elem);
+ selem_none_t *s = snd_amixer_elem_get_private(elem);
+ sm_elem_t *sm = snd_amixer_elem_get_sm(elem);
+
if ((unsigned int) channel >= s->str[dir].channels)
return 0;
- if (s->selem.caps &
+ if (sm->caps &
(dir == SM_PLAY ? SM_CAP_PSWITCH_JOIN : SM_CAP_CSWITCH_JOIN))
channel = 0;
if (value) {
@@ -984,9 +992,10 @@ static int _snd_mixer_selem_set_switch(snd_mixer_elem_t *elem, int dir, snd_mixe
return 0;
}
-static int is_ops(snd_mixer_elem_t *elem, int dir, int cmd, int val)
+static int is_ops(snd_amixer_elem_t *elem, snd_amixer_dir_t dir, int cmd, int val)
{
- selem_none_t *s = snd_mixer_elem_get_private(elem);
+ selem_none_t *s = snd_amixer_elem_get_private(elem);
+ sm_elem_t *sm = snd_amixer_elem_get_sm(elem);
switch (cmd) {
@@ -998,37 +1007,31 @@ static int is_ops(snd_mixer_elem_t *elem, int dir, int cmd, int val)
return 1;
}
- case SM_OPS_IS_MONO:
- return s->str[dir].channels == 1;
-
case SM_OPS_IS_CHANNEL:
return (unsigned int) val < s->str[dir].channels;
case SM_OPS_IS_ENUMERATED:
- if (val == 1) {
- if (dir == SM_PLAY && (s->selem.caps & SM_CAP_PENUM) && !(s->selem.caps & SM_CAP_CENUM) )
- return 1;
- if (dir == SM_CAPT && (s->selem.caps & SM_CAP_CENUM) && !(s->selem.caps & SM_CAP_PENUM) )
- return 1;
- return 0;
- }
- if (s->selem.caps & (SM_CAP_CENUM | SM_CAP_PENUM) )
+ if (dir == SM_PLAY && (sm->caps & SM_CAP_PENUM) && !(sm->caps & SM_CAP_CENUM))
+ return 1;
+ if (dir == SM_CAPT && (sm->caps & SM_CAP_CENUM) && !(sm->caps & SM_CAP_PENUM))
+ return 1;
+ if (dir == SM_COMM && (sm->caps & (SM_CAP_CENUM|SM_CAP_PENUM)) == (SM_CAP_CENUM|SM_CAP_PENUM))
return 1;
return 0;
case SM_OPS_IS_ENUMCNT:
/* Both */
- if ( (s->selem.caps & (SM_CAP_CENUM | SM_CAP_PENUM)) == (SM_CAP_CENUM | SM_CAP_PENUM) ) {
+ if ( (sm->caps & (SM_CAP_CENUM | SM_CAP_PENUM)) == (SM_CAP_CENUM | SM_CAP_PENUM) ) {
if (! s->ctls[CTL_GLOBAL_ENUM].elem)
return -EINVAL;
return s->ctls[CTL_GLOBAL_ENUM].max;
/* Only Playback */
- } else if (s->selem.caps & SM_CAP_PENUM ) {
+ } else if (sm->caps & SM_CAP_PENUM ) {
if (! s->ctls[CTL_PLAYBACK_ENUM].elem)
return -EINVAL;
return s->ctls[CTL_PLAYBACK_ENUM].max;
/* Only Capture */
- } else if (s->selem.caps & SM_CAP_CENUM ) {
+ } else if (sm->caps & SM_CAP_CENUM ) {
if (! s->ctls[CTL_CAPTURE_ENUM].elem)
return -EINVAL;
return s->ctls[CTL_CAPTURE_ENUM].max;
@@ -1039,19 +1042,25 @@ static int is_ops(snd_mixer_elem_t *elem, int dir, int cmd, int val)
return 1;
}
-static int get_range_ops(snd_mixer_elem_t *elem, int dir,
+static int get_channels_ops(snd_amixer_elem_t *elem, snd_amixer_dir_t dir)
+{
+ selem_none_t *s = snd_amixer_elem_get_private(elem);
+ return s->str[dir].channels;
+}
+
+static int get_range_ops(snd_amixer_elem_t *elem, snd_amixer_dir_t dir,
long *min, long *max)
{
- selem_none_t *s = snd_mixer_elem_get_private(elem);
+ selem_none_t *s = snd_amixer_elem_get_private(elem);
*min = s->str[dir].min;
*max = s->str[dir].max;
return 0;
}
-static int set_range_ops(snd_mixer_elem_t *elem, int dir,
+static int set_range_ops(snd_amixer_elem_t *elem, snd_amixer_dir_t dir,
long min, long max)
{
- selem_none_t *s = snd_mixer_elem_get_private(elem);
+ selem_none_t *s = snd_amixer_elem_get_private(elem);
int err;
s->str[dir].range = 1;
@@ -1062,11 +1071,12 @@ static int set_range_ops(snd_mixer_elem_t *elem, int dir,
return 0;
}
-static int get_volume_ops(snd_mixer_elem_t *elem, int dir,
- snd_mixer_selem_channel_id_t channel, long *value)
+static int get_volume_ops(snd_amixer_elem_t *elem, snd_amixer_dir_t dir,
+ snd_amixer_elem_channel_id_t channel, long *value)
{
- selem_none_t *s = snd_mixer_elem_get_private(elem);
- if (s->selem.caps & SM_CAP_GVOLUME)
+ selem_none_t *s = snd_amixer_elem_get_private(elem);
+ sm_elem_t *sm = snd_amixer_elem_get_sm(elem);
+ if (sm->caps & SM_CAP_GVOLUME)
dir = SM_PLAY;
if ((unsigned int) channel >= s->str[dir].channels)
return -EINVAL;
@@ -1074,9 +1084,9 @@ static int get_volume_ops(snd_mixer_elem_t *elem, int dir,
return 0;
}
-static int init_db_range(snd_hctl_elem_t *ctl, struct selem_str *rec);
+static int init_db_range(snd_ctl_elem_t *ctl, struct selem_str *rec);
-static int convert_to_dB(snd_hctl_elem_t *ctl, struct selem_str *rec,
+static int convert_to_dB(snd_ctl_elem_t *ctl, struct selem_str *rec,
long volume, long *db_gain)
{
if (init_db_range(ctl, rec) < 0)
@@ -1087,7 +1097,7 @@ static int convert_to_dB(snd_hctl_elem_t *ctl, struct selem_str *rec,
/* initialize dB range information, reading TLV via hcontrol
*/
-static int init_db_range(snd_hctl_elem_t *ctl, struct selem_str *rec)
+static int init_db_range(snd_ctl_elem_t *ctl, struct selem_str *rec)
{
snd_ctl_elem_info_t *info;
unsigned int *tlv = NULL;
@@ -1101,14 +1111,14 @@ static int init_db_range(snd_hctl_elem_t *ctl, struct selem_str *rec)
return 0;
snd_ctl_elem_info_alloca(&info);
- if (snd_hctl_elem_info(ctl, info) < 0)
+ if (snd_ctl_celem_info(ctl, info) < 0)
goto error;
if (! snd_ctl_elem_info_is_tlv_readable(info))
goto error;
tlv = malloc(tlv_size);
if (! tlv)
return -ENOMEM;
- if (snd_hctl_elem_tlv_read(ctl, tlv, tlv_size) < 0)
+ if (snd_ctl_celem_tlv_read(ctl, tlv, tlv_size) < 0)
goto error;
db_size = snd_tlv_parse_dB_info(tlv, tlv_size, &dbrec);
if (db_size < 0)
@@ -1128,7 +1138,7 @@ static int init_db_range(snd_hctl_elem_t *ctl, struct selem_str *rec)
}
/* get selem_ctl for TLV access */
-static selem_ctl_t *get_selem_ctl(selem_none_t *s, int dir)
+static selem_ctl_t *get_selem_ctl(selem_none_t *s, snd_amixer_dir_t dir)
{
selem_ctl_t *c;
if (dir == SM_PLAY)
@@ -1147,7 +1157,7 @@ static selem_ctl_t *get_selem_ctl(selem_none_t *s, int dir)
return c;
}
-static int get_dB_range(snd_hctl_elem_t *ctl, struct selem_str *rec,
+static int get_dB_range(snd_ctl_elem_t *ctl, struct selem_str *rec,
long *min, long *max)
{
if (init_db_range(ctl, rec) < 0)
@@ -1156,13 +1166,14 @@ static int get_dB_range(snd_hctl_elem_t *ctl, struct selem_str *rec,
return snd_tlv_get_dB_range(rec->db_info, rec->min, rec->max, min, max);
}
-static int get_dB_range_ops(snd_mixer_elem_t *elem, int dir,
+static int get_dB_range_ops(snd_amixer_elem_t *elem, snd_amixer_dir_t dir,
long *min, long *max)
{
- selem_none_t *s = snd_mixer_elem_get_private(elem);
+ selem_none_t *s = snd_amixer_elem_get_private(elem);
+ sm_elem_t *sm = snd_amixer_elem_get_sm(elem);
selem_ctl_t *c;
- if (s->selem.caps & SM_CAP_GVOLUME)
+ if (sm->caps & SM_CAP_GVOLUME)
dir = SM_PLAY;
c = get_selem_ctl(s, dir);
if (! c)
@@ -1170,7 +1181,7 @@ static int get_dB_range_ops(snd_mixer_elem_t *elem, int dir,
return get_dB_range(c->elem, &s->str[dir], min, max);
}
-static int convert_from_dB(snd_hctl_elem_t *ctl, struct selem_str *rec,
+static int convert_from_dB(snd_ctl_elem_t *ctl, struct selem_str *rec,
long db_gain, long *value, int xdir)
{
if (init_db_range(ctl, rec) < 0)
@@ -1180,12 +1191,12 @@ static int convert_from_dB(snd_hctl_elem_t *ctl, struct selem_str *rec,
db_gain, value, xdir);
}
-static int ask_vol_dB_ops(snd_mixer_elem_t *elem,
- int dir,
+static int ask_vol_dB_ops(snd_amixer_elem_t *elem,
+ snd_amixer_dir_t dir,
long value,
long *dBvalue)
{
- selem_none_t *s = snd_mixer_elem_get_private(elem);
+ selem_none_t *s = snd_amixer_elem_get_private(elem);
selem_ctl_t *c;
c = get_selem_ctl(s, dir);
@@ -1195,17 +1206,18 @@ static int ask_vol_dB_ops(snd_mixer_elem_t *elem,
return res;
}
-static int get_dB_ops(snd_mixer_elem_t *elem,
- int dir,
- snd_mixer_selem_channel_id_t channel,
+static int get_dB_ops(snd_amixer_elem_t *elem,
+ snd_amixer_dir_t dir,
+ snd_amixer_elem_channel_id_t channel,
long *value)
{
- selem_none_t *s = snd_mixer_elem_get_private(elem);
+ selem_none_t *s = snd_amixer_elem_get_private(elem);
+ sm_elem_t *sm = snd_amixer_elem_get_sm(elem);
selem_ctl_t *c;
int err;
long volume, db_gain;
- if (s->selem.caps & SM_CAP_GVOLUME)
+ if (sm->caps & SM_CAP_GVOLUME)
dir = SM_PLAY;
c = get_selem_ctl(s, dir);
if (! c)
@@ -1220,11 +1232,12 @@ static int get_dB_ops(snd_mixer_elem_t *elem,
return err;
}
-static int get_switch_ops(snd_mixer_elem_t *elem, int dir,
- snd_mixer_selem_channel_id_t channel, int *value)
+static int get_switch_ops(snd_amixer_elem_t *elem, snd_amixer_dir_t dir,
+ snd_amixer_elem_channel_id_t channel, int *value)
{
- selem_none_t *s = snd_mixer_elem_get_private(elem);
- if (s->selem.caps & SM_CAP_GSWITCH)
+ selem_none_t *s = snd_amixer_elem_get_private(elem);
+ sm_elem_t *sm = snd_amixer_elem_get_sm(elem);
+ if (sm->caps & SM_CAP_GSWITCH)
dir = SM_PLAY;
if ((unsigned int) channel >= s->str[dir].channels)
return -EINVAL;
@@ -1232,11 +1245,11 @@ static int get_switch_ops(snd_mixer_elem_t *elem, int dir,
return 0;
}
-static int set_volume_ops(snd_mixer_elem_t *elem, int dir,
- snd_mixer_selem_channel_id_t channel, long value)
+static int set_volume_ops(snd_amixer_elem_t *elem, snd_amixer_dir_t dir,
+ snd_amixer_elem_channel_id_t channel, long value)
{
int changed;
- changed = _snd_mixer_selem_set_volume(elem, dir, channel, value);
+ changed = _snd_amixer_selem_set_volume(elem, dir, channel, value);
if (changed < 0)
return changed;
if (changed)
@@ -1244,13 +1257,14 @@ static int set_volume_ops(snd_mixer_elem_t *elem, int dir,
return 0;
}
-static int ask_dB_vol_ops(snd_mixer_elem_t *elem, int dir,
+static int ask_dB_vol_ops(snd_amixer_elem_t *elem, snd_amixer_dir_t dir,
long dbValue, long *value, int xdir)
{
- selem_none_t *s = snd_mixer_elem_get_private(elem);
+ selem_none_t *s = snd_amixer_elem_get_private(elem);
+ sm_elem_t *sm = snd_amixer_elem_get_sm(elem);
selem_ctl_t *c;
- if (s->selem.caps & SM_CAP_GVOLUME)
+ if (sm->caps & SM_CAP_GVOLUME)
dir = SM_PLAY;
c = get_selem_ctl(s, dir);
if (! c)
@@ -1258,16 +1272,17 @@ static int ask_dB_vol_ops(snd_mixer_elem_t *elem, int dir,
return convert_from_dB(c->elem, &s->str[dir], dbValue, value, xdir);
}
-static int set_dB_ops(snd_mixer_elem_t *elem, int dir,
- snd_mixer_selem_channel_id_t channel,
+static int set_dB_ops(snd_amixer_elem_t *elem, snd_amixer_dir_t dir,
+ snd_amixer_elem_channel_id_t channel,
long db_gain, int xdir)
{
- selem_none_t *s = snd_mixer_elem_get_private(elem);
+ selem_none_t *s = snd_amixer_elem_get_private(elem);
+ sm_elem_t *sm = snd_amixer_elem_get_sm(elem);
selem_ctl_t *c;
long value;
int err;
- if (s->selem.caps & SM_CAP_GVOLUME)
+ if (sm->caps & SM_CAP_GVOLUME)
dir = SM_PLAY;
c = get_selem_ctl(s, dir);
if (! c)
@@ -1278,21 +1293,21 @@ static int set_dB_ops(snd_mixer_elem_t *elem, int dir,
return set_volume_ops(elem, dir, channel, value);
}
-static int set_switch_ops(snd_mixer_elem_t *elem, int dir,
- snd_mixer_selem_channel_id_t channel, int value)
+static int set_switch_ops(snd_amixer_elem_t *elem, snd_amixer_dir_t dir,
+ snd_amixer_elem_channel_id_t channel, int value)
{
int changed;
- selem_none_t *s = snd_mixer_elem_get_private(elem);
- if (s->selem.caps & SM_CAP_GSWITCH)
+ sm_elem_t *sm = snd_amixer_elem_get_sm(elem);
+ if (sm->caps & SM_CAP_GSWITCH)
dir = SM_PLAY;
if (dir == SM_PLAY) {
- if (! (s->selem.caps & (SM_CAP_GSWITCH|SM_CAP_PSWITCH)))
+ if (! (sm->caps & (SM_CAP_GSWITCH|SM_CAP_PSWITCH)))
return -EINVAL;
} else {
- if (! (s->selem.caps & (SM_CAP_GSWITCH|SM_CAP_CSWITCH)))
+ if (! (sm->caps & (SM_CAP_GSWITCH|SM_CAP_CSWITCH)))
return -EINVAL;
}
- changed = _snd_mixer_selem_set_switch(elem, dir, channel, value);
+ changed = _snd_amixer_selem_set_switch(elem, dir, channel, value);
if (changed < 0)
return changed;
if (changed)
@@ -1300,13 +1315,13 @@ static int set_switch_ops(snd_mixer_elem_t *elem, int dir,
return 0;
}
-static int enum_item_name_ops(snd_mixer_elem_t *elem,
+static int enum_item_name_ops(snd_amixer_elem_t *elem,
unsigned int item,
size_t maxlen, char *buf)
{
- selem_none_t *s = snd_mixer_elem_get_private(elem);
+ selem_none_t *s = snd_amixer_elem_get_private(elem);
snd_ctl_elem_info_t *info;
- snd_hctl_elem_t *helem;
+ snd_ctl_elem_t *helem;
int type;
type = CTL_GLOBAL_ENUM;
@@ -1323,20 +1338,20 @@ static int enum_item_name_ops(snd_mixer_elem_t *elem,
if (item >= (unsigned int)s->ctls[type].max)
return -EINVAL;
snd_ctl_elem_info_alloca(&info);
- snd_hctl_elem_info(helem, info);
+ snd_ctl_celem_info(helem, info);
snd_ctl_elem_info_set_item(info, item);
- snd_hctl_elem_info(helem, info);
+ snd_ctl_celem_info(helem, info);
strncpy(buf, snd_ctl_elem_info_get_item_name(info), maxlen);
return 0;
}
-static int get_enum_item_ops(snd_mixer_elem_t *elem,
- snd_mixer_selem_channel_id_t channel,
+static int get_enum_item_ops(snd_amixer_elem_t *elem,
+ snd_amixer_elem_channel_id_t channel,
unsigned int *itemp)
{
- selem_none_t *s = snd_mixer_elem_get_private(elem);
+ selem_none_t *s = snd_amixer_elem_get_private(elem);
snd_ctl_elem_value_t *ctl;
- snd_hctl_elem_t *helem;
+ snd_ctl_elem_t *helem;
int err;
if ((unsigned int) channel >= s->str[0].channels)
@@ -1346,19 +1361,19 @@ static int get_enum_item_ops(snd_mixer_elem_t *elem,
if (!helem) helem = s->ctls[CTL_CAPTURE_ENUM].elem;
assert(helem);
snd_ctl_elem_value_alloca(&ctl);
- err = snd_hctl_elem_read(helem, ctl);
+ err = snd_ctl_celem_read(helem, ctl);
if (! err)
*itemp = snd_ctl_elem_value_get_enumerated(ctl, channel);
return err;
}
-static int set_enum_item_ops(snd_mixer_elem_t *elem,
- snd_mixer_selem_channel_id_t channel,
+static int set_enum_item_ops(snd_amixer_elem_t *elem,
+ snd_amixer_elem_channel_id_t channel,
unsigned int item)
{
- selem_none_t *s = snd_mixer_elem_get_private(elem);
+ selem_none_t *s = snd_amixer_elem_get_private(elem);
snd_ctl_elem_value_t *ctl;
- snd_hctl_elem_t *helem;
+ snd_ctl_elem_t *helem;
int err;
int type;
@@ -1380,16 +1395,17 @@ static int set_enum_item_ops(snd_mixer_elem_t *elem,
return -EINVAL;
}
snd_ctl_elem_value_alloca(&ctl);
- err = snd_hctl_elem_read(helem, ctl);
+ err = snd_ctl_celem_read(helem, ctl);
if (err < 0) {
return err;
}
snd_ctl_elem_value_set_enumerated(ctl, channel, item);
- return snd_hctl_elem_write(helem, ctl);
+ return snd_ctl_celem_write(helem, ctl);
}
static struct sm_elem_ops simple_none_ops = {
.is = is_ops,
+ .get_channels = get_channels_ops,
.get_range = get_range_ops,
.get_dB_range = get_dB_range_ops,
.set_range = set_range_ops,
@@ -1406,12 +1422,13 @@ static struct sm_elem_ops simple_none_ops = {
.set_enum_item = set_enum_item_ops
};
-static int simple_add1(snd_mixer_class_t *class, const char *name,
- snd_hctl_elem_t *helem, selem_ctl_type_t type,
+static int simple_add1(snd_amixer_t *amixer, const char *name,
+ snd_ctl_elem_t *helem, selem_ctl_type_t type,
unsigned int value)
{
- snd_mixer_elem_t *melem;
- snd_mixer_selem_id_t *id;
+ snd_amixer_elem_t *melem;
+ sm_elem_t *sm;
+ snd_amixer_elem_id_t *id;
int new = 0;
int err;
snd_ctl_elem_info_t *info;
@@ -1421,7 +1438,7 @@ static int simple_add1(snd_mixer_class_t *class, const char *name,
unsigned long values;
snd_ctl_elem_info_alloca(&info);
- err = snd_hctl_elem_info(helem, info);
+ err = snd_ctl_celem_info(helem, info);
if (err < 0)
return err;
ctype = snd_ctl_elem_info_get_type(info);
@@ -1508,39 +1525,42 @@ static int simple_add1(snd_mixer_class_t *class, const char *name,
break;
}
name1 = get_short_name(name);
- if (snd_mixer_selem_id_malloc(&id))
+ if (snd_amixer_elem_id_malloc(&id))
return -ENOMEM;
- snd_mixer_selem_id_set_name(id, name1);
- snd_mixer_selem_id_set_index(id, snd_hctl_elem_get_index(helem));
- melem = snd_mixer_find_selem(snd_mixer_class_get_mixer(class), id);
+ snd_amixer_elem_id_set_name(id, name1);
+ snd_amixer_elem_id_set_index(id, snd_ctl_elem_get_index(helem));
+ melem = snd_amixer_find_elem(amixer, id);
if (!melem) {
simple = calloc(1, sizeof(*simple));
if (!simple) {
- snd_mixer_selem_id_free(id);
+ snd_amixer_elem_id_free(id);
return -ENOMEM;
}
- simple->selem.id = id;
- simple->selem.ops = &simple_none_ops;
- err = snd_mixer_elem_new(&melem, SND_MIXER_ELEM_SIMPLE,
- get_compare_weight(snd_mixer_selem_id_get_name(simple->selem.id), snd_mixer_selem_id_get_index(simple->selem.id)),
- simple, selem_free);
+ err = snd_amixer_elem_new(amixer,
+ &melem,
+ id,
+ get_compare_weight(snd_amixer_elem_id_get_name(id), snd_amixer_elem_id_get_index(id)),
+ simple, selem_free);
+ snd_amixer_elem_id_free(id);
if (err < 0) {
- snd_mixer_selem_id_free(id);
+ snd_amixer_elem_id_free(id);
free(simple);
return err;
}
+ sm = snd_amixer_elem_get_sm(melem);
+ sm->ops = &simple_none_ops;
new = 1;
} else {
- simple = snd_mixer_elem_get_private(melem);
- snd_mixer_selem_id_free(id);
+ simple = snd_amixer_elem_get_private(melem);
+ snd_amixer_elem_id_free(id);
}
if (simple->ctls[type].elem) {
SNDERR("helem (%s,'%s',%u,%u,%u) appears twice or more",
- snd_ctl_elem_iface_name(snd_hctl_elem_get_interface(helem)),
- snd_hctl_elem_get_name(helem),
- snd_hctl_elem_get_index(helem),
- snd_hctl_elem_get_device(helem),
- snd_hctl_elem_get_subdevice(helem));
+ snd_ctl_elem_iface_name(snd_ctl_elem_get_interface(helem)),
+ snd_ctl_elem_get_name(helem),
+ snd_ctl_elem_get_index(helem),
+ snd_ctl_elem_get_device(helem),
+ snd_ctl_elem_get_subdevice(helem));
err = -EINVAL;
goto __error;
}
@@ -1566,7 +1586,7 @@ static int simple_add1(snd_mixer_class_t *class, const char *name,
default:
break;
}
- err = snd_mixer_elem_attach(melem, helem);
+ err = snd_amixer_elem_attach(melem, helem);
if (err < 0)
goto __error;
err = simple_update(melem);
@@ -1576,36 +1596,36 @@ static int simple_add1(snd_mixer_class_t *class, const char *name,
return err;
}
if (new)
- err = snd_mixer_elem_add(melem, class);
+ err = snd_amixer_elem_add(amixer, melem);
else
- err = snd_mixer_elem_info(melem);
+ err = snd_amixer_elem_info(melem);
if (err < 0)
return err;
err = selem_read(melem);
if (err < 0)
return err;
if (err)
- err = snd_mixer_elem_value(melem);
+ err = snd_amixer_elem_value(melem);
return err;
__error:
if (new)
- snd_mixer_elem_free(melem);
+ snd_amixer_elem_free(melem);
return -EINVAL;
}
-static int simple_event_add(snd_mixer_class_t *class, snd_hctl_elem_t *helem)
+static int simple_event_add(snd_amixer_t *amixer, snd_ctl_elem_t *helem)
{
- const char *name = snd_hctl_elem_get_name(helem);
+ const char *name = snd_ctl_elem_get_name(helem);
size_t len;
selem_ctl_type_t type = CTL_SINGLE; /* to shut up warning */
- if (snd_hctl_elem_get_interface(helem) != SND_CTL_ELEM_IFACE_MIXER)
+ if (snd_ctl_elem_get_interface(helem) != SND_CTL_ELEM_IFACE_MIXER)
return 0;
if (strcmp(name, "Capture Source") == 0) {
snd_ctl_elem_info_t *info;
unsigned int k, items;
int err;
snd_ctl_elem_info_alloca(&info);
- err = snd_hctl_elem_info(helem, info);
+ err = snd_ctl_celem_info(helem, info);
assert(err >= 0);
if (snd_ctl_elem_info_get_type(info) != SND_CTL_ELEM_TYPE_ENUMERATED)
return 0;
@@ -1613,11 +1633,11 @@ static int simple_event_add(snd_mixer_class_t *class, snd_hctl_elem_t *helem)
for (k = 0; k < items; ++k) {
const char *n;
snd_ctl_elem_info_set_item(info, k);
- err = snd_hctl_elem_info(helem, info);
+ err = snd_ctl_celem_info(helem, info);
if (err < 0)
return err;
n = snd_ctl_elem_info_get_item_name(info);
- err = simple_add1(class, n, helem, CTL_CAPTURE_SOURCE, k);
+ err = simple_add1(amixer, n, helem, CTL_CAPTURE_SOURCE, k);
if (err < 0)
return err;
}
@@ -1625,7 +1645,7 @@ static int simple_event_add(snd_mixer_class_t *class, snd_hctl_elem_t *helem)
}
len = base_len(name, &type);
if (len == 0) {
- return simple_add1(class, name, helem, CTL_SINGLE, 0);
+ return simple_add1(amixer, name, helem, CTL_SINGLE, 0);
} else {
char ename[128];
if (len >= sizeof(ename))
@@ -1637,14 +1657,14 @@ static int simple_event_add(snd_mixer_class_t *class, snd_hctl_elem_t *helem)
type = CTL_CAPTURE_VOLUME;
else if (type == CTL_GLOBAL_SWITCH && !strcmp(ename, "Capture"))
type = CTL_CAPTURE_SWITCH;
- return simple_add1(class, ename, helem, type, 0);
+ return simple_add1(amixer, ename, helem, type, 0);
}
}
-static int simple_event_remove(snd_hctl_elem_t *helem,
- snd_mixer_elem_t *melem)
+static int simple_event_remove(snd_ctl_elem_t *helem,
+ snd_amixer_elem_t *melem)
{
- selem_none_t *simple = snd_mixer_elem_get_private(melem);
+ selem_none_t *simple = snd_amixer_elem_get_private(melem);
int err;
int k;
for (k = 0; k <= CTL_LAST; k++) {
@@ -1653,23 +1673,23 @@ static int simple_event_remove(snd_hctl_elem_t *helem,
}
assert(k <= CTL_LAST);
simple->ctls[k].elem = NULL;
- err = snd_mixer_elem_detach(melem, helem);
+ err = snd_amixer_elem_detach(melem, helem);
if (err < 0)
return err;
- if (snd_mixer_elem_empty(melem))
- return snd_mixer_elem_remove(melem);
+ if (snd_amixer_elem_is_empty(melem))
+ return snd_amixer_elem_remove(melem);
err = simple_update(melem);
- return snd_mixer_elem_info(melem);
+ return snd_amixer_elem_info(melem);
}
-static int simple_event(snd_mixer_class_t *class, unsigned int mask,
- snd_hctl_elem_t *helem, snd_mixer_elem_t *melem)
+static int simple_event(snd_amixer_t *amixer, unsigned int mask,
+ snd_ctl_elem_t *helem, snd_amixer_elem_t *melem)
{
int err;
if (mask == SND_CTL_EVENT_MASK_REMOVE)
return simple_event_remove(helem, melem);
if (mask & SND_CTL_EVENT_MASK_ADD) {
- err = simple_event_add(class, helem);
+ err = simple_event_add(amixer, helem);
if (err < 0)
return err;
}
@@ -1677,7 +1697,7 @@ static int simple_event(snd_mixer_class_t *class, unsigned int mask,
err = simple_event_remove(helem, melem);
if (err < 0)
return err;
- err = simple_event_add(class, helem);
+ err = simple_event_add(amixer, helem);
if (err < 0)
return err;
return 0;
@@ -1687,7 +1707,7 @@ static int simple_event(snd_mixer_class_t *class, unsigned int mask,
if (err < 0)
return err;
if (err) {
- err = snd_mixer_elem_value(melem);
+ err = snd_amixer_elem_value(melem);
if (err < 0)
return err;
}
@@ -1695,30 +1715,75 @@ static int simple_event(snd_mixer_class_t *class, unsigned int mask,
return 0;
}
+#ifndef DOC_HIDDEN
/**
- * \brief Register mixer simple element class - none abstraction
- * \param mixer Mixer handle
- * \param options Options container
- * \param classp Pointer to returned mixer simple element class handle (or NULL)
+ * \brief Open mixer - none abstraction
+ * \param amixer Mixer handle
+ * \param name Device name
+ * \param pcm_playback PCM handle for playback
+ * \param pcm_capture PCM handle for capture
+ * \param mode Open mode
* \return 0 on success otherwise a negative error code
*/
-int snd_mixer_simple_none_register(snd_mixer_t *mixer,
- struct snd_mixer_selem_regopt *options ATTRIBUTE_UNUSED,
- snd_mixer_class_t **classp)
+int _snd_amixer_none_open(snd_amixer_t *amixer,
+ snd_config_t *root ATTRIBUTE_UNUSED,
+ snd_config_t *conf,
+ struct sm_open *sm_open)
{
- snd_mixer_class_t *class;
+ snd_config_iterator_t i, next;
+ const char *str;
int err;
-
- if (snd_mixer_class_malloc(&class))
- return -ENOMEM;
- snd_mixer_class_set_event(class, simple_event);
- snd_mixer_class_set_compare(class, snd_mixer_selem_compare);
- err = snd_mixer_class_register(class, mixer);
- if (err < 0) {
- free(class);
- return err;
+ snd_config_t *n;
+ char ctlname[64];
+
+ ctlname[0] = '\0';
+ if (sm_open->pcm_playback || sm_open->pcm_capture)
+ return -ENXIO;
+ snd_config_for_each(i, next, conf) {
+ const char *id;
+ n = snd_config_iterator_entry(i);
+ if (snd_config_get_id(n, &id) < 0)
+ continue;
+ if (snd_amixer_conf_generic_id(id))
+ continue;
+ if (strcmp(id, "card") == 0) {
+ long card = -1;
+ err = snd_config_get_integer(n, &card);
+ if (err < 0) {
+ err = snd_config_get_string(n, &str);
+ if (err < 0) {
+ SNDERR("Invalid type for %s", id);
+ return -EINVAL;
+ }
+ card = snd_card_get_index(str);
+ if (card < 0) {
+ SNDERR("Invalid value for %s", id);
+ return card;
+ }
+ }
+ sprintf(ctlname, "hw:%li", card);
+ continue;
+ }
+ if (strcmp(id, "ctlname") == 0) {
+ err = snd_config_get_string(n, &str);
+ if (err < 0) {
+ SNDERR("ctlname must be a string");
+ return -EINVAL;
+ }
+ strncpy(ctlname, str, sizeof(ctlname)-1);
+ ctlname[sizeof(ctlname)-1] = '\0';
+ continue;
+ }
+ SNDERR("Unknown field %s", id);
+ return -EINVAL;
}
- if (classp)
- *classp = class;
- return 0;
+ if (ctlname[0] == '\0') {
+ SNDERR("card or ctlname is not defined");
+ return -EINVAL;
+ }
+ snd_amixer_set_event(amixer, simple_event);
+ return snd_ctl_open(&sm_open->ctl[0], ctlname, SND_CTL_CACHE);
}
+
+SND_DLSYM_BUILD_VERSION(_snd_amixer_none_open, SND_AMIXER_DLSYM_VERSION);
+#endif
diff --git a/src/mixer/simple_old.c b/src/mixer/simple_old.c
new file mode 100644
index 00000000..339b9940
--- /dev/null
+++ b/src/mixer/simple_old.c
@@ -0,0 +1,805 @@
+/**
+ * \file mixer/simple.c
+ * \brief Mixer Simple Element Class Interface
+ * \author Jaroslav Kysela <perex@perex.cz>
+ * \author Abramo Bagnara <abramo@alsa-project.org>
+ * \date 2001-2004
+ *
+ * Mixer simple element class interface.
+ */
+/*
+ * Mixer Interface - simple controls
+ * Copyright (c) 2000,2004 by Jaroslav Kysela <perex@perex.cz>
+ * 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 Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <math.h>
+#include "mixer_old_local.h"
+
+#define SM_PLAY SND_MIXER_DIR_PLAYBACK
+#define SM_CAPT SND_MIXER_DIR_CAPTURE
+#define SM_COMM SND_MIXER_DIR_COMMON
+
+/**
+ * \brief Register mixer simple element class
+ * \param mixer Mixer handle
+ * \param options Options container
+ * \param nothing Pass NULL
+ * \return zero on success, otherwise a negative error code
+ */
+int snd_mixer_selem_register(snd_mixer_t *mixer,
+ struct snd_mixer_selem_regopt *options,
+ void **nothing ATTRIBUTE_UNUSED)
+{
+ int err;
+
+ if (options && options->ver == 1) {
+ if (options->device != NULL &&
+ (options->playback_pcm != NULL ||
+ options->capture_pcm != NULL))
+ return -EINVAL;
+ if (options->device == NULL &&
+ options->playback_pcm == NULL &&
+ options->capture_pcm == NULL)
+ return -EINVAL;
+ }
+ if (options == NULL ||
+ (options->ver == 1 && options->abstract == SND_MIXER_SABSTRACT_NONE)) {
+ if (options != NULL) {
+ err = snd_mixer_attach(mixer, options->device);
+ if (err < 0)
+ return err;
+ }
+ return 0;
+ } else if (options->ver == 1) {
+ if (options->abstract == SND_MIXER_SABSTRACT_BASIC)
+ return snd_mixer_attach(mixer, options->device);
+ }
+ return -ENXIO;
+}
+
+/**
+ * \brief Find a mixer simple element
+ * \param mixer Mixer handle
+ * \param id Mixer simple element identifier
+ * \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)
+{
+ return snd_amixer_find_elem(mixer->amixer, id);
+}
+
+/**
+ * \brief Get mixer simple element identifier
+ * \param elem Mixer simple element handle
+ * \param id returned mixer simple element identifier
+ */
+void snd_mixer_selem_get_id(snd_mixer_elem_t *elem,
+ snd_mixer_selem_id_t *id)
+{
+ return snd_amixer_elem_get_id(elem, id);
+}
+
+/**
+ * \brief Get name part of mixer simple element identifier
+ * \param elem Mixer simple element handle
+ * \return name part of simple element identifier
+ */
+const char *snd_mixer_selem_get_name(snd_mixer_elem_t *elem)
+{
+ return snd_amixer_elem_get_name(elem);
+}
+
+/**
+ * \brief Get index part of mixer simple element identifier
+ * \param elem Mixer simple element handle
+ * \return index part of simple element identifier
+ */
+unsigned int snd_mixer_selem_get_index(snd_mixer_elem_t *elem)
+{
+ return snd_amixer_elem_get_index(elem);
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_elem_has_volume(elem, SM_COMM);
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_elem_has_switch(elem, SM_COMM);
+}
+
+/**
+ * \brief Return name of mixer simple element channel
+ * \param channel mixer simple element channel identifier
+ * \return channel name
+ */
+const char *snd_mixer_selem_channel_name(snd_mixer_selem_channel_id_t channel)
+{
+ return snd_amixer_elem_channel_name(channel);
+}
+
+/**
+ * \brief Get info about the active state of a mixer simple element
+ * \param elem Mixer simple element handle
+ * \return 0 if not active, 1 if active
+ */
+int snd_mixer_selem_is_active(snd_mixer_elem_t *elem)
+{
+ return snd_amixer_elem_is_active(elem);
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_elem_get_channels(elem, SM_PLAY) == 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 identifier
+ * \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)
+{
+ return snd_amixer_elem_has_channel(elem, SM_PLAY, channel);
+}
+
+/**
+ * \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
+ */
+int snd_mixer_selem_get_playback_volume_range(snd_mixer_elem_t *elem,
+ long *min, long *max)
+{
+ return snd_amixer_elem_get_volume_range(elem, SM_PLAY, min, max);
+}
+
+/**
+ * \brief Get range in dB for playback volume of a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param min Pointer to returned minimum (dB * 100)
+ * \param max Pointer to returned maximum (dB * 100)
+ */
+int snd_mixer_selem_get_playback_dB_range(snd_mixer_elem_t *elem,
+ long *min, long *max)
+{
+ return snd_amixer_elem_get_dB_range(elem, SM_PLAY, min, max);
+}
+
+/**
+ * \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
+ */
+int snd_mixer_selem_set_playback_volume_range(snd_mixer_elem_t *elem,
+ long min, long max)
+{
+ return snd_amixer_elem_set_volume_range(elem, SM_PLAY, min, max);
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_elem_has_volume(elem, SM_PLAY);
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_elem_has_volume_joined(elem, SM_PLAY);
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_elem_has_switch(elem, SM_PLAY);
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_elem_has_switch_joined(elem, SM_PLAY);
+}
+
+/**
+ * \brief Return corresponding dB value to an integer playback volume for a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param value value to be converted to dB range
+ * \param dBvalue pointer to returned dB value
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_mixer_selem_ask_playback_vol_dB(snd_mixer_elem_t *elem, long value, long *dBvalue)
+{
+ return snd_amixer_elem_ask_vol_dB(elem, SM_PLAY, value, dBvalue);
+}
+
+/**
+ * \brief Return corresponding integer playback volume for given dB value for a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param value value to be converted to dB range
+ * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
+ * \param dBvalue pointer to returned dB value
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_mixer_selem_ask_playback_dB_vol(snd_mixer_elem_t *elem, long dBvalue, int dir, long *value)
+{
+ return snd_amixer_elem_ask_dB_vol(elem, SM_PLAY, dBvalue, dir, value);
+}
+
+/**
+ * \brief Return value of playback volume control of a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param channel mixer simple element channel identifier
+ * \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)
+{
+ return snd_amixer_elem_get_volume(elem, SM_PLAY, channel, value);
+}
+
+/**
+ * \brief Return value of playback volume in dB control of a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param channel mixer simple element channel identifier
+ * \param value pointer to returned value (dB * 100)
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_mixer_selem_get_playback_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value)
+{
+ return snd_amixer_elem_get_dB(elem, SM_PLAY, channel, value);
+}
+
+/**
+ * \brief Return value of playback switch control of a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param channel mixer simple element channel identifier
+ * \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)
+{
+ return snd_amixer_elem_get_switch(elem, SM_PLAY, channel, value);
+}
+
+/**
+ * \brief Set value of playback volume control of a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param channel mixer simple element channel identifier
+ * \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)
+{
+ return snd_amixer_elem_set_volume(elem, SM_PLAY, channel, value);
+}
+
+/**
+ * \brief Set value in dB of playback volume control of a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param channel mixer simple element channel identifier
+ * \param value control value in dB * 100
+ * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_mixer_selem_set_playback_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value, int dir)
+{
+ return snd_amixer_elem_set_dB(elem, SM_PLAY, channel, value, dir);
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_elem_set_volume_all(elem, SM_PLAY, value);
+}
+
+/**
+ * \brief Set value in dB of playback volume control for all channels of a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param value control value in dB * 100
+ * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_mixer_selem_set_playback_dB_all(snd_mixer_elem_t *elem, long value, int dir)
+{
+ return snd_amixer_elem_set_dB_all(elem, SM_PLAY, value, dir);
+}
+
+/**
+ * \brief Set value of playback switch control of a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param channel mixer simple element channel identifier
+ * \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)
+{
+ return snd_amixer_elem_set_switch(elem, SM_PLAY, channel, value);
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_elem_set_switch_all(elem, SM_PLAY, value);
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_elem_get_channels(elem, SM_CAPT) == 1;
+}
+
+/**
+ * \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 identifier
+ * \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)
+{
+ return snd_amixer_elem_has_channel(elem, SM_CAPT, channel);
+}
+
+/**
+ * \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
+ */
+int snd_mixer_selem_get_capture_volume_range(snd_mixer_elem_t *elem,
+ long *min, long *max)
+{
+ return snd_amixer_elem_get_volume_range(elem, SM_CAPT, min, max);
+}
+
+/**
+ * \brief Get range in dB for capture volume of a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param min Pointer to returned minimum (dB * 100)
+ * \param max Pointer to returned maximum (dB * 100)
+ */
+int snd_mixer_selem_get_capture_dB_range(snd_mixer_elem_t *elem,
+ long *min, long *max)
+{
+ return snd_amixer_elem_get_dB_range(elem, SM_CAPT, min, 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
+ */
+int snd_mixer_selem_set_capture_volume_range(snd_mixer_elem_t *elem,
+ long min, long max)
+{
+ return snd_amixer_elem_set_volume_range(elem, SM_CAPT, min, 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)
+{
+ return snd_amixer_elem_has_volume(elem, SM_CAPT);
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_elem_has_volume_joined(elem, SM_CAPT);
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_elem_has_switch(elem, SM_CAPT);
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_elem_has_switch_joined(elem, SM_CAPT);
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_elem_has_switch_exclusive(elem, SM_CAPT);
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_elem_get_group(elem, SM_CAPT);
+}
+
+/**
+ * \brief Return corresponding dB value to an integer capture volume for a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param value value to be converted to dB range
+ * \param dBvalue pointer to returned dB value
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_mixer_selem_ask_capture_vol_dB(snd_mixer_elem_t *elem, long value, long *dBvalue)
+{
+ return snd_amixer_elem_ask_vol_dB(elem, SM_CAPT, value, dBvalue);
+}
+
+/**
+ * \brief Return corresponding integer capture volume for given dB value for a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param dBvalue dB value to be converted to integer range
+ * \param value pointer to returned integer value
+ * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_mixer_selem_ask_capture_dB_vol(snd_mixer_elem_t *elem, long dBvalue, int dir, long *value)
+{
+ return snd_amixer_elem_ask_dB_vol(elem, SM_CAPT, dBvalue, dir, value);
+}
+
+/**
+ * \brief Return value of capture volume control of a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param channel mixer simple element channel identifier
+ * \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)
+{
+ return snd_amixer_elem_get_volume(elem, SM_CAPT, channel, value);
+}
+
+/**
+ * \brief Return value of capture volume in dB control of a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param channel mixer simple element channel identifier
+ * \param value pointer to returned value (dB * 100)
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_mixer_selem_get_capture_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long *value)
+{
+ return snd_amixer_elem_get_dB(elem, SM_CAPT, channel, value);
+}
+
+/**
+ * \brief Return value of capture switch control of a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param channel mixer simple element channel identifier
+ * \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)
+{
+ return snd_amixer_elem_get_switch(elem, SM_CAPT, channel, value);
+}
+
+/**
+ * \brief Set value of capture volume control of a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param channel mixer simple element channel identifier
+ * \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)
+{
+ return snd_amixer_elem_set_volume(elem, SM_CAPT, channel, value);
+}
+
+/**
+ * \brief Set value in dB of capture volume control of a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param channel mixer simple element channel identifier
+ * \param value control value in dB * 100
+ * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_mixer_selem_set_capture_dB(snd_mixer_elem_t *elem, snd_mixer_selem_channel_id_t channel, long value, int dir)
+{
+ return snd_amixer_elem_set_dB(elem, SM_CAPT, channel, value, dir);
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_elem_set_volume_all(elem, SM_CAPT, value);
+}
+
+/**
+ * \brief Set value in dB of capture volume control for all channels of a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param value control value in dB * 100
+ * \param dir select direction (-1 = accurate or first bellow, 0 = accurate, 1 = accurate or first above)
+ * \return 0 on success otherwise a negative error code
+ */
+int snd_mixer_selem_set_capture_dB_all(snd_mixer_elem_t *elem, long value, int dir)
+{
+ return snd_amixer_elem_set_dB_all(elem, SM_CAPT, value, dir);
+}
+
+/**
+ * \brief Set value of capture switch control of a mixer simple element
+ * \param elem Mixer simple element handle
+ * \param channel mixer simple element channel identifier
+ * \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)
+{
+ return snd_amixer_elem_set_switch(elem, SM_CAPT, channel, 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)
+{
+ return snd_amixer_elem_set_switch_all(elem, SM_CAPT, value);
+}
+
+/**
+ * \brief Return true if mixer simple element is an enumerated control
+ * \param elem Mixer simple element handle
+ * \return 0 normal volume/switch control, 1 enumerated control
+ */
+int snd_mixer_selem_is_enumerated(snd_mixer_elem_t *elem)
+{
+ return snd_amixer_elem_is_enum(elem, SM_COMM) ||
+ snd_amixer_elem_is_enum(elem, SM_PLAY) ||
+ snd_amixer_elem_is_enum(elem, SM_CAPT);
+}
+
+/**
+ * \brief Return true if mixer simple enumerated element belongs to the playback direction
+ * \param elem Mixer simple element handle
+ * \return 0 no playback direction, 1 playback direction
+ */
+int snd_mixer_selem_is_enum_playback(snd_mixer_elem_t *elem)
+{
+ return snd_amixer_elem_is_enum(elem, SM_PLAY);
+}
+
+/**
+ * \brief Return true if mixer simple enumerated element belongs to the capture direction
+ * \param elem Mixer simple element handle
+ * \return 0 no capture direction, 1 capture direction
+ */
+int snd_mixer_selem_is_enum_capture(snd_mixer_elem_t *elem)
+{
+ return snd_amixer_elem_is_enum(elem, SM_CAPT);
+}
+
+/**
+ * \brief Return the number of enumerated items of the given mixer simple element
+ * \param elem Mixer simple element handle
+ * \return the number of enumerated items, otherwise a negative error code
+ */
+int snd_mixer_selem_get_enum_items(snd_mixer_elem_t *elem)
+{
+ return snd_amixer_elem_get_enum_items(elem);
+}
+
+/**
+ * \brief get the enumerated item string for the given mixer simple element
+ * \param elem Mixer simple element handle
+ * \param item the index of the enumerated item to query
+ * \param maxlen the maximal length to be stored
+ * \param buf the buffer to store the name string
+ * \return 0 if successful, otherwise a negative error code
+ */
+int snd_mixer_selem_get_enum_item_name(snd_mixer_elem_t *elem,
+ unsigned int item,
+ size_t maxlen, char *buf)
+{
+ return snd_amixer_elem_get_enum_item_name(elem, item, maxlen, buf);
+}
+
+/**
+ * \brief get the current selected enumerated item for the given mixer simple element
+ * \param elem Mixer simple element handle
+ * \param channel mixer simple element channel identifier
+ * \param itemp the pointer to store the index of the enumerated item
+ * \return 0 if successful, otherwise a negative error code
+ */
+int snd_mixer_selem_get_enum_item(snd_mixer_elem_t *elem,
+ snd_mixer_selem_channel_id_t channel,
+ unsigned int *itemp)
+{
+ return snd_amixer_elem_get_enum_item(elem, channel, itemp);
+}
+
+/**
+ * \brief set the current selected enumerated item for the given mixer simple element
+ * \param elem Mixer simple element handle
+ * \param channel mixer simple element channel identifier
+ * \param item the enumerated item index
+ * \return 0 if successful, otherwise a negative error code
+ */
+int snd_mixer_selem_set_enum_item(snd_mixer_elem_t *elem,
+ snd_mixer_selem_channel_id_t channel,
+ unsigned int item)
+{
+ return snd_amixer_elem_set_enum_item(elem, channel, item);
+}
+
+/**
+ * \brief get size of #snd_mixer_selem_id_t
+ * \return size in bytes
+ */
+size_t snd_mixer_selem_id_sizeof(void)
+{
+ return snd_amixer_elem_id_sizeof();
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_elem_id_malloc(ptr);
+}
+
+/**
+ * \brief frees a previously allocated #snd_mixer_selem_id_t
+ * \param obj pointer to object to free
+ */
+void snd_mixer_selem_id_free(snd_mixer_selem_id_t *obj)
+{
+ return snd_amixer_elem_id_free(obj);
+}
+
+/**
+ * \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)
+{
+ return snd_amixer_elem_id_copy(dst, src);
+}
+
+/**
+ * \brief Get name part of a mixer simple element identifier
+ * \param obj Mixer simple element identifier
+ * \return name part
+ */
+const char *snd_mixer_selem_id_get_name(const snd_mixer_selem_id_t *obj)
+{
+ return snd_amixer_elem_id_get_name(obj);
+}
+
+/**
+ * \brief Get index part of a mixer simple element identifier
+ * \param obj Mixer simple element identifier
+ * \return index part
+ */
+unsigned int snd_mixer_selem_id_get_index(const snd_mixer_selem_id_t *obj)
+{
+ return snd_amixer_elem_id_get_index(obj);
+}
+
+/**
+ * \brief Set name part of a mixer simple element identifier
+ * \param obj Mixer simple element identifier
+ * \param val name part
+ */
+void snd_mixer_selem_id_set_name(snd_mixer_selem_id_t *obj, const char *val)
+{
+ return snd_amixer_elem_id_set_name(obj, val);
+}
+
+/**
+ * \brief Set index part of a mixer simple element identifier
+ * \param obj Mixer simple element identifier
+ * \param val index part
+ */
+void snd_mixer_selem_id_set_index(snd_mixer_selem_id_t *obj, unsigned int val)
+{
+ return snd_amixer_elem_id_set_index(obj, val);
+}