diff options
| author | Gary Scavone <gary@music.mcgill.ca> | 2014-03-14 12:44:06 -0400 |
|---|---|---|
| committer | Gary Scavone <gary@music.mcgill.ca> | 2014-03-14 12:44:06 -0400 |
| commit | d2530d10261f65c0e79541fc642092c178eec17c (patch) | |
| tree | 76664eb294feaca429aa508ba38c63b217716040 | |
| parent | cfb945a9c2aa53b631a0790f9554704e9e520aa6 (diff) | |
Updated OS-X sysex sending mechanism according to patch submitted by ptarabbia
| -rw-r--r-- | RtMidi.cpp | 62 | ||||
| -rw-r--r-- | doc/release.txt | 1 | ||||
| -rw-r--r-- | tests/sysextest.cpp | 2 |
3 files changed, 32 insertions, 33 deletions
@@ -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 ) @@ -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?"; diff --git a/doc/release.txt b/doc/release.txt index 7eefe46..3d8b59a 100644 --- a/doc/release.txt +++ b/doc/release.txt @@ -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)
diff --git a/tests/sysextest.cpp b/tests/sysextest.cpp index 68b9a0d..39228ea 100644 --- a/tests/sysextest.cpp +++ b/tests/sysextest.cpp @@ -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 ); |
