From e4700cd355087d8b46f49ada1a5d7aeb97462920 Mon Sep 17 00:00:00 2001 From: Dorian Zedler Date: Sat, 3 Oct 2020 18:33:17 +0200 Subject: [PATCH] some more error handling for sound playing --- ScStwLibraries/headers/scstwrace.h | 2 +- ScStwLibraries/headers/scstwsoundplayer.h | 12 +++-- ScStwLibraries/sources/scstwrace.cpp | 57 +++++++++++++++------ ScStwLibraries/sources/scstwsoundplayer.cpp | 22 ++++---- ScStwLibraries/sources/scstwtimer.cpp | 3 -- 5 files changed, 64 insertions(+), 32 deletions(-) diff --git a/ScStwLibraries/headers/scstwrace.h b/ScStwLibraries/headers/scstwrace.h index 210a64a..c745038 100644 --- a/ScStwLibraries/headers/scstwrace.h +++ b/ScStwLibraries/headers/scstwrace.h @@ -134,7 +134,7 @@ private slots: void handleTimerWantsToBeDisabledChange(ScStwTimer* timer, bool wantsToBeDisabled); int handleFalseStart(); bool playSoundsAndStartTimers(); - bool doDelayAndSoundOfCurrentStartState(double *timeOfSoundPlaybackStart = nullptr); + ScStwSoundPlayer::PlayResult doDelayAndSoundOfCurrentStartState(double *timeOfSoundPlaybackStart = nullptr); void technicalIncident(); /** diff --git a/ScStwLibraries/headers/scstwsoundplayer.h b/ScStwLibraries/headers/scstwsoundplayer.h index 3356a51..28d9bdc 100644 --- a/ScStwLibraries/headers/scstwsoundplayer.h +++ b/ScStwLibraries/headers/scstwsoundplayer.h @@ -49,6 +49,12 @@ public: FalseStart = 3 }; + enum PlayResult { + Success = 0, + Cancelled = -1, + Error = -2 + }; + private: /*! * \brief A map containing all sound files @@ -91,16 +97,16 @@ public slots: * \param action The action to play (0: AtYourMarks, 1:Ready, 2:Start) * \param volume The volume to play at * \param timeOfStop The time the playback actually started (msecs since epoch) - * \return true if the playback was successfully started, false otherwise + * \return TODO true if the playback was successfully started, false otherwise */ - bool play(StartSound sound, double volume, double *timeOfStart = nullptr); + ScStwSoundPlayer::PlayResult play(StartSound sound, double volume, double *timeOfStart = nullptr); /*! * \brief Function to wait for the playback to finish * \param timeOfStop the point in time when the plyback actually stopped (msecs since epoch) * \return false if there was any error (eg. there was no playback currently), true otherwise */ - bool waitForSoundFinish(double *timeOfStop = nullptr); + ScStwSoundPlayer::PlayResult waitForSoundFinish(double *timeOfStop = nullptr); /*! * \brief Function to cancel the current playback diff --git a/ScStwLibraries/sources/scstwrace.cpp b/ScStwLibraries/sources/scstwrace.cpp index a3ef689..3f91b1c 100644 --- a/ScStwLibraries/sources/scstwrace.cpp +++ b/ScStwLibraries/sources/scstwrace.cpp @@ -197,6 +197,8 @@ void ScStwRace::technicalIncident() { foreach(ScStwTimer *timer, this->timers){ timer->cancel(); } + + this->soundPlayer->cancel(); this->setState(INCIDENT); } @@ -223,8 +225,16 @@ bool ScStwRace::playSoundsAndStartTimers() { return true; // The check if all timers are ready has already happened at this point - if(!this->doDelayAndSoundOfCurrentStartState()) + ScStwSoundPlayer::PlayResult res = this->doDelayAndSoundOfCurrentStartState(); + + if(res == ScStwSoundPlayer::Error) { + qDebug() << "[ERROR][RACE] error playing at your marks sound"; + this->technicalIncident(); return false; + } + else if(res == ScStwSoundPlayer::Cancelled) { + return false; + } // check if the start was cancelled if(!this->isStarting()) @@ -234,8 +244,6 @@ bool ScStwRace::playSoundsAndStartTimers() { // do climber readiness tests - // wait until both climbers are ready - // if the automatic ready tone is enabled, wait for the climbers to become ready if(this->competitionMode && this->getSoundEnabledSetting(ScStwSoundPlayer::Ready)) { @@ -290,11 +298,16 @@ bool ScStwRace::playSoundsAndStartTimers() { qDebug() << "[DEBUG][RACE] Wait finished, starting now!"; // play ready tone - if(!this->soundPlayer->play(ScStwSoundPlayer::Ready, this->getSoundVolume())) { - qDebug() << "[ERROR][RACE] Ready sound returned false!"; + ScStwSoundPlayer::PlayResult res = this->soundPlayer->play(ScStwSoundPlayer::Ready, this->getSoundVolume()); + + if(res == ScStwSoundPlayer::Error) { + qDebug() << "[ERROR][RACE] error playing ready sound"; this->technicalIncident(); return false; } + else if(res == ScStwSoundPlayer::Cancelled) { + return false; + } } else if(this->competitionMode) { // wait for climbers and manual start @@ -308,8 +321,14 @@ bool ScStwRace::playSoundsAndStartTimers() { } while(loopExitCode != LoopManualExit || !this->getIsReadyForNextState()); } else { - if(!this->doDelayAndSoundOfCurrentStartState()) { - this->cancel(); + ScStwSoundPlayer::PlayResult res = this->doDelayAndSoundOfCurrentStartState(); + + if(res == ScStwSoundPlayer::Error) { + qDebug() << "[ERROR][RACE] error playing ready sound"; + this->technicalIncident(); + return false; + } + else if(res == ScStwSoundPlayer::Cancelled) { return false; } } @@ -319,10 +338,16 @@ bool ScStwRace::playSoundsAndStartTimers() { // play start tone double timeOfSoundPlaybackStart; - if(!this->doDelayAndSoundOfCurrentStartState(&timeOfSoundPlaybackStart)) { + res = this->doDelayAndSoundOfCurrentStartState(&timeOfSoundPlaybackStart); + + if(res == ScStwSoundPlayer::Error) { + qDebug() << "[ERROR][RACE] error playing at your marks sound"; this->technicalIncident(); return false; } + else if(res == ScStwSoundPlayer::Cancelled) { + return false; + } // perform start @@ -339,7 +364,7 @@ bool ScStwRace::playSoundsAndStartTimers() { return false; } - if(!this->soundPlayer->waitForSoundFinish()) { + if(this->soundPlayer->waitForSoundFinish() == ScStwSoundPlayer::Error) { qDebug() << "[ERROR][RACE] start sound wait error"; this->technicalIncident(); return false; @@ -347,7 +372,7 @@ bool ScStwRace::playSoundsAndStartTimers() { // check if a false start occured if(!this->isStarting()) - return true; + return false; this->setState(RUNNING); @@ -356,7 +381,7 @@ bool ScStwRace::playSoundsAndStartTimers() { } -bool ScStwRace::doDelayAndSoundOfCurrentStartState(double *timeOfSoundPlaybackStart) { +ScStwSoundPlayer::PlayResult ScStwRace::doDelayAndSoundOfCurrentStartState(double *timeOfSoundPlaybackStart) { ScStwSoundPlayer::StartSound sound = this->getSoundForState(this->state); if(this->getSoundEnabledSetting(sound)) { @@ -374,18 +399,18 @@ bool ScStwRace::doDelayAndSoundOfCurrentStartState(double *timeOfSoundPlaybackSt emit this->currentStartDelayChanged(); if(this->startWaitLoop->exec() == LoopCancelExit) - return false; + return ScStwSoundPlayer::Cancelled; } } if(!this->isStarting()) - return false; + return ScStwSoundPlayer::Error; - if(!this->soundPlayer->play(sound, this->getSoundVolume(), timeOfSoundPlaybackStart)) - return false; + + return this->soundPlayer->play(sound, this->getSoundVolume(), timeOfSoundPlaybackStart); } - return true; + return ScStwSoundPlayer::Success; } void ScStwRace::setState(RaceState newState) { diff --git a/ScStwLibraries/sources/scstwsoundplayer.cpp b/ScStwLibraries/sources/scstwsoundplayer.cpp index e68caee..463d716 100644 --- a/ScStwLibraries/sources/scstwsoundplayer.cpp +++ b/ScStwLibraries/sources/scstwsoundplayer.cpp @@ -35,9 +35,11 @@ ScStwSoundPlayer::ScStwSoundPlayer(QObject *parent) : QObject(parent) connect(this->soundEffect, &QSoundEffect::playingChanged, this->waitLoop, &QEventLoop::quit); } -bool ScStwSoundPlayer::play(ScStwSoundPlayer::StartSound sound, double volume, double *timeOfStart) { - if(!this->soundFiles.contains(sound)) - return false; +ScStwSoundPlayer::PlayResult ScStwSoundPlayer::play(ScStwSoundPlayer::StartSound sound, double volume, double *timeOfStart) { + if(!this->soundFiles.contains(sound)) { + qDebug() << "[ERROR][SoundPlayer] Sound file was not found for sound" << sound; + return ScStwSoundPlayer::Error; + } // stop playback if(this->soundEffect->isPlaying()) @@ -55,6 +57,7 @@ bool ScStwSoundPlayer::play(ScStwSoundPlayer::StartSound sound, double volume, d // wait for the effect to load QEventLoop loop; while(this->soundEffect->status() != QSoundEffect::Ready) { + qDebug() << "[DEBUG][Sound] Sound is not ready yet, status is: " << this->soundEffect->status(); QObject::connect(this->soundEffect, &QSoundEffect::statusChanged, &loop, &QEventLoop::quit); loop.exec(); } @@ -76,7 +79,7 @@ bool ScStwSoundPlayer::play(ScStwSoundPlayer::StartSound sound, double volume, d if(sound < Start) return this->waitForSoundFinish(); - return true; + return ScStwSoundPlayer::Success; } bool ScStwSoundPlayer::cancel() { @@ -85,17 +88,18 @@ bool ScStwSoundPlayer::cancel() { // stop playback this->soundEffect->stop(); - this->waitLoop->quit(); + this->waitLoop->exit(-1); return true; } -bool ScStwSoundPlayer::waitForSoundFinish(double *timeOfStop) { +ScStwSoundPlayer::PlayResult ScStwSoundPlayer::waitForSoundFinish(double *timeOfStop) { if(!this->soundEffect->isPlaying()) - return false; + return ScStwSoundPlayer::Error; // wait until the audio output reports the sound is over - waitLoop->exec(); + if(waitLoop->exec() == -1) + return ScStwSoundPlayer::Cancelled; // wait until the sound is actually over // the timeOffset is the buffer time before the audio started! @@ -113,7 +117,7 @@ bool ScStwSoundPlayer::waitForSoundFinish(double *timeOfStop) { *timeOfStop = QDateTime::currentMSecsSinceEpoch() - latency; } - return true; + return ScStwSoundPlayer::Success; } bool ScStwSoundPlayer::isPlaying() { diff --git a/ScStwLibraries/sources/scstwtimer.cpp b/ScStwLibraries/sources/scstwtimer.cpp index f7f77ba..efa429a 100644 --- a/ScStwLibraries/sources/scstwtimer.cpp +++ b/ScStwLibraries/sources/scstwtimer.cpp @@ -217,9 +217,6 @@ QString ScStwTimer::getLetter() { } QString ScStwTimer::getText() { - - qDebug() << "getting text: start time: " << this->startTime << " state: " << this->state; - QString newText = ""; int newTime = 0; switch (this->state) {