From: Jaroslav Kysela Date: Sun, 2 May 1999 16:21:30 +0000 (+0000) Subject: Mixer v2.0 merged to the main CVS tree... X-Git-Tag: v1.0.3~1481 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=a5b307a71193c387e2bfa988718856a4b0d6f13f;p=alsa-lib.git Mixer v2.0 merged to the main CVS tree... --- diff --git a/acinclude.m4 b/acinclude.m4 index cd289edc..69bceea9 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -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" ]) diff --git a/include/control.h b/include/control.h index 86cb4c56..d32c1176 100644 --- a/include/control.h +++ b/include/control.h @@ -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); diff --git a/include/mixer.h b/include/mixer.h index 8879f62d..c9ef66d2 100644 --- a/include/mixer.h +++ b/include/mixer.h @@ -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 diff --git a/src/control/Makefile.am b/src/control/Makefile.am index 5390f278..34712264 100644 --- a/src/control/Makefile.am +++ b/src/control/Makefile.am @@ -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 index 00000000..536f2458 --- /dev/null +++ b/src/control/defaults.c @@ -0,0 +1,108 @@ +/* + * Control Interface - defaults + * Copyright (c) 1998 by Jaroslav Kysela + * + * + * 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 +#include +#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"); +} diff --git a/src/mixer/Makefile.am b/src/mixer/Makefile.am index 1350aba6..cc126ba4 100644 --- a/src/mixer/Makefile.am +++ b/src/mixer/Makefile.am @@ -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 index 00000000..5fed5250 --- /dev/null +++ b/src/mixer/elements.c @@ -0,0 +1,314 @@ +/* + * Mixer Interface - elements + * Copyright (c) 1999 by Jaroslav Kysela + * + * + * 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 +#include +#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; +} diff --git a/src/mixer/mixer.c b/src/mixer/mixer.c index 3ded577a..a9a32348 100644 --- a/src/mixer/mixer.c +++ b/src/mixer/mixer.c @@ -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; +} diff --git a/test/control.c b/test/control.c index 9a465640..c8d67478 100644 --- a/test/control.c +++ b/test/control.c @@ -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); } diff --git a/test/mixer.c b/test/mixer.c index c8777a7d..3550acbe 100644 --- a/test/mixer.c +++ b/test/mixer.c @@ -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);