1

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.

Community
  • 1
  • 1
notadam
  • 2,754
  • 2
  • 19
  • 35
  • Maybe you have correct `~/.asoundrc` or `~/.alsarc` in user's home dir, but don't have correct `/etc/asound.conf`? Maybe run `alsactl init` as root (I don't know if this matters)? – gavv Aug 14 '16 at 19:31
  • @gavv I don't have any of those files, and running that command didn't help at all – notadam Aug 14 '16 at 19:36
  • I'm going to try it on Ubuntu in a second, see if it works there – notadam Aug 14 '16 at 19:38
  • Well, I can't get it to compile on Ubuntu for some reason. The linker complains that it doesn't find references to the ALSA functions, even though I have the library installed and I'm using the correct linker flag. But anyway, the problem still persists on my Pi. – notadam Aug 14 '16 at 19:50
  • 1
    Try running your program under ptrace/strace and compare outputs from user and root? BTW, working fine for me either way (on Gentoo though). – mike.dld Aug 14 '16 at 20:11
  • for raspberry pi you want to use PCM instead of Master static const char* selem_name{ "PCM" }; – Gary Jun 04 '20 at 18:52

0 Answers0