Fix issues with changing default audio device

This commit is contained in:
Dorian Zedler 2021-05-02 20:16:55 +02:00
parent 43b809d5d6
commit 9dad927239
Signed by: dorian
GPG key ID: 989DE36109AFA354
3 changed files with 103 additions and 25 deletions

View file

@ -15,6 +15,11 @@ ScStwLibraries_ClientLibs {
DEFINES += ScStwLibraries_ClientLibs DEFINES += ScStwLibraries_ClientLibs
} }
ScStwLibraries_Raspi {
LIBS += -lasound
DEFINES += ScStwLibraries_Raspi
}
INCLUDEPATH += $$PWD/headers $$PWD INCLUDEPATH += $$PWD/headers $$PWD
SOURCES += \ SOURCES += \

View file

@ -27,9 +27,10 @@
#include <QTimer> #include <QTimer>
#include <QDateTime> #include <QDateTime>
#include <QSoundEffect> #include <QSoundEffect>
#include <QAudioDeviceInfo>
#ifdef RASPI #ifdef ScStwLibraries_Raspi
#include <QProcess> #include <alsa/asoundlib.h>
#endif #endif
/*! /*!
@ -60,6 +61,11 @@ public:
}; };
private: private:
bool _setSoundVolume(double volume);
void _initializeSondEffect();
/*! /*!
* \brief A map containing all sound files * \brief A map containing all sound files
* 0: AtYourMarksSound * 0: AtYourMarksSound
@ -74,6 +80,8 @@ private:
*/ */
QSoundEffect *soundEffect; QSoundEffect *soundEffect;
QAudioDeviceInfo *_audioOutputDevice;
/*! /*!
* \brief The QEventLoop used to wait for the sound to finish * \brief The QEventLoop used to wait for the sound to finish
*/ */

View file

@ -28,8 +28,7 @@ ScStwSoundPlayer::ScStwSoundPlayer(QObject *parent) : QObject(parent)
this->soundFiles.insert(Start, {{"path","qrc:/sound/StartsignalSoundExtended.wav"}, {"duration", 3200}}); this->soundFiles.insert(Start, {{"path","qrc:/sound/StartsignalSoundExtended.wav"}, {"duration", 3200}});
this->soundFiles.insert(FalseStart, {{"path","qrc:/sound/FalseStartSound.wav"}, {"duration", 2000}}); this->soundFiles.insert(FalseStart, {{"path","qrc:/sound/FalseStartSound.wav"}, {"duration", 2000}});
this->soundEffect = new QSoundEffect(this); this->_initializeSondEffect();
this->soundEffect->setLoopCount(1);
connect(this, &ScStwSoundPlayer::playbackStarted, this->waitLoop, &QEventLoop::quit); connect(this, &ScStwSoundPlayer::playbackStarted, this->waitLoop, &QEventLoop::quit);
connect(this->soundEffect, &QSoundEffect::playingChanged, this->waitLoop, &QEventLoop::quit); connect(this->soundEffect, &QSoundEffect::playingChanged, this->waitLoop, &QEventLoop::quit);
@ -48,28 +47,8 @@ ScStwSoundPlayer::PlayResult ScStwSoundPlayer::play(ScStwSoundPlayer::StartSound
// update currently playing action // update currently playing action
this->currentlyPlayingSound = sound; this->currentlyPlayingSound = sound;
#ifdef RASPI if(!this->_setSoundVolume(volume))
// set volume on raspi using amixer
QProcess soundProcess;
// determine current audio output device
soundProcess.start("amixer", {"scontrols"});
soundProcess.waitForFinished();
QStringList outputDeviceNameList = QString(soundProcess.readAllStandardOutput()).split("'");
if(outputDeviceNameList.length() == 3) {
QString outputDeviceName = outputDeviceNameList[1];
soundProcess.execute("amixer", {"sset", outputDeviceName, QString::number(volume * 100, 'f', 0) + "%"});
}
else {
qDebug() << "[WARNING][SoundPlayer] Could not determine output device to set volume";
return Error; return Error;
}
this->soundEffect->setVolume(1);
#else
this->soundEffect->setVolume(volume);
#endif
// load // load
this->soundEffect->setSource(this->soundFiles[sound]["path"].toString()); this->soundEffect->setSource(this->soundFiles[sound]["path"].toString());
@ -145,3 +124,89 @@ ScStwSoundPlayer::PlayResult ScStwSoundPlayer::waitForSoundFinish(double *timeOf
bool ScStwSoundPlayer::isPlaying() { bool ScStwSoundPlayer::isPlaying() {
return this->soundEffect->isPlaying(); return this->soundEffect->isPlaying();
} }
#ifdef ScStwLibraries_Raspi
void ScStwSoundPlayer::_initializeSondEffect() {
this->_audioOutputDevice = nullptr;
for(QAudioDeviceInfo info : QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)) {
qDebug() << info.deviceName();
if(info.deviceName().contains("Headphones"))
this->_audioOutputDevice = new QAudioDeviceInfo(info);
}
if(this->_audioOutputDevice == nullptr)
this->_audioOutputDevice = new QAudioDeviceInfo(QAudioDeviceInfo::defaultOutputDevice());
this->soundEffect = new QSoundEffect(*this->_audioOutputDevice, this);
this->soundEffect->setLoopCount(1);
}
#else
void ScStwSoundPlayer::_initializeSondEffect() {
this->_audioOutputDevice = new QAudioDeviceInfo(QAudioDeviceInfo::defaultOutputDevice());
this->soundEffect = new QSoundEffect(*this->_audioOutputDevice, this);
this->soundEffect->setLoopCount(1);
}
#endif
#ifdef ScStwLibraries_Raspi
bool ScStwSoundPlayer::_setSoundVolume(double volume) {
QString cardName = this->_audioOutputDevice->deviceName();
QStringRef shortCardName = cardName.midRef(cardName.indexOf(QLatin1String("="), 0) + 1);
int cardIndex = snd_card_get_index(shortCardName.toLocal8Bit().constData());
QString soundDevice = QString(QLatin1String("hw:%1")).arg(cardIndex);
qDebug() << "[INFO][SoundPlayer] Using audio device: " << soundDevice;
long min, max;
snd_mixer_t *handle;
snd_mixer_selem_id_t *sid;
snd_mixer_elem_t *elem;
if(snd_mixer_open(&handle, 0) < 0) {
qDebug() << "[ERROR][SoundPlayer] Could not open mixer";
return false;
}
if(snd_mixer_selem_register(handle, NULL, NULL) < 0) {
qDebug() << "[ERROR][SoundPlayer] Could not register selem";
return false;
}
if(snd_mixer_attach(handle, soundDevice.toStdString().c_str()) < 0) {
qDebug() << "[ERROR][SoundPlayer] Could not attach mixer";
return false;
}
if(snd_mixer_load(handle) < 0) {
qDebug() << "[ERROR][SoundPlayer] Could not load mixer";
return false;
}
// set volume for all channels
snd_mixer_selem_id_alloca(&sid);
bool success = false;
for (elem = snd_mixer_first_elem(handle); elem; elem = snd_mixer_elem_next(elem)) {
snd_mixer_selem_get_id(elem, sid);
if (!snd_mixer_selem_is_active(elem))
continue;
elem = snd_mixer_find_selem(handle, sid);
if(!elem)
continue;
snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
snd_mixer_selem_set_playback_volume_all(elem, min + (volume) * (max - min));
success = true;
}
snd_mixer_close(handle);
this->soundEffect->setVolume(1);
return success;
}
#else
bool ScStwSoundPlayer::_setSoundVolume(double volume) {
this->soundEffect->setVolume(volume);
return true;
}
#endif