aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Chris Xiong <chirs241097@gmail.com> 2020-12-25 01:09:18 +0800
committerGravatar Chris Xiong <chirs241097@gmail.com> 2020-12-25 01:11:58 +0800
commit5e6e4615264214cf86cd74d63938c503fd36b74d (patch)
treecbda1f7c9376a140ce81ff2439f77ef75d353ddd
parent14e01896cae2cbc7bf9aae37660e837f787ea20a (diff)
downloadQMidiPlayer-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.cpp27
-rw-r--r--core/qmpmidiplay.hpp5
-rw-r--r--visualization/renderer/CMakeLists.txt1
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)