116 lines
3.7 KiB
C++
116 lines
3.7 KiB
C++
#pragma once
|
|
|
|
#include <AH/Error/Error.hpp>
|
|
|
|
#include "BLEMIDI/BLEAPI.hpp"
|
|
#include "MIDI_Interface.hpp"
|
|
|
|
#include <chrono>
|
|
|
|
BEGIN_CS_NAMESPACE
|
|
|
|
/**
|
|
* @brief Bluetooth Low Energy MIDI Interface.
|
|
*/
|
|
template <class Backend>
|
|
class GenericBLEMIDI_Interface : public MIDI_Interface {
|
|
public:
|
|
template <class... Args>
|
|
GenericBLEMIDI_Interface(Args &&...args)
|
|
: backend {std::forward<Args>(args)...} {}
|
|
|
|
private:
|
|
// MIDI send implementations
|
|
template <class L, class F>
|
|
void sendImpl(L &lck, F add_to_buffer);
|
|
void sendChannelMessageImpl(ChannelMessage) override;
|
|
void sendSysCommonImpl(SysCommonMessage) override;
|
|
void sendSysExImpl(SysExMessage) override;
|
|
void sendRealTimeImpl(RealTimeMessage) override;
|
|
void sendNowImpl() override;
|
|
|
|
private:
|
|
#if !DISABLE_PIPES
|
|
void handleStall() override { MIDI_Interface::handleStall(this); }
|
|
#ifdef DEBUG_OUT
|
|
const char *getName() const override { return "ble"; }
|
|
#endif
|
|
#endif
|
|
|
|
public:
|
|
/// @name Initialization and polling
|
|
/// @{
|
|
|
|
/// Initialize the BLE hardware and start advertising as a MIDI over BLE
|
|
/// peripheral.
|
|
void begin() override;
|
|
/// @todo Currently not implemented.
|
|
void end();
|
|
/// Poll the backend (if necessary) and invoke the callbacks for any
|
|
/// received MIDI messages, as well as sending them over the pipes connected
|
|
/// to this interface.
|
|
void update() override { MIDI_Interface::updateIncoming(this); }
|
|
/// Returns true if a BLE central is currently connected.
|
|
/// @note This is useful for e.g. turning on/off an LED or showing a
|
|
/// message to the user, but it's not all that useful for anything
|
|
/// else, because the connection could be terminated at any moment.
|
|
bool isConnected() const { return backend.isConnected(); }
|
|
|
|
/// @}
|
|
|
|
public:
|
|
/// @name Reading incoming MIDI messages
|
|
/// @{
|
|
|
|
/// Try reading and parsing a single incoming MIDI message.
|
|
/// @return Returns the type of the message read, or
|
|
/// `MIDIReadEvent::NO_MESSAGE` if no MIDI message was available.
|
|
MIDIReadEvent read();
|
|
|
|
/// Return the received channel voice message.
|
|
ChannelMessage getChannelMessage() const;
|
|
/// Return the received system common message.
|
|
SysCommonMessage getSysCommonMessage() const;
|
|
/// Return the received real-time message.
|
|
RealTimeMessage getRealTimeMessage() const;
|
|
/// Return the received system exclusive message.
|
|
SysExMessage getSysExMessage() const;
|
|
/// Get the BLE-MIDI timestamp of the latest MIDI message.
|
|
/// @note Invalid for SysEx chunks (except the last chunk of a message).
|
|
uint16_t getTimestamp() const;
|
|
|
|
/// @}
|
|
|
|
private:
|
|
/// Incoming message that can be from retrieved using the
|
|
/// `getChannelMessage()`, `getSysCommonMessage()`, `getRealTimeMessage()`
|
|
/// and `getSysExMessage()` methods.
|
|
typename Backend::IncomingMIDIMessage incomingMessage;
|
|
|
|
public:
|
|
/// @name BLE configuration options
|
|
/// @{
|
|
|
|
/// Set the BLE device name. Must be called before @ref begin().
|
|
/// Length is limited by the size of the BLE advertising packets.
|
|
void setName(const char *name);
|
|
/// Set the timeout, the number of milliseconds to buffer the outgoing MIDI
|
|
/// messages. A shorter timeout usually results in lower latency, but also
|
|
/// causes more overhead, because more packets might be required.
|
|
void setTimeout(std::chrono::milliseconds timeout) {
|
|
backend.setTimeout(timeout);
|
|
}
|
|
/// BLE backend configuration option.
|
|
BLESettings ble_settings;
|
|
|
|
/// @}
|
|
|
|
public:
|
|
/// Low-level BLE backend for sending and receiving MIDI over BLE packets.
|
|
Backend backend;
|
|
};
|
|
|
|
END_CS_NAMESPACE
|
|
|
|
#include "GenericBLEMIDI_Interface.ipp"
|