在Linux中以C语言获得主音量 [英] Get master sound volume in C in Linux
问题描述
我正在尝试检索(并可能在以后设置)Linux中的主音量.我正在使用PulseAudio,但理想情况下,它也应适用于ALSA.
I'm trying to retrieve (and probably later set) the master sound volume in Linux. I'm using PulseAudio, but ideally it should work for ALSA too.
我发现这关于如何设置音量,并由此推断出snd_mixer_selem_get_playback_volume()的存在以检索当前设置.但是,在我的系统上,这似乎给了我错误的读数-混音器程序显示100%,最高显示为66%.
I found this very helpful post on how to set the volume, and from that I was able to deduce the existence of snd_mixer_selem_get_playback_volume() to retrieve the current setting. However on my system, this seems to be giving me wrong readings - where mixer programs show 100%, this tops out at about 66%.
如果我打开pavucontrol,我可以看到此输出设备的音量与从此处获得的读数相匹配,因此我认为它是在给我硬件音量设置,而不是我想要的全局主音量.
If I open pavucontrol I can see the volume for this output device matches the readings I get from here, so I assume it's giving me the hardware volume setting, not the global master volume that I wanted.
推荐答案
使用gcc audio_volume.c -o audio_volume -lasound
或可替代地使用gcc audio_volume.c -o audio_volume_oss -DOSSCONTROL
编译以下代码. OSS版本写得很粗糙,不能给出精确的结果.将音量设置为100将在我的系统中将音量设置为97%. ALSA版本适用于我,并且适用于openSUSE中的PulseAudio.需要一些清理和爱,但我希望这是您所需要的,我已授予在 WTFPL许可证上使用它的权限.
Compile the below code with gcc audio_volume.c -o audio_volume -lasound
or altenatively with gcc audio_volume.c -o audio_volume_oss -DOSSCONTROL
. OSS version is written very crudely and does not give precise results. Setting volume to 100 sets 97% volume in my system. ALSA version works for me and PulseAudio in openSUSE. Needs some cleanup and love but I hope it is what you need, I grant the permission to use it on the WTFPL license.
#include <unistd.h>
#include <fcntl.h>
#ifdef OSSCONTROL
#define MIXER_DEV "/dev/dsp"
#include <sys/soundcard.h>
#include <sys/ioctl.h>
#include <stdio.h>
#else
#include <alsa/asoundlib.h>
#endif
typedef enum {
AUDIO_VOLUME_SET,
AUDIO_VOLUME_GET,
} audio_volume_action;
/*
Drawbacks. Sets volume on both channels but gets volume on one. Can be easily adapted.
*/
int audio_volume(audio_volume_action action, long* outvol)
{
#ifdef OSSCONTROL
int ret = 0;
int fd, devs;
if ((fd = open(MIXER_DEV, O_WRONLY)) > 0)
{
if(action == AUDIO_VOLUME_SET) {
if(*outvol < 0 || *outvol > 100)
return -2;
*outvol = (*outvol << 8) | *outvol;
ioctl(fd, SOUND_MIXER_WRITE_VOLUME, outvol);
}
else if(action == AUDIO_VOLUME_GET) {
ioctl(fd, SOUND_MIXER_READ_VOLUME, outvol);
*outvol = *outvol & 0xff;
}
close(fd);
return 0;
}
return -1;;
#else
snd_mixer_t* handle;
snd_mixer_elem_t* elem;
snd_mixer_selem_id_t* sid;
static const char* mix_name = "Master";
static const char* card = "default";
static int mix_index = 0;
long pmin, pmax;
long get_vol, set_vol;
float f_multi;
snd_mixer_selem_id_alloca(&sid);
//sets simple-mixer index and name
snd_mixer_selem_id_set_index(sid, mix_index);
snd_mixer_selem_id_set_name(sid, mix_name);
if ((snd_mixer_open(&handle, 0)) < 0)
return -1;
if ((snd_mixer_attach(handle, card)) < 0) {
snd_mixer_close(handle);
return -2;
}
if ((snd_mixer_selem_register(handle, NULL, NULL)) < 0) {
snd_mixer_close(handle);
return -3;
}
ret = snd_mixer_load(handle);
if (ret < 0) {
snd_mixer_close(handle);
return -4;
}
elem = snd_mixer_find_selem(handle, sid);
if (!elem) {
snd_mixer_close(handle);
return -5;
}
long minv, maxv;
snd_mixer_selem_get_playback_volume_range (elem, &minv, &maxv);
fprintf(stderr, "Volume range <%i,%i>\n", minv, maxv);
if(action == AUDIO_VOLUME_GET) {
if(snd_mixer_selem_get_playback_volume(elem, 0, outvol) < 0) {
snd_mixer_close(handle);
return -6;
}
fprintf(stderr, "Get volume %i with status %i\n", *outvol, ret);
/* make the value bound to 100 */
*outvol -= minv;
maxv -= minv;
minv = 0;
*outvol = 100 * (*outvol) / maxv; // make the value bound from 0 to 100
}
else if(action == AUDIO_VOLUME_SET) {
if(*outvol < 0 || *outvol > VOLUME_BOUND) // out of bounds
return -7;
*outvol = (*outvol * (maxv - minv) / (100-1)) + minv;
if(snd_mixer_selem_set_playback_volume(elem, 0, *outvol) < 0) {
snd_mixer_close(handle);
return -8;
}
if(snd_mixer_selem_set_playback_volume(elem, 1, *outvol) < 0) {
snd_mixer_close(handle);
return -9;
}
fprintf(stderr, "Set volume %i with status %i\n", *outvol, ret);
}
snd_mixer_close(handle);
return 0;
#endif
}
int main(void)
{
long vol = -1;
printf("Ret %i\n", audio_volume(AUDIO_VOLUME_GET, &vol));
printf("Master volume is %i\n", vol);
vol = 100;
printf("Ret %i\n", audio_volume(AUDIO_VOLUME_SET, &vol));
return 0;
}
这篇关于在Linux中以C语言获得主音量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!