diff -r 4d777d6c8024 -r ef8f4023e32e AlsaBridge.cpp --- a/AlsaBridge.cpp Fri Dec 18 23:58:03 2020 +0100 +++ b/AlsaBridge.cpp Sat Dec 19 17:33:16 2020 +0100 @@ -15,6 +15,9 @@ * along with this program. If not, see . */ #include +#include +#include +#include #include @@ -26,32 +29,63 @@ class AlsaBridgeImpl : public AlsaBridge, private djmfix::MidiSender { private: djmfix::DJMFix* djmFix; + snd_rawmidi_t* input; + snd_rawmidi_t* output; + std::thread receivingThread; + std::atomic stopped{false}; + + void run() { + while (!stopped) { + // TODO: poll + uint8_t buffer[256]; + ssize_t length = snd_rawmidi_read(input, buffer, sizeof (buffer)); + if (length > 0 && length <= sizeof (buffer)) { + // TODO: multiple messages combined together? + djmFix->receive(MidiMessage(buffer, buffer + length)); + } + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + } public: - AlsaBridgeImpl(djmfix::DJMFix* djmFix) : djmFix(djmFix) { + AlsaBridgeImpl(djmfix::DJMFix* djmFix, const std::string& deviceName) : djmFix(djmFix) { + if (djmFix == nullptr) throw std::invalid_argument("need a djmFix for AlsaBridge"); + + int error = snd_rawmidi_open(&input, &output, deviceName.c_str(), SND_RAWMIDI_NONBLOCK); + if (error) throw std::invalid_argument("unable to open ALSA device"); + + djmFix->setMidiSender(this); } virtual ~AlsaBridgeImpl() { + // TODO: do not use raw/exclusive access to the device + snd_rawmidi_close(input); + snd_rawmidi_close(output); std::cerr << "~AlsaBridgeImpl()" << std::endl; // TODO: do not mess STDIO } virtual void start() override { djmFix->start(); + receivingThread = std::thread(&AlsaBridgeImpl::run, this); } virtual void stop() override { + stopped = true; + receivingThread.join(); djmFix->stop(); } virtual void send(MidiMessage midiMessage) override { - std::cerr << "AlsaBridgeImpl::send()" << std::endl; // TODO: do not mess STDIO + ssize_t length = snd_rawmidi_write(output, midiMessage.data(), midiMessage.size()); + std::cerr << "AlsaBridgeImpl::send(): length = " << length << std::endl; // TODO: do not mess STDIO } }; -AlsaBridge* create(djmfix::DJMFix* djmFix) { - return new AlsaBridgeImpl(djmFix); +AlsaBridge* create(djmfix::DJMFix* djmFix, const std::string& deviceName) { + return new AlsaBridgeImpl(djmFix, deviceName); } }