Skip to content

Commit

Permalink
Updated OS-X sysex sending mechanism according to patch submitted by …
Browse files Browse the repository at this point in the history
…ptarabbia
  • Loading branch information
garyscavone committed Mar 14, 2014
1 parent cfb945a commit d2530d1
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 33 deletions.
62 changes: 30 additions & 32 deletions RtMidi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -993,13 +993,9 @@ void MidiOutCore :: openVirtualPort( std::string portName )
data->endpoint = endpoint;
}

static char *sysexBuffer = 0;

static void sysexCompletionProc( MIDISysexSendRequest * /*sreq*/ )
static void sysexCompletionProc( MIDISysexSendRequest *sreq )
{
//std::cout << "Completed SysEx send\n";
delete sysexBuffer;
sysexBuffer = 0;
free( sreq );
}

void MidiOutCore :: sendMessage( std::vector<unsigned char> *message )
Expand All @@ -1021,32 +1017,34 @@ void MidiOutCore :: sendMessage( std::vector<unsigned char> *message )

if ( message->at(0) == 0xF0 ) {

while ( sysexBuffer != 0 ) usleep( 1000 ); // sleep 1 ms

sysexBuffer = new char[nBytes];
if ( sysexBuffer == NULL ) {
errorString_ = "MidiOutCore::sendMessage: error allocating sysex message memory!";
error( RtMidiError::MEMORY_ERROR, errorString_ );
return;
}

// Copy data to buffer.
for ( unsigned int i=0; i<nBytes; ++i ) sysexBuffer[i] = message->at(i);

data->sysexreq.destination = data->destinationId;
data->sysexreq.data = (Byte *)sysexBuffer;
data->sysexreq.bytesToSend = nBytes;
data->sysexreq.complete = 0;
data->sysexreq.completionProc = sysexCompletionProc;
data->sysexreq.completionRefCon = &(data->sysexreq);

result = MIDISendSysex( &(data->sysexreq) );
if ( result != noErr ) {
errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations.";
error( RtMidiError::WARNING, errorString_ );
return;
}
return;
// 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 ( nBytes > 3 ) {
errorString_ = "MidiOutCore::sendMessage: message format problem ... not sysex but > 3 bytes?";
Expand Down
1 change: 1 addition & 0 deletions doc/release.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ v2.1.0: (?? 2014)
- added custom error hook that allows the client to capture an RtMidi error outside of the RtMidi code
- fix for portnames in Windows when UNICODE is defined
- added RtMidi::isPortOpen function
- updated OS-X sysex sending mechanism (ptarabbia)

v2.0.1: (26 July 2012)
- small fixes for problems reported by Chris Arndt (scoping, preprocessor, and include)
Expand Down
2 changes: 1 addition & 1 deletion tests/sysextest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ int main( int argc, char *argv[] )
midiout->sendMessage( &message );
SLEEP( 500 ); // pause a little

// Create a long sysex messages of numbered bytes and send it out.
// Create a long sysex message of numbered bytes and send it out.
for ( int n=0; n<2; n++ ) {
message.clear();
message.push_back( 240 );
Expand Down

0 comments on commit d2530d1

Please sign in to comment.