From 9a81d87451154935a976d65e2b199d6ed22eb917 Mon Sep 17 00:00:00 2001 From: Dorian Zedler Date: Fri, 2 Oct 2020 17:05:52 +0200 Subject: [PATCH 1/2] some fixes in race and soundplayer --- ScStwLibraries/headers/scstwsoundplayer.h | 9 ++-- ScStwLibraries/sources/scstwrace.cpp | 51 +++++++++++++-------- ScStwLibraries/sources/scstwsoundplayer.cpp | 4 +- 3 files changed, 39 insertions(+), 25 deletions(-) diff --git a/ScStwLibraries/headers/scstwsoundplayer.h b/ScStwLibraries/headers/scstwsoundplayer.h index 1e977db..ac05926 100644 --- a/ScStwLibraries/headers/scstwsoundplayer.h +++ b/ScStwLibraries/headers/scstwsoundplayer.h @@ -42,10 +42,11 @@ public: explicit ScStwSoundPlayer(QObject *parent = nullptr); enum StartSound { - AtYourMarks, - Ready, - Start, - FalseStart + None = -1, + AtYourMarks = 0, + Ready = 1, + Start = 2, + FalseStart = 3 }; private: diff --git a/ScStwLibraries/sources/scstwrace.cpp b/ScStwLibraries/sources/scstwrace.cpp index 803e23a..f90f0de 100644 --- a/ScStwLibraries/sources/scstwrace.cpp +++ b/ScStwLibraries/sources/scstwrace.cpp @@ -58,11 +58,9 @@ ScStw::StatusCode ScStwRace::start(bool asyncronous) { return ScStw::CurrentStateNotVaildForOperationError; } - qDebug() << "[INFO][RACE] checking timers"; if(!this->isReadyForNextState()) return ScStw::TimersNotReadyError; - qDebug() << "[INFO][RACE] starting race"; this->setState(PREPAIRING); if(asyncronous) { @@ -156,6 +154,8 @@ ScStw::StatusCode ScStwRace::reset() { if(returnCode == ScStw::Success) this->setState(IDLE); + this->soundPlayer->cancel(); + return returnCode; } @@ -181,6 +181,8 @@ ScStw::StatusCode ScStwRace::cancel() { this->soundPlayer->cancel(this->soundVolume); this->startDelayTimer->stop(); + emit this->currentStartDelayChanged(); + return returnCode; } @@ -233,7 +235,10 @@ bool ScStwRace::playSoundsAndStartTimers() { this->startDelayTimer->setInterval(minimumReadyDelay); - // wait for climbers to become ready initially + // wait for all climbers to be ready for the ReadyActionDelay, but at least one second continuosly + // the climber ready wait loop will also quit, if the climber steps of the pad + // -> wait for both climbers to stand on the pad for at least one second + bool timerTriggered = true; do { @@ -252,10 +257,7 @@ bool ScStwRace::playSoundsAndStartTimers() { emit this->currentStartDelayChanged(); - - qDebug() << "entering wait loop..."; int loopExitCode = this->startWaitLoop->exec(); - qDebug() << "wait loop exited with code " << loopExitCode; switch (loopExitCode) { case LoopAutomaticExit: @@ -268,21 +270,18 @@ bool ScStwRace::playSoundsAndStartTimers() { return false; } - qDebug() << "At end of loop: remaining time: " << this->startDelayTimer->remainingTime() << " timer triggered: " << timerTriggered << " ready for next state: " << this->isReadyForNextState(); + //qDebug() << "At end of loop: remaining time: " << this->startDelayTimer->remainingTime() << " timer triggered: " << timerTriggered << " ready for next state: " << this->isReadyForNextState(); } while(this->startDelayTimer->remainingTime() > 0 || !timerTriggered || !this->isReadyForNextState()); - qDebug() << "[RACE][DEBUG] Initial wait finished"; - - // wait for all climbers to be ready for the ReadyActionDelay, but at least one second continuosly - // the climber ready wait loop will also quit, if the climber steps of the pad - // -> wait for both climbers to stand on the pad for at least one second - qDebug() << "[RACE][DEBUG] Wait finished, starting now!"; // play ready tone - if(!this->soundPlayer->play(ScStwSoundPlayer::Ready, this->soundVolume)) + if(!this->soundPlayer->play(ScStwSoundPlayer::Ready, this->soundVolume)) { + qDebug() << "Ready sound redturned false!"; + this->setState(INCIDENT); return false; + } } else if(this->competitionMode) { // wait for climbers and manual start @@ -297,8 +296,10 @@ bool ScStwRace::playSoundsAndStartTimers() { } else { qDebug() << "now playing ready sound"; - if(!this->doDelayAndSoundOfCurrentStartState()) + if(!this->doDelayAndSoundOfCurrentStartState()) { + this->cancel(); return false; + } } qDebug() << "now in starting state"; @@ -309,7 +310,10 @@ bool ScStwRace::playSoundsAndStartTimers() { // play start tone qDebug() << "now playing start sound"; double timeOfSoundPlaybackStart; - this->doDelayAndSoundOfCurrentStartState(&timeOfSoundPlaybackStart); + if(!this->doDelayAndSoundOfCurrentStartState(&timeOfSoundPlaybackStart)) { + this->setState(INCIDENT); + return false; + } // perform start @@ -322,11 +326,13 @@ bool ScStwRace::playSoundsAndStartTimers() { } if(!startOk) { qDebug() << "[ERROR][START] error staring all timers"; + this->setState(INCIDENT); return false; } if(!this->soundPlayer->waitForSoundFinish()) { qDebug() << "[ERROR][START] start sound wait error"; + this->setState(INCIDENT); return false; } @@ -529,17 +535,24 @@ void ScStwRace::enableAllTimers() { } QVariantList ScStwRace::getCurrentStartDelay() { - int nextActionDelay = 0; + int nextActionDelay = -1; double nextActionDelayProg = -1; - if(this->state == PREPAIRING || this->state == WAITING) { + if(this->state == WAITING && !this->isReadyForNextState()) { + // indicate that we are waiting for climbers and the progress shall be zero + nextActionDelayProg = 0; + } + else if(this->state == PREPAIRING || this->state == WAITING) { // get the total delay and the delay progress of the next action timer double remaining = this->startDelayTimer->remainingTime(); - nextActionDelay = this->startDelayTimer->interval();; + nextActionDelay = this->startDelayTimer->interval(); if(remaining < 0) { remaining = nextActionDelay; } nextActionDelayProg = 1 - (remaining / nextActionDelay); + + if(nextActionDelayProg < 0) + nextActionDelayProg = 0; } return { diff --git a/ScStwLibraries/sources/scstwsoundplayer.cpp b/ScStwLibraries/sources/scstwsoundplayer.cpp index 79b82d0..be694c5 100644 --- a/ScStwLibraries/sources/scstwsoundplayer.cpp +++ b/ScStwLibraries/sources/scstwsoundplayer.cpp @@ -76,7 +76,7 @@ bool ScStwSoundPlayer::play(ScStwSoundPlayer::StartSound sound, double volume, d *timeOfStart = this->playingStartedAt; } - if(sound < 2) + if(sound < Start) return this->waitForSoundFinish(); return true; @@ -90,7 +90,7 @@ bool ScStwSoundPlayer::cancel(double volume) { this->soundEffect->stop(); this->waitLoop->quit(); - if(this->currentlyPlayingSound != 2) + if(this->currentlyPlayingSound != Start) return true; // update volume From ef8ceff27ef215d94ca2323d2121e95cf2c5e428 Mon Sep 17 00:00:00 2001 From: Dorian Zedler Date: Fri, 2 Oct 2020 19:53:07 +0200 Subject: [PATCH 2/2] - some bug fixes - added race details --- ScStwLibraries/headers/ScStw.hpp | 5 ++-- ScStwLibraries/headers/scstwrace.h | 4 +++ ScStwLibraries/sources/scstwrace.cpp | 32 +++++++++++++++++++-- ScStwLibraries/sources/scstwsoundplayer.cpp | 17 ----------- 4 files changed, 37 insertions(+), 21 deletions(-) diff --git a/ScStwLibraries/headers/ScStw.hpp b/ScStwLibraries/headers/ScStw.hpp index fac3f33..a05be82 100644 --- a/ScStwLibraries/headers/ScStw.hpp +++ b/ScStwLibraries/headers/ScStw.hpp @@ -62,7 +62,8 @@ public: TimersChanged = 9001, ExtensionsChanged = 9002, CurrentStartDelayChanged = 9003, /*, ProfilesChanged*/ - SettingChanged = 9004 + SettingChanged = 9004, + RaceDetailsChanged = 9005 }; Q_ENUM(SignalKey) @@ -82,7 +83,7 @@ public: CancelRaceCommand = 1003, GetRaceStateCommand = 2000, - GetNextStartActionCommand = 2005, + GetRaceDetailsCommand = 2001, GetExtensionsCommand = 2006, GetTimersCommand = 2007, GetCurrentStartDelayCommand = 2009, diff --git a/ScStwLibraries/headers/scstwrace.h b/ScStwLibraries/headers/scstwrace.h index 80906da..779bc86 100644 --- a/ScStwLibraries/headers/scstwrace.h +++ b/ScStwLibraries/headers/scstwrace.h @@ -52,6 +52,7 @@ class ScStwRace : public QObject Q_PROPERTY(RaceState state READ getState NOTIFY stateChanged) Q_PROPERTY(QVariantList timers READ getTimerDetailList NOTIFY timersChanged) Q_PROPERTY(QVariantList currentStartDelay READ getCurrentStartDelay NOTIFY currentStartDelayChanged) + Q_PROPERTY(QVariantMap details READ getDetails NOTIFY detailsChanged) public: explicit ScStwRace(QObject *parent = nullptr); @@ -133,6 +134,7 @@ public slots: virtual QVariantList getCurrentStartDelay(); QList getTimers(); QVariantList getTimerDetailList(); + QVariantMap getDetails(); protected slots: @@ -152,6 +154,7 @@ private slots: bool isStarting(); bool isReadyForNextState(); + void handleTimerReadyStateChange(ScStwTimer::ReadyState readyState); signals: void startTimers(); @@ -160,6 +163,7 @@ signals: void stateChanged(RaceState state); void currentStartDelayChanged(); void timersChanged(); + void detailsChanged(); }; diff --git a/ScStwLibraries/sources/scstwrace.cpp b/ScStwLibraries/sources/scstwrace.cpp index f90f0de..c9ebb3d 100644 --- a/ScStwLibraries/sources/scstwrace.cpp +++ b/ScStwLibraries/sources/scstwrace.cpp @@ -32,6 +32,9 @@ ScStwRace::ScStwRace(QObject *parent) : QObject(parent) connect(this->startDelayTimer, &QTimer::timeout, this->startWaitLoop, &QEventLoop::quit); + connect(this, &ScStwRace::currentStartDelayChanged, this, &ScStwRace::detailsChanged); + connect(this, &ScStwRace::timersChanged, this, &ScStwRace::detailsChanged); + // write default settings this->startSoundSettings.insert(ScStwSoundPlayer::Start, {{"Enabled", true}, {"Delay", 1}}); this->writeStartSoundSetting(ScStwSoundPlayer::AtYourMarks, false, 0); @@ -198,7 +201,8 @@ int ScStwRace::handleFalseStart() { } this->setState(STOPPED); - this->soundPlayer->cancel(this->soundVolume); + this->soundPlayer->cancel(); + this->soundPlayer->play(ScStwSoundPlayer::FalseStart, this->soundVolume); return returnCode; } @@ -597,10 +601,11 @@ bool ScStwRace::addTimer(ScStwTimer *timer) { this->timers.append(timer); connect(timer, &ScStwTimer::stateChanged, this, &ScStwRace::refreshTimerStates); - connect(timer, &ScStwTimer::wantsToBeDisabledChanged, this, &ScStwRace::handleTimerWantsToBeDisabledChange); connect(timer, &ScStwTimer::stateChanged, this, &ScStwRace::timersChanged); + connect(timer, &ScStwTimer::wantsToBeDisabledChanged, this, &ScStwRace::handleTimerWantsToBeDisabledChange); connect(timer, &ScStwTimer::reactionTimeChanged, this, &ScStwRace::timersChanged); connect(timer, &ScStwTimer::readyStateChanged, this->startWaitLoop, &QEventLoop::quit); + connect(timer, &ScStwTimer::readyStateChanged, this, &ScStwRace::handleTimerReadyStateChange); if(this->competitionMode && timer->getState() == ScStwTimer::DISABLED) timer->setDisabled(false); @@ -628,12 +633,35 @@ QVariantList ScStwRace::getTimerDetailList() { tmpTimer.insert("reactionTime", timer->getReactionTime()); tmpTimer.insert("text", timer->getText()); tmpTimer.insert("letter", timer->getLetter()); + tmpTimer.insert("readyState", timer->getReadyState()); tmpTimers.append(tmpTimer); } return tmpTimers; } +QVariantMap ScStwRace::getDetails() { + QVariantMap tmpDetails; + + tmpDetails.insert("timers", this->getTimerDetailList()); + tmpDetails.insert("currentStartDelay", this->getCurrentStartDelay()); + tmpDetails.insert("competitionMode", this->competitionMode); + tmpDetails.insert("readySoundEnabled", this->startSoundSettings[ScStwSoundPlayer::Ready]["Enabled"].toBool()); + + if(this->state == WAITING) + tmpDetails.insert("isReady", this->isReadyForNextState()); + + return tmpDetails; +} + bool ScStwRace::isStarting() { return this->state == PREPAIRING || this->state == WAITING || this->state == STARTING; } + +void ScStwRace::handleTimerReadyStateChange(ScStwTimer::ReadyState readyState) { + Q_UNUSED(readyState) + + // only continue if the current state is waiting + if(this->state == WAITING) + emit this->timersChanged(); +} diff --git a/ScStwLibraries/sources/scstwsoundplayer.cpp b/ScStwLibraries/sources/scstwsoundplayer.cpp index be694c5..07de6f0 100644 --- a/ScStwLibraries/sources/scstwsoundplayer.cpp +++ b/ScStwLibraries/sources/scstwsoundplayer.cpp @@ -39,9 +39,6 @@ bool ScStwSoundPlayer::play(ScStwSoundPlayer::StartSound sound, double volume, d if(!this->soundFiles.contains(sound)) return false; - if(sound > Start || sound < AtYourMarks) - return false; - // stop playback if(this->soundEffect->isPlaying()) this->soundEffect->stop(); @@ -89,20 +86,6 @@ bool ScStwSoundPlayer::cancel(double volume) { // stop playback this->soundEffect->stop(); this->waitLoop->quit(); - - if(this->currentlyPlayingSound != Start) - return true; - - // update volume - this->soundEffect->setVolume(volume); - - // load - this->soundEffect->setSource(this->soundFiles[FalseStart]["path"].toString()); - - // play - this->soundEffect->play(); - - return true; } bool ScStwSoundPlayer::waitForSoundFinish(double *timeOfStop) {