11// https://www.ietf.org/rfc/rfc4695.html#section-3
22
3- parserReturn decodeMidiSection (RtpBuffer_t &buffer)
3+ parserReturn decodeMIDICommandSection (RtpBuffer_t &buffer)
44{
5- int cmdCount = 0 ;
6-
75 // https://www.ietf.org/rfc/rfc4695.html#section-3.2
86 //
97 // The first MIDI channel command in the MIDI list MUST include a status
@@ -39,92 +37,90 @@ parserReturn decodeMidiSection(RtpBuffer_t &buffer)
3937 // line.
4038
4139 // (lathoub: RTP_MIDI_CS_FLAG_P((phantom) not implemented
42-
43- uint8_t runningstatus = 0 ;
4440
4541 /* Multiple MIDI-commands might follow - the exact number can only be discovered by really decoding the commands! */
4642 while (midiCommandLength)
4743 {
44+ Serial.print (" midiCommandLength: " );
45+ Serial.print (midiCommandLength);
46+ Serial.print (" cmdCount: " );
47+ Serial.println (cmdCount);
48+
4849 /* for the first command we only have a delta-time if Z-Flag is set */
4950 if ((cmdCount) || (rtpMidi_Flags & RTP_MIDI_CS_FLAG_Z))
5051 {
51- auto consumed = decodeTime (buffer );
52+ Serial. println ( " decoding time " );
5253
53- midiCommandLength -= consumed;
54+ size_t consumed = 0 ;
55+ auto retVal = decodeTime (buffer, consumed);
56+ if (retVal != parserReturn::Processed) return retVal;
5457
58+ midiCommandLength -= consumed;
5559 while (consumed--)
5660 buffer.pop_front ();
57-
58- if (midiCommandLength > 0 && 0 >= buffer.size ())
59- return parserReturn::NotEnoughData;
6061 }
6162
6263 if (midiCommandLength > 0 )
6364 {
64- /* Decode a MIDI-command - if 0 is returned something went wrong */
65- size_t consumed = decodeMidi (buffer, runningstatus);
66- if (consumed == 0 )
67- {
68- }
69- else if (consumed > buffer.size ())
70- {
71- // sysex split in decodeMidi
72- return parserReturn::NotEnoughData;
73- }
65+ Serial.println (" decoding MIDIcommand section" );
66+
67+ cmdCount++;
7468
75- if (consumed > midiCommandLength) {
76- buffer.clear ();
77- return parserReturn::UnexpectedMidiData;
69+ size_t consumed = 0 ;
70+ auto retVal = decodeMidi (buffer, runningstatus, consumed);
71+ if (retVal == parserReturn::NotEnoughData) {
72+ cmdCount = 0 ; // avoid first command again
73+ return retVal;
7874 }
7975
8076 midiCommandLength -= consumed;
81-
8277 while (consumed--)
8378 buffer.pop_front ();
84-
85- if (midiCommandLength > 0 && 0 >= buffer.size ())
86- return parserReturn::NotEnoughData;
87-
88- cmdCount++;
8979 }
9080 }
9181
9282 return parserReturn::Processed;
9383}
9484
95- size_t decodeTime (RtpBuffer_t &buffer)
85+ parserReturn decodeTime (RtpBuffer_t &buffer, size_t &consumed )
9686{
97- uint8_t consumed = 0 ;
9887 uint32_t deltatime = 0 ;
9988
10089 /* RTP-MIDI deltatime is "compressed" using only the necessary amount of octets */
10190 for (uint8_t j = 0 ; j < 4 ; j++)
10291 {
92+ if (buffer.size () < 1 )
93+ return parserReturn::NotEnoughData;
94+
10395 uint8_t octet = buffer[consumed];
10496 deltatime = (deltatime << 7 ) | (octet & RTP_MIDI_DELTA_TIME_OCTET_MASK);
10597 consumed++;
10698
10799 if ((octet & RTP_MIDI_DELTA_TIME_EXTENSION) == 0 )
108100 break ;
109101 }
110- return consumed;
102+
103+ return parserReturn::Processed;
111104}
112105
113- size_t decodeMidi (RtpBuffer_t &buffer, uint8_t &runningstatus)
106+ parserReturn decodeMidi (RtpBuffer_t &buffer, uint8_t &runningstatus, size_t &consumed )
114107{
115- size_t consumed = 0 ;
108+ if (buffer.size () < 1 )
109+ return parserReturn::NotEnoughData;
116110
117- auto octet = buffer[ 0 ] ;
111+ auto octet = buffer. front () ;
118112
119113 /* MIDI realtime-data -> one octet -- unlike serial-wired MIDI realtime-commands in RTP-MIDI will
120114 * not be intermingled with other MIDI-commands, so we handle this case right here and return */
121115 if (octet >= 0xf8 )
122116 {
117+ consumed = 1 ;
118+
123119 session->StartReceivedMidi ();
124- session->ReceivedMidi (buffer[ 0 ] );
120+ session->ReceivedMidi (octet );
125121 session->EndReceivedMidi ();
126122
127- return 1 ;
123+ return parserReturn::Processed ;
128124 }
129125
130126 /* see if this first octet is a status message */
@@ -133,7 +129,7 @@ size_t decodeMidi(RtpBuffer_t &buffer, uint8_t &runningstatus)
133129 /* if we have no running status yet -> error */
134130 if (((runningstatus)&RTP_MIDI_COMMAND_STATUS_FLAG) == 0 )
135131 {
136- return 0 ;
132+ return parserReturn::Processed ;
137133 }
138134 /* our first octet is "virtual" coming from a preceding MIDI-command,
139135 * so actually we have not really consumed anything yet */
@@ -160,10 +156,8 @@ size_t decodeMidi(RtpBuffer_t &buffer, uint8_t &runningstatus)
160156 /* non-system MIDI-commands encode the command in the high nibble and the channel
161157 * in the low nibble - so we will take care of those cases next */
162158 if (octet < 0xf0 )
163- {
164- uint8_t type = (octet & 0xf0 );
165-
166- switch (type)
159+ {
160+ switch (octet & 0xf0 )
167161 {
168162 case MIDI_NAMESPACE::MidiType::NoteOff:
169163 consumed += 2 ;
@@ -188,22 +182,25 @@ size_t decodeMidi(RtpBuffer_t &buffer, uint8_t &runningstatus)
188182 break ;
189183 }
190184
185+ if (buffer.size () < consumed)
186+ return parserReturn::NotEnoughData;
187+
191188 session->StartReceivedMidi ();
192189 for (size_t j = 0 ; j < consumed; j++)
193190 session->ReceivedMidi (buffer[j]);
194191 session->EndReceivedMidi ();
195192
196- return consumed ;
193+ return parserReturn::Processed ;
197194 }
198195
199196 /* Here we catch the remaining system-common commands */
200197 switch (octet)
201198 {
202199 case MIDI_NAMESPACE::MidiType::SystemExclusiveStart:
203200 case MIDI_NAMESPACE::MidiType::SystemExclusiveEnd:
204- consumed = decodeMidiSysEx (buffer);
205- if (consumed > buffer.max_size ())
206- return consumed;
201+ consumed = decodeMidiSysEx (buffer, consumed );
202+ // if (consumed > buffer.max_size())
203+ // return consumed;
207204 break ;
208205 case MIDI_NAMESPACE::MidiType::TimeCodeQuarterFrame:
209206 consumed += 1 ;
@@ -218,17 +215,20 @@ size_t decodeMidi(RtpBuffer_t &buffer, uint8_t &runningstatus)
218215 break ;
219216 }
220217
218+ if (buffer.size () < consumed)
219+ return parserReturn::NotEnoughData;
220+
221221 session->StartReceivedMidi ();
222222 for (size_t j = 0 ; j < consumed; j++)
223223 session->ReceivedMidi (buffer[j]);
224224 session->EndReceivedMidi ();
225225
226- return consumed ;
226+ return parserReturn::Processed ;
227227}
228228
229- size_t decodeMidiSysEx (RtpBuffer_t &buffer)
229+ parserReturn decodeMidiSysEx (RtpBuffer_t &buffer, size_t &consumed )
230230{
231- size_t consumed = 1 ; // beginning SysEx Token is not counted (as it could remain)
231+ consumed = 1 ; // beginning SysEx Token is not counted (as it could remain)
232232 size_t i = 0 ;
233233 auto octet = buffer[++i];
234234
@@ -237,9 +237,9 @@ size_t decodeMidiSysEx(RtpBuffer_t &buffer)
237237 consumed++;
238238 octet = buffer[i++];
239239 if (octet == MIDI_NAMESPACE::MidiType::SystemExclusiveEnd) // Complete message
240- return consumed ;
240+ return parserReturn::Processed ;
241241 else if (octet == MIDI_NAMESPACE::MidiType::SystemExclusiveStart) // Start
242- return consumed ;
242+ return parserReturn::Processed ;
243243 }
244244
245245 // begin of the SysEx is found, not the end.
@@ -266,5 +266,7 @@ size_t decodeMidiSysEx(RtpBuffer_t &buffer)
266266 midiCommandLength += 1 ; // adding the manual SysEx SystemExclusiveEnd
267267
268268 // indicates split SysEx
269- return buffer.max_size () + 1 ;
269+ consumed = buffer.max_size () + 1 ;
270+
271+ return parserReturn::Processed;
270272}
0 commit comments