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 2f34476ab597f
parent 1 98274757fcf6
child 3 e238528eb19c
background thread + AlsaBridge skeleton
AlsaBridge.cpp
AlsaBridge.h
DJMFix.cpp
DJMFix.h
Makefile
djm-fix.cpp
     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  }