|
@@ -0,0 +1,87 @@
|
|
|
+#include "Clock.h"
|
|
|
+
|
|
|
+namespace midi {
|
|
|
+
|
|
|
+Clock::Clock()
|
|
|
+ : bpm(60), running(false)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+unsigned int Clock::getBpm()
|
|
|
+{
|
|
|
+ bpm_mutex.lock();
|
|
|
+ bpm_type b = bpm;
|
|
|
+ bpm_mutex.unlock();
|
|
|
+ return b;
|
|
|
+}
|
|
|
+
|
|
|
+void Clock::setBpm(bpm_type b)
|
|
|
+{
|
|
|
+ if(b == 0) {
|
|
|
+ throw "bpm may not be 0.";
|
|
|
+ }
|
|
|
+ bpm_mutex.lock();
|
|
|
+ bpm = b;
|
|
|
+ bpm_mutex.unlock();
|
|
|
+}
|
|
|
+
|
|
|
+Clock::duration Clock::getTickInterval()
|
|
|
+{
|
|
|
+ Clock::duration minute = std::chrono::duration_cast<Clock::duration>(
|
|
|
+ std::chrono::minutes(1)
|
|
|
+ );
|
|
|
+ return minute / getBpm();
|
|
|
+}
|
|
|
+
|
|
|
+void Clock::start()
|
|
|
+{
|
|
|
+ if(isRunning()) {
|
|
|
+ throw "already running";
|
|
|
+ }
|
|
|
+ setRunning(true);
|
|
|
+ stopTickThread = false;
|
|
|
+ lastTickTime = time_point(); // epoch
|
|
|
+ tickThread = std::thread(&Clock::run, this);
|
|
|
+}
|
|
|
+
|
|
|
+void Clock::stop()
|
|
|
+{
|
|
|
+ if(!isRunning()) {
|
|
|
+ throw "not running";
|
|
|
+ }
|
|
|
+ tickThread.detach();
|
|
|
+ stopTickThread = true;
|
|
|
+}
|
|
|
+
|
|
|
+bool Clock::isRunning()
|
|
|
+{
|
|
|
+ running_mutex.lock();
|
|
|
+ bool r = running;
|
|
|
+ running_mutex.unlock();
|
|
|
+ return r;
|
|
|
+}
|
|
|
+
|
|
|
+void Clock::tick()
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+void Clock::run()
|
|
|
+{
|
|
|
+ while(!stopTickThread) {
|
|
|
+ if((now() - lastTickTime) >= getTickInterval()) {
|
|
|
+ lastTickTime = now();
|
|
|
+ tick();
|
|
|
+ }
|
|
|
+ std::this_thread::sleep_for(std::chrono::microseconds(1000));
|
|
|
+ }
|
|
|
+ setRunning(false);
|
|
|
+}
|
|
|
+
|
|
|
+void Clock::setRunning(bool r)
|
|
|
+{
|
|
|
+ running_mutex.lock();
|
|
|
+ running = r;
|
|
|
+ running_mutex.unlock();
|
|
|
+}
|
|
|
+
|
|
|
+};
|