background thread + AlsaBridge skeleton v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Fri, 18 Dec 2020 23:19:32 +0100
branchv_0
changeset 2 f34476ab597f
parent 1 98274757fcf6
child 3 e238528eb19c
background thread + AlsaBridge skeleton
AlsaBridge.cpp
AlsaBridge.h
DJMFix.cpp
DJMFix.h
Makefile
djm-fix.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AlsaBridge.cpp	Fri Dec 18 23:19:32 2020 +0100
@@ -0,0 +1,56 @@
+/**
+ * DJM-Fix
+ * Copyright © 2020 František Kučera (Frantovo.cz, GlobalCode.info)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <iostream>
+
+#include "AlsaBridge.h"
+
+namespace djmfix {
+namespace alsa {
+
+class AlsaBridgeImpl : public AlsaBridge, private djmfix::MidiSender {
+private:
+	djmfix::DJMFix* djmFix;
+public:
+
+	AlsaBridgeImpl(djmfix::DJMFix* djmFix) : djmFix(djmFix) {
+		djmFix->setMidiSender(this);
+	}
+
+	virtual ~AlsaBridgeImpl() {
+		std::cerr << "~AlsaBridgeImpl()" << std::endl; // TODO: do not mess STDIO
+	}
+
+	virtual void start() override {
+		djmFix->start();
+	}
+
+	virtual void stop() override {
+		djmFix->stop();
+	}
+
+	virtual void send(MidiMessage midiMessage) override {
+		std::cerr << "AlsaBridgeImpl::send()" << std::endl; // TODO: do not mess STDIO
+	}
+
+};
+
+AlsaBridge* create(djmfix::DJMFix* djmFix) {
+	return new AlsaBridgeImpl(djmFix);
+}
+
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AlsaBridge.h	Fri Dec 18 23:19:32 2020 +0100
@@ -0,0 +1,35 @@
+/**
+ * DJM-Fix
+ * Copyright © 2020 František Kučera (Frantovo.cz, GlobalCode.info)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include "DJMFix.h"
+
+namespace djmfix {
+namespace alsa {
+
+class AlsaBridge {
+public:
+	virtual ~AlsaBridge() = default;
+	virtual void start() = 0;
+	virtual void stop() = 0;
+
+};
+
+AlsaBridge* create(djmfix::DJMFix* djmFix);
+
+}
+}
\ No newline at end of file
--- a/DJMFix.cpp	Fri Dec 18 21:35:36 2020 +0100
+++ b/DJMFix.cpp	Fri Dec 18 23:19:32 2020 +0100
@@ -15,6 +15,9 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 #include <iostream>
+#include <thread>
+#include <chrono>
+#include <stdexcept>
 
 #include "DJMFix.h"
 
@@ -22,34 +25,55 @@
 
 class DJMFixImpl : public DJMFix {
 private:
-	MidiSender midiSender;
-public:
+	MidiSender* midiSender;
+	std::thread keepAliveThread;
+	bool running = false;
+	bool stopped = false;
 
-	DJMFixImpl(MidiSender midiSender) : midiSender(midiSender) {
-		std::cerr << "DJMFixImpl()" << std::endl; // TODO: do not mess STDIO
+	void run() {
+		while (!stopped) {
+			std::cerr << "DJMFixImpl::run()" << std::endl; // TODO: do not mess STDIO
+			// TODO: send keep-alive messages
+			std::this_thread::sleep_for(std::chrono::milliseconds(200));
+		}
 	}
 
+public:
+
 	virtual ~DJMFixImpl() override {
 		std::cerr << "~DJMFixImpl()" << std::endl; // TODO: do not mess STDIO
+		if (running) stop();
+	}
+
+	void setMidiSender(MidiSender* midiSender) {
+		std::cerr << "DJMFixImpl::setMidiSender()" << std::endl; // TODO: do not mess STDIO
+		this->midiSender = midiSender;
 	}
 
 	virtual void receive(MidiMessage midiMessage) override {
 		std::cerr << "DJMFixImpl::receive()" << std::endl; // TODO: do not mess STDIO
-
-		midiSender({0xf0, 0xf7});
 	}
 
 	void start() override {
 		std::cerr << "DJMFixImpl::start()" << std::endl; // TODO: do not mess STDIO
+		if (midiSender == nullptr) throw std::logic_error("need a midiSender when starting");
+		midiSender->send({0xf0, 0xf7});
+
+		keepAliveThread = std::thread(&DJMFixImpl::run, this);
+		running = true;
+
 	}
 
 	void stop() override {
+		stopped = true;
+		keepAliveThread.join();
+		running = false;
 		std::cerr << "DJMFixImpl::stop()" << std::endl; // TODO: do not mess STDIO
 	}
 };
 
-DJMFix* create(MidiSender midiSender) {
-	return new DJMFixImpl(midiSender);
+DJMFix* create() {
+	return new DJMFixImpl();
 }
 
 }
--- a/DJMFix.h	Fri Dec 18 21:35:36 2020 +0100
+++ b/DJMFix.h	Fri Dec 18 23:19:32 2020 +0100
@@ -17,21 +17,26 @@
 #pragma once
 
 #include <vector>
-#include <functional>
 
 namespace djmfix {
 
 using MidiMessage = std::vector<uint8_t>;
-using MidiSender = std::function<void(MidiMessage) >;
+
+class MidiSender {
+public:
+	virtual ~MidiSender() = default;
+	virtual void send(MidiMessage midiMessage) = 0;
+};
 
 class DJMFix {
 public:
 	virtual ~DJMFix() = default;
+	virtual void setMidiSender(MidiSender* midiSender) = 0;
 	virtual void receive(MidiMessage midiMessage) = 0;
 	virtual void start() = 0;
 	virtual void stop() = 0;
 };
 
-DJMFix* create(MidiSender midiSender);
+DJMFix* create();
 
 }
--- a/Makefile	Fri Dec 18 21:35:36 2020 +0100
+++ b/Makefile	Fri Dec 18 23:19:32 2020 +0100
@@ -23,6 +23,6 @@
 
 .PHONY: all clean run
 
-build/djm-fix: DJMFix.cpp DJMFix.h djm-fix.cpp
+build/djm-fix: DJMFix.cpp DJMFix.h AlsaBridge.cpp AlsaBridge.h djm-fix.cpp
 	mkdir -p build
-	g++ -o $@ DJMFix.cpp djm-fix.cpp
+	g++ -o $@ DJMFix.cpp AlsaBridge.cpp djm-fix.cpp -lpthread
--- a/djm-fix.cpp	Fri Dec 18 21:35:36 2020 +0100
+++ b/djm-fix.cpp	Fri Dec 18 23:19:32 2020 +0100
@@ -17,19 +17,28 @@
 
 #include <memory>
 #include <iostream>
+#include <chrono>
+#include <thread>
+#include <csignal>
 
 #include "DJMFix.h"
+#include "AlsaBridge.h"
+
+volatile static bool run = true;
+
+void interrupt(int signal) {
+	run = false;
+	std::cerr << "interrupt()" << std::endl; // TODO: do not mess STDIO
+}
 
 int main(int argc, char**argv) {
-
-	std::shared_ptr<djmfix::DJMFix> djmFix(djmfix::create([](djmfix::MidiMessage midiMessage) {
-		std::cerr << "main: will send midiMessage" << std::endl; // TODO: do not mess STDIO
-	}));
+	signal(SIGINT, interrupt);
+	std::unique_ptr<djmfix::DJMFix> djmFix(djmfix::create());
+	std::unique_ptr<djmfix::alsa::AlsaBridge> alsaBridge(djmfix::alsa::create(djmFix.get()));
 
-	djmFix->start();
-	djmFix->receive({0xf0, 0xf7});
-	djmFix->stop();
-
+	alsaBridge->start();
+	while (run) std::this_thread::sleep_for(std::chrono::milliseconds(100));
+	alsaBridge->stop();
 
 	return 0;
 }