LCOV - code coverage report
Current view: top level - src/MIDI_Interfaces/BLEMIDI - BufferedBLEMIDIParser.hpp (source / functions) Hit Total Coverage
Test: 3a807a259ebe0769dd942f7f612dca5273937539 Lines: 33 35 94.3 %
Date: 2024-03-24 17:16:54 Functions: 3 3 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include <Settings/NamespaceSettings.hpp>
       4             : 
       5             : #include "BLERingBuf.hpp"
       6             : #include <MIDI_Parsers/AnyMIDI_Message.hpp>
       7             : #include <MIDI_Parsers/BLEMIDIParser.hpp>
       8             : #include <MIDI_Parsers/SerialMIDI_Parser.hpp>
       9             : 
      10             : BEGIN_CS_NAMESPACE
      11             : 
      12             : /// FIFO buffer that you can push BLE packets into, and pop MIDI messages out of.
      13             : /// If @p SizeT is chosen to be atomic, one thread can push packets, and another
      14             : /// thread can pop MIDI messages, without additional synchronization.
      15             : template <uint16_t Capacity, class SizeT = NonatomicBLERingBufSize<uint16_t>>
      16             : class BufferedBLEMIDIParser {
      17             :   private:
      18             :     /// Contains incoming data to be parsed.
      19             :     BLERingBuf<Capacity, SizeT> ble_buffer {};
      20             :     /// Parses the (chunked) BLE packet obtained from @ref ble_buffer.
      21             :     BLEMIDIParser ble_parser {nullptr, 0};
      22             :     /// Parser for MIDI data extracted from the BLE packet by @ref ble_parser.
      23             :     SerialMIDI_Parser parser {false};
      24             : 
      25             :   public:
      26             :     using IncomingMIDIMessage = AnyMIDIMessage;
      27             : 
      28             :     /// Add a new BLE packet or chunk to the buffer.
      29          15 :     bool pushPacket(BLEDataView packet,
      30             :                     BLEDataType type = BLEDataType::Packet) {
      31          15 :         return ble_buffer.push(packet, type);
      32             :     }
      33             : 
      34             :     /// Retrieve and remove a single incoming MIDI message from the buffer.
      35          52 :     bool popMessage(IncomingMIDIMessage &incomingMessage) {
      36             :         // Try reading a MIDI message from the parser
      37         306 :         auto try_read = [&] {
      38         134 :             MIDIReadEvent event = parser.pull(ble_parser);
      39          67 :             switch (event) {
      40          33 :                 case MIDIReadEvent::CHANNEL_MESSAGE:
      41         132 :                     incomingMessage = {parser.getChannelMessage(),
      42          33 :                                        ble_parser.getTimestamp()};
      43          33 :                     return true;
      44           4 :                 case MIDIReadEvent::SYSEX_CHUNK: // fallthrough
      45             :                 case MIDIReadEvent::SYSEX_MESSAGE:
      46          16 :                     incomingMessage = {parser.getSysExMessage(),
      47           4 :                                        ble_parser.getTimestamp()};
      48           4 :                     return true;
      49           2 :                 case MIDIReadEvent::REALTIME_MESSAGE:
      50           8 :                     incomingMessage = {parser.getRealTimeMessage(),
      51           2 :                                        ble_parser.getTimestamp()};
      52           2 :                     return true;
      53           1 :                 case MIDIReadEvent::SYSCOMMON_MESSAGE:
      54           4 :                     incomingMessage = {parser.getSysCommonMessage(),
      55           1 :                                        ble_parser.getTimestamp()};
      56           1 :                     return true;
      57          27 :                 case MIDIReadEvent::NO_MESSAGE: return false;
      58             :                 default: break; // LCOV_EXCL_LINE
      59             :             }
      60           0 :             return false;
      61             :         };
      62          15 :         while (true) {
      63             :             // Try reading a MIDI message from the current buffer
      64          67 :             if (try_read())
      65          40 :                 return true; // success, incomingMessage updated
      66             :             // Get the next chunk of the BLE packet (if available)
      67          27 :             BLEDataView chunk;
      68          27 :             auto popped = ble_buffer.pop(chunk);
      69          27 :             if (popped == BLEDataType::None)
      70          12 :                 return false; // no more BLE data available
      71          15 :             else if (popped == BLEDataType::Continuation)
      72           0 :                 ble_parser.extend(chunk.data, chunk.length); // same BLE packet
      73          15 :             else if (popped == BLEDataType::Packet)
      74          15 :                 ble_parser = {chunk.data, chunk.length}; // new BLE packet
      75             :         }
      76             :     }
      77             : };
      78             : 
      79             : END_CS_NAMESPACE

Generated by: LCOV version 1.15