1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/AlsaBridge.cpp Fri Dec 18 23:19:32 2020 +0100
1.3 @@ -0,0 +1,56 @@
1.4 +/**
1.5 + * DJM-Fix
1.6 + * Copyright © 2020 František Kučera (Frantovo.cz, GlobalCode.info)
1.7 + *
1.8 + * This program is free software: you can redistribute it and/or modify
1.9 + * it under the terms of the GNU General Public License as published by
1.10 + * the Free Software Foundation, version 3 of the License.
1.11 + *
1.12 + * This program is distributed in the hope that it will be useful,
1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.15 + * GNU General Public License for more details.
1.16 + *
1.17 + * You should have received a copy of the GNU General Public License
1.18 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
1.19 + */
1.20 +#include <iostream>
1.21 +
1.22 +#include "AlsaBridge.h"
1.23 +
1.24 +namespace djmfix {
1.25 +namespace alsa {
1.26 +
1.27 +class AlsaBridgeImpl : public AlsaBridge, private djmfix::MidiSender {
1.28 +private:
1.29 + djmfix::DJMFix* djmFix;
1.30 +public:
1.31 +
1.32 + AlsaBridgeImpl(djmfix::DJMFix* djmFix) : djmFix(djmFix) {
1.33 + djmFix->setMidiSender(this);
1.34 + }
1.35 +
1.36 + virtual ~AlsaBridgeImpl() {
1.37 + std::cerr << "~AlsaBridgeImpl()" << std::endl; // TODO: do not mess STDIO
1.38 + }
1.39 +
1.40 + virtual void start() override {
1.41 + djmFix->start();
1.42 + }
1.43 +
1.44 + virtual void stop() override {
1.45 + djmFix->stop();
1.46 + }
1.47 +
1.48 + virtual void send(MidiMessage midiMessage) override {
1.49 + std::cerr << "AlsaBridgeImpl::send()" << std::endl; // TODO: do not mess STDIO
1.50 + }
1.51 +
1.52 +};
1.53 +
1.54 +AlsaBridge* create(djmfix::DJMFix* djmFix) {
1.55 + return new AlsaBridgeImpl(djmFix);
1.56 +}
1.57 +
1.58 +}
1.59 +}
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/AlsaBridge.h Fri Dec 18 23:19:32 2020 +0100
2.3 @@ -0,0 +1,35 @@
2.4 +/**
2.5 + * DJM-Fix
2.6 + * Copyright © 2020 František Kučera (Frantovo.cz, GlobalCode.info)
2.7 + *
2.8 + * This program is free software: you can redistribute it and/or modify
2.9 + * it under the terms of the GNU General Public License as published by
2.10 + * the Free Software Foundation, version 3 of the License.
2.11 + *
2.12 + * This program is distributed in the hope that it will be useful,
2.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2.15 + * GNU General Public License for more details.
2.16 + *
2.17 + * You should have received a copy of the GNU General Public License
2.18 + * along with this program. If not, see <http://www.gnu.org/licenses/>.
2.19 + */
2.20 +#pragma once
2.21 +
2.22 +#include "DJMFix.h"
2.23 +
2.24 +namespace djmfix {
2.25 +namespace alsa {
2.26 +
2.27 +class AlsaBridge {
2.28 +public:
2.29 + virtual ~AlsaBridge() = default;
2.30 + virtual void start() = 0;
2.31 + virtual void stop() = 0;
2.32 +
2.33 +};
2.34 +
2.35 +AlsaBridge* create(djmfix::DJMFix* djmFix);
2.36 +
2.37 +}
2.38 +}
2.39 \ No newline at end of file
3.1 --- a/DJMFix.cpp Fri Dec 18 21:35:36 2020 +0100
3.2 +++ b/DJMFix.cpp Fri Dec 18 23:19:32 2020 +0100
3.3 @@ -15,6 +15,9 @@
3.4 * along with this program. If not, see <http://www.gnu.org/licenses/>.
3.5 */
3.6 #include <iostream>
3.7 +#include <thread>
3.8 +#include <chrono>
3.9 +#include <stdexcept>
3.10
3.11 #include "DJMFix.h"
3.12
3.13 @@ -22,34 +25,55 @@
3.14
3.15 class DJMFixImpl : public DJMFix {
3.16 private:
3.17 - MidiSender midiSender;
3.18 + MidiSender* midiSender;
3.19 + std::thread keepAliveThread;
3.20 + bool running = false;
3.21 + bool stopped = false;
3.22 +
3.23 + void run() {
3.24 + while (!stopped) {
3.25 + std::cerr << "DJMFixImpl::run()" << std::endl; // TODO: do not mess STDIO
3.26 + // TODO: send keep-alive messages
3.27 + std::this_thread::sleep_for(std::chrono::milliseconds(200));
3.28 + }
3.29 + }
3.30 +
3.31 public:
3.32
3.33 - DJMFixImpl(MidiSender midiSender) : midiSender(midiSender) {
3.34 - std::cerr << "DJMFixImpl()" << std::endl; // TODO: do not mess STDIO
3.35 - }
3.36 -
3.37 virtual ~DJMFixImpl() override {
3.38 std::cerr << "~DJMFixImpl()" << std::endl; // TODO: do not mess STDIO
3.39 + if (running) stop();
3.40 + }
3.41 +
3.42 + void setMidiSender(MidiSender* midiSender) {
3.43 + std::cerr << "DJMFixImpl::setMidiSender()" << std::endl; // TODO: do not mess STDIO
3.44 + this->midiSender = midiSender;
3.45 }
3.46
3.47 virtual void receive(MidiMessage midiMessage) override {
3.48 std::cerr << "DJMFixImpl::receive()" << std::endl; // TODO: do not mess STDIO
3.49 -
3.50 - midiSender({0xf0, 0xf7});
3.51 }
3.52
3.53 void start() override {
3.54 std::cerr << "DJMFixImpl::start()" << std::endl; // TODO: do not mess STDIO
3.55 + if (midiSender == nullptr) throw std::logic_error("need a midiSender when starting");
3.56 + midiSender->send({0xf0, 0xf7});
3.57 +
3.58 + keepAliveThread = std::thread(&DJMFixImpl::run, this);
3.59 + running = true;
3.60 +
3.61 }
3.62
3.63 void stop() override {
3.64 + stopped = true;
3.65 + keepAliveThread.join();
3.66 + running = false;
3.67 std::cerr << "DJMFixImpl::stop()" << std::endl; // TODO: do not mess STDIO
3.68 }
3.69 };
3.70
3.71 -DJMFix* create(MidiSender midiSender) {
3.72 - return new DJMFixImpl(midiSender);
3.73 +DJMFix* create() {
3.74 + return new DJMFixImpl();
3.75 }
3.76
3.77 }
4.1 --- a/DJMFix.h Fri Dec 18 21:35:36 2020 +0100
4.2 +++ b/DJMFix.h Fri Dec 18 23:19:32 2020 +0100
4.3 @@ -17,21 +17,26 @@
4.4 #pragma once
4.5
4.6 #include <vector>
4.7 -#include <functional>
4.8
4.9 namespace djmfix {
4.10
4.11 using MidiMessage = std::vector<uint8_t>;
4.12 -using MidiSender = std::function<void(MidiMessage) >;
4.13 +
4.14 +class MidiSender {
4.15 +public:
4.16 + virtual ~MidiSender() = default;
4.17 + virtual void send(MidiMessage midiMessage) = 0;
4.18 +};
4.19
4.20 class DJMFix {
4.21 public:
4.22 virtual ~DJMFix() = default;
4.23 + virtual void setMidiSender(MidiSender* midiSender) = 0;
4.24 virtual void receive(MidiMessage midiMessage) = 0;
4.25 virtual void start() = 0;
4.26 virtual void stop() = 0;
4.27 };
4.28
4.29 -DJMFix* create(MidiSender midiSender);
4.30 +DJMFix* create();
4.31
4.32 }
5.1 --- a/Makefile Fri Dec 18 21:35:36 2020 +0100
5.2 +++ b/Makefile Fri Dec 18 23:19:32 2020 +0100
5.3 @@ -23,6 +23,6 @@
5.4
5.5 .PHONY: all clean run
5.6
5.7 -build/djm-fix: DJMFix.cpp DJMFix.h djm-fix.cpp
5.8 +build/djm-fix: DJMFix.cpp DJMFix.h AlsaBridge.cpp AlsaBridge.h djm-fix.cpp
5.9 mkdir -p build
5.10 - g++ -o $@ DJMFix.cpp djm-fix.cpp
5.11 + g++ -o $@ DJMFix.cpp AlsaBridge.cpp djm-fix.cpp -lpthread
6.1 --- a/djm-fix.cpp Fri Dec 18 21:35:36 2020 +0100
6.2 +++ b/djm-fix.cpp Fri Dec 18 23:19:32 2020 +0100
6.3 @@ -17,19 +17,28 @@
6.4
6.5 #include <memory>
6.6 #include <iostream>
6.7 +#include <chrono>
6.8 +#include <thread>
6.9 +#include <csignal>
6.10
6.11 #include "DJMFix.h"
6.12 +#include "AlsaBridge.h"
6.13 +
6.14 +volatile static bool run = true;
6.15 +
6.16 +void interrupt(int signal) {
6.17 + run = false;
6.18 + std::cerr << "interrupt()" << std::endl; // TODO: do not mess STDIO
6.19 +}
6.20
6.21 int main(int argc, char**argv) {
6.22 + signal(SIGINT, interrupt);
6.23 + std::unique_ptr<djmfix::DJMFix> djmFix(djmfix::create());
6.24 + std::unique_ptr<djmfix::alsa::AlsaBridge> alsaBridge(djmfix::alsa::create(djmFix.get()));
6.25
6.26 - std::shared_ptr<djmfix::DJMFix> djmFix(djmfix::create([](djmfix::MidiMessage midiMessage) {
6.27 - std::cerr << "main: will send midiMessage" << std::endl; // TODO: do not mess STDIO
6.28 - }));
6.29 -
6.30 - djmFix->start();
6.31 - djmFix->receive({0xf0, 0xf7});
6.32 - djmFix->stop();
6.33 -
6.34 + alsaBridge->start();
6.35 + while (run) std::this_thread::sleep_for(std::chrono::milliseconds(100));
6.36 + alsaBridge->stop();
6.37
6.38 return 0;
6.39 }