diff options
author | Chris Xiong <chirs241097@gmail.com> | 2020-12-25 01:09:18 +0800 |
---|---|---|
committer | Chris Xiong <chirs241097@gmail.com> | 2020-12-25 01:11:58 +0800 |
commit | 5e6e4615264214cf86cd74d63938c503fd36b74d (patch) | |
tree | cbda1f7c9376a140ce81ff2439f77ef75d353ddd | |
parent | 14e01896cae2cbc7bf9aae37660e837f787ea20a (diff) | |
download | QMidiPlayer-5e6e4615264214cf86cd74d63938c503fd36b74d.tar.xz |
Proper event-based playback interruption.
Also fixed random pauses after seeking.
This should address everything left over by 64fd118e.
-rw-r--r-- | core/qmpmidiplay.cpp | 27 | ||||
-rw-r--r-- | core/qmpmidiplay.hpp | 5 | ||||
-rw-r--r-- | visualization/renderer/CMakeLists.txt | 1 |
3 files changed, 23 insertions, 10 deletions
diff --git a/core/qmpmidiplay.cpp b/core/qmpmidiplay.cpp index aeb39be..7e35b95 100644 --- a/core/qmpmidiplay.cpp +++ b/core/qmpmidiplay.cpp @@ -242,21 +242,21 @@ void CMidiPlayer::playEvents() double correction = (getTick() - ttick) * dpt - (b - ttime).count(); if (correction > 0) correction = 0; - if (ns_sleep + correction > 2e8) + if (ns_sleep + correction > 2.5e8) { high_resolution_clock::time_point t = high_resolution_clock::now(); uint64_t tts = uint64_t(ns_sleep + correction); - while (tts > 2e8 && !tcstop && midiReaders) + std::unique_lock<std::mutex> lock(intmtx); + std::cv_status intr = intcv.wait_for(lock, std::chrono::nanoseconds(uint64_t(ns_sleep + correction - 5e7))); + if (intr == std::cv_status::no_timeout) { -#ifdef _WIN32 - w32usleep(2e5); -#else - std::this_thread::sleep_for(std::chrono::nanoseconds(uint64_t(2e8))); -#endif - tts -= uint64_t((high_resolution_clock::now() - t).count()); - t = high_resolution_clock::now(); + if (tcstop) + { + break; + } } - if (tts > 0 && !tcstop && midiReaders) + tts -= uint64_t((high_resolution_clock::now() - t).count()); + if (tts > 0 && intr == std::cv_status::timeout && !tcstop && midiReaders) { #ifdef _WIN32 w32usleep(tts / 1000); @@ -442,6 +442,7 @@ void CMidiPlayer::playerDeinit() { tceptr = 0; tcstop = true; + interrupt(); tcpaused = 0; delete midiFile; midiFile = nullptr; @@ -470,6 +471,7 @@ void CMidiPlayer::setTCeptr(uint32_t ep, uint32_t st) if (ep == ecnt) tcstop = true; else tceptr = ep; + this->interrupt(); for (int i = 0; i < 16; ++i) { qmpMidiOutDevice *dest = mididev[mappedoutput[i]].dev; @@ -560,6 +562,11 @@ void CMidiPlayer::setTCpaused(uint32_t ps) { tcpaused = ps; } + +void CMidiPlayer::interrupt() +{ + intcv.notify_one(); +} uint32_t CMidiPlayer::isFinished() { return finished; diff --git a/core/qmpmidiplay.hpp b/core/qmpmidiplay.hpp index b6a40d9..a4245ae 100644 --- a/core/qmpmidiplay.hpp +++ b/core/qmpmidiplay.hpp @@ -3,7 +3,9 @@ #define QMPMIDIPLAY_H #include <cstring> #include <cstdlib> +#include <condition_variable> #include <chrono> +#include <mutex> #include <unordered_map> #include <tuple> #include <utility> @@ -70,6 +72,8 @@ private: //raw tempo, timesig num., timesig den., division, keysig //thread control uint32_t tceptr, tcpaused, ct; + std::mutex intmtx; + std::condition_variable intcv; bool tcstop; uint32_t finished, resumed; uint32_t pbr[16], pbv[16]; @@ -121,6 +125,7 @@ public: void setTCeptr(uint32_t ep, uint32_t st); uint32_t getTCpaused(); void setTCpaused(uint32_t ps); + void interrupt(); uint32_t isFinished(); bool stopFlag(); void setResumed(); diff --git a/visualization/renderer/CMakeLists.txt b/visualization/renderer/CMakeLists.txt index bbd3daf..106d453 100644 --- a/visualization/renderer/CMakeLists.txt +++ b/visualization/renderer/CMakeLists.txt @@ -21,6 +21,7 @@ target_link_libraries(qmpvisrender Qt5::Core qmpcore ${CMAKE_DL_LIBS} + ${CMAKE_THREAD_LIBS_INIT} ) if(WIN32) |