LCOV - code coverage report
Current view: top level - src/MIDI_Parsers - SerialMIDI_Parser.cpp (source / functions) Hit Total Coverage
Test: e224b347cd670555e44f06608ac41bd1ace9d9d8 Lines: 40 43 93.0 %
Date: 2020-09-08 17:44:46 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #include "SerialMIDI_Parser.hpp"
       2             : 
       3             : BEGIN_CS_NAMESPACE
       4             : 
       5         459 : MIDIReadEvent SerialMIDI_Parser::parse(uint8_t midiByte) {
       6         459 :     DEBUGFN(hex << NAMEDVALUE(midiByte) << dec);
       7             : #if !IGNORE_SYSEX
       8             :     // SysEx constants
       9         459 :     constexpr uint8_t SysExStart =
      10             :         static_cast<uint8_t>(MIDIMessageType::SYSEX_START);
      11         459 :     constexpr uint8_t SysExEnd =
      12             :         static_cast<uint8_t>(MIDIMessageType::SYSEX_END);
      13             : 
      14             :     // If the previous byte was a SysExStart
      15             :     // I have to handle a start in the next time step, because a start can also
      16             :     // end the previous message. When that happens, I have to return
      17             :     // SYSEX_MESSAGE without resetting the buffer.
      18             :     // Then, after handling the message by the user, I do have to reset the
      19             :     // buffer.
      20         459 :     if (midimsg.header == SysExStart && !sysexbuffer.isReceiving()) {
      21          25 :         startSysEx();
      22          25 :         addSysExByte(SysExStart);
      23          25 :     }
      24             : #endif
      25             : 
      26             :     // If it's a status byte (first byte of a message)
      27         459 :     if (isStatus(midiByte)) {
      28             :         // If it's a Real-Time message
      29          91 :         if (midiByte >= uint8_t(MIDIMessageType::TIMING_CLOCK)) {
      30           8 :             rtmsg.message = midiByte;
      31           8 :             return MIDIReadEvent::REALTIME_MESSAGE;
      32             :         }
      33             :         // Normal header (channel message, system exclusive, system common)
      34             :         else {
      35             :             // If a SysEx message was being received, and now we receive
      36             :             // another status byte, remember to correctly terminate the SysEx
      37             :             // message later
      38          83 :             bool unterminatedSysEx = midimsg.header == SysExStart;
      39             : 
      40             :             // Save the newly received status byte
      41          83 :             midimsg.header = midiByte;
      42             :             // A new message starts, so we haven't received the second byte yet
      43          83 :             thirdByte = false;
      44             : 
      45          83 :             if (midimsg.header == uint8_t(MIDIMessageType::TUNE_REQUEST)) {
      46             :                 // Tune request (not implemented)
      47             :                 // TODO: should I implement this as a Real-Time message?
      48             :                 // (That might lead to problems when a SysEx message is
      49             :                 // terminated by a Tune Request, see unterminatedSysEx below)
      50             :                 // TODO: should I set midimsg.header in this case?
      51           0 :             }
      52             : 
      53             : #if !IGNORE_SYSEX
      54          83 :             if (unterminatedSysEx) {
      55             :                 // If we're currently receiving a SysEx message
      56          25 :                 addSysExByte(SysExEnd); // Try to add SysExEnd byte to buffer
      57             :                 // Even if the buffer is full, end the message anyway
      58          25 :                 endSysEx();
      59          25 :                 return MIDIReadEvent::SYSEX_MESSAGE;
      60             :             }
      61             : #else
      62             :             (void)unterminatedSysEx;
      63             : #endif // IGNORE_SYSEX
      64          83 :         }
      65          58 :     }
      66             : 
      67             :     // If it's a data byte
      68             :     else {
      69         368 :         if (midimsg.header == 0) {
      70           0 :             DEBUGFN("Warning: No header");
      71             :             ; // Ignore
      72           0 :         }
      73             :         // Third byte of three (data 2)
      74         368 :         else if (thirdByte) {
      75          23 :             midimsg.data2 = midiByte;
      76          23 :             thirdByte = false;
      77          23 :             return MIDIReadEvent::CHANNEL_MESSAGE;
      78             :         }
      79             :         // Second byte (data 1) or SysEx data
      80             :         else {
      81             :             // Channel message with two data bytes
      82         345 :             if (midimsg.hasTwoDataBytes()) {
      83          23 :                 midimsg.data1 = midiByte;
      84          23 :                 thirdByte = true; // expect a third byte next
      85          23 :             }
      86             :             // Channel message with one data byte
      87         322 :             else if (midimsg.hasValidHeader()) {
      88           6 :                 midimsg.data1 = midiByte;
      89           6 :                 return MIDIReadEvent::CHANNEL_MESSAGE;
      90             :             }
      91             :             // Not a channel message
      92             : #if !IGNORE_SYSEX
      93             :             // SysEx data byte
      94         316 :             else if (midimsg.header == SysExStart) {
      95         307 :                 addSysExByte(midiByte);
      96         307 :             }
      97             : #endif // IGNORE_SYSEX
      98             :             else {
      99           9 :                 DEBUGFN("Data byte ignored");
     100             :             }
     101             :         }
     102             :     }
     103         397 :     return MIDIReadEvent::NO_MESSAGE;
     104         459 : }
     105             : 
     106             : END_CS_NAMESPACE

Generated by: LCOV version 1.14-6-g40580cd