Commit a014e441 authored by Leander Schulten's avatar Leander Schulten

SystemVolume: Implement SystemVolume for Linux

parent 09657b32
Pipeline #204440 passed with stage
in 4 minutes and 42 seconds
......@@ -298,4 +298,6 @@ macx{
linux{
# needed for dynamic libs
LIBS += -ldl
# needed for the SystemVolume class
LIBS += -lasound
}
......@@ -104,7 +104,85 @@ SystemVolume::SystemVolume() {
emit volumeChanged();
}
#endif
#ifdef Q_OS_LINUX
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) {
qWarning() << "SystemVolume: Failed to open the mixer";
return;
}
if ((snd_mixer_attach(handle, card)) < 0) {
snd_mixer_close(handle);
handle = nullptr;
qWarning() << "SystemVolume: Failed to attach the card 'default'";
return;
}
if ((snd_mixer_selem_register(handle, nullptr, nullptr)) < 0) {
snd_mixer_close(handle);
handle = nullptr;
qWarning() << "SystemVolume: Failed to register the mixer";
return;
}
if (snd_mixer_load(handle) < 0) {
snd_mixer_close(handle);
handle = nullptr;
qWarning() << "SystemVolume: Failed to load the mixer";
return;
}
elem = snd_mixer_find_selem(handle, sid);
if (!elem) {
snd_mixer_close(handle);
handle = nullptr;
qWarning() << "SystemVolume: Failed to find a mixer element";
return;
}
if (snd_mixer_selem_get_playback_volume_range(elem, &minv, &maxv) < 0) {
snd_mixer_close(handle);
handle = nullptr;
qWarning() << "SystemVolume: Failed to get the mixer playback volume range";
return;
}
snd_mixer_elem_set_callback(elem, snd_mixer_elem_callback);
startTimer(16);
long volume;
if (snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_MONO, &volume) < 0) {
snd_mixer_close(handle);
handle = nullptr;
qWarning() << "SystemVolume: Failed to get the volume";
return;
}
this->volume = (volume - minv) / static_cast<double>(maxv - minv);
emit volumeChanged();
#endif
}
#ifdef Q_OS_LINUX
void SystemVolume::timerEvent(QTimerEvent * /*event*/) {
if (handle) {
snd_mixer_handle_events(handle);
}
}
int SystemVolume::snd_mixer_elem_callback(snd_mixer_elem_t *elem, unsigned int mask) {
// testet, don't know why value 1, but only mask == 1 works
if (mask == 1) {
long volume;
if (snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_MONO, &volume) >= 0) {
get().volume = (volume - get().minv) / static_cast<double>(get().maxv - get().minv);
emit get().volumeChanged();
} else {
qWarning() << "SystemVolume: Failed to get the volume";
}
}
return 0;
}
#endif
SystemVolume::~SystemVolume() {
#ifdef Q_OS_WIN
......@@ -123,6 +201,11 @@ SystemVolume::~SystemVolume() {
}
CoUninitialize();
#endif
#ifdef Q_OS_LINUX
if (handle) {
snd_mixer_close(handle);
}
#endif
}
void SystemVolume::setVolume(double volume) {
......@@ -154,6 +237,14 @@ void SystemVolume::setVolume(double volume) {
}
}
}
#endif
#ifdef Q_OS_LINUX
if (handle) {
long outvol = static_cast<long>(volume * (maxv - minv)) + minv;
if (snd_mixer_selem_set_playback_volume_all(elem, outvol) < 0) {
qWarning() << "SystemVolume: Can not set system volume for all channels";
}
}
#endif
}
}
......@@ -18,6 +18,10 @@
#include <CoreAudio/CoreAudio.h>
#endif
#ifdef Q_OS_LINUX
#include <alsa/asoundlib.h>
#endif
#ifdef Q_OS_WIN
class Callback : public IAudioEndpointVolumeCallback {
......@@ -45,12 +49,31 @@ class SystemVolume : public QObject {
#endif
#ifdef Q_OS_MAC
AudioDeviceID defaultOutputDeviceID = kAudioDeviceUnknown;
#endif
#ifdef Q_OS_LINUX
// code from here: https://stackoverflow.com/questions/7657624/get-master-sound-volume-in-c-in-linux
snd_mixer_t *handle = nullptr;
snd_mixer_elem_t *elem = nullptr;
snd_mixer_selem_id_t *sid = nullptr;
long minv, maxv;
static constexpr const char *mix_name = "Master";
static constexpr const char *card = "default";
static constexpr int mix_index = 0;
#endif
double volume = -1;
Q_PROPERTY(double volume READ getVolume WRITE setVolume NOTIFY volumeChanged)
SystemVolume();
#ifdef Q_OS_LINUX
protected:
void timerEvent(QTimerEvent *event) override;
private:
static int snd_mixer_elem_callback(snd_mixer_elem_t *elem, unsigned int mask);
#endif
public:
static SystemVolume &get() {
static SystemVolume sv;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment