Control Surface new-input
MIDI Control Surface library for Arduino
Go to the documentation of this file.
1 #pragma once
3 #include <AH/Error/Error.hpp>
7 #include "MIDI_Interface.hpp"
8 #include "Util/ESP32Threads.hpp"
12 #include <atomic>
13 #include <chrono>
14 #include <condition_variable>
15 #include <mutex>
16 #include <thread>
18 #ifndef ARDUINO
19 #include <gmock/gmock.h>
20 #endif
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  }
43  public:
45  void flush() {
46  lock_t lock(mtx);
47  flushImpl(lock);
48  }
53  void setTimeout(std::chrono::milliseconds timeout) {
54  lock_t lock(mtx);
55  this->timeout = timeout;
56  }
58  public:
59  void begin() override;
60  void end();
64  void update() override { MIDI_Interface::updateIncoming(this); }
66  private:
67  void handleStall() override { MIDI_Interface::handleStall(this); }
69  public:
80  uint16_t getTimestamp() const;
82  protected:
83  // MIDI send implementations
85  void sendSysCommonImpl(SysCommonMessage) override;
86  void sendSysExImpl(SysExMessage) override;
87  void sendRealTimeImpl(RealTimeMessage) override;
88  void sendNowImpl() override { flush(); }
93  public:
94  void parse(const uint8_t *const data, const size_t len);
96  private:
98  std::atomic_uint_fast16_t min_mtu{23};
102  std::atomic_uint_fast16_t force_min_mtu{0};
106  void updateMTU(uint16_t mtu);
108  public:
110  uint16_t getMinMTU() const { return min_mtu; }
113  void forceMinMTU(uint16_t mtu);
115  private:
129  private:
130  // Synchronization for asynchronous BLE sending
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};
150  private:
152  void startSendingThread();
158  bool handleSendEvents();
165  void flushImpl(lock_t &lock);
167 #if !defined(ARDUINO) && !defined(DOXYGEN)
168  public:
169 #endif
171  void stopSendingThread();
173  public:
174  static void midi_write_callback(const uint8_t *data, size_t length) {
175  if (instance)
176  instance->parse(data, length);
177  }
179  static void midi_mtu_callback(uint16_t mtu) {
180  if (instance)
181  instance->updateMTU(mtu);
182  }
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 };
Values returned by the MIDI reading functions.
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...