diff --git a/ScStwLibraries/ScStwLibraries.pri b/ScStwLibraries/ScStwLibraries.pri index 28d1ab7..60205a6 100644 --- a/ScStwLibraries/ScStwLibraries.pri +++ b/ScStwLibraries/ScStwLibraries.pri @@ -15,6 +15,11 @@ ScStwLibraries_ClientLibs { DEFINES += ScStwLibraries_ClientLibs } +ScStwLibraries_Raspi { + LIBS += -lasound + DEFINES += ScStwLibraries_Raspi +} + INCLUDEPATH += $$PWD/headers $$PWD SOURCES += \ diff --git a/ScStwLibraries/headers/scstwsoundplayer.h b/ScStwLibraries/headers/scstwsoundplayer.h index e89915e..47a678b 100644 --- a/ScStwLibraries/headers/scstwsoundplayer.h +++ b/ScStwLibraries/headers/scstwsoundplayer.h @@ -27,9 +27,10 @@ #include #include #include +#include -#ifdef RASPI -#include +#ifdef ScStwLibraries_Raspi +#include #endif /*! @@ -60,6 +61,11 @@ public: }; private: + + bool _setSoundVolume(double volume); + + void _initializeSondEffect(); + /*! * \brief A map containing all sound files * 0: AtYourMarksSound @@ -74,6 +80,8 @@ private: */ QSoundEffect *soundEffect; + QAudioDeviceInfo *_audioOutputDevice; + /*! * \brief The QEventLoop used to wait for the sound to finish */ diff --git a/ScStwLibraries/sources/scstwsoundplayer.cpp b/ScStwLibraries/sources/scstwsoundplayer.cpp index 2f9887d..3b50309 100644 --- a/ScStwLibraries/sources/scstwsoundplayer.cpp +++ b/ScStwLibraries/sources/scstwsoundplayer.cpp @@ -28,8 +28,7 @@ ScStwSoundPlayer::ScStwSoundPlayer(QObject *parent) : QObject(parent) this->soundFiles.insert(Start, {{"path","qrc:/sound/StartsignalSoundExtended.wav"}, {"duration", 3200}}); this->soundFiles.insert(FalseStart, {{"path","qrc:/sound/FalseStartSound.wav"}, {"duration", 2000}}); - this->soundEffect = new QSoundEffect(this); - this->soundEffect->setLoopCount(1); + this->_initializeSondEffect(); connect(this, &ScStwSoundPlayer::playbackStarted, 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 this->currentlyPlayingSound = sound; -#ifdef RASPI - // 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"; + if(!this->_setSoundVolume(volume)) return Error; - } - - this->soundEffect->setVolume(1); -#else - this->soundEffect->setVolume(volume); -#endif // load this->soundEffect->setSource(this->soundFiles[sound]["path"].toString()); @@ -145,3 +124,89 @@ ScStwSoundPlayer::PlayResult ScStwSoundPlayer::waitForSoundFinish(double *timeOf bool ScStwSoundPlayer::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