如何增加一个ALSA 控制接口:
static struct snd_kcontrol_new wm8976_output_volume_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Output Volume",
.info = wm8976_ctl_integer_output_volume_info,
.get = wm8976_output_volume_get,
.put = wm8976_output_volume_put,
};
/* global output volume param */
int wm8976_ctl_integer_output_volume_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = 100;
return 0;
}
/* 增加一个控制接口 */
err = snd_ctl_add(codec->card,
snd_soc_cnew(&wm8976_output_volume_control, codec, NULL));
android/libaudio
--------------------------------------------------------------------------------------------
int setVolumeItem(const char *elem_name, int volume)
{
int err = 0;
int orig_volume = 0;
snd_ctl_t *handle = NULL;
snd_ctl_elem_info_t *info;
snd_ctl_elem_id_t *id;
snd_ctl_elem_value_t *control;
snd_ctl_elem_type_t type;
int count;
snd_ctl_elem_info_alloca(&info);
snd_ctl_elem_id_alloca(&id);
snd_ctl_elem_value_alloca(&control);
snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);/* default */
snd_ctl_elem_id_set_name(id, elem_name);
// snd_ctl_elem_id_set_index(id, 1); // does not have index.
if ((err = snd_ctl_open(&handle, sControlDevice, 0)) < 0) {
LOGE("Error: snd_ctl_open error: %s", snd_strerror(err));
return err;
}
snd_ctl_elem_info_set_id(info, id);
if ((err = snd_ctl_elem_info(handle, info)) < 0) {
LOGE("Error: snd_ctl_elem_info volume error: %s", snd_strerror(err));
snd_ctl_close(handle);
handle = NULL;
return err;
}
type = snd_ctl_elem_info_get_type(info);
count = snd_ctl_elem_info_get_count(info);
/* SNDRV_CTL_ELEM_TYPE_INTEGER驱动层的定义 */
if ((type != SND_CTL_ELEM_TYPE_INTEGER) || (1 != count)) {
LOGE("Error: snd_ctl_elem_info volume type should be INTEGER and count should be 1: type:%d, count:%d", type, count);
snd_ctl_close(handle);
handle = NULL;
return err;
}
snd_ctl_elem_value_set_id(control, id);
if (!snd_ctl_elem_read(handle, control)) {
orig_volume = snd_ctl_elem_value_get_integer(control, 0);
}
//if (volume != orig_volume) {
snd_ctl_elem_value_set_integer(control, 0, volume);
if ((err = snd_ctl_elem_write(handle, control)) < 0) {
LOGE("Error: snd_ctl_elem_write set volume error: %s", snd_strerror(err));
snd_ctl_close(handle);
handle = NULL;
return err;
}
//}
snd_ctl_close(handle);
handle = NULL;
return err;
}
int getVolumeItem(const char *elem_name)
{
int err = 0;
int volume = 0;
snd_ctl_t *handle = NULL;
snd_ctl_elem_info_t *info;
snd_ctl_elem_id_t *id;
snd_ctl_elem_value_t *control;
snd_ctl_elem_type_t type;
int count;
snd_ctl_elem_info_alloca(&info);
snd_ctl_elem_id_alloca(&id);
snd_ctl_elem_value_alloca(&control);
snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);/* default */
snd_ctl_elem_id_set_name(id, elem_name);
// snd_ctl_elem_id_set_index(id, 1); // does not have index.
if ((err = snd_ctl_open(&handle, sControlDevice, 0)) < 0) {
LOGE("Error: snd_ctl_open error: %s", snd_strerror(err));
return err;
}
snd_ctl_elem_info_set_id(info, id);
if ((err = snd_ctl_elem_info(handle, info)) < 0) {
LOGE("Error: snd_ctl_elem_info volume error: %s", snd_strerror(err));
snd_ctl_close(handle);
handle = NULL;
return err;
}
type = snd_ctl_elem_info_get_type(info);
count = snd_ctl_elem_info_get_count(info);
if ((type != SND_CTL_ELEM_TYPE_INTEGER) || (1 != count)) {
LOGE("Error: snd_ctl_elem_info volume type should be INTEGER and count should be 1: type:%d, count:%d", type, count);
snd_ctl_close(handle);
handle = NULL;
return err;
}
snd_ctl_elem_value_set_id(control, id);
if ((err = snd_ctl_elem_read(handle, control)) < 0) {
LOGE("Error: snd_ctl_elem_read get volume error: %s", snd_strerror(err));
snd_ctl_close(handle);
handle = NULL;
return err;
}
volume = snd_ctl_elem_value_get_integer(control, 0);
snd_ctl_close(handle);
handle = NULL;
return volume;
}