Control Surface master
MIDI Control Surface library for Arduino
BluetoothMIDI_Interface.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <AH/Error/Error.hpp>
4
7#include "MIDI_Interface.hpp"
11
12#include <atomic>
13#include <chrono>
14#include <condition_variable>
15#include <mutex>
16#include <thread>
17
18#ifndef ARDUINO
19#include <gmock/gmock.h>
20#endif
21
23
30
31 public:
33 if (instance)
34 FATAL_ERROR(F("Only one instance is supported"), 0x1345);
35 instance = this;
36 };
38 instance = nullptr;
40 end();
41 }
42
43 public:
45 void flush() {
46 lock_t lock(mtx);
47 flushImpl(lock);
48 }
49
53 void setTimeout(std::chrono::milliseconds timeout) {
54 lock_t lock(mtx);
55 this->timeout = timeout;
56 }
57
58 public:
59 void begin() override;
60 void end();
61
63
64 void update() override { MIDI_Interface::updateIncoming(this); }
65
66 private:
67 void handleStall() override { MIDI_Interface::handleStall(this); }
68
69 public:
80 uint16_t getTimestamp() const;
81
82 protected:
83 // MIDI send implementations
86 void sendSysExImpl(SysExMessage) override;
87 void sendRealTimeImpl(RealTimeMessage) override;
88 void sendNowImpl() override { flush(); }
89
92
93 public:
94 void parse(const uint8_t *const data, const size_t len);
95
96 private:
98 std::atomic_uint_fast16_t min_mtu{23};
102 std::atomic_uint_fast16_t force_min_mtu{0};
103
106 void updateMTU(uint16_t mtu);
107
108 public:
110 uint16_t getMinMTU() const { return min_mtu; }
111
113 void forceMinMTU(uint16_t mtu);
114
115 private:
128
129 private:
130 // Synchronization for asynchronous BLE sending
131
133 using lock_t = std::unique_lock<std::mutex>;
135 std::mutex mtx;
139 std::condition_variable cv;
141 std::thread send_thread;
143 std::atomic_bool stop_sending{false};
145 bool flushnow = false;
148 std::chrono::milliseconds timeout{10};
149
150 private:
152 void startSendingThread();
153
158 bool handleSendEvents();
159
165 void flushImpl(lock_t &lock);
166
167#if !defined(ARDUINO) && !defined(DOXYGEN)
168 public:
169#endif
171 void stopSendingThread();
172
173 public:
174 static void midi_write_callback(const uint8_t *data, size_t length) {
175 if (instance)
176 instance->parse(data, length);
177 }
178
179 static void midi_mtu_callback(uint16_t mtu) {
180 if (instance)
181 instance->updateMTU(mtu);
182 }
183
184#ifdef ARDUINO
185 private:
186 void notifyMIDIBLE(const std::vector<uint8_t> &packet);
187#else
188 public:
189 MOCK_METHOD(void, notifyMIDIBLE, (const std::vector<uint8_t> &), ());
190#endif
191};
192
MIDIReadEvent
Values returned by the MIDI reading functions.
#define END_CS_NAMESPACE
#define BEGIN_CS_NAMESPACE
Class for building MIDI over Bluetooth Low Energy packets.
Bluetooth Low Energy MIDI Interface for the ESP32.
ChannelMessage getChannelMessage() const
Return the received channel voice message.
RealTimeMessage getRealTimeMessage() const
Return the received real-time message.
std::condition_variable cv
Condition variable used by the background sender thread to wait for data to send, and for the main th...
uint16_t getMinMTU() const
Get the minimum MTU of all connected clients.
std::unique_lock< std::mutex > lock_t
Lock type used to lock the mutex.
std::chrono::milliseconds timeout
Timeout before the sender thread sends a packet.
void setTimeout(std::chrono::milliseconds timeout)
Set the timeout, the number of milliseconds to buffer the outgoing MIDI messages.
MIDIMessageQueue::MIDIMessageQueueElement incomingMessage
Incoming message that can be from retrieved using the getChannelMessage(), getSysCommonMessage(),...
bool handleSendEvents()
Function that waits for BLE packets and sends them in the background.
void sendChannelMessageImpl(ChannelMessage) override
Low-level function for sending a MIDI channel voice message.
void parse(const uint8_t *const data, const size_t len)
void handleStall() override
Call back that should finish any MIDI messages that are in progress, and un-stall the pipe or MIDI so...
void forceMinMTU(uint16_t mtu)
Force the MTU to an artificially small value (used for testing).
void update() override
Read the MIDI interface and call the callback if a message was received.
void sendNowImpl() override
Low-level function for sending any buffered outgoing MIDI messages.
static BluetoothMIDI_Interface * instance
Only one active instance.
SysCommonMessage getSysCommonMessage() const
Return the received system common message.
void sendRealTimeImpl(RealTimeMessage) override
Low-level function for sending a MIDI real-time message.
std::atomic_uint_fast16_t force_min_mtu
Override the minimum MTU (0 means don't override, nonzero overrides if it's smaller than the minimum ...
void flushImpl(lock_t &lock)
Tell the background BLE sender thread to send the current packet.
void begin() override
Initialize this updatable.
BLEMIDIPacketBuilder packetbuilder
Builds outgoing MIDI BLE packets.
MIDIMessageQueue queue
Queue for incoming MIDI messages.
void sendChannelMessageImpl2Bytes(ChannelMessage)
void stopSendingThread()
Tell the background BLE sender thread to stop gracefully, and join it.
void sendSysExImpl(SysExMessage) override
Low-level function for sending a system exclusive MIDI message.
static void midi_mtu_callback(uint16_t mtu)
void startSendingThread()
Launch a thread that sends the BLE packets in the background.
void sendChannelMessageImpl3Bytes(ChannelMessage)
void sendSysCommonImpl(SysCommonMessage) override
Low-level function for sending a MIDI system common message.
bool flushnow
Flag to tell the sender thread to send the packet immediately.
std::thread send_thread
Background thread that sends the actual MIDI BLE packets.
void notifyMIDIBLE(const std::vector< uint8_t > &packet)
std::mutex mtx
Mutex to lock the MIDI BLE packet builder and the flush flag.
void flush()
Send the buffered MIDI BLE packet immediately.
void updateMTU(uint16_t mtu)
Set the maximum transmission unit of the Bluetooth link.
std::atomic_bool stop_sending
Flag to stop the background thread.
SysExMessage getSysExMessage() const
Return the received system exclusive message.
std::atomic_uint_fast16_t min_mtu
The minimum MTU of all connected clients.
SerialMIDI_Parser parser
MIDI Parser for incoming data.
uint16_t getTimestamp() const
Get the BLE-MIDI timestamp of the latest MIDI message.
static void midi_write_callback(const uint8_t *data, size_t length)
An abstract class for MIDI interfaces.
static void updateIncoming(MIDIInterface_t *iface)
Read, parse and dispatch incoming MIDI messages on the given interface.
Parser for Serial MIDI streams (and BLE-MIDI).
#define FATAL_ERROR(msg, errc)
Print the error message and error code, and stop the execution.
Definition: Error.hpp:60
virtual void handleStall()=0
Call back that should finish any MIDI messages that are in progress, and un-stall the pipe or MIDI so...