Control Surface disable-pipes
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:
60 void setName(const char *name);
61
62 void begin() override;
63 void end();
64
66
67 void update() override { MIDI_Interface::updateIncoming(this); }
68
69 private:
70#if !DISABLE_PIPES
71 void handleStall() override { MIDI_Interface::handleStall(this); }
72#endif
73
74 public:
85 uint16_t getTimestamp() const;
86
87 protected:
88 // MIDI send implementations
91 void sendSysExImpl(SysExMessage) override;
92 void sendRealTimeImpl(RealTimeMessage) override;
93 void sendNowImpl() override { flush(); }
94
97
98 public:
99 void parse(const uint8_t *const data, const size_t len);
100
101 private:
103 std::atomic_uint_fast16_t min_mtu{23};
107 std::atomic_uint_fast16_t force_min_mtu{0};
108
111 void updateMTU(uint16_t mtu);
112
113 public:
115 uint16_t getMinMTU() const { return min_mtu; }
116
118 void forceMinMTU(uint16_t mtu);
119
120 private:
133
134 private:
135 // Synchronization for asynchronous BLE sending
136
138 using lock_t = std::unique_lock<std::mutex>;
140 std::mutex mtx;
144 std::condition_variable cv;
146 std::thread send_thread;
148 std::atomic_bool stop_sending{false};
150 bool flushnow = false;
153 std::chrono::milliseconds timeout{10};
154
155 private:
157 void startSendingThread();
158
163 bool handleSendEvents();
164
170 void flushImpl(lock_t &lock);
171
172#if !defined(ARDUINO) && !defined(DOXYGEN)
173 public:
174#endif
176 void stopSendingThread();
177
178 public:
179 static void midi_write_callback(const uint8_t *data, size_t length) {
180 if (instance)
181 instance->parse(data, length);
182 }
183
184 static void midi_mtu_callback(uint16_t mtu) {
185 if (instance)
186 instance->updateMTU(mtu);
187 }
188
189#ifdef ARDUINO
190 private:
191 void notifyMIDIBLE(const std::vector<uint8_t> &packet);
192#else
193 public:
194 MOCK_METHOD(void, notifyMIDIBLE, (const std::vector<uint8_t> &), ());
195#endif
196};
197
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.
void setName(const char *name)
Set the BLE device name. Must be called before begin().
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...