I'm trying to set the system's playback volume from C++ code with a function that I got from here (although I made some minor modifications like not leaving variables uninitialized).
This is a fully working simple example:
#include <iostream>
#include <alsa/asoundlib.h>
#include <alsa/mixer.h>
using namespace std;
void setVolume(long volume) {
long vMin{ 0 };
long vMax{ 0 };
snd_mixer_t* handle{ nullptr };
snd_mixer_selem_id_t* sid{ nullptr };
static const char* card{ "default" };
static const char* selem_name{ "Master" };
snd_mixer_open(&handle, 0);
snd_mixer_attach(handle, card);
snd_mixer_selem_register(handle, nullptr, nullptr);
snd_mixer_load(handle);
snd_mixer_selem_id_alloca(&sid);
snd_mixer_selem_id_set_index(sid, 0);
snd_mixer_selem_id_set_name(sid, selem_name);
auto elem = snd_mixer_find_selem(handle, sid);
snd_mixer_selem_get_playback_volume_range(elem, &vMin, &vMax);
snd_mixer_selem_set_playback_volume_all(elem, vMin + static_cast<long>(static_cast<double>(vMax - vMin) / 100.0 * static_cast<double>(volume)));
snd_mixer_close(handle);
}
int main() {
cout << "Volume (0-100): ";
long vol{ 0 };
cin >> vol;
setVolume(vol);
}
To compile it, you need the
libasound2-dev
package, the-lasound
linker flag and a C++11 compiler
The code is pretty self-explanetory. You type in an integer in the range 0-100, and the program will set the playback volume to that value. This is just a simple program to test the setVolume
function really.
It works perfectly fine when launched normally, but whenever I launch it with root privileges (sudo), it doesn't work. The problem is that snd_mixer_find_selem
will return NULL
when the program runs as root.
I tried looking at ALSA documentation as well as the actual source files of the library itself, but I couldn't find anything useful.
I'm running this on my Raspberry Pi 3 on Raspbian, but it should work on any Linux machine really.