LCOV - code coverage report
Current view: top level - src/MIDI_Interfaces - GenericBLEMIDI_Interface.ipp (source / functions) Hit Total Coverage
Test: 169c36a3797bc662d84b5726f34a3f37d3c58247 Lines: 73 74 98.6 %
Date: 2024-11-09 15:32:27 Functions: 20 20 100.0 %
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          53 :         sendImpl(lck, [&] {
      35          45 :             return lck.packet->add3B(msg.header, msg.data1, msg.data2,
      36           9 :                                      timestamp);
      37             :         });
      38             :     } else {
      39          19 :         sendImpl(lck, [&] {
      40          16 :             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          27 :     sendImpl(lck, [&] {
      59          16 :         return lck.packet->addSysCommon(msg.getNumberOfDataBytes(), msg.header,
      60          12 :                                         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          66 :                : 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           2 :                : 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           4 :                : 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          16 :                     : 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          28 : void GenericBLEMIDI_Interface<BackendT>::begin() {
     158          28 :     backend.begin(ble_settings);
     159          28 : }
     160             : 
     161             : template <class BackendT>
     162             : void GenericBLEMIDI_Interface<BackendT>::end() {
     163             :     backend.end();
     164             : }
     165             : 
     166             : // -------------------------------------------------------------------------- //
     167             : 
     168             : END_CS_NAMESPACE

Generated by: LCOV version 1.15