summaryrefslogtreecommitdiff
path: root/lib/libsalsa/mix.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libsalsa/mix.c')
-rw-r--r--lib/libsalsa/mix.c1125
1 files changed, 1125 insertions, 0 deletions
diff --git a/lib/libsalsa/mix.c b/lib/libsalsa/mix.c
new file mode 100644
index 0000000..5131518
--- /dev/null
+++ b/lib/libsalsa/mix.c
@@ -0,0 +1,1125 @@
+/*
+ * Copyright (c) 2004 by Hannu Savolainen < hannu@opensound.com>
+ *
+ * Parts of the code is derived from the alsa-lib package that is
+ * copyrighted by Jaroslav Kysela and the other ALSA team members.
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * 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 "local.h"
+
+#define SND_VERS(a, b, c) (a<<16|b<<8|c)
+
+typedef struct _snd_mixer
+{
+ int mixdev;
+ int nrext;
+
+ oss_mixerinfo info;
+
+ snd_mixer_elem_t *elems;
+} snd_mixer_t;
+
+#define MAX_MIXERS 32
+static snd_mixer_t *mixers[MAX_MIXERS];
+static int nmixers = 0;
+
+typedef struct _snd_mixer_selem_id
+{
+ int number;
+ char name[32];
+} snd_mixer_selem_id_t;
+
+typedef struct _snd_mixer_class
+{
+ int dummy;
+} snd_mixer_class_t;
+
+typedef struct _snd_mixer_elem
+{
+ snd_mixer_t *mixer;
+ int ctrl;
+ oss_mixext ext;
+
+ snd_mixer_elem_t *next;
+
+ int low, high;
+} snd_mixer_elem_t;
+
+/**
+ * \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)
+{
+ snd_mixer_t *mixer;
+ dbg_printf2 ("snd_mixer_open()\n");
+
+ ALIB_INIT ();
+ if (!alib_appcheck ())
+ return -ENODEV;
+
+ if ((mixer = malloc (sizeof (*mixer))) == NULL)
+ return -ENOMEM;
+
+ memset (mixer, 0, sizeof (*mixer));
+ *mixerp = mixer;
+
+ return 0;
+}
+
+/**
+ * \brief Attach an HCTL to an opened mixer
+ * \param mixer Mixer handle
+ * \param name HCTL name (see #snd_hctl_open)
+ * \return 0 on success otherwise a negative error code
+ */
+int
+snd_mixer_attach (snd_mixer_t * mixer, const char *name)
+{
+ int dev = 0;
+
+ ALIB_INIT ();
+ dbg_printf2 ("snd_mixer_attach(%s)\n", name);
+
+
+ if (strcmp (name, "default") == 0)
+ dev = 0;
+ else if (name[0] == 'h' && name[1] == 'w' && name[2] == ':')
+ {
+ if (sscanf (name + 3, "%d", &dev) != 1)
+ return -ENOENT;
+
+ if (dev < 0 || dev >= sysinfo.nummixers)
+ return -ENXIO;
+ }
+ else
+ return -ENOENT;
+
+ mixer->mixdev = dev;
+
+ mixer->info.dev = dev;
+ if (ioctl (mixer_fd, SNDCTL_MIXERINFO, &mixer->info) == -1)
+ return -errno;
+
+ mixer->nrext = mixer->info.nrext;
+
+ if (nmixers < MAX_MIXERS)
+ mixers[nmixers++] = mixer;
+
+ return 0;
+}
+
+
+/**
+ * \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)
+{
+ dbg_printf2 ("snd_mixer_close()\n");
+
+ free (mixer);
+ return 0;
+}
+
+/**
+ * \brief Register mixer simple element class
+ * \param mixer Mixer handle
+ * \param options Options container (not used now)
+ * \param classp Pointer to returned mixer simple element class handle (or NULL) * \return 0 on success otherwise a negative error code
+ */
+#if 1
+int
+snd_mixer_selem_register (snd_mixer_t * mixer,
+ struct snd_mixer_selem_regopt *arg,
+ snd_mixer_class_t ** classp)
+#else
+int
+snd_mixer_selem_register (snd_mixer_t * mixer, void *arg,
+ snd_mixer_class_t ** classp)
+#endif
+{
+ snd_mixer_class_t *class;
+
+ dbg_printf2 ("snd_mixer_selem_register()\n");
+
+ if (classp == NULL) /* Why this call was ever made ? */
+ return 0;
+
+ if ((class = malloc (sizeof (*class))) == NULL)
+ return -ENOMEM;
+
+ memset (class, 0, sizeof (*class));
+ *classp = class;
+
+ return 0;
+}
+
+/**
+ * \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)
+{
+ dbg_printf2 ("snd_mixer_selem_has_playback_volume(%x)\n", elem);
+ fflush (stdout);
+
+ if (elem->ext.type == MIXT_STEREOSLIDER)
+ return 1;
+ if (elem->ext.type == MIXT_MONOSLIDER)
+ return 1;
+ if (elem->ext.type == MIXT_SLIDER)
+ return 1;
+
+ return 0;
+}
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_selem_has_playback_volume_joined()\n");
+
+ return elem->ext.type != MIXT_STEREOSLIDER;
+}
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_selem_has_capture_volume()\n");
+
+ return 0;
+}
+
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_selem_has_playback_switch()\n");
+
+ if (elem->ext.type == MIXT_ONOFF || elem->ext.type == MIXT_MUTE)
+ return 1;
+ return 0;
+}
+
+/**
+ * \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)
+{
+ int vol, range;
+ oss_mixer_value rec;
+
+ dbg_printf2 ("snd_mixer_selem_set_playback_volume(%ld)\n", value);
+
+ if (value < elem->low)
+ value = elem->low;
+ if (value > elem->high)
+ value = elem->high;
+
+ range = elem->high - elem->low;
+ if (range == 0)
+ range = 100;
+ value -= elem->low;
+ vol = (value * elem->ext.maxvalue) / range;
+
+ rec.dev = elem->ext.dev;
+ rec.ctrl = elem->ext.ctrl;
+ rec.ctrl = elem->ext.ctrl;
+ rec.timestamp = elem->ext.timestamp;
+ rec.value = vol | (vol << 8);
+
+ if (ioctl (mixer_fd, SNDCTL_MIX_WRITE, &rec) == -1)
+ return -errno;
+
+ return 0;
+}
+
+/**
+ * \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
+ */
+#if SND_LIB_VERSION > SND_VERS(1,0,9)
+int
+#else
+void
+#endif
+snd_mixer_selem_set_capture_volume_range (snd_mixer_elem_t * elem,
+ long min, long max)
+{
+ dbg_printf ("snd_mixer_selem_set_capture_volume_range()\n");
+
+#if SND_LIB_VERSION > SND_VERS(1,0,9)
+ return 0;
+#endif
+}
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_selem_set_capture_volume()\n");
+
+ return 0;
+}
+
+/**
+ * \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
+ */
+#if SND_LIB_VERSION > SND_VERS(1,0,9)
+int
+#else
+void
+#endif
+snd_mixer_selem_set_playback_volume_range (snd_mixer_elem_t * elem,
+ long min, long max)
+{
+ dbg_printf2 ("snd_mixer_selem_set_playback_volume_range(%s, %d, %d)\n",
+ elem->ext.extname, min, max);
+
+ elem->low = min;
+ elem->high = max;
+
+#if SND_LIB_VERSION > SND_VERS(1,0,9)
+ return 0;
+#endif
+}
+
+/**
+ * \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)
+{
+ int vol, range, left, right;
+ oss_mixer_value rec;
+
+ dbg_printf2 ("snd_mixer_selem_get_playback_volume()\n");
+
+ rec.dev = elem->ext.dev;
+ rec.ctrl = elem->ext.ctrl;
+ rec.timestamp = elem->ext.timestamp;
+
+ if (ioctl (mixer_fd, SNDCTL_MIX_READ, &rec) == -1)
+ return -errno;
+
+ left = rec.value & 0xff;
+ right = (rec.value >> 8) & 0xff;
+
+ if (left > right)
+ vol = left;
+ else
+ vol = right;
+ range = elem->high - elem->low;
+
+ vol = (vol * range) / elem->ext.maxvalue;
+ vol += elem->low;
+ *value = vol;
+
+ return 0;
+}
+
+/**
+ * \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
+ */
+#if SND_LIB_VERSION > SND_VERS(1,0,9)
+int
+#else
+void
+#endif
+snd_mixer_selem_get_playback_volume_range (snd_mixer_elem_t * elem,
+ long *min, long *max)
+{
+ dbg_printf2 ("snd_mixer_selem_get_playback_volume_range()\n");
+#if 1
+ *min = elem->low;
+ *max = elem->high;
+#endif
+
+#if SND_LIB_VERSION > SND_VERS(1,0,9)
+ return 0;
+#endif
+}
+
+/**
+ * \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)
+{
+ dbg_printf2 ("snd_mixer_first_elem()\n");
+
+ return mixer->elems;
+}
+
+/**
+ * \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)
+{
+ dbg_printf2 ("snd_mixer_elem_next(%x/%d)\n", elem, elem);
+
+ if (elem == NULL || (long) elem < 4096)
+ {
+ dbg_printf2 ("Returning NULL\n");
+ return NULL;
+ }
+
+ if (elem->next == NULL)
+ dbg_printf ("No more elemsnts\n");
+ else
+ dbg_printf2 ("Returning %d/%s\n", elem->next->ctrl,
+ elem->next->ext.extname);
+ return elem->next;
+}
+
+/**
+ * \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
+ *
+ * Wuld somebody kindly explain me what in hell is the logic
+ * behind this idiotic "simple" mixer stuff.
+ */
+snd_mixer_elem_t *
+snd_mixer_find_selem (snd_mixer_t * mixer, const snd_mixer_selem_id_t * id)
+{
+ int i;
+
+ dbg_printf2 ("snd_mixer_find_selem(%d/%s)\n", id->number, id->name);
+
+ if (*id->name == 0 && id->number == 0)
+ return NULL;
+
+ for (i = 0; i < mixer->nrext; i++)
+ {
+ oss_mixext *ext = &mixer->elems[i].ext;
+
+ if (ext->type == MIXT_GROUP ||
+ ext->type == MIXT_DEVROOT || ext->type == MIXT_MARKER)
+ continue;
+
+ if (strcasecmp (ext->extname, id->name) == 0)
+ {
+ return &mixer->elems[i];
+ }
+
+ if (ext->ctrl == id->number)
+ {
+ return &mixer->elems[i];
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * \brief Handle pending mixer events invoking callbacks
+ * \param mixer Mixer handle
+ * \return 0 otherwise a negative error code on failure
+ */
+int
+snd_mixer_handle_events (snd_mixer_t * mixer)
+{
+ dbg_printf2 ("snd_mixer_handle_events()\n");
+ // NOP
+}
+
+/**
+ * \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)
+{
+ snd_mixer_elem_t *elems;
+ int i, n = 0;
+
+ dbg_printf2 ("snd_mixer_load()\n");
+
+ if (mixer->elems != NULL)
+ free (mixer->elems);
+
+ if ((elems = malloc (sizeof (*elems) * mixer->nrext)) == NULL)
+ return -ENOMEM;
+
+ memset (elems, 0, sizeof (*elems) * mixer->nrext);
+
+ for (i = 0; i < mixer->nrext; i++)
+ {
+ oss_mixext *ext = &elems[n].ext;
+ snd_mixer_elem_t *elem;
+
+ elem = &elems[n];
+
+ ext->dev = mixer->mixdev;
+ ext->ctrl = i;
+
+ if (ioctl (mixer_fd, SNDCTL_MIX_EXTINFO, ext) < 0)
+ {
+ int e = errno;
+ perror ("SNDCTL_MIX_EXTINFO");
+ return -e;
+ }
+
+ if (ext->type == MIXT_DEVROOT)
+ continue;
+ if (ext->type == MIXT_GROUP)
+ continue;
+ if (ext->type == MIXT_MARKER)
+ continue;
+
+ elem->low = 0;
+ elem->high = ext->maxvalue;
+ elem->ctrl = elem->ext.ctrl;
+
+ if (n > 0)
+ elems[n - 1].next = &elems[n];
+
+ n++;
+ }
+
+ mixer->nrext = n;
+ mixer->elems = elems;
+ return 0;
+}
+
+/**
+ * \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)
+{
+ dbg_printf2 ("snd_mixer_selem_get_name()\n");
+
+ return elem->ext.extname;
+}
+
+/**
+ * \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)
+{
+ dbg_printf2 ("snd_mixer_selem_id_set_index(%u)\n", val);
+
+ obj->number = val;
+}
+
+/**
+ * \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)
+{
+ dbg_printf2 ("snd_mixer_selem_id_set_name(%s)\n", val);
+
+ strcpy (obj->name, val);
+}
+
+/**
+ * \brief get size of #snd_mixer_selem_id_t
+ * \return size in bytes
+ */
+size_t
+snd_mixer_selem_id_sizeof ()
+{
+ return sizeof (snd_mixer_selem_id_t);
+}
+
+
+/**
+ * \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)
+{
+ dbg_printf2 ("snd_mixer_selem_is_active()\n");
+ return 1;
+}
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_selem_get_capture_switch()\n");
+
+ *value = 0;
+ return 0;
+}
+
+/**
+ * \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)
+{
+ oss_mixer_value rec;
+
+ dbg_printf ("snd_mixer_selem_get_playback_switch()\n");
+
+ *value = 0;
+
+ rec.dev = elem->ext.dev;
+ rec.ctrl = elem->ext.ctrl;
+ rec.ctrl = elem->ext.ctrl;
+ rec.timestamp = elem->ext.timestamp;
+
+ if (ioctl (mixer_fd, SNDCTL_MIX_READ, &rec) == -1)
+ return -errno;
+
+ *value = !!rec.value;
+ return 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)
+{
+ dbg_printf ("snd_mixer_selem_has_capture_channel()\n");
+
+ return (channel < 2);
+}
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_selem_has_capture_switch()\n");
+
+ return 0;
+}
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_selem_has_capture_switch_joined()\n");
+
+ return 1;
+}
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_selem_is_capture_mono()\n");
+ return 0;
+}
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_selem_is_playback_mono()\n");
+ 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)
+{
+ dbg_printf ("snd_mixer_selem_set_capture_switch()\n");
+
+ return 0;
+}
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_selem_set_capture_switch_all()\n");
+
+ return 0;
+}
+
+/**
+ * \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)
+{
+ oss_mixer_value rec;
+
+ dbg_printf ("snd_mixer_selem_set_playback_switch_all()\n");
+
+ rec.dev = elem->ext.dev;
+ rec.ctrl = elem->ext.ctrl;
+ rec.ctrl = elem->ext.ctrl;
+ rec.timestamp = elem->ext.timestamp;
+ rec.value = !!value;
+
+ if (ioctl (mixer_fd, SNDCTL_MIX_WRITE, &rec) == -1)
+ return -errno;
+
+ return 0;
+}
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_selem_get_capture_volume()\n");
+
+ *value = 0;
+ return 0;
+}
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_selem_get_id()\n");
+ // What in hell is this?
+
+ id->number = elem->ctrl;
+ strcpy (id->name, elem->ext.extname);
+ dbg_printf ("ID=%d / %s\n", id->number, id->name);
+}
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_selem_id_get_name()=%s\n", obj->name);
+//return "Objname";
+ return obj->name;
+}
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_selem_id_get_index()\n");
+
+ return 0;
+}
+
+
+/**
+ * \brief Get elements count for a mixer
+ * \param mixer mixer handle
+ * \return elements count
+ */
+unsigned int
+snd_mixer_get_count (const snd_mixer_t * obj)
+{
+ dbg_printf ("snd_mixer_get_count()\n");
+
+ return obj->nrext;
+}
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_poll_descriptors()\n");
+
+ return 0;
+}
+
+/**
+ * \brief get count of poll descriptors for mixer handle
+ * \param mixer Mixer handle
+ * \return count of poll descriptors
+ */
+int
+snd_mixer_poll_descriptors_count (snd_mixer_t * mixer)
+{
+ dbg_printf ("snd_mixer_poll_descriptors_count()\n");
+
+ return 0;
+}
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_poll_descriptors_revents()\n");
+
+ return 0;
+}
+
+/**
+ * \brief Set callback function for a mixer
+ * \param mixer mixer handle
+ * \param callback callback function
+ */
+void
+snd_mixer_set_callback (snd_mixer_t * obj, snd_mixer_callback_t val)
+{
+ dbg_printf0 ("snd_mixer_set_callback()\n");
+
+}
+
+/**
+ * \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
+ */
+#if SND_LIB_VERSION > SND_VERS(1,0,9)
+int
+#else
+void
+#endif
+snd_mixer_selem_get_capture_volume_range (snd_mixer_elem_t * elem,
+ long *min, long *max)
+{
+ dbg_printf ("snd_mixer_selem_get_capture_volume_range()\n");
+
+ *min = 0;
+ *max = 100;
+
+#if SND_LIB_VERSION > SND_VERS(1,0,9)
+ return 0;
+#endif
+}
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_selem_is_enumerated()\n");
+
+ return 0;
+}
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_selem_get_enum_item()\n");
+
+ return 0;
+}
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_selem_get_enum_items()\n");
+ return 0;
+}
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_selem_get_enum_item_name()\n");
+ strncpy (buf, "Enum", maxlen);
+ buf[maxlen - 1] = 0;
+
+ return 0;
+}
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_selem_has_capture_volume_joined()\n");
+ return elem->ext.type != MIXT_STEREOSLIDER;
+}
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_selem_has_playback_channel(%s, %d)\n",
+ elem->ext.extname, channel);
+
+ if (elem->ext.type == MIXT_SLIDER && channel == 0)
+ return 1;
+ if (elem->ext.type == MIXT_MONOSLIDER && channel == 0)
+ return 1;
+ if (elem->ext.type == MIXT_STEREOSLIDER && channel < 2)
+ return 1;
+
+ return 0;
+}
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_selem_has_playback_switch_joined()\n");
+
+ return 0;
+}
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_selem_id_copy()\n");
+ memcpy (dst, src, sizeof (*dst));
+}
+
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_selem_set_enum_item()\n");
+
+ return 0;
+}
+
+/**
+ * \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)
+{
+ dbg_printf ("snd_mixer_selem_set_playback_switch()\n");
+
+ return 0;
+}
+
+/**
+ * * \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 0; // TODO
+}
+
+/**
+ * * \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 0; // TODO
+}