summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgaryscavone <garyscavone@users.noreply.github.com>2014-11-03 14:17:37 -0500
committergaryscavone <garyscavone@users.noreply.github.com>2014-11-03 14:17:37 -0500
commitbde543abbf4b22eaf5b250c81761d984ce9060e6 (patch)
treeafb6b01ed0a64580697160966a9f5b693a6a5342
parente52bfa207cec24fc0c1cc1cb017e8f63de4a5a11 (diff)
parent4e5974b6e3c805183c2dc33ecab829ff9b89c406 (diff)
Merge pull request #34 from olilarkin/fixsysex
Fix CoreMIDI sysex
-rw-r--r--RtMidi.cpp65
1 files changed, 16 insertions, 49 deletions
diff --git a/RtMidi.cpp b/RtMidi.cpp
index 4dd9f02..27a4705 100644
--- a/RtMidi.cpp
+++ b/RtMidi.cpp
@@ -1007,62 +1007,29 @@ void MidiOutCore :: sendMessage( std::vector<unsigned char> *message )
return;
}
- // unsigned int packetBytes, bytesLeft = nBytes;
- // unsigned int messageIndex = 0;
MIDITimeStamp timeStamp = AudioGetCurrentHostTime();
CoreMidiData *data = static_cast<CoreMidiData *> (apiData_);
OSStatus result;
- ///*
- // It would be nice if the following "special-case" code for sysex
- // messages longer than 1024 bytes wasn't necessary. In fact, we
- // can send sysex messages through the normal messaging mechanism.
- // However, that does not work for messages greater than 1024
- // bytes. From a previous note, there may be a problem of virtual
- // ports not receiving sysex messages when using this section of
- // code.
-
- if ( message->at(0) == 0xF0 && nBytes > 1022 ) {
-
- // Apple's fantastic API requires us to free the allocated data in
- // the completion callback but trashes the pointer and size before
- // we get a chance to free it!! This is a somewhat ugly hack
- // submitted by ptarabbia that puts the sysex buffer data right at
- // the end of the MIDISysexSendRequest structure. This solution
- // does not require that we wait for a previous sysex buffer to be
- // sent before sending a new one, which was the old way we did it.
- MIDISysexSendRequest *newRequest = (MIDISysexSendRequest *) malloc(sizeof(struct MIDISysexSendRequest) + nBytes);
- char * sysexBuffer = ((char *) newRequest) + sizeof(struct MIDISysexSendRequest);
-
- // Copy data to buffer.
- for ( unsigned int i=0; i<nBytes; ++i ) sysexBuffer[i] = message->at(i);
-
- newRequest->destination = data->destinationId;
- newRequest->data = (Byte *)sysexBuffer;
- newRequest->bytesToSend = nBytes;
- newRequest->complete = 0;
- newRequest->completionProc = sysexCompletionProc;
- newRequest->completionRefCon = newRequest;
-
- result = MIDISendSysex(newRequest);
- if ( result != noErr ) {
- free( newRequest );
- errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations.";
- error( RtMidiError::WARNING, errorString_ );
- return;
- }
- return;
- }
- else if ( message->at(0) != 0xF0 && nBytes > 3 ) {
+ if ( message->at(0) != 0xF0 && nBytes > 3 ) {
errorString_ = "MidiOutCore::sendMessage: message format problem ... not sysex but > 3 bytes?";
error( RtMidiError::WARNING, errorString_ );
return;
}
- //*/
- MIDIPacketList packetList;
- MIDIPacket *packet = MIDIPacketListInit( &packetList );
- packet = MIDIPacketListAdd( &packetList, sizeof(packetList), packet, timeStamp, nBytes, (const Byte *) &message->at( 0 ) );
+ Byte buffer[nBytes+(sizeof(MIDIPacketList))];
+ ByteCount listSize = sizeof(buffer);
+ MIDIPacketList *packetList = (MIDIPacketList*)buffer;
+ MIDIPacket *packet = MIDIPacketListInit( packetList );
+
+ ByteCount remainingBytes = nBytes;
+ while (remainingBytes && packet) {
+ ByteCount bytesForPacket = remainingBytes > 65535 ? 65535 : remainingBytes; // 65535 = maximum size of a MIDIPacket
+ const Byte* dataStartPtr = (const Byte *) &message->at( nBytes - remainingBytes );
+ packet = MIDIPacketListAdd( packetList, listSize, packet, timeStamp, bytesForPacket, dataStartPtr);
+ remainingBytes -= bytesForPacket;
+ }
+
if ( !packet ) {
errorString_ = "MidiOutCore::sendMessage: could not allocate packet list";
error( RtMidiError::DRIVER_ERROR, errorString_ );
@@ -1071,7 +1038,7 @@ void MidiOutCore :: sendMessage( std::vector<unsigned char> *message )
// Send to any destinations that may have connected to us.
if ( data->endpoint ) {
- result = MIDIReceived( data->endpoint, &packetList );
+ result = MIDIReceived( data->endpoint, packetList );
if ( result != noErr ) {
errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations.";
error( RtMidiError::WARNING, errorString_ );
@@ -1080,7 +1047,7 @@ void MidiOutCore :: sendMessage( std::vector<unsigned char> *message )
// And send to an explicit destination port if we're connected.
if ( connected_ ) {
- result = MIDISend( data->port, data->destinationId, &packetList );
+ result = MIDISend( data->port, data->destinationId, packetList );
if ( result != noErr ) {
errorString_ = "MidiOutCore::sendMessage: error sending MIDI message to port.";
error( RtMidiError::WARNING, errorString_ );