Skip to content

Commit

Permalink
Better types and stricter value checking when looping over MIDIPacket…
Browse files Browse the repository at this point in the history
… data in [MIKMIDICommand commandsWithMIDIPacket:].
  • Loading branch information
PatrickMIK committed Oct 17, 2024
1 parent 1447c9e commit ca6cbe4
Showing 1 changed file with 28 additions and 11 deletions.
39 changes: 28 additions & 11 deletions Source/MIKMIDICommand.m
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,33 @@ + (instancetype)commandWithMIDIPacket:(MIDIPacket *)packet;
+ (NSArray *)commandsWithMIDIPacket:(MIDIPacket *)inputPacket
{
NSMutableArray *result = [NSMutableArray array];
NSInteger dataOffset = 0;
ByteCount dataOffset = 0;
while (dataOffset < inputPacket->length) {
const Byte *packetData = inputPacket->data + dataOffset;
MIKMIDICommandType commandType = (MIKMIDICommandType)packetData[0];
NSInteger standardLength = MIKMIDIStandardLengthOfMessageForCommandType(commandType);
if (commandType == MIKMIDICommandTypeSystemExclusive) {
// For sysex, the packet can only contain a single MIDI message (as per documentation for MIDIPacket)
standardLength = inputPacket->length;
ByteCount eventDataLength = 0;
const Byte *eventData = inputPacket->data + dataOffset;
MIKMIDICommandType commandType = (MIKMIDICommandType)eventData[0];
switch (commandType) {
// For sysex, the packet can only contain a single MIDI message (as per documentation for MIDIPacket)
case MIKMIDICommandTypeSystemExclusive:
eventDataLength = inputPacket->length;
break;

// Is MIKMIDIStandardLengthOfMessageForCommandType() correct returning -1?
// This seems to be the realtime 'System Reset' message coming from a device
// (but could be a meta packet when coming from a file?)
case MIKMIDICommandTypeSystemMessage:
eventDataLength = 1;
break;

default: {
__auto_type standardLength = MIKMIDIStandardLengthOfMessageForCommandType(commandType);
NSAssert(standardLength > 0, @"message length failed for command type %lu", commandType);
eventDataLength = (ByteCount)standardLength;
break;
}
}
if (dataOffset > (inputPacket->length - standardLength)) break;

if (dataOffset > (inputPacket->length - eventDataLength)) break;

// This is gross, but it's the only way I can find to reliably create a
// single-message MIDIPacket.
Expand All @@ -74,12 +91,12 @@ + (NSArray *)commandsWithMIDIPacket:(MIDIPacket *)inputPacket
sizeof(MIDIPacketList),
midiPacket,
inputPacket->timeStamp,
standardLength,
packetData);
eventDataLength,
eventData);

MIKMIDICommand *command = [MIKMIDICommand commandWithMIDIPacket:midiPacket];
if (command) [result addObject:command];
dataOffset += standardLength;
dataOffset += eventDataLength;
}

return result;
Expand Down

1 comment on commit ca6cbe4

@armadsen
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Please sign in to comment.