Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
a46e916999
12 changed files with 102 additions and 194 deletions
|
@ -1,20 +1,41 @@
|
||||||
!isEmpty(SCSTWLIBRARIES_LIB):error("ScStwLibraries.pri already included")
|
!isEmpty(SCSTWLIBRARIES_LIB):error("ScStwLibraries.pri already included")
|
||||||
SCSTWLIBRARIES_LIB = 1
|
SCSTWLIBRARIES_LIB = 1
|
||||||
|
|
||||||
#DEPENDS
|
ScStwLibraries_QML {
|
||||||
CONFIG(release, debug|release): {
|
QT += qml quickcontrols2
|
||||||
SCSTWLIBRARIES_LIB_OUTPUT_DIR="$$PWD/build/release"
|
DEFINES += ScStwLibraries_QML
|
||||||
} else {
|
|
||||||
SCSTWLIBRARIES_LIB_OUTPUT_DIR="$$PWD/build/debug"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unix:LIBS += -L$$SCSTWLIBRARIES_LIB_OUTPUT_DIR -lScStwLibraries
|
ScStwLibraries_ClientLibs {
|
||||||
|
DEFINES += ScStwLibraries_ClientLibs
|
||||||
win32:LIBS += -L$$SCSTWLIBRARIES_LIB_OUTPUT_DIR -lScStwLibraries1
|
|
||||||
|
|
||||||
android {
|
|
||||||
ANDROID_EXTRA_LIBS += $$SCSTWLIBRARIES_LIB_OUTPUT_DIR/libScStwLibraries.so
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INCLUDEPATH += "$$PWD"
|
INCLUDEPATH += $$PWD/headers $$PWD
|
||||||
INCLUDEPATH += "$$PWD"/headers
|
|
||||||
|
SOURCES += \
|
||||||
|
$$PWD/sources/ScStw.cpp \
|
||||||
|
$$PWD/sources/scstwsoundplayer.cpp \
|
||||||
|
$$PWD/sources/scstwlibraries.cpp \
|
||||||
|
$$PWD/sources/scstwrace.cpp \
|
||||||
|
$$PWD/sources/scstwtimer.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
$$PWD/headers/ScStw.hpp \
|
||||||
|
$$PWD/headers/ScStwLibraries_global.h \
|
||||||
|
$$PWD/headers/scstwlibraries.h \
|
||||||
|
$$PWD/headers/scstwrace.h \
|
||||||
|
$$PWD/headers/scstwsoundplayer.h \
|
||||||
|
$$PWD/headers/scstwtimer.h
|
||||||
|
|
||||||
|
ScStwLibraries_ClientLibs {
|
||||||
|
SOURCES += \
|
||||||
|
$$PWD/sources/scstwclient.cpp
|
||||||
|
$$PWD/sources/scstwremotemonitorrace.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
$$PWD/headers/scstwclient.h \
|
||||||
|
$$PWD/headers/scstwremotemonitorrace.h
|
||||||
|
}
|
||||||
|
|
||||||
|
RESOURCES += \
|
||||||
|
$$PWD/resources/ScStwLibrariesShared.qrc
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
QT -= gui
|
|
||||||
QT += network multimedia quick
|
|
||||||
|
|
||||||
CONFIG(contains(QMAKE_LFLAGS_CONSOLE)){
|
|
||||||
message("this is console")
|
|
||||||
}
|
|
||||||
|
|
||||||
TEMPLATE = lib
|
|
||||||
DEFINES += SCSTWLIBRARIES_LIBRARY
|
|
||||||
|
|
||||||
CONFIG += c++11
|
|
||||||
|
|
||||||
# The following define makes your compiler emit warnings if you use
|
|
||||||
# any Qt feature that has been marked deprecated (the exact warnings
|
|
||||||
# depend on your compiler). Please consult the documentation of the
|
|
||||||
# deprecated API in order to know how to port your code away from it.
|
|
||||||
DEFINES += QT_DEPRECATED_WARNINGS
|
|
||||||
|
|
||||||
# You can also make your code fail to compile if it uses deprecated APIs.
|
|
||||||
# In order to do so, uncomment the following line.
|
|
||||||
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
|
||||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
|
||||||
|
|
||||||
SOURCES += \
|
|
||||||
sources/ScStw.cpp \
|
|
||||||
sources/scstwclient.cpp \
|
|
||||||
sources/scstwlibraries.cpp \
|
|
||||||
sources/scstwrace.cpp \
|
|
||||||
sources/scstwremotemonitorrace.cpp \
|
|
||||||
sources/scstwsoundplayer.cpp \
|
|
||||||
sources/scstwtimer.cpp
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
headers/ScStw.hpp \
|
|
||||||
headers/ScStwLibraries_global.h \
|
|
||||||
headers/scstwlibraries.h \
|
|
||||||
headers/scstwrace.h \
|
|
||||||
headers/scstwclient.h \
|
|
||||||
headers/scstwremotemonitorrace.h \
|
|
||||||
headers/scstwsoundplayer.h \
|
|
||||||
headers/scstwtimer.h
|
|
||||||
|
|
||||||
RESOURCES += \
|
|
||||||
resources/ScStwLibrariesShared.qrc
|
|
||||||
|
|
||||||
DISTFILES +=
|
|
||||||
|
|
||||||
#DEPENDS
|
|
||||||
CONFIG(release, debug|release): {
|
|
||||||
DESTDIR="$$PWD/build/release"
|
|
||||||
} else {
|
|
||||||
DESTDIR="$$PWD/build/debug"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Default rules for deployment.
|
|
||||||
target.path = /usr/local/lib
|
|
||||||
!isEmpty(target.path): INSTALLS += target
|
|
|
@ -150,6 +150,8 @@ public:
|
||||||
AccessDeniedError = 401,
|
AccessDeniedError = 401,
|
||||||
NoSessionActiveError = 408,
|
NoSessionActiveError = 408,
|
||||||
|
|
||||||
|
UpdateFailedError = 500,
|
||||||
|
|
||||||
Error = 900,
|
Error = 900,
|
||||||
NotConnectedError = 910,
|
NotConnectedError = 910,
|
||||||
TimeoutError = 911,
|
TimeoutError = 911,
|
||||||
|
|
|
@ -131,15 +131,7 @@ public slots:
|
||||||
*/
|
*/
|
||||||
QVariantMap sendCommand(int header, QJsonValue data = "", int timeout = 3000);
|
QVariantMap sendCommand(int header, QJsonValue data = "", int timeout = 3000);
|
||||||
|
|
||||||
/*! updater functions */
|
/*! helper functions */
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Function to check wether the firmware of the base station is up-to-date
|
|
||||||
* \see getFirmwareVersion()
|
|
||||||
* \see updateFirmware()
|
|
||||||
* \return true or false
|
|
||||||
*/
|
|
||||||
bool isFirmwareUpToDate();
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Function to write a setting on the base station
|
* \brief Function to write a setting on the base station
|
||||||
|
|
|
@ -20,10 +20,15 @@
|
||||||
#define SCSTWLIBRARIES_H
|
#define SCSTWLIBRARIES_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#ifdef ScStwLibraries_QML
|
||||||
#include <QQmlApplicationEngine>
|
#include <QQmlApplicationEngine>
|
||||||
#include "scstwclient.h"
|
#endif
|
||||||
#include "scstwtimer.h"
|
#include "scstwtimer.h"
|
||||||
#include "scstwrace.h"
|
#include "scstwrace.h"
|
||||||
|
#ifdef ScStwLibraries_ClientLibs
|
||||||
|
#include "scstwremotemonitorrace.h"
|
||||||
|
#include "scstwclient.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
class ScStwLibraries : public QObject
|
class ScStwLibraries : public QObject
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <QEventLoop>
|
#include <QEventLoop>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
#include <QSoundEffect>
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief The ScStwSoundPlayer class is used for ultra low latency sound playback of the speed clibing start tones and commands
|
* \brief The ScStwSoundPlayer class is used for ultra low latency sound playback of the speed clibing start tones and commands
|
||||||
|
@ -46,18 +47,14 @@ private:
|
||||||
* 0: AtYourMarksSound
|
* 0: AtYourMarksSound
|
||||||
* 1: ReadySound
|
* 1: ReadySound
|
||||||
* 2: StartSound
|
* 2: StartSound
|
||||||
|
* 3: FalseStartSound
|
||||||
*/
|
*/
|
||||||
QMap<int, QFile*> soundFiles;
|
QMap<int, QVariantMap> soundFiles;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Containng the false start sound file
|
* \brief The sound effect object
|
||||||
*/
|
*/
|
||||||
QFile *falseStartSoundFile;
|
QSoundEffect *soundEffect;
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief The audio output object
|
|
||||||
*/
|
|
||||||
QAudioOutput *audioOutput;
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief The QEventLoop used to wait for the sound to finish
|
* \brief The QEventLoop used to wait for the sound to finish
|
||||||
|
@ -74,6 +71,11 @@ private:
|
||||||
*/
|
*/
|
||||||
int currentlyPlayingAction;
|
int currentlyPlayingAction;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Holds the time the playback started at
|
||||||
|
*/
|
||||||
|
double playingStartedAt;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -104,12 +106,6 @@ public slots:
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Handle a state change of the audio output
|
|
||||||
* \param newState the new state of the audio output
|
|
||||||
*/
|
|
||||||
void handleStateChanged(QAudio::State newState);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,10 +1,10 @@
|
||||||
<RCC>
|
<RCC>
|
||||||
<qresource prefix="/">
|
<qresource prefix="/">
|
||||||
<file>ScStwBasestation.sb64</file>
|
|
||||||
<file>sound/AtYourMarksSound.wav</file>
|
<file>sound/AtYourMarksSound.wav</file>
|
||||||
<file>sound/IFSC frequenzy and duration conform false start sound.wav</file>
|
<file>sound/IFSC frequenzy and duration conform false start sound.wav</file>
|
||||||
<file>sound/ReadySound.wav</file>
|
<file>sound/ReadySound.wav</file>
|
||||||
<file>sound/FalseStartSound.wav</file>
|
<file>sound/FalseStartSound.wav</file>
|
||||||
<file>sound/StartsignalSound.wav</file>
|
<file>sound/StartsignalSound.wav</file>
|
||||||
|
<file>sound/StartsignalSoundExtended.wav</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
BIN
ScStwLibraries/resources/sound/StartsignalSoundExtended.wav
Normal file
BIN
ScStwLibraries/resources/sound/StartsignalSoundExtended.wav
Normal file
Binary file not shown.
|
@ -106,7 +106,7 @@ bool ScStwClient::init() {
|
||||||
this->firmwareVersion = initResponse["data"].toMap()["firmwareVersion"].toString();
|
this->firmwareVersion = initResponse["data"].toMap()["firmwareVersion"].toString();
|
||||||
this->timeOffset = initResponse["data"].toMap()["time"].toDouble() - this->date->currentMSecsSinceEpoch();
|
this->timeOffset = initResponse["data"].toMap()["time"].toDouble() - this->date->currentMSecsSinceEpoch();
|
||||||
|
|
||||||
qDebug() << "[INFO][BaseStation] Init done! firmware: version: " << this->firmwareVersion << " up-to-date: " << this->isFirmwareUpToDate() << " time offset: " << this->timeOffset;
|
qDebug() << "[INFO][BaseStation] Init done! firmware: " << this->firmwareVersion << " time offset: " << this->timeOffset;
|
||||||
|
|
||||||
this->setState(CONNECTED);
|
this->setState(CONNECTED);
|
||||||
return true;
|
return true;
|
||||||
|
@ -188,6 +188,8 @@ QVariantMap ScStwClient::sendCommand(int header, QJsonValue data, int timeout, b
|
||||||
//wait for an answer to finish (programm gets stuck in here)
|
//wait for an answer to finish (programm gets stuck in here)
|
||||||
loop->exec();
|
loop->exec();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool replyFound = false;
|
bool replyFound = false;
|
||||||
|
|
||||||
// find reply and delete the request from waiting list
|
// find reply and delete the request from waiting list
|
||||||
|
@ -386,22 +388,6 @@ void ScStwClient::handleSignal(QVariantMap data) {
|
||||||
emit this->gotSignal(signalKey, data["data"]);
|
emit this->gotSignal(signalKey, data["data"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------
|
|
||||||
// --- updater functions ---
|
|
||||||
// -------------------------
|
|
||||||
|
|
||||||
bool ScStwClient::isFirmwareUpToDate() {
|
|
||||||
QString file = ":/ScStwBasestation.sb64";
|
|
||||||
QFile f(file);
|
|
||||||
if (!f.open(QFile::ReadOnly)) return false;
|
|
||||||
QString fileContents = f.readAll();
|
|
||||||
|
|
||||||
QString newFirmwareVersion = fileContents.split("<VER>")[1].split("</VER>")[0];
|
|
||||||
QString currentFirmwareVersion = this->firmwareVersion;
|
|
||||||
|
|
||||||
return ScStw::firmwareCompare(newFirmwareVersion, currentFirmwareVersion) <= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------
|
// ------------------------
|
||||||
// --- helper functions ---
|
// --- helper functions ---
|
||||||
// ------------------------
|
// ------------------------
|
||||||
|
|
|
@ -24,11 +24,16 @@ ScStwLibraries::ScStwLibraries(QObject *parent) : QObject(parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScStwLibraries::init() {
|
void ScStwLibraries::init() {
|
||||||
|
#ifdef ScStwLibraries_QML
|
||||||
qmlRegisterType<ScStw>("de.itsblue.ScStw", 2, 0, "ScStw");
|
qmlRegisterType<ScStw>("de.itsblue.ScStw", 2, 0, "ScStw");
|
||||||
qRegisterMetaType<ScStw::BaseStationSetting>("ScStw::BaseStationSetting");
|
qRegisterMetaType<ScStw::BaseStationSetting>("ScStw::BaseStationSetting");
|
||||||
qRegisterMetaType<ScStw::SocketCommand>("ScStw::SocketCommand");
|
qRegisterMetaType<ScStw::SocketCommand>("ScStw::SocketCommand");
|
||||||
|
|
||||||
qmlRegisterType<ScStwRace>("de.itsblue.ScStw", 2, 0, "ScStwRace");
|
qmlRegisterType<ScStwRace>("de.itsblue.ScStw", 2, 0, "ScStwRace");
|
||||||
qmlRegisterType<ScStwTimer>("de.itsblue.ScStw", 2, 0, "ScStwTimer");
|
qmlRegisterType<ScStwTimer>("de.itsblue.ScStw", 2, 0, "ScStwTimer");
|
||||||
|
|
||||||
|
#ifdef ScStwLibraries_ClientLibs
|
||||||
qmlRegisterType<ScStwClient>("de.itsblue.ScStw", 2, 0, "ScStwClient");
|
qmlRegisterType<ScStwClient>("de.itsblue.ScStw", 2, 0, "ScStwClient");
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,66 +23,57 @@ ScStwSoundPlayer::ScStwSoundPlayer(QObject *parent) : QObject(parent)
|
||||||
this->waitLoop = new QEventLoop(this);
|
this->waitLoop = new QEventLoop(this);
|
||||||
this->waitTimer = new QTimer(this);
|
this->waitTimer = new QTimer(this);
|
||||||
|
|
||||||
this->soundFiles.insert(0, new QFile(":/sound/AtYourMarksSound.wav", this));
|
this->soundFiles.insert(0, {{"path","qrc:/sound/AtYourMarksSound.wav"}, {"duration", 1000}});
|
||||||
this->soundFiles.insert(1, new QFile(":/sound/ReadySound.wav", this));
|
this->soundFiles.insert(1, {{"path","qrc:/sound/ReadySound.wav"}, {"duration", 570}});
|
||||||
this->soundFiles.insert(2, new QFile(":/sound/StartsignalSound.wav", this));
|
this->soundFiles.insert(2, {{"path","qrc:/sound/StartsignalSoundExtended.wav"}, {"duration", 3200}});
|
||||||
this->falseStartSoundFile = new QFile(":/sound/FalseStartSound.wav", this);
|
this->soundFiles.insert(3, {{"path","qrc:/sound/FalseStartSound.wav"}, {"duration", 2000}});
|
||||||
|
|
||||||
// init sound format
|
this->soundEffect = new QSoundEffect(this);
|
||||||
QAudioFormat format;
|
this->soundEffect->setLoopCount(1);
|
||||||
format.setSampleRate(44100);
|
|
||||||
format.setChannelCount(2);
|
|
||||||
format.setSampleSize(16);
|
|
||||||
format.setCodec("audio/pcm");
|
|
||||||
format.setByteOrder(QAudioFormat::LittleEndian);
|
|
||||||
format.setSampleType(QAudioFormat::SignedInt);
|
|
||||||
|
|
||||||
// check if format is valid
|
|
||||||
QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
|
|
||||||
if (!info.isFormatSupported(format)) {
|
|
||||||
qWarning() << "Raw audio format not supported by backend, cannot play audio.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->audioOutput = new QAudioOutput(format, this);
|
|
||||||
this->audioOutput->setCategory("media");
|
|
||||||
|
|
||||||
connect(this->audioOutput, SIGNAL(stateChanged(QAudio::State)), this, SLOT(handleStateChanged(QAudio::State)));
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScStwSoundPlayer::play(int action, double volume, double *timeOfStart) {
|
bool ScStwSoundPlayer::play(int action, double volume, double *timeOfStart) {
|
||||||
if(!this->soundFiles.contains(action))
|
if(!this->soundFiles.contains(action))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if(action > 2 || action < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
// stop playback
|
// stop playback
|
||||||
if(this->audioOutput->state() == QAudio::ActiveState)
|
if(this->soundEffect->isPlaying())
|
||||||
this->audioOutput->stop();
|
this->soundEffect->stop();
|
||||||
|
|
||||||
// update currently playing action
|
// update currently playing action
|
||||||
this->currentlyPlayingAction = action;
|
this->currentlyPlayingAction = action;
|
||||||
|
|
||||||
QFile *playbackFile = this->soundFiles[action];
|
// update volume
|
||||||
|
this->soundEffect->setVolume(volume);
|
||||||
|
|
||||||
// close soundfile
|
// load
|
||||||
if(playbackFile->isOpen())
|
this->soundEffect->setSource(this->soundFiles[action]["path"].toString());
|
||||||
playbackFile->close();
|
|
||||||
|
|
||||||
// open soundfile
|
// wait for the effect to load
|
||||||
if(!playbackFile->open(QFile::ReadOnly)) {
|
QEventLoop loop;
|
||||||
qWarning() << "[ERROR][SOUNDS] Could not open sound file " << action << " !!";
|
while(this->soundEffect->status() != QSoundEffect::Ready) {
|
||||||
return false;
|
QObject::connect(this->soundEffect, &QSoundEffect::statusChanged, &loop, &QEventLoop::quit);
|
||||||
|
loop.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
// update volume
|
|
||||||
this->audioOutput->setVolume(volume);
|
|
||||||
|
|
||||||
// start
|
// start
|
||||||
this->audioOutput->start(playbackFile);
|
this->soundEffect->play();
|
||||||
|
|
||||||
|
// emit a playback start
|
||||||
|
emit this->playbackStarted();
|
||||||
|
|
||||||
|
// save started at
|
||||||
|
this->playingStartedAt = QDateTime::currentMSecsSinceEpoch();
|
||||||
|
|
||||||
// pass the time of start if requested
|
// pass the time of start if requested
|
||||||
if(timeOfStart != nullptr) {
|
if(timeOfStart != nullptr) {
|
||||||
*timeOfStart = QDateTime::currentMSecsSinceEpoch() - (this->audioOutput->elapsedUSecs() / 1000);
|
*timeOfStart = this->playingStartedAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(action < 2)
|
if(action < 2)
|
||||||
|
@ -92,37 +83,30 @@ bool ScStwSoundPlayer::play(int action, double volume, double *timeOfStart) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScStwSoundPlayer::cancel(double volume) {
|
bool ScStwSoundPlayer::cancel(double volume) {
|
||||||
if(!QList<QAudio::State>{QAudio::ActiveState}.contains(this->audioOutput->state()) )
|
if(!this->soundEffect->isPlaying() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// stop playback
|
// stop playback
|
||||||
this->audioOutput->stop();
|
this->soundEffect->stop();
|
||||||
this->waitLoop->quit();
|
this->waitLoop->quit();
|
||||||
|
|
||||||
if(this->currentlyPlayingAction != 2)
|
if(this->currentlyPlayingAction != 2)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// close soundfile
|
|
||||||
if(this->falseStartSoundFile->isOpen())
|
|
||||||
this->falseStartSoundFile->close();
|
|
||||||
|
|
||||||
// open sound file
|
|
||||||
if(!this->falseStartSoundFile->open(QFile::ReadOnly)) {
|
|
||||||
qWarning() << "[ERROR][SOUNDS] Could not open false start sound file!!";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// update volume
|
// update volume
|
||||||
this->audioOutput->setVolume(volume);
|
this->soundEffect->setVolume(volume);
|
||||||
|
|
||||||
// start
|
// load
|
||||||
this->audioOutput->start(this->falseStartSoundFile);
|
this->soundEffect->setSource(this->soundFiles[3]["path"].toString());
|
||||||
|
|
||||||
|
// play
|
||||||
|
this->soundEffect->play();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScStwSoundPlayer::waitForSoundFinish(double *timeOfStop) {
|
bool ScStwSoundPlayer::waitForSoundFinish(double *timeOfStop) {
|
||||||
if(this->audioOutput->state() != QAudio::ActiveState)
|
if(!this->soundEffect->isPlaying())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// wait until the audio output reports the sound is over
|
// wait until the audio output reports the sound is over
|
||||||
|
@ -130,7 +114,7 @@ bool ScStwSoundPlayer::waitForSoundFinish(double *timeOfStop) {
|
||||||
|
|
||||||
// wait until the sound is actually over
|
// wait until the sound is actually over
|
||||||
// the timeOffset is the buffer time before the audio started!
|
// the timeOffset is the buffer time before the audio started!
|
||||||
int timeOffset = ((this->audioOutput->processedUSecs() - this->audioOutput->elapsedUSecs()) / 1000);
|
int timeOffset = this->soundFiles[this->currentlyPlayingAction]["duration"].toDouble() - (QDateTime::currentMSecsSinceEpoch() - playingStartedAt);
|
||||||
|
|
||||||
if(timeOffset > 0) {
|
if(timeOffset > 0) {
|
||||||
QTimer timer;
|
QTimer timer;
|
||||||
|
@ -140,34 +124,9 @@ bool ScStwSoundPlayer::waitForSoundFinish(double *timeOfStop) {
|
||||||
|
|
||||||
// calculate the point in time where the sound playback actually ended
|
// calculate the point in time where the sound playback actually ended
|
||||||
if(timeOfStop != nullptr) {
|
if(timeOfStop != nullptr) {
|
||||||
int latency = (this->audioOutput->processedUSecs() - this->audioOutput->elapsedUSecs()) / 1000;
|
int latency = this->playingStartedAt + this->soundFiles[this->currentlyPlayingAction]["duration"].toDouble();
|
||||||
*timeOfStop = QDateTime::currentMSecsSinceEpoch() - latency;
|
*timeOfStop = QDateTime::currentMSecsSinceEpoch() - latency;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScStwSoundPlayer::handleStateChanged(QAudio::State newState)
|
|
||||||
{
|
|
||||||
switch (newState) {
|
|
||||||
case QAudio::IdleState:
|
|
||||||
// Finished playing (no more data)
|
|
||||||
waitLoop->exit();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case QAudio::StoppedState:
|
|
||||||
// Stopped for other reasons
|
|
||||||
if (this->audioOutput->error() != QAudio::NoError) {
|
|
||||||
// Error handling
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case QAudio::ActiveState:
|
|
||||||
emit this->playbackStarted();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// ... other cases as appropriate
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Reference in a new issue