Browse Source

Midi parsing fix for embedded realtime messages, and CoreMidi fix for sending large packets.

tags/2021-05-28
jules 13 years ago
parent
commit
a5a4e69f37
2 changed files with 69 additions and 24 deletions
  1. +40
    -9
      modules/juce_audio_devices/native/juce_MidiDataConcatenator.h
  2. +29
    -15
      modules/juce_audio_devices/native/juce_mac_CoreMidi.cpp

+ 40
- 9
modules/juce_audio_devices/native/juce_MidiDataConcatenator.h View File

@@ -37,13 +37,14 @@ public:
//============================================================================== //==============================================================================
MidiDataConcatenator (const int initialBufferSize) MidiDataConcatenator (const int initialBufferSize)
: pendingData ((size_t) initialBufferSize), : pendingData ((size_t) initialBufferSize),
pendingBytes (0), pendingDataTime (0)
pendingBytes (0), runningStatus (0), pendingDataTime (0)
{ {
} }
void reset() void reset()
{ {
pendingBytes = 0; pendingBytes = 0;
runningStatus = 0;
pendingDataTime = 0; pendingDataTime = 0;
} }
@@ -57,18 +58,48 @@ public:
if (pendingBytes > 0 || d[0] == 0xf0) if (pendingBytes > 0 || d[0] == 0xf0)
{ {
processSysex (d, numBytes, time, input, callback); processSysex (d, numBytes, time, input, callback);
runningStatus = 0;
} }
else else
{ {
int used = 0;
const MidiMessage m (d, numBytes, used, 0, time);
int len = 0;
uint8 data[3];
if (used <= 0)
break; // malformed message..
while (numBytes > 0)
{
// If there's a realtime message embedded in the middle of
// the normal message, handle it now..
if (*d >= 0xf8 && *d <= 0xfe)
{
const MidiMessage m (*d++, time);
callback.handleIncomingMidiMessage (input, m);
--numBytes;
}
else
{
if (len == 0 && *d < 0x80 && runningStatus >= 0x80)
data[len++] = runningStatus;
data[len++] = *d++;
--numBytes;
callback.handleIncomingMidiMessage (input, m);
numBytes -= used;
d += used;
if (len >= MidiMessage::getMessageLengthFromFirstByte (data[0]))
break;
}
}
if (len > 0)
{
int used = 0;
const MidiMessage m (data, len, used, 0, time);
if (used <= 0)
break; // malformed message..
jassert (used == len);
callback.handleIncomingMidiMessage (input, m);
runningStatus = data[0];
}
} }
} }
} }
@@ -133,7 +164,7 @@ private:
} }
MemoryBlock pendingData; MemoryBlock pendingData;
int pendingBytes;
int pendingBytes, runningStatus;
double pendingDataTime; double pendingDataTime;
JUCE_DECLARE_NON_COPYABLE (MidiDataConcatenator); JUCE_DECLARE_NON_COPYABLE (MidiDataConcatenator);


+ 29
- 15
modules/juce_audio_devices/native/juce_mac_CoreMidi.cpp View File

@@ -359,24 +359,27 @@ MidiOutput::~MidiOutput()
void MidiOutput::sendMessageNow (const MidiMessage& message) void MidiOutput::sendMessageNow (const MidiMessage& message)
{ {
CoreMidiHelpers::MidiPortAndEndpoint* const mpe = static_cast<CoreMidiHelpers::MidiPortAndEndpoint*> (internal);
#if JUCE_IOS #if JUCE_IOS
const MIDITimeStamp timeStamp = mach_absolute_time(); const MIDITimeStamp timeStamp = mach_absolute_time();
#else #else
const MIDITimeStamp timeStamp = AudioGetCurrentHostTime(); const MIDITimeStamp timeStamp = AudioGetCurrentHostTime();
#endif #endif
HeapBlock <MIDIPacketList> allocatedPackets;
MIDIPacketList stackPacket;
MIDIPacketList* packetToSend = &stackPacket;
const size_t dataSize = (size_t) message.getRawDataSize();
if (message.isSysEx()) if (message.isSysEx())
{ {
const int maxPacketSize = 256; const int maxPacketSize = 256;
int pos = 0, bytesLeft = message.getRawDataSize();
int pos = 0, bytesLeft = (int) dataSize;
const int numPackets = (bytesLeft + maxPacketSize - 1) / maxPacketSize; const int numPackets = (bytesLeft + maxPacketSize - 1) / maxPacketSize;
HeapBlock <MIDIPacketList> packets;
packets.malloc ((size_t) (32 * numPackets + message.getRawDataSize()), 1);
packets->numPackets = (UInt32) numPackets;
allocatedPackets.malloc ((size_t) (32 * numPackets + dataSize), 1);
packetToSend = allocatedPackets;
packetToSend->numPackets = (UInt32) numPackets;
MIDIPacket* p = packets->packet;
MIDIPacket* p = packetToSend->packet;
for (int i = 0; i < numPackets; ++i) for (int i = 0; i < numPackets; ++i)
{ {
@@ -387,19 +390,30 @@ void MidiOutput::sendMessageNow (const MidiMessage& message)
bytesLeft -= p->length; bytesLeft -= p->length;
p = MIDIPacketNext (p); p = MIDIPacketNext (p);
} }
}
else if (dataSize < 65536) // max packet size
{
const size_t stackCapacity = sizeof (stackPacket.packet->data);
mpe->send (packets);
if (dataSize > stackCapacity)
{
allocatedPackets.malloc ((sizeof (MIDIPacketList) - stackCapacity) + dataSize, 1);
packetToSend = allocatedPackets;
}
packetToSend->numPackets = 1;
MIDIPacket& p = *(packetToSend->packet);
p.timeStamp = timeStamp;
p.length = (UInt16) dataSize;
memcpy (p.data, message.getRawData(), dataSize);
} }
else else
{ {
MIDIPacketList packets;
packets.numPackets = 1;
packets.packet[0].timeStamp = timeStamp;
packets.packet[0].length = (UInt16) message.getRawDataSize();
*(int*) (packets.packet[0].data) = *(const int*) message.getRawData();
mpe->send (&packets);
jassertfalse; // packet too large to send!
return;
} }
static_cast<CoreMidiHelpers::MidiPortAndEndpoint*> (internal)->send (packetToSend);
} }
//============================================================================== //==============================================================================


Loading…
Cancel
Save