diff --git a/interface/src/scripting/RecordingScriptingInterface.cpp b/interface/src/scripting/RecordingScriptingInterface.cpp index 4ca3881e8d..d549de84b2 100644 --- a/interface/src/scripting/RecordingScriptingInterface.cpp +++ b/interface/src/scripting/RecordingScriptingInterface.cpp @@ -47,19 +47,19 @@ RecordingScriptingInterface::RecordingScriptingInterface() { connect(audioClient.data(), &AudioClient::inputReceived, this, &RecordingScriptingInterface::processAudioInput); } -bool RecordingScriptingInterface::isPlaying() { +bool RecordingScriptingInterface::isPlaying() const { return _player->isPlaying(); } -bool RecordingScriptingInterface::isPaused() { +bool RecordingScriptingInterface::isPaused() const { return _player->isPaused(); } -float RecordingScriptingInterface::playerElapsed() { +float RecordingScriptingInterface::playerElapsed() const { return _player->position(); } -float RecordingScriptingInterface::playerLength() { +float RecordingScriptingInterface::playerLength() const { return _player->length(); } @@ -103,6 +103,10 @@ void RecordingScriptingInterface::setPlayerAudioOffset(float audioOffset) { } void RecordingScriptingInterface::setPlayerTime(float time) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setPlayerTime", Qt::BlockingQueuedConnection, Q_ARG(float, time)); + return; + } _player->seek(time); } @@ -130,23 +134,27 @@ void RecordingScriptingInterface::setPlayerUseSkeletonModel(bool useSkeletonMode _useSkeletonModel = useSkeletonModel; } -void RecordingScriptingInterface::play() { - _player->play(); -} - void RecordingScriptingInterface::pausePlayer() { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "pausePlayer", Qt::BlockingQueuedConnection); + return; + } _player->pause(); } void RecordingScriptingInterface::stopPlaying() { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "stopPlaying", Qt::BlockingQueuedConnection); + return; + } _player->stop(); } -bool RecordingScriptingInterface::isRecording() { +bool RecordingScriptingInterface::isRecording() const { return _recorder->isRecording(); } -float RecordingScriptingInterface::recorderElapsed() { +float RecordingScriptingInterface::recorderElapsed() const { return _recorder->position(); } diff --git a/interface/src/scripting/RecordingScriptingInterface.h b/interface/src/scripting/RecordingScriptingInterface.h index 510a4b6898..27193e6f9a 100644 --- a/interface/src/scripting/RecordingScriptingInterface.h +++ b/interface/src/scripting/RecordingScriptingInterface.h @@ -25,12 +25,17 @@ public: RecordingScriptingInterface(); public slots: - bool isPlaying(); - bool isPaused(); - float playerElapsed(); - float playerLength(); void loadRecording(const QString& filename); + void startPlaying(); + void pausePlayer(); + void stopPlaying(); + bool isPlaying() const; + bool isPaused() const; + + float playerElapsed() const; + float playerLength() const; + void setPlayerVolume(float volume); void setPlayerAudioOffset(float audioOffset); void setPlayerTime(float time); @@ -40,13 +45,13 @@ public slots: void setPlayerUseAttachments(bool useAttachments); void setPlayerUseHeadModel(bool useHeadModel); void setPlayerUseSkeletonModel(bool useSkeletonModel); - void play(); - void pausePlayer(); - void stopPlaying(); - bool isRecording(); - float recorderElapsed(); + void startRecording(); void stopRecording(); + bool isRecording() const; + + float recorderElapsed() const; + void saveRecording(const QString& filename); void loadLastRecording(); diff --git a/libraries/recording/src/recording/Deck.cpp b/libraries/recording/src/recording/Deck.cpp index e52fcc16e6..6f624db191 100644 --- a/libraries/recording/src/recording/Deck.cpp +++ b/libraries/recording/src/recording/Deck.cpp @@ -8,6 +8,8 @@ #include "Deck.h" +#include + #include #include @@ -101,9 +103,13 @@ float Deck::position() const { } static const Frame::Time MIN_FRAME_WAIT_INTERVAL = Frame::secondsToFrameTime(0.001f); -static const Frame::Time MAX_FRAME_PROCESSING_TIME = Frame::secondsToFrameTime(0.002f); +static const Frame::Time MAX_FRAME_PROCESSING_TIME = Frame::secondsToFrameTime(0.004f); void Deck::processFrames() { + if (qApp->thread() != QThread::currentThread()) { + qWarning() << "Processing frames must only happen on the main thread."; + return; + } Locker lock(_mutex); if (_pause) { return; @@ -115,10 +121,17 @@ void Deck::processFrames() { // FIXME add code to start dropping frames if we fall behind. // Alternatively, add code to cache frames here and then process only the last frame of a given type // ... the latter will work for Avatar, but not well for audio I suspect. + bool overLimit = false; for (nextClip = getNextClip(); nextClip; nextClip = getNextClip()) { auto currentPosition = Frame::frameTimeFromEpoch(_startEpoch); if ((currentPosition - startingPosition) >= MAX_FRAME_PROCESSING_TIME) { qCWarning(recordingLog) << "Exceeded maximum frame processing time, breaking early"; +#ifdef WANT_RECORDING_DEBUG + qCDebug(recordingLog) << "Starting: " << currentPosition; + qCDebug(recordingLog) << "Current: " << startingPosition; + qCDebug(recordingLog) << "Trigger: " << triggerPosition; +#endif + overLimit = true; break; } @@ -150,9 +163,19 @@ void Deck::processFrames() { // If we have more clip frames available, set the timer for the next one _position = Frame::frameTimeFromEpoch(_startEpoch); - auto nextFrameTime = nextClip->positionFrameTime(); - auto interval = Frame::frameTimeToMilliseconds(nextFrameTime - _position); - _timer.singleShot(interval, [this] { + int nextInterval = 1; + if (!overLimit) { + auto nextFrameTime = nextClip->positionFrameTime(); + nextInterval = (int)Frame::frameTimeToMilliseconds(nextFrameTime - _position); +#ifdef WANT_RECORDING_DEBUG + qCDebug(recordingLog) << "Now " << _position; + qCDebug(recordingLog) << "Next frame time " << nextInterval; +#endif + } +#ifdef WANT_RECORDING_DEBUG + qCDebug(recordingLog) << "Setting timer for next processing " << nextInterval; +#endif + _timer.singleShot(nextInterval, [this] { processFrames(); }); }