mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-28 05:40:23 -04:00
Mixer v2.0 merged to the main CVS tree...
This commit is contained in:
parent
3f541735e3
commit
a5b307a711
10 changed files with 536 additions and 167 deletions
|
|
@ -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"
|
||||
])
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
108
src/control/defaults.c
Normal file
108
src/control/defaults.c
Normal file
|
|
@ -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");
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
EXTRA_LTLIBRARIES=libmixer.la
|
||||
|
||||
libmixer_la_SOURCES = mixer.c
|
||||
libmixer_la_SOURCES = mixer.c elements.c
|
||||
|
||||
all: libmixer.la
|
||||
|
||||
|
|
|
|||
314
src/mixer/elements.c
Normal file
314
src/mixer/elements.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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)
|
||||
if (ioctl(mixer->fd, SND_MIXER_IOCTL_ELEMENTS, elements) < 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)
|
||||
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_INFO, info) < 0)
|
||||
if (ioctl(mixer->fd, SND_MIXER_IOCTL_ROUTES, routes) < 0)
|
||||
return -errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int snd_mixer_channel_output_info(void *handle, int channel, snd_mixer_channel_direction_info_t * info)
|
||||
int snd_mixer_groups(void *handle, snd_mixer_groups_t * groups)
|
||||
{
|
||||
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_OINFO, info) < 0)
|
||||
if (ioctl(mixer->fd, SND_MIXER_IOCTL_GROUPS, groups) < 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_group(void *handle, snd_mixer_group_t * group)
|
||||
{
|
||||
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_GROUP, group) < 0)
|
||||
return -errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int snd_mixer_channel_read(void *handle, int channel, snd_mixer_channel_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_READ, data) < 0)
|
||||
if (ioctl(mixer->fd, SND_MIXER_IOCTL_ELEMENT_INFO, info) < 0)
|
||||
return -errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int snd_mixer_channel_write(void *handle, int channel, snd_mixer_channel_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)
|
||||
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_ELEMENT_READ, element) < 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_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;
|
||||
bzero(data, sizeof(snd_mixer_channel_t));
|
||||
data->channel = channel;
|
||||
if (ioctl(mixer->fd, SND_MIXER_IOCTL_CHANNEL_OREAD, data) < 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)
|
||||
{
|
||||
snd_mixer_t *mixer;
|
||||
|
||||
mixer = (snd_mixer_t *) handle;
|
||||
if (!mixer || !data || channel < 0)
|
||||
return -EINVAL;
|
||||
bzero(data, sizeof(snd_mixer_channel_t));
|
||||
data->channel = channel;
|
||||
if (ioctl(mixer->fd, SND_MIXER_IOCTL_CHANNEL_IREAD, data) < 0)
|
||||
return -errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int snd_mixer_channel_input_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_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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
14
test/mixer.c
14
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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue