Line data Source code
1 : #pragma once 2 : 3 : #include <AH/Error/Error.hpp> 4 : 5 : #include "BLEMIDI/BLEAPI.hpp" 6 : #include "MIDI_Interface.hpp" 7 : 8 : #include <chrono> 9 : 10 : BEGIN_CS_NAMESPACE 11 : 12 : /** 13 : * @brief Bluetooth Low Energy MIDI Interface. 14 : */ 15 : template <class Backend> 16 : class GenericBLEMIDI_Interface : public MIDI_Interface { 17 : public: 18 : template <class... Args> 19 29 : GenericBLEMIDI_Interface(Args &&...args) 20 29 : : backend {std::forward<Args>(args)...} {} 21 : 22 : private: 23 : // MIDI send implementations 24 : template <class L, class F> 25 : void sendImpl(L &lck, F add_to_buffer); 26 : void sendChannelMessageImpl(ChannelMessage) override; 27 : void sendSysCommonImpl(SysCommonMessage) override; 28 : void sendSysExImpl(SysExMessage) override; 29 : void sendRealTimeImpl(RealTimeMessage) override; 30 : void sendNowImpl() override; 31 : 32 : private: 33 : #if !DISABLE_PIPES 34 0 : void handleStall() override { MIDI_Interface::handleStall(this); } 35 : #ifdef DEBUG_OUT 36 : const char *getName() const override { return "ble"; } 37 : #endif 38 : #endif 39 : 40 : public: 41 : /// @name Initialization and polling 42 : /// @{ 43 : 44 : /// Initialize the BLE hardware and start advertising as a MIDI over BLE 45 : /// peripheral. 46 : void begin() override; 47 : /// @todo Currently not implemented. 48 : void end(); 49 : /// Poll the backend (if necessary) and invoke the callbacks for any 50 : /// received MIDI messages, as well as sending them over the pipes connected 51 : /// to this interface. 52 12 : void update() override { MIDI_Interface::updateIncoming(this); } 53 : /// Returns true if a BLE central is currently connected. 54 : /// @note This is useful for e.g. turning on/off an LED or showing a 55 : /// message to the user, but it's not all that useful for anything 56 : /// else, because the connection could be terminated at any moment. 57 : bool isConnected() const { return backend.isConnected(); } 58 : 59 : /// @} 60 : 61 : public: 62 : /// @name Reading incoming MIDI messages 63 : /// @{ 64 : 65 : /// Try reading and parsing a single incoming MIDI message. 66 : /// @return Returns the type of the message read, or 67 : /// `MIDIReadEvent::NO_MESSAGE` if no MIDI message was available. 68 : MIDIReadEvent read(); 69 : 70 : /// Return the received channel voice message. 71 : ChannelMessage getChannelMessage() const; 72 : /// Return the received system common message. 73 : SysCommonMessage getSysCommonMessage() const; 74 : /// Return the received real-time message. 75 : RealTimeMessage getRealTimeMessage() const; 76 : /// Return the received system exclusive message. 77 : SysExMessage getSysExMessage() const; 78 : /// Get the BLE-MIDI timestamp of the latest MIDI message. 79 : /// @note Invalid for SysEx chunks (except the last chunk of a message). 80 : uint16_t getTimestamp() const; 81 : 82 : /// @} 83 : 84 : private: 85 : /// Incoming message that can be from retrieved using the 86 : /// `getChannelMessage()`, `getSysCommonMessage()`, `getRealTimeMessage()` 87 : /// and `getSysExMessage()` methods. 88 : typename Backend::IncomingMIDIMessage incomingMessage; 89 : 90 : public: 91 : /// @name BLE configuration options 92 : /// @{ 93 : 94 : /// Set the BLE device name. Must be called before @ref begin(). 95 : /// Length is limited by the size of the BLE advertising packets. 96 : void setName(const char *name); 97 : /// Set the timeout, the number of milliseconds to buffer the outgoing MIDI 98 : /// messages. A shorter timeout usually results in lower latency, but also 99 : /// causes more overhead, because more packets might be required. 100 3 : void setTimeout(std::chrono::milliseconds timeout) { 101 3 : backend.setTimeout(timeout); 102 3 : } 103 : /// BLE backend configuration option. 104 : BLESettings ble_settings; 105 : 106 : /// @} 107 : 108 : public: 109 : /// Low-level BLE backend for sending and receiving MIDI over BLE packets. 110 : Backend backend; 111 : }; 112 : 113 : END_CS_NAMESPACE 114 : 115 : #include "GenericBLEMIDI_Interface.ipp"