some more error handling for sound playing
This commit is contained in:
parent
6709a1fd2b
commit
e4700cd355
5 changed files with 64 additions and 32 deletions
|
@ -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();
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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) {
|
||||
|
|
Reference in a new issue