]> git.alsa-project.org Git - alsa-lib.git/commitdiff
Mixer v2.0 merged to the main CVS tree...
authorJaroslav Kysela <perex@perex.cz>
Sun, 2 May 1999 16:21:30 +0000 (16:21 +0000)
committerJaroslav Kysela <perex@perex.cz>
Sun, 2 May 1999 16:21:30 +0000 (16:21 +0000)
acinclude.m4
include/control.h
include/mixer.h
src/control/Makefile.am
src/control/defaults.c [new file with mode: 0644]
src/mixer/Makefile.am
src/mixer/elements.c [new file with mode: 0644]
src/mixer/mixer.c
test/control.c
test/mixer.c

index cd289edc07786f54c2d3f432e49c9ecc93447012..69bceea9f6fc8e301eff299b21510370a93f313f 100644 (file)
@@ -16,7 +16,7 @@ void main(void)
 #if !defined(SND_PROTOCOL_VERSION) || !defined(SND_PROTOCOL_UNCOMPATIBLE)
 #error not found
 #else
-#if !defined(SND_MIXER_IOCTL_CHANNEL_IREAD)
+#if !defined(SND_MIXER_IOCTL_ELEMENTS)
 #error wrong version
 #endif
   exit(0);
@@ -25,7 +25,7 @@ void main(void)
 ],
   AC_MSG_RESULT(present),
   [AC_MSG_RESULT(not found or wrong version);
-   AC_MSG_ERROR([Install alsa-driver v0.3.0pre1+ package first...])]
+   AC_MSG_ERROR([Install alsa-driver v0.3.0pre5+ package first...])]
 )
 CFLAGS="$OLD_CFLAGS"
 ])
index 86cb4c56108f4f6e77d0d7ff414f8a6a94752bfa..d32c1176317fdfd7c934258efd447381d3b6a8af 100644 (file)
@@ -14,6 +14,14 @@ int snd_cards(void);
 unsigned int snd_cards_mask(void);
 int snd_card_name(const char *name);
 
+int snd_defaults_card(void);
+int snd_defaults_mixer_card(void);
+int snd_defaults_mixer_device(void);
+int snd_defaults_pcm_card(void);
+int snd_defaults_pcm_device(void);
+int snd_defaults_rawmidi_card(void);
+int snd_defaults_rawmidi_device(void);
+
 int snd_ctl_open(void **handle, int card);
 int snd_ctl_close(void *handle);
 int snd_ctl_file_descriptor(void *handle);
index 8879f62d7159212f8d709745b8af859a2379988c..c9ef66d2aaf1388d54325e5cf19eb04908f3ffb3 100644 (file)
@@ -6,12 +6,12 @@
  ****************************************************************************/
 
 typedef struct snd_mixer_callbacks {
-       void *private_data;     /* should be used by application */
-       void (*channel_was_changed) (void *private_data, int channel);
-       void (*output_channel_was_changed) (void *private_data, int channel);
-       void (*input_channel_was_changed) (void *private_data, int channel);
-       void (*switch_was_changed) (void *private_data, int switchn);
-       void *reserved[15];     /* reserved for future use - must be NULL!!! */
+       void *private_data;     /* should be used by an application */
+       void (*rebuild) (void *private_data);
+       void (*element) (void *private_data, int cmd, snd_mixer_eid_t *eid);
+       void (*group) (void *private_data, int cmd, snd_mixer_gid_t *gid);
+       void (*xswitch) (void *private_data, int cmd, snd_switch_list_item_t *item);
+       void *reserved[27];     /* reserved for the future use - must be NULL!!! */
 } snd_mixer_callbacks_t;
 
 #ifdef __cplusplus
@@ -21,24 +21,29 @@ extern "C" {
 int snd_mixer_open(void **handle, int card, int device);
 int snd_mixer_close(void *handle);
 int snd_mixer_file_descriptor(void *handle);
-int snd_mixer_channels(void *handle);
 int snd_mixer_info(void *handle, snd_mixer_info_t * info);
-int snd_mixer_exact_mode(void *handle, int enable);
-int snd_mixer_channel(void *handle, const char *channel_id);
-int snd_mixer_channel_info(void *handle, int channel, snd_mixer_channel_info_t * info);
-int snd_mixer_channel_output_info(void *handle, int channel, snd_mixer_channel_direction_info_t * info);
-int snd_mixer_channel_input_info(void *handle, int channel, snd_mixer_channel_direction_info_t * info);
-int snd_mixer_channel_read(void *handle, int channel, snd_mixer_channel_t * data);
-int snd_mixer_channel_write(void *handle, int channel, snd_mixer_channel_t * data);
-int snd_mixer_channel_output_read(void *handle, int channel, snd_mixer_channel_direction_t * data);
-int snd_mixer_channel_output_write(void *handle, int channel, snd_mixer_channel_direction_t * data);
-int snd_mixer_channel_input_read(void *handle, int channel, snd_mixer_channel_direction_t * data);
-int snd_mixer_channel_input_write(void *handle, int channel, snd_mixer_channel_direction_t * data);
+int snd_mixer_elements(void *handle, snd_mixer_elements_t * elements);
+int snd_mixer_routes(void *handle, snd_mixer_routes_t * routes);
+int snd_mixer_groups(void *handle, snd_mixer_groups_t * groups);
+int snd_mixer_group(void *handle, snd_mixer_group_t * group);
+int snd_mixer_element_info(void *handle, snd_mixer_element_info_t * info);
+int snd_mixer_element_read(void *handle, snd_mixer_element_t * element);
+int snd_mixer_element_write(void *handle, snd_mixer_element_t * element);
 int snd_mixer_switch_list(void *handle, snd_switch_list_t * list);
 int snd_mixer_switch_read(void *handle, snd_switch_t * sw);
 int snd_mixer_switch_write(void *handle, snd_switch_t * sw);
 int snd_mixer_read(void *handle, snd_mixer_callbacks_t * callbacks);
 
+void snd_mixer_set_bit(unsigned int *bitmap, int bit, int val);
+int snd_mixer_get_bit(unsigned int *bitmap, int bit);
+
+int snd_mixer_element_has_info(snd_mixer_eid_t *eid);
+int snd_mixer_element_info_build(void *handle, snd_mixer_element_info_t * info);
+int snd_mixer_element_info_free(snd_mixer_element_info_t * info);
+int snd_mixer_element_has_control(snd_mixer_eid_t *eid);
+int snd_mixer_element_build(void *handle, snd_mixer_element_t * element);
+int snd_mixer_element_free(snd_mixer_element_t * element);
+
 #ifdef __cplusplus
 }
 #endif
index 5390f278daccd8d7d384ff321c8347b475618561..34712264823befe59134697f7ef849bd2ed171e9 100644 (file)
@@ -1,6 +1,6 @@
 EXTRA_LTLIBRARIES = libcontrol.la
 
-libcontrol_la_SOURCES = cards.c control.c
+libcontrol_la_SOURCES = cards.c control.c defaults.c
 
 all: libcontrol.la
 
diff --git a/src/control/defaults.c b/src/control/defaults.c
new file mode 100644 (file)
index 0000000..536f245
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ *  Control Interface - defaults
+ *  Copyright (c) 1998 by Jaroslav Kysela <perex@jcu.cz>
+ *
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Library General Public License as
+ *   published by the Free Software Foundation; either version 2 of
+ *   the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU Library General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Library General Public
+ *   License along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include "asoundlib.h"
+
+static int defaults_card(const char *env)
+{
+       char *e;
+       
+       e = getenv(env);
+       if (!e)
+               return -ENOENT;
+       return snd_card_name(e);
+}
+
+static int defaults_device(const char *env)
+{
+       char *e;
+       int dev;
+
+       e = getenv(env);
+       if (e) {
+               dev = atoi(env);
+               if (dev >= 0 && dev < 1024 * 1024)
+                       return dev;
+       }
+       return 0;
+}
+
+int snd_defaults_card(void)
+{
+       int result;
+       unsigned int mask;
+
+       result = defaults_card("ALSA_CARD");
+       if (result >= 0)
+               return result;
+       mask = snd_cards_mask();
+       for (result = 0; result < 31; result++)
+               if (mask & (1 << result))
+                       return result;
+       return -ENOENT;
+}
+
+int snd_defaults_mixer_card(void)
+{
+       int result;
+       
+       result = defaults_card("ALSA_MIXER_CARD");
+       if (result >= 0)
+               return result;
+       return snd_defaults_card();
+}
+
+int snd_defaults_mixer_device(void)
+{
+       return defaults_device("ALSA_MIXER_DEVICE");
+}
+
+int snd_defaults_pcm_card(void)
+{
+       int result;
+       
+       result = defaults_card("ALSA_PCM_CARD");
+       if (result >= 0)
+               return result;
+       return snd_defaults_card();
+}
+
+int snd_defaults_pcm_device(void)
+{
+       return defaults_device("ALSA_PCM_DEVICE");
+}
+
+int snd_defaults_rawmidi_card(void)
+{
+       int result;
+       
+       result = defaults_card("ALSA_PCM_CARD");
+       if (result >= 0)
+               return result;
+       return snd_defaults_card();
+}
+
+int snd_defaults_rawmidi_device(void)
+{
+       return defaults_device("ALSA_RAWMIDI_DEVICE");
+}
index 1350aba6dd2ccdc0559c54716d67e84a907bb77c..cc126ba48d54c6df120635ddf44e255a759cbd42 100644 (file)
@@ -1,6 +1,6 @@
 EXTRA_LTLIBRARIES=libmixer.la
 
-libmixer_la_SOURCES = mixer.c
+libmixer_la_SOURCES = mixer.c elements.c
 
 all: libmixer.la
 
diff --git a/src/mixer/elements.c b/src/mixer/elements.c
new file mode 100644 (file)
index 0000000..5fed525
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ *  Mixer Interface - elements
+ *  Copyright (c) 1999 by Jaroslav Kysela <perex@jcu.cz>
+ *
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Library General Public License as
+ *   published by the Free Software Foundation; either version 2 of
+ *   the License, or (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU Library General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Library General Public
+ *   License along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include "asoundlib.h"
+
+static inline void safe_free(void **ptr)
+{
+       if (*ptr)
+               free(*ptr);
+       *ptr = NULL;
+}
+
+int snd_mixer_element_has_info(snd_mixer_eid_t *eid)
+{
+       if (!eid)
+               return -EINVAL;
+       switch (eid->type) {
+       case SND_MIXER_ETYPE_INPUT:
+       case SND_MIXER_ETYPE_OUTPUT:
+       case SND_MIXER_ETYPE_CAPTURE:
+       case SND_MIXER_ETYPE_PLAYBACK:
+       case SND_MIXER_ETYPE_ADC:
+       case SND_MIXER_ETYPE_DAC:
+       case SND_MIXER_ETYPE_SWITCH3:
+       case SND_MIXER_ETYPE_VOLUME1:
+       case SND_MIXER_ETYPE_VOLUME2:
+       case SND_MIXER_ETYPE_ACCU1:
+       case SND_MIXER_ETYPE_ACCU2:
+       case SND_MIXER_ETYPE_ACCU3:
+       case SND_MIXER_ETYPE_MUX1:
+       case SND_MIXER_ETYPE_MUX2:
+       case SND_MIXER_ETYPE_TONE_CONTROL1:
+       case SND_MIXER_ETYPE_3D_EFFECT1:
+       case SND_MIXER_ETYPE_PRE_EFFECT1:
+               return 1;
+       }
+       return 0;
+}
+
+int snd_mixer_element_info_build(void *handle, snd_mixer_element_info_t *element)
+{
+       int err;
+       
+       if (!handle || !element)
+               return -EINVAL;
+       if ((err = snd_mixer_element_info(handle, element)) < 0)
+               return err;
+       switch (element->eid.type) {
+       case SND_MIXER_ETYPE_INPUT:
+       case SND_MIXER_ETYPE_OUTPUT:
+               element->data.io.voices_size = element->data.io.voices_over;
+               element->data.io.voices = element->data.io.voices_over = 0;
+               element->data.io.pvoices = (snd_mixer_voice_t *)malloc(element->data.io.voices_size * sizeof(snd_mixer_voice_t));
+               if (!element->data.io.pvoices)
+                       return -ENOMEM;
+               if ((err = snd_mixer_element_info(handle, element)) < 0)
+                       return err;
+               break;
+       case SND_MIXER_ETYPE_CAPTURE:
+       case SND_MIXER_ETYPE_PLAYBACK:
+               element->data.pcm.devices_size = element->data.pcm.devices_over;
+               element->data.pcm.devices = element->data.pcm.devices_over = 0;
+               element->data.pcm.pdevices = (int *)malloc(element->data.pcm.devices_size * sizeof(int));
+               if (!element->data.pcm.pdevices)
+                       return -ENOMEM;
+               if ((err = snd_mixer_element_info(handle, element)) < 0)
+                       return err;
+               break;
+       case SND_MIXER_ETYPE_SWITCH3:
+               element->data.switch3.voices_size = element->data.switch3.voices_over;
+               element->data.switch3.voices = element->data.switch3.voices_over = 0;
+               element->data.switch3.pvoices = (snd_mixer_voice_t *)malloc(element->data.switch3.voices_size * sizeof(snd_mixer_voice_t));
+               if (!element->data.switch3.pvoices)
+                       return -ENOMEM;
+               if ((err = snd_mixer_element_info(handle, element)) < 0)
+                       return err;
+               break;
+       case SND_MIXER_ETYPE_VOLUME1:
+               element->data.volume1.range_size = element->data.volume1.range_over;
+               element->data.volume1.range = element->data.volume1.range_over = 0;
+               element->data.volume1.prange = (struct snd_mixer_element_volume1_range *)malloc(element->data.volume1.range_size * sizeof(struct snd_mixer_element_volume1_range));
+               if (!element->data.volume1.prange)
+                       return -ENOMEM;
+               if ((err = snd_mixer_element_info(handle, element)) < 0)
+                       return err;
+               break;
+       case SND_MIXER_ETYPE_VOLUME2:
+               element->data.volume2.svoices_size = element->data.volume2.svoices_over;
+               element->data.volume2.svoices = element->data.volume2.svoices_over = 0;
+               element->data.volume2.psvoices = (snd_mixer_voice_t *)malloc(element->data.volume2.svoices_size * sizeof(snd_mixer_voice_t));
+               if (!element->data.volume2.psvoices)
+                       return -ENOMEM;
+               element->data.volume2.range_size = element->data.volume2.range_over;
+               element->data.volume2.range = element->data.volume2.range_over = 0;
+               element->data.volume2.prange = (struct snd_mixer_element_volume2_range *)malloc(element->data.volume2.range_size * sizeof(struct snd_mixer_element_volume2_range));
+               if (!element->data.volume1.prange) {
+                       safe_free((void **)&element->data.volume2.psvoices);
+                       return -ENOMEM;
+               }
+               if ((err = snd_mixer_element_info(handle, element)) < 0)
+                       return err;
+               break;
+       case SND_MIXER_ETYPE_ACCU3:
+               element->data.accu3.range_size = element->data.accu3.range_over;
+               element->data.accu3.range = element->data.accu3.range_over = 0;
+               element->data.accu3.prange = (struct snd_mixer_element_accu3_range *)malloc(element->data.accu3.range_size * sizeof(struct snd_mixer_element_accu3_range));
+               if (!element->data.accu3.prange)
+                       return -ENOMEM;
+               if ((err = snd_mixer_element_info(handle, element)) < 0)
+                       return err;
+               break;
+       case SND_MIXER_ETYPE_PRE_EFFECT1:
+               element->data.peffect1.items_size = element->data.peffect1.items_over;
+               element->data.peffect1.items = element->data.peffect1.items_over = 0;
+               element->data.peffect1.pitems = (struct snd_mixer_element_pre_effect1_info_item *)malloc(element->data.peffect1.items_size * sizeof(struct snd_mixer_element_pre_effect1_info_item));
+               if (!element->data.peffect1.pitems) 
+                       return -ENOMEM;
+               element->data.peffect1.parameters_size = element->data.peffect1.parameters_over;
+               element->data.peffect1.parameters = element->data.peffect1.parameters_over = 0;
+               element->data.peffect1.pparameters = (struct snd_mixer_element_pre_effect1_info_parameter *)malloc(element->data.peffect1.parameters_size * sizeof(struct snd_mixer_element_pre_effect1_info_parameter));
+               if (!element->data.peffect1.pparameters) {
+                       safe_free((void **)&element->data.peffect1.pitems);
+                       return -ENOMEM;
+               }
+               if ((err = snd_mixer_element_info(handle, element)) < 0)
+                       return err;
+               break;
+       }
+       return 0;
+}
+
+int snd_mixer_element_info_free(snd_mixer_element_info_t *element)
+{
+       if (!element)
+               return -EINVAL;
+       switch (element->eid.type) {
+       case SND_MIXER_ETYPE_INPUT:
+       case SND_MIXER_ETYPE_OUTPUT:
+               safe_free((void **)&element->data.io.pvoices);
+               break;
+       case SND_MIXER_ETYPE_CAPTURE:
+       case SND_MIXER_ETYPE_PLAYBACK:
+               safe_free((void **)&element->data.pcm.pdevices);
+               break;
+       case SND_MIXER_ETYPE_SWITCH3:
+               safe_free((void **)&element->data.switch3.pvoices);
+               break;
+       case SND_MIXER_ETYPE_VOLUME1:
+               safe_free((void **)&element->data.volume1.prange);
+               break;
+       case SND_MIXER_ETYPE_VOLUME2:
+               safe_free((void **)&element->data.volume2.psvoices);
+               safe_free((void **)&element->data.volume1.prange);
+               break;
+       case SND_MIXER_ETYPE_ACCU3:
+               safe_free((void **)&element->data.accu3.prange);
+               break;
+       case SND_MIXER_ETYPE_PRE_EFFECT1:
+               safe_free((void **)&element->data.peffect1.pitems);
+               safe_free((void **)&element->data.peffect1.pparameters);
+               break;
+       }
+       return 0;
+}
+
+int snd_mixer_element_has_control(snd_mixer_eid_t *eid)
+{
+       if (!eid)
+               return -EINVAL;
+       switch (eid->type) {
+       case SND_MIXER_ETYPE_SWITCH1:
+       case SND_MIXER_ETYPE_SWITCH2:
+       case SND_MIXER_ETYPE_SWITCH3:
+       case SND_MIXER_ETYPE_VOLUME1:
+       case SND_MIXER_ETYPE_VOLUME2:
+       case SND_MIXER_ETYPE_ACCU3:
+       case SND_MIXER_ETYPE_MUX1:
+       case SND_MIXER_ETYPE_MUX2:
+       case SND_MIXER_ETYPE_TONE_CONTROL1:
+       case SND_MIXER_ETYPE_3D_EFFECT1:
+       case SND_MIXER_ETYPE_PRE_EFFECT1:
+               return 1;
+       }
+       return 0;
+}
+
+int snd_mixer_element_build(void *handle, snd_mixer_element_t *element)
+{
+       int err;
+       
+       if (!handle || !element)
+               return -EINVAL;
+       if ((err = snd_mixer_element_read(handle, element)) < 0)
+               return err;
+       switch (element->eid.type) {
+       case SND_MIXER_ETYPE_SWITCH1:
+               element->data.switch1.sw_size = element->data.switch1.sw_over;
+               element->data.switch1.sw = element->data.switch1.sw_over = 0;
+               element->data.switch1.psw = (unsigned int *)malloc(((element->data.switch1.sw_size + 31) / 32) * sizeof(unsigned int));
+               if (!element->data.switch1.psw)
+                       return -ENOMEM;
+               if ((err = snd_mixer_element_read(handle, element)) < 0)
+                       return err;
+               break;
+       case SND_MIXER_ETYPE_SWITCH3:
+               element->data.switch3.rsw_size = element->data.switch3.rsw_over;
+               element->data.switch3.rsw = element->data.switch3.rsw_over = 0;
+               element->data.switch3.prsw = (unsigned int *)malloc(((element->data.switch3.rsw_size + 31) / 32) * sizeof(unsigned int));
+               if (!element->data.switch3.prsw)
+                       return -ENOMEM;
+               if ((err = snd_mixer_element_read(handle, element)) < 0)
+                       return err;
+               break;
+       case SND_MIXER_ETYPE_VOLUME1:
+               element->data.volume1.voices_size = element->data.volume1.voices_over;
+               element->data.volume1.voices = element->data.volume1.voices_over = 0;
+               element->data.volume1.pvoices = (int *)malloc(element->data.volume1.voices_size * sizeof(int));
+               if (!element->data.volume1.pvoices)
+                       return -ENOMEM;
+               if ((err = snd_mixer_element_read(handle, element)) < 0)
+                       return err;
+               break;
+       case SND_MIXER_ETYPE_VOLUME2:
+               element->data.volume2.avoices_size = element->data.volume2.avoices_over;
+               element->data.volume2.avoices = element->data.volume2.avoices_over = 0;
+               element->data.volume2.pavoices = (int *)malloc(element->data.volume2.avoices_size * sizeof(int));
+               if (!element->data.volume2.pavoices)
+                       return -ENOMEM;
+               if ((err = snd_mixer_element_read(handle, element)) < 0)
+                       return err;
+               break;
+       case SND_MIXER_ETYPE_ACCU3:
+               element->data.accu3.voices_size = element->data.accu3.voices_over;
+               element->data.accu3.voices = element->data.accu3.voices_over = 0;
+               element->data.accu3.pvoices = (int *)malloc(element->data.accu3.voices_size * sizeof(int));
+               if (!element->data.accu3.pvoices)
+                       return -ENOMEM;
+               if ((err = snd_mixer_element_read(handle, element)) < 0)
+                       return err;
+               break;
+       case SND_MIXER_ETYPE_MUX1:
+               element->data.mux1.output_size = element->data.mux1.output_over;
+               element->data.mux1.output = element->data.mux1.output_over = 0;
+               element->data.mux1.poutput = (snd_mixer_eid_t *)malloc(element->data.mux1.output_size * sizeof(snd_mixer_eid_t));
+               if (!element->data.mux1.poutput)
+                       return -ENOMEM;
+               if ((err = snd_mixer_element_read(handle, element)) < 0)
+                       return err;
+               break;
+       case SND_MIXER_ETYPE_PRE_EFFECT1:
+               if (element->data.peffect1.item < 0) {
+                       element->data.peffect1.parameters_size = element->data.peffect1.parameters_over;
+                       element->data.peffect1.parameters = element->data.peffect1.parameters_over = 0;
+                       element->data.peffect1.pparameters = (int *)malloc(element->data.peffect1.parameters_size * sizeof(int));
+                       if (!element->data.peffect1.pparameters)
+                               return -ENOMEM;
+                       if ((err = snd_mixer_element_read(handle, element)) < 0)
+                               return err;
+               }
+               break;
+       }
+       return 0;
+}
+
+int snd_mixer_element_free(snd_mixer_element_t *element)
+{
+       if (!element)
+               return -EINVAL;
+       switch (element->eid.type) {
+       case SND_MIXER_ETYPE_SWITCH1:
+               safe_free((void **)&element->data.switch1.psw);
+               break;
+       case SND_MIXER_ETYPE_SWITCH3:
+               safe_free((void **)&element->data.switch3.prsw);
+               break;
+       case SND_MIXER_ETYPE_VOLUME1:
+               safe_free((void **)&element->data.volume1.pvoices);
+               break;
+       case SND_MIXER_ETYPE_VOLUME2:
+               safe_free((void **)&element->data.volume2.pavoices);
+               break;
+       case SND_MIXER_ETYPE_ACCU3:
+               safe_free((void **)&element->data.accu3.pvoices);
+               break;
+       case SND_MIXER_ETYPE_MUX1:
+               safe_free((void **)&element->data.mux1.poutput);
+               break;
+       case SND_MIXER_ETYPE_PRE_EFFECT1:
+               if (element->data.peffect1.item < 0)
+                       safe_free((void **)&element->data.peffect1.pparameters);
+               break;
+       }
+       return 0;
+}
index 3ded577aa2f65f2e53efe78469d7cf62ef61543f..a9a3234882cf1357309ccd3435f810da3136d98e 100644 (file)
@@ -29,7 +29,7 @@
 #include "asoundlib.h"
 
 #define SND_FILE_MIXER         "/dev/snd/mixerC%iD%i"
-#define SND_MIXER_VERSION_MAX  SND_PROTOCOL_VERSION( 1, 1, 0 )
+#define SND_MIXER_VERSION_MAX  SND_PROTOCOL_VERSION(2, 0, 0)
 
 typedef struct {
        int card;
@@ -96,19 +96,6 @@ int snd_mixer_file_descriptor(void *handle)
        return mixer->fd;
 }
 
-int snd_mixer_channels(void *handle)
-{
-       snd_mixer_t *mixer;
-       int result;
-
-       mixer = (snd_mixer_t *) handle;
-       if (!mixer)
-               return -EINVAL;
-       if (ioctl(mixer->fd, SND_MIXER_IOCTL_CHANNELS, &result) < 0)
-               return -errno;
-       return result;
-}
-
 int snd_mixer_info(void *handle, snd_mixer_info_t * info)
 {
        snd_mixer_t *mixer;
@@ -121,156 +108,87 @@ int snd_mixer_info(void *handle, snd_mixer_info_t * info)
        return 0;
 }
 
-int snd_mixer_exact_mode(void *handle, int enable)
+int snd_mixer_elements(void *handle, snd_mixer_elements_t * elements)
 {
        snd_mixer_t *mixer;
 
        mixer = (snd_mixer_t *) handle;
        if (!mixer)
                return -EINVAL;
-       if (ioctl(mixer->fd, SND_MIXER_IOCTL_EXACT, &enable) < 0)
-               return -errno;
-       return 0;
-}
-
-int snd_mixer_channel(void *handle, const char *channel_id)
-{
-       snd_mixer_t *mixer;
-       snd_mixer_channel_info_t info;
-       int idx, channels, err;
-
-       mixer = (snd_mixer_t *) handle;
-       if (!mixer || !channel_id)
-               return -EINVAL;
-       /* bellow implementation isn't optimized for speed */
-       /* info about channels should be cached in the snd_mixer_t structure */
-       if ((channels = snd_mixer_channels(handle)) < 0)
-               return channels;
-       for (idx = 0; idx < channels; idx++) {
-               if ((err = snd_mixer_channel_info(handle, idx, &info)) < 0)
-                       return err;
-               if (!strncmp(channel_id, info.name, sizeof(info.name)))
-                       return idx;
-       }
-       return -EINVAL;
-}
-
-int snd_mixer_channel_info(void *handle, int channel, snd_mixer_channel_info_t * info)
-{
-       snd_mixer_t *mixer;
-
-       mixer = (snd_mixer_t *) handle;
-       if (!mixer || !info || channel < 0)
-               return -EINVAL;
-       info->channel = channel;
-       if (ioctl(mixer->fd, SND_MIXER_IOCTL_CHANNEL_INFO, info) < 0)
-               return -errno;
-       return 0;
-}
-
-int snd_mixer_channel_output_info(void *handle, int channel, snd_mixer_channel_direction_info_t * info)
-{
-       snd_mixer_t *mixer;
-
-       mixer = (snd_mixer_t *) handle;
-       if (!mixer || !info || channel < 0)
-               return -EINVAL;
-       info->channel = channel;
-       if (ioctl(mixer->fd, SND_MIXER_IOCTL_CHANNEL_OINFO, info) < 0)
+       if (ioctl(mixer->fd, SND_MIXER_IOCTL_ELEMENTS, elements) < 0)
                return -errno;
        return 0;
 }
 
-int snd_mixer_channel_input_info(void *handle, int channel, snd_mixer_channel_direction_info_t * info)
+int snd_mixer_routes(void *handle, snd_mixer_routes_t * routes)
 {
        snd_mixer_t *mixer;
 
        mixer = (snd_mixer_t *) handle;
-       if (!mixer || !info || channel < 0)
+       if (!mixer)
                return -EINVAL;
-       info->channel = channel;
-       if (ioctl(mixer->fd, SND_MIXER_IOCTL_CHANNEL_IINFO, info) < 0)
+       if (ioctl(mixer->fd, SND_MIXER_IOCTL_ROUTES, routes) < 0)
                return -errno;
        return 0;
 }
 
-int snd_mixer_channel_read(void *handle, int channel, snd_mixer_channel_t * data)
+int snd_mixer_groups(void *handle, snd_mixer_groups_t * groups)
 {
        snd_mixer_t *mixer;
 
        mixer = (snd_mixer_t *) handle;
-       if (!mixer || !data || channel < 0)
+       if (!mixer)
                return -EINVAL;
-       bzero(data, sizeof(snd_mixer_channel_t));
-       data->channel = channel;
-       if (ioctl(mixer->fd, SND_MIXER_IOCTL_CHANNEL_READ, data) < 0)
+       if (ioctl(mixer->fd, SND_MIXER_IOCTL_GROUPS, groups) < 0)
                return -errno;
        return 0;
 }
 
-int snd_mixer_channel_write(void *handle, int channel, snd_mixer_channel_t * data)
+int snd_mixer_group(void *handle, snd_mixer_group_t * group)
 {
        snd_mixer_t *mixer;
 
        mixer = (snd_mixer_t *) handle;
-       if (!mixer || !data)
+       if (!mixer)
                return -EINVAL;
-       data->channel = channel;
-       if (ioctl(mixer->fd, SND_MIXER_IOCTL_CHANNEL_WRITE, data) < 0)
+       if (ioctl(mixer->fd, SND_MIXER_IOCTL_GROUP, group) < 0)
                return -errno;
        return 0;
 }
 
-int snd_mixer_channel_output_read(void *handle, int channel, snd_mixer_channel_direction_t * data)
+int snd_mixer_element_info(void *handle, snd_mixer_element_info_t * info)
 {
        snd_mixer_t *mixer;
 
        mixer = (snd_mixer_t *) handle;
-       if (!mixer || !data || channel < 0)
+       if (!mixer)
                return -EINVAL;
-       bzero(data, sizeof(snd_mixer_channel_t));
-       data->channel = channel;
-       if (ioctl(mixer->fd, SND_MIXER_IOCTL_CHANNEL_OREAD, data) < 0)
+       if (ioctl(mixer->fd, SND_MIXER_IOCTL_ELEMENT_INFO, info) < 0)
                return -errno;
        return 0;
 }
 
-int snd_mixer_channel_output_write(void *handle, int channel, snd_mixer_channel_direction_t * data)
-{
-       snd_mixer_t *mixer;
-
-       mixer = (snd_mixer_t *) handle;
-       if (!mixer || !data || channel < 0)
-               return -EINVAL;
-       data->channel = channel;
-       if (ioctl(mixer->fd, SND_MIXER_IOCTL_CHANNEL_OWRITE, data) < 0)
-               return -errno;
-       return 0;
-}
 
-int snd_mixer_channel_input_read(void *handle, int channel, snd_mixer_channel_direction_t * data)
+int snd_mixer_element_read(void *handle, snd_mixer_element_t * element)
 {
        snd_mixer_t *mixer;
 
        mixer = (snd_mixer_t *) handle;
-       if (!mixer || !data || channel < 0)
+       if (!mixer)
                return -EINVAL;
-       bzero(data, sizeof(snd_mixer_channel_t));
-       data->channel = channel;
-       if (ioctl(mixer->fd, SND_MIXER_IOCTL_CHANNEL_IREAD, data) < 0)
+       if (ioctl(mixer->fd, SND_MIXER_IOCTL_ELEMENT_READ, element) < 0)
                return -errno;
        return 0;
 }
 
-int snd_mixer_channel_input_write(void *handle, int channel, snd_mixer_channel_direction_t * data)
+int snd_mixer_element_write(void *handle, snd_mixer_element_t * element)
 {
        snd_mixer_t *mixer;
 
        mixer = (snd_mixer_t *) handle;
-       if (!mixer || !data || channel < 0)
+       if (!mixer)
                return -EINVAL;
-       data->channel = channel;
-       if (ioctl(mixer->fd, SND_MIXER_IOCTL_CHANNEL_IWRITE, data) < 0)
+       if (ioctl(mixer->fd, SND_MIXER_IOCTL_ELEMENT_WRITE, element) < 0)
                return -errno;
        return 0;
 }
@@ -314,40 +232,60 @@ int snd_mixer_switch_write(void *handle, snd_switch_t * sw)
 int snd_mixer_read(void *handle, snd_mixer_callbacks_t * callbacks)
 {
        snd_mixer_t *mixer;
-       int idx, result, count;
-       unsigned int cmd, tmp;
-       unsigned char buffer[64];
+       int result, count;
+       snd_mixer_read_t r;
 
        mixer = (snd_mixer_t *) handle;
        if (!mixer)
                return -EINVAL;
        count = 0;
-       while ((result = read(mixer->fd, &buffer, sizeof(buffer))) > 0) {
-               if (result & 7)
+       while ((result = read(mixer->fd, &r, sizeof(r))) > 0) {
+               if (result != sizeof(r))
                        return -EIO;
                if (!callbacks)
                        continue;
-               for (idx = 0; idx < result; idx += 8) {
-                       cmd = *(unsigned int *) &buffer[idx];
-                       tmp = *(unsigned int *) &buffer[idx + 4];
-                       if (cmd == SND_MIXER_CHANGED && 
-                           callbacks->channel_was_changed) {
-                               callbacks->channel_was_changed(callbacks->private_data, (int) tmp);
-                       }
-                       if (cmd == SND_MIXER_OUTPUT_CHANGED && 
-                           callbacks->output_channel_was_changed) {
-                               callbacks->output_channel_was_changed(callbacks->private_data, (int) tmp);
-                       }
-                       if (cmd == SND_MIXER_INPUT_CHANGED && 
-                           callbacks->input_channel_was_changed) {
-                               callbacks->input_channel_was_changed(callbacks->private_data, (int) tmp);
-                       }
-                       if (cmd == SND_MIXER_SWITCH_CHANGED && 
-                           callbacks->switch_was_changed) {
-                               callbacks->switch_was_changed(callbacks->private_data, (int) tmp);
-                       }
+               switch (r.cmd) {
+               case SND_MIXER_READ_REBUILD:
+                       if (callbacks->rebuild)
+                               callbacks->rebuild(callbacks->private_data);
+                       break;
+               case SND_MIXER_READ_ELEMENT_VALUE:
+               case SND_MIXER_READ_ELEMENT_CHANGE:
+               case SND_MIXER_READ_ELEMENT_ROUTE:
+               case SND_MIXER_READ_ELEMENT_ADD:
+               case SND_MIXER_READ_ELEMENT_REMOVE:
+                       if (callbacks->element)
+                               callbacks->element(callbacks->private_data, r.cmd, &r.data.eid);
+                       break;
+               case SND_MIXER_READ_GROUP_CHANGE:
+               case SND_MIXER_READ_GROUP_ADD:
+               case SND_MIXER_READ_GROUP_REMOVE:
+                       if (callbacks->group)
+                               callbacks->group(callbacks->private_data, r.cmd, &r.data.gid);
+                       break;
+               case SND_MIXER_READ_SWITCH_VALUE:
+               case SND_MIXER_READ_SWITCH_CHANGE:
+               case SND_MIXER_READ_SWITCH_ADD:
+               case SND_MIXER_READ_SWITCH_REMOVE:
+                       if (callbacks->xswitch)
+                               callbacks->xswitch(callbacks->private_data, r.cmd, &r.data.switem);
+                       break;
                }
-               count += result >> 3;   /* return only number of changes */
+               count++;
        }
        return result >= 0 ? count : -errno;
 }
+
+void snd_mixer_set_bit(unsigned int *bitmap, int bit, int val)
+{
+       if (val) {
+               bitmap[bit >> 5] |= 1 << (bit & 31);
+       } else {
+               bitmap[bit >> 5] &= ~(1 << (bit & 31));
+       }
+}
+
+int snd_mixer_get_bit(unsigned int *bitmap, int bit)
+{
+       return (bitmap[bit >> 5] & (1 << (bit & 31))) ? 1 : 0;
+}
index 9a465640b9295091686688913b8854a6b439e211..c8d67478c27b2930d9f5a7c62f1012d0fffbc0a3 100644 (file)
@@ -28,11 +28,9 @@ void main(void)
                }
                printf("Soundcard #%i:\n", idx + 1);
                printf("  type - %i\n", info.type);
-               printf("  gcaps - 0x%x\n", info.gcaps);
-               printf("  lcaps - 0x%x\n", info.lcaps);
-               printf("  pcm devs - 0x%x\n", info.pcmdevs);
-               printf("  mixer devs - 0x%x\n", info.mixerdevs);
-               printf("  midi devs - 0x%x\n", info.mididevs);
+               printf("  pcm devs - %i\n", info.pcmdevs);
+               printf("  mixer devs - %i\n", info.mixerdevs);
+               printf("  midi devs - %i\n", info.mididevs);
                memset(str, 0, sizeof(str));
                strncpy(str, info.id, sizeof(info.id));
                printf("  id - '%s'\n", str);
@@ -57,8 +55,10 @@ void main(void)
                                continue;
                        }
                        printf("  type - %i\n", mixerinfo.type);
-                       printf("  channels - %i\n", mixerinfo.channels);
-                       printf("  caps - 0x%x\n", mixerinfo.caps);
+                       printf("  elements - %i\n", mixerinfo.elements);
+                       printf("  groups - %i\n", mixerinfo.groups);
+                       printf("  switches - %i\n", mixerinfo.switches);
+                       printf("  attribute - 0x%x\n", mixerinfo.attribute);
                        printf("  id - '%s'\n", mixerinfo.id);
                        printf("  name - '%s'\n", mixerinfo.name);
                }
index c8777a7d6664889e11b711eacce278643fabc69e..3550acbed84ca162afdb6bc107f8fe68f428ca98 100644 (file)
@@ -4,7 +4,7 @@
 
 static void mixer_test(int card, int device)
 {
-       int err, channels;
+       int err;
        void *handle;
        snd_mixer_info_t info;
 
@@ -13,20 +13,16 @@ static void mixer_test(int card, int device)
                return;
        }
        printf("Mixer %i/%i open ok...\n", card, device);
-       channels = snd_mixer_channels(handle);
-       if (channels < 0) {
-               printf("Mixer channels error: %s\n", snd_strerror(channels));
-               return;
-       }
-       printf("  Mixer have %i channel%s.\n", channels, channels > 1 ? "s" : "");
        if ((err = snd_mixer_info(handle, &info)) < 0) {
                printf("Mixer info error: %s\n", snd_strerror(err));
                return;
        }
        printf("  Info:\n");
        printf("    type - %i\n", info.type);
-       printf("    channels - %i\n", info.channels);
-       printf("    caps - 0x%x\n", info.caps);
+       printf("    elements - %i\n", info.elements);
+       printf("    groups - %i\n", info.groups);
+       printf("    switches - %i\n", info.switches);
+       printf("    attribute - 0x%x\n", info.attribute);
        printf("    id - '%s'\n", info.id);
        printf("    name - '%s'\n", info.name);
        snd_mixer_close(handle);