再搞V3S的Codec,实在是不想用Shell的方式控制音量和静音,于是翻了各种帖子,大部分都是:
amixer -c 0 sset 'Headphone',0 70% unmute
aplay 01.wav
CSDN上有控制音量的C代码:
https://blog.csdn.net/augu_/article/details/140218122
https://blog.csdn.net/cnclenovo/article/details/46044831
https://blog.csdn.net/a827143452/article/details/89248136
但是静音控制一直没翻到,无奈只能看“amixer”的源代码了,搜关键字“unmute”倒是很容易找到。
buildroot-2020.02.8\output\build\alsa-utils-1.2.1\amixer\amixer.c
static int sset_channels(snd_mixer_elem_t *elem, unsigned int argc, char **argv)
{
unsigned int channels = ~0U;
unsigned int dir = 3, okflag = 3;
unsigned int idx;
snd_mixer_selem_channel_id_t chn;
int check_flag = ignore_error ? 0 : -1;
for (idx = 1; idx < argc; idx++) {
char *ptr = argv[idx], *optr;
int multi, firstchn = 1;
channels = channels_mask(&ptr, channels);
if (*ptr == '\0')
continue;
dir = dir_mask(&ptr, dir);
if (*ptr == '\0')
continue;
multi = (strchr(ptr, ',') != NULL);
optr = ptr;
for (chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) {
char *sptr = NULL;
int ival;
if (!(channels & (1 << chn)))
continue;
if ((dir & 1) && snd_mixer_selem_has_playback_channel(elem, chn)) {
sptr = ptr;
if (!strncmp(ptr, "mute", 4) && snd_mixer_selem_has_playback_switch(elem)) {
snd_mixer_selem_get_playback_switch(elem, chn, &ival);
if (snd_mixer_selem_set_playback_switch(elem, chn, get_bool_simple(&ptr, "mute", 1, ival)) >= 0)
check_flag = 1;
} else if (!strncmp(ptr, "off", 3) && snd_mixer_selem_has_playback_switch(elem)) {
snd_mixer_selem_get_playback_switch(elem, chn, &ival);
if (snd_mixer_selem_set_playback_switch(elem, chn, get_bool_simple(&ptr, "off", 1, ival)) >= 0)
check_flag = 1;
} else if (!strncmp(ptr, "unmute", 6) && snd_mixer_selem_has_playback_switch(elem)) {
snd_mixer_selem_get_playback_switch(elem, chn, &ival);
if (snd_mixer_selem_set_playback_switch(elem, chn, get_bool_simple(&ptr, "unmute", 0, ival)) >= 0)
check_flag = 1;
} else if (!strncmp(ptr, "on", 2) && snd_mixer_selem_has_playback_switch(elem)) {
snd_mixer_selem_get_playback_switch(elem, chn, &ival);
if (snd_mixer_selem_set_playback_switch(elem, chn, get_bool_simple(&ptr, "on", 0, ival)) >= 0)
check_flag = 1;
} else if (!strncmp(ptr, "toggle", 6) && snd_mixer_selem_has_playback_switch(elem)) {
if (firstchn || !snd_mixer_selem_has_playback_switch_joined(elem)) {
snd_mixer_selem_get_playback_switch(elem, chn, &ival);
if (snd_mixer_selem_set_playback_switch(elem, chn, (ival ? 1 : 0) ^ 1) >= 0)
check_flag = 1;
}
simple_skip_word(&ptr, "toggle");
} else if (isdigit(*ptr) || *ptr == '-' || *ptr == '+') {
if (set_volume_simple(elem, chn, &ptr, 0) >= 0)
check_flag = 1;
} else if (simple_skip_word(&ptr, "cap") || simple_skip_word(&ptr, "rec") ||
simple_skip_word(&ptr, "nocap") || simple_skip_word(&ptr, "norec")) {
/* nothing */
} else {
okflag &= ~1;
}
}
if ((dir & 2) && snd_mixer_selem_has_capture_channel(elem, chn)) {
if (sptr != NULL)
ptr = sptr;
sptr = ptr;
if (!strncmp(ptr, "cap", 3) && snd_mixer_selem_has_capture_switch(elem)) {
snd_mixer_selem_get_capture_switch(elem, chn, &ival);
if (snd_mixer_selem_set_capture_switch(elem, chn, get_bool_simple(&ptr, "cap", 0, ival)) >= 0)
check_flag = 1;
} else if (!strncmp(ptr, "rec", 3) && snd_mixer_selem_has_capture_switch(elem)) {
snd_mixer_selem_get_capture_switch(elem, chn, &ival);
if (snd_mixer_selem_set_capture_switch(elem, chn, get_bool_simple(&ptr, "rec", 0, ival)) >= 0)
check_flag = 1;
} else if (!strncmp(ptr, "nocap", 5) && snd_mixer_selem_has_capture_switch(elem)) {
snd_mixer_selem_get_capture_switch(elem, chn, &ival);
if (snd_mixer_selem_set_capture_switch(elem, chn, get_bool_simple(&ptr, "nocap", 1, ival)) >= 0)
check_flag = 1;
} else if (!strncmp(ptr, "norec", 5) && snd_mixer_selem_has_capture_switch(elem)) {
snd_mixer_selem_get_capture_switch(elem, chn, &ival);
if (snd_mixer_selem_set_capture_switch(elem, chn, get_bool_simple(&ptr, "norec", 1, ival)) >= 0)
check_flag = 1;
} else if (!strncmp(ptr, "toggle", 6) && snd_mixer_selem_has_capture_switch(elem)) {
if (firstchn || !snd_mixer_selem_has_capture_switch_joined(elem)) {
snd_mixer_selem_get_capture_switch(elem, chn, &ival);
if (snd_mixer_selem_set_capture_switch(elem, chn, (ival ? 1 : 0) ^ 1) >= 0)
check_flag = 1;
}
simple_skip_word(&ptr, "toggle");
} else if (isdigit(*ptr) || *ptr == '-' || *ptr == '+') {
if (set_volume_simple(elem, chn, &ptr, 1) >= 0)
check_flag = 1;
} else if (simple_skip_word(&ptr, "mute") || simple_skip_word(&ptr, "off") ||
simple_skip_word(&ptr, "unmute") || simple_skip_word(&ptr, "on")) {
/* nothing */
} else {
okflag &= ~2;
}
}
if (okflag == 0) {
if (debugflag) {
if (dir & 1)
error("Unknown playback setup '%s'..", ptr);
if (dir & 2)
error("Unknown capture setup '%s'..", ptr);
}
return 0; /* just skip it */
}
if (!multi)
ptr = optr;
firstchn = 0;
}
}
return check_flag;
}
找到关键代码:
snd_mixer_selem_set_playback_switch(elem, chn, get_bool_simple(&ptr, "unmute", 0, ival)
然后去 alsa-lib 中找到了:
int snd_mixer_selem_set_playback_switch_all(snd_mixer_elem_t *elem, int value)
索性把所有channel都取消静音好了。
离线
源代码如下(借鉴了CSDN上的代码):
void volume_control_init(void)
{
snd_mixer_t *mixer;
snd_mixer_elem_t *elem;
debug_msg(snd_mixer_open(&mixer,0),"opening mixer"); // 打开混音器设备
debug_msg(snd_mixer_attach(mixer, "default"),"attaching mixer"); // 连接到默认的声卡
debug_msg(snd_mixer_selem_register(mixer, NULL, NULL),"registering mixer"); // 载入声卡配置
debug_msg(snd_mixer_load(mixer),"load mixer");
// 循环找到自己想要的element
elem = snd_mixer_first_elem(mixer);
while(elem){
// find element name(此处要找的就是上面看的speaker元素)
if(strcmp("Headphone",snd_mixer_selem_get_name(elem)) == 0){
printf("elem name : %s\n",snd_mixer_selem_get_name(elem));
break;
}
elem = snd_mixer_elem_next(elem);
}
if(!elem){
printf("snd_mixer_find_selem Error\n");
snd_mixer_close(mixer);
mixer = NULL;
return;
}
long min, max;
snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
printf("volume range: %ld -- %ld\n", min, max);
long lVal, rVal;
snd_mixer_handle_events(mixer); // 确保混音器状态和应用程序状态的同步
snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &lVal);
snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, &rVal);
printf("currnet volume: leftVal = %ld, rightVal = %ld\n", lVal, rVal);
/* 设置 音量 */
snd_mixer_selem_set_playback_volume_all(elem, 50);
/* 关闭 静音 */
snd_mixer_selem_set_playback_switch_all(elem, 1);
// 释放资源
snd_mixer_close(mixer);
}
离线