#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);
],
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"
])
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);
****************************************************************************/
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
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
EXTRA_LTLIBRARIES = libcontrol.la
-libcontrol_la_SOURCES = cards.c control.c
+libcontrol_la_SOURCES = cards.c control.c defaults.c
all: libcontrol.la
--- /dev/null
+/*
+ * 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");
+}
EXTRA_LTLIBRARIES=libmixer.la
-libmixer_la_SOURCES = mixer.c
+libmixer_la_SOURCES = mixer.c elements.c
all: libmixer.la
--- /dev/null
+/*
+ * 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;
+}
#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;
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;
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;
}
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;
+}
}
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);
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);
}
static void mixer_test(int card, int device)
{
- int err, channels;
+ int err;
void *handle;
snd_mixer_info_t info;
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);