LCOV - code coverage report
Current view: top level - src/MIDI_Interfaces - GenericBLEMIDI_Interface.ipp (source / functions) Coverage Total Hit
Test: 73449d9b107c772cf65493691543348214e5d5eb Lines: 98.6 % 74 73
Test Date: 2026-06-06 17:44:35 Functions: 100.0 % 20 20
Legend: Lines:     hit not hit

            Line data    Source code
       1              : #include "GenericBLEMIDI_Interface.hpp"
       2              : 
       3              : BEGIN_CS_NAMESPACE
       4              : 
       5              : // -------------------------------------------------------------------------- //
       6              : 
       7              : // The following section implements the MIDI sending functions.
       8              : 
       9              : template <class BackendT>
      10              : template <class L, class F>
      11           18 : void GenericBLEMIDI_Interface<BackendT>::sendImpl(L &lck, F add_to_buffer) {
      12              :     // BLE packets are sent asynchronously, so we need a lock to access the
      13              :     // packet buffer
      14              :     //     assert(lck.lck.owns_lock());
      15              : 
      16              :     // Try adding the message to the current packet
      17           18 :     if (!add_to_buffer()) {
      18              :         // If that doesn't work, flush the packet (send it now and wait until
      19              :         // it is sent)
      20            4 :         backend.sendNow(lck);
      21              :         // And then add it to the (now emtpy) buffer
      22            4 :         add_to_buffer();
      23              :     }
      24              :     // Notify the sending thread that data has been added to the buffer
      25           18 :     backend.releasePacketAndNotify(lck);
      26           18 : }
      27              : 
      28              : template <class BackendT>
      29           11 : void GenericBLEMIDI_Interface<BackendT>::sendChannelMessageImpl(
      30              :     ChannelMessage msg) {
      31           11 :     uint16_t timestamp = millis(); // BLE MIDI timestamp
      32           11 :     auto lck = backend.acquirePacket();
      33           11 :     if (msg.hasTwoDataBytes()) {
      34            8 :         sendImpl(lck, [&] {
      35            9 :             return lck.packet->add3B(msg.header, msg.data1, msg.data2,
      36            9 :                                      timestamp);
      37              :         });
      38              :     } else {
      39            3 :         sendImpl(lck, [&] {
      40            4 :             return lck.packet->add2B(msg.header, msg.data1, timestamp);
      41              :         });
      42              :     }
      43           22 : }
      44              : 
      45              : template <class BackendT>
      46            4 : void GenericBLEMIDI_Interface<BackendT>::sendRealTimeImpl(RealTimeMessage msg) {
      47            4 :     uint16_t timestamp = millis(); // BLE MIDI timestamp
      48            4 :     auto lck = backend.acquirePacket();
      49            4 :     sendImpl(lck,
      50            5 :              [&] { return lck.packet->addRealTime(msg.message, timestamp); });
      51            8 : }
      52              : 
      53              : template <class BackendT>
      54            3 : void GenericBLEMIDI_Interface<BackendT>::sendSysCommonImpl(
      55              :     SysCommonMessage msg) {
      56            3 :     uint16_t timestamp = millis(); // BLE MIDI timestamp
      57            3 :     auto lck = backend.acquirePacket();
      58            3 :     sendImpl(lck, [&] {
      59            8 :         return lck.packet->addSysCommon(msg.getNumberOfDataBytes(), msg.header,
      60            8 :                                         msg.data1, msg.data2, timestamp);
      61              :     });
      62            6 : }
      63              : 
      64              : template <class BackendT>
      65            3 : void GenericBLEMIDI_Interface<BackendT>::sendSysExImpl(SysExMessage msg) {
      66            3 :     uint16_t timestamp = millis(); // BLE MIDI timestamp
      67            3 :     size_t length = msg.length;
      68            3 :     const uint8_t *data = msg.data;
      69              : 
      70              :     // BLE packets are sent asynchronously, so we need a lock to access the
      71              :     // packet buffer
      72            3 :     auto lck = backend.acquirePacket();
      73              : 
      74              :     // TODO: I have no idea why, but the last byte gets cut off when the LSB
      75              :     // of the timestamp is 0x77 ... (Problem is probably in the BlueZ parser)
      76            3 :     if ((timestamp & 0x77) == 0x77)
      77            0 :         timestamp &= 0xFFFE;
      78              : 
      79              :     // Try adding at least the SysExStart header to the current packet
      80            3 :     if (!lck.packet->addSysEx(data, length, timestamp)) {
      81              :         // If that didn't fit, flush the packet
      82            1 :         backend.sendNow(lck);
      83              :         // Add the first part of the SysEx message to this packet
      84            1 :         lck.packet->addSysEx(data, length, timestamp);
      85              :     }
      86              :     // As long as there's data to be sent in the next packet
      87            7 :     while (data) {
      88              :         // Send the previous (full) packet
      89            4 :         backend.sendNow(lck);
      90              :         // And add the next part of the SysEx message to a continuation packet
      91            4 :         lck.packet->continueSysEx(data, length, timestamp);
      92              :     }
      93              :     // Notify the sending thread that data has been added to the buffer
      94            3 :     backend.releasePacketAndNotify(lck);
      95            6 : }
      96              : 
      97              : template <class BackendT>
      98           12 : void GenericBLEMIDI_Interface<BackendT>::sendNowImpl() {
      99           12 :     auto lck = backend.acquirePacket();
     100           12 :     backend.sendNow(lck);
     101           24 : }
     102              : 
     103              : // -------------------------------------------------------------------------- //
     104              : 
     105              : template <class BackendT>
     106           52 : MIDIReadEvent GenericBLEMIDI_Interface<BackendT>::read() {
     107              :     // Pop a new message from the queue
     108           52 :     if (!backend.popMessage(incomingMessage))
     109           12 :         return MIDIReadEvent::NO_MESSAGE;
     110           40 :     return incomingMessage.eventType;
     111              : }
     112              : 
     113              : template <class BackendT>
     114           33 : ChannelMessage GenericBLEMIDI_Interface<BackendT>::getChannelMessage() const {
     115           33 :     return incomingMessage.eventType == MIDIReadEvent::CHANNEL_MESSAGE
     116           33 :                ? incomingMessage.message.channelmessage
     117           33 :                : ChannelMessage(0, 0, 0);
     118              : }
     119              : 
     120              : template <class BackendT>
     121              : SysCommonMessage
     122            1 : GenericBLEMIDI_Interface<BackendT>::getSysCommonMessage() const {
     123            1 :     return incomingMessage.eventType == MIDIReadEvent::SYSCOMMON_MESSAGE
     124            1 :                ? incomingMessage.message.syscommonmessage
     125            1 :                : SysCommonMessage(0, 0, 0);
     126              : }
     127              : 
     128              : template <class BackendT>
     129            2 : RealTimeMessage GenericBLEMIDI_Interface<BackendT>::getRealTimeMessage() const {
     130            2 :     return incomingMessage.eventType == MIDIReadEvent::REALTIME_MESSAGE
     131            2 :                ? incomingMessage.message.realtimemessage
     132            2 :                : RealTimeMessage(0);
     133              : }
     134              : 
     135              : template <class BackendT>
     136            8 : SysExMessage GenericBLEMIDI_Interface<BackendT>::getSysExMessage() const {
     137            8 :     auto evt = incomingMessage.eventType;
     138            8 :     bool hasSysEx = evt == MIDIReadEvent::SYSEX_MESSAGE ||
     139              :                     evt == MIDIReadEvent::SYSEX_CHUNK;
     140            8 :     return hasSysEx ? incomingMessage.message.sysexmessage
     141            8 :                     : SysExMessage(nullptr, 0);
     142              : }
     143              : 
     144              : template <class BackendT>
     145           13 : uint16_t GenericBLEMIDI_Interface<BackendT>::getTimestamp() const {
     146           13 :     return incomingMessage.timestamp;
     147              : }
     148              : 
     149              : // -------------------------------------------------------------------------- //
     150              : 
     151              : template <class BackendT>
     152              : void GenericBLEMIDI_Interface<BackendT>::setName(const char *name) {
     153              :     ble_settings.device_name = name;
     154              : }
     155              : 
     156              : template <class BackendT>
     157              : void GenericBLEMIDI_Interface<BackendT>::requireEncryption(bool require) {
     158              :     ble_settings.require_encryption = require;
     159              : }
     160              : 
     161              : template <class BackendT>
     162           28 : void GenericBLEMIDI_Interface<BackendT>::begin() {
     163           28 :     backend.begin(ble_settings);
     164           28 : }
     165              : 
     166              : template <class BackendT>
     167              : void GenericBLEMIDI_Interface<BackendT>::end() {
     168              :     backend.end();
     169              : }
     170              : 
     171              : // -------------------------------------------------------------------------- //
     172              : 
     173              : END_CS_NAMESPACE
        

Generated by: LCOV version 2.4-beta