diff options
| author | Gary Scavone <gary@music.mcgill.ca> | 2013-10-11 14:49:11 +0200 |
|---|---|---|
| committer | Stephen Sinclair <sinclair@music.mcgill.ca> | 2013-10-11 14:49:11 +0200 |
| commit | 94ef7a9c9202314c5fe9de2dc24b16ded6b7d98c (patch) | |
| tree | 2cd7541d54992c8cc486e001d7784d6f461b6e59 | |
| parent | fca075f4b54cb4600d06783a225a94e3dd45d640 (diff) | |
Version 1.0.11
| -rw-r--r-- | RtMidi.cpp | 115 | ||||
| -rw-r--r-- | RtMidi.h | 4 | ||||
| -rw-r--r-- | doc/doxygen/Doxyfile | 2 | ||||
| -rw-r--r-- | doc/doxygen/footer.html | 2 | ||||
| -rw-r--r-- | doc/doxygen/tutorial.txt | 7 | ||||
| -rw-r--r-- | doc/release.txt | 8 | ||||
| -rw-r--r-- | readme | 4 |
7 files changed, 79 insertions, 63 deletions
@@ -8,7 +8,7 @@ RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/ RtMidi: realtime MIDI i/o C++ classes - Copyright (c) 2003-2009 Gary P. Scavone + Copyright (c) 2003-2010 Gary P. Scavone Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -35,7 +35,7 @@ */ /**********************************************************************/ -// RtMidi: Version 1.0.10 +// RtMidi: Version 1.0.11 #include "RtMidi.h" #include <sstream> @@ -166,6 +166,7 @@ RtMidiOut :: RtMidiOut( const std::string clientName ) : RtMidi() // OS-X CoreMIDI header files. #include <CoreMIDI/CoreMIDI.h> #include <CoreAudio/HostTime.h> +#include <CoreServices/CoreServices.h> // A structure to hold variables related to the CoreMIDI API // implementation. @@ -226,7 +227,7 @@ void midiInputCallback( const MIDIPacketList *list, void *procRef, void *srcRef // We have a continuing, segmented sysex message. if ( !( data->ignoreFlags & 0x01 ) ) { // If we're not ignoring sysex messages, copy the entire packet. - for ( unsigned int j=0; j<nBytes; j++ ) + for ( unsigned int j=0; j<nBytes; ++j ) message.bytes.push_back( packet->data[j] ); } continueSysex = packet->data[nBytes-1] != 0xF7; @@ -368,7 +369,7 @@ void RtMidiIn :: openPort( unsigned int portNumber, const std::string portName ) // Get the desired input source identifier. MIDIEndpointRef endpoint = MIDIGetSource( portNumber ); - if ( endpoint == NULL ) { + if ( endpoint == 0 ) { MIDIPortDispose( port ); MIDIClientDispose( data->client ); errorString_ = "RtMidiIn::openPort: error getting MIDI input source reference."; @@ -451,7 +452,7 @@ CFStringRef EndpointName( MIDIEndpointRef endpoint, bool isExternal ) MIDIEntityRef entity = NULL; MIDIEndpointGetEntity( endpoint, &entity ); - if ( entity == NULL ) + if ( entity == 0 ) // probably virtual return result; @@ -465,9 +466,9 @@ CFStringRef EndpointName( MIDIEndpointRef endpoint, bool isExternal ) } } // now consider the device's name - MIDIDeviceRef device = NULL; + MIDIDeviceRef device = 0; MIDIEntityGetDevice( entity, &device ); - if ( device == NULL ) + if ( device == 0 ) return result; str = NULL; @@ -665,7 +666,7 @@ void RtMidiOut :: openPort( unsigned int portNumber, const std::string portName // Get the desired output port identifier. MIDIEndpointRef destination = MIDIGetDestination( portNumber ); - if ( destination == NULL ) { + if ( destination == 0 ) { MIDIPortDispose( port ); MIDIClientDispose( data->client ); errorString_ = "RtMidiOut::openPort: error getting MIDI output destination reference."; @@ -1042,7 +1043,7 @@ unsigned int portInfo( snd_seq_t *seq, snd_seq_port_info_t *pinfo, unsigned int unsigned int caps = snd_seq_port_info_get_capability( pinfo ); if ( ( caps & type ) != type ) continue; if ( count == portNumber ) return 1; - count++; + ++count; } } @@ -1225,8 +1226,8 @@ RtMidiIn :: ~RtMidiIn() if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport ); #ifndef AVOID_TIMESTAMPING snd_seq_free_queue( data->seq, data->queue_id ); - snd_seq_close( data->seq ); #endif + snd_seq_close( data->seq ); delete data; } @@ -1458,7 +1459,7 @@ void RtMidiOut :: sendMessage( std::vector<unsigned char> *message ) snd_seq_ev_set_source(&ev, data->vport); snd_seq_ev_set_subs(&ev); snd_seq_ev_set_direct(&ev); - for ( unsigned int i=0; i<nBytes; i++ ) data->buffer[i] = message->at(i); + for ( unsigned int i=0; i<nBytes; ++i ) data->buffer[i] = message->at(i); result = snd_midi_event_encode( data->coder, data->buffer, (long)nBytes, &ev ); if ( result < (int)nBytes ) { errorString_ = "RtMidiOut::sendMessage: event parsing error!"; @@ -1564,7 +1565,7 @@ extern "C" void *irixMidiHandler( void *ptr ) if ( continueSysex ) { // We have a continuing, segmented sysex message. Append // the new bytes to our existing message. - for ( int i=0; i<event.msglen; i++ ) + for ( int i=0; i<event.msglen; ++i ) message.bytes.push_back( event.sysexmsg[i] ); if ( event.sysexmsg[event.msglen-1] == 0xF7 ) continueSysex = false; if ( !continueSysex ) { @@ -1858,11 +1859,11 @@ void RtMidiOut :: sendMessage( std::vector<unsigned char> *message ) event.msg[0] = 0xF0; event.msglen = nBytes; buffer = (char *) malloc( nBytes ); - for ( int i=0; i<nBytes; i++ ) buffer[i] = message->at(i); + for ( int i=0; i<nBytes; ++i ) buffer[i] = message->at(i); event.sysexmsg = buffer; } else { - for ( int i=0; i<nBytes; i++ ) + for ( int i=0; i<nBytes; ++i ) event.msg[i] = message->at(i); } @@ -1897,6 +1898,9 @@ void RtMidiOut :: sendMessage( std::vector<unsigned char> *message ) #include <windows.h> #include <mmsystem.h> +#define RT_SYSEX_BUFFER_SIZE 1024 +#define RT_SYSEX_BUFFER_COUNT 4 + // A structure to hold variables related to the CoreMIDI API // implementation. struct WinMidiData { @@ -1904,11 +1908,9 @@ struct WinMidiData { HMIDIOUT outHandle; // Handle to Midi Output Device DWORD lastTime; RtMidiIn::MidiMessage message; - LPMIDIHDR sysexBuffer; + LPMIDIHDR sysexBuffer[RT_SYSEX_BUFFER_COUNT]; }; -#define RT_SYSEX_BUFFER_SIZE 1024 - //*********************************************************************// // API: Windows MM // Class Definitions: RtMidiIn @@ -1920,7 +1922,7 @@ static void CALLBACK midiInputCallback( HMIDIOUT hmin, DWORD midiMessage, DWORD timestamp ) { - if ( inputStatus != MIM_DATA && inputStatus != MIM_LONGDATA ) return; + if ( inputStatus != MIM_DATA && inputStatus != MIM_LONGDATA && inputStatus != MIM_LONGERROR ) return; //RtMidiIn::RtMidiInData *data = static_cast<RtMidiIn::RtMidiInData *> (instancePtr); RtMidiIn::RtMidiInData *data = (RtMidiIn::RtMidiInData *)instancePtr; @@ -1960,13 +1962,13 @@ static void CALLBACK midiInputCallback( HMIDIOUT hmin, // Copy bytes to our MIDI message. unsigned char *ptr = (unsigned char *) &midiMessage; - for ( int i=0; i<nBytes; i++ ) apiData->message.bytes.push_back( *ptr++ ); + for ( int i=0; i<nBytes; ++i ) apiData->message.bytes.push_back( *ptr++ ); } - else { // Sysex message ( MIM_LONGDATA ) + else { // Sysex message ( MIM_LONGDATA or MIM_LONGERROR ) MIDIHDR *sysex = ( MIDIHDR *) midiMessage; - if ( !( data->ignoreFlags & 0x01 ) ) { + if ( !( data->ignoreFlags & 0x01 ) && inputStatus != MIM_LONGERROR ) { // Sysex message and we're not ignoring it - for ( int i=0; i<(int)sysex->dwBytesRecorded; i++ ) + for ( int i=0; i<(int)sysex->dwBytesRecorded; ++i ) apiData->message.bytes.push_back( sysex->lpData[i] ); } @@ -1978,9 +1980,9 @@ static void CALLBACK midiInputCallback( HMIDIOUT hmin, // buffer when an application closes and in this case, we should // avoid requeueing it, else the computer suddenly reboots after // one or two minutes. - if ( apiData->sysexBuffer->dwBytesRecorded > 0 ) { - //if ( sysex->dwBytesRecorded > 0 ) { - MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer, sizeof(MIDIHDR) ); + if ( apiData->sysexBuffer[sysex->dwUser]->dwBytesRecorded > 0 ) { + //if ( sysex->dwBytesRecorded > 0 ) { + MMRESULT result = midiInAddBuffer( apiData->inHandle, apiData->sysexBuffer[sysex->dwUser], sizeof(MIDIHDR) ); if ( result != MMSYSERR_NOERROR ) std::cerr << "\nRtMidiIn::midiInputCallback: error sending sysex to Midi device!!\n\n"; @@ -2054,25 +2056,28 @@ void RtMidiIn :: openPort( unsigned int portNumber, const std::string /*portName error( RtError::DRIVER_ERROR ); } - // Allocate and init the sysex buffer. - data->sysexBuffer = (MIDIHDR*) new char[ sizeof(MIDIHDR) ]; - data->sysexBuffer->lpData = new char[ RT_SYSEX_BUFFER_SIZE ]; - data->sysexBuffer->dwBufferLength = RT_SYSEX_BUFFER_SIZE; - data->sysexBuffer->dwFlags = 0; + // Allocate and init the sysex buffers. + for ( int i=0; i<RT_SYSEX_BUFFER_COUNT; ++i ) { + data->sysexBuffer[i] = (MIDIHDR*) new char[ sizeof(MIDIHDR) ]; + data->sysexBuffer[i]->lpData = new char[ RT_SYSEX_BUFFER_SIZE ]; + data->sysexBuffer[i]->dwBufferLength = RT_SYSEX_BUFFER_SIZE; + data->sysexBuffer[i]->dwUser = i; // We use the dwUser parameter as buffer indicator + data->sysexBuffer[i]->dwFlags = 0; - result = midiInPrepareHeader( data->inHandle, data->sysexBuffer, sizeof(MIDIHDR) ); - if ( result != MMSYSERR_NOERROR ) { - midiInClose( data->inHandle ); - errorString_ = "RtMidiIn::openPort: error starting Windows MM MIDI input port (PrepareHeader)."; - error( RtError::DRIVER_ERROR ); - } + result = midiInPrepareHeader( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + errorString_ = "RtMidiIn::openPort: error starting Windows MM MIDI input port (PrepareHeader)."; + error( RtError::DRIVER_ERROR ); + } - // Register the buffer. - result = midiInAddBuffer( data->inHandle, data->sysexBuffer, sizeof(MIDIHDR) ); - if ( result != MMSYSERR_NOERROR ) { - midiInClose( data->inHandle ); - errorString_ = "RtMidiIn::openPort: error starting Windows MM MIDI input port (AddBuffer)."; - error( RtError::DRIVER_ERROR ); + // Register the buffer. + result = midiInAddBuffer( data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR) ); + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + errorString_ = "RtMidiIn::openPort: error starting Windows MM MIDI input port (AddBuffer)."; + error( RtError::DRIVER_ERROR ); + } } result = midiInStart( data->inHandle ); @@ -2099,13 +2104,15 @@ void RtMidiIn :: closePort( void ) midiInReset( data->inHandle ); midiInStop( data->inHandle ); - int result = midiInUnprepareHeader(data->inHandle, data->sysexBuffer, sizeof(MIDIHDR)); - delete [] data->sysexBuffer->lpData; - delete [] data->sysexBuffer; - if ( result != MMSYSERR_NOERROR ) { - midiInClose( data->inHandle ); - errorString_ = "RtMidiIn::openPort: error closing Windows MM MIDI input port (midiInUnprepareHeader)."; - error( RtError::DRIVER_ERROR ); + for ( int i=0; i<RT_SYSEX_BUFFER_COUNT; ++i ) { + int result = midiInUnprepareHeader(data->inHandle, data->sysexBuffer[i], sizeof(MIDIHDR)); + delete [] data->sysexBuffer[i]->lpData; + delete [] data->sysexBuffer[i]; + if ( result != MMSYSERR_NOERROR ) { + midiInClose( data->inHandle ); + errorString_ = "RtMidiIn::openPort: error closing Windows MM MIDI input port (midiInUnprepareHeader)."; + error( RtError::DRIVER_ERROR ); + } } midiInClose( data->inHandle ); @@ -2145,7 +2152,7 @@ std::string RtMidiIn :: getPortName( unsigned int portNumber ) // UNICODE (thanks to Eduardo Coutinho!). //std::string stringName = std::string( deviceCaps.szPname ); char nameString[MAXPNAMELEN]; - for( int i=0; i<MAXPNAMELEN; i++ ) + for( int i=0; i<MAXPNAMELEN; ++i ) nameString[i] = (char)( deviceCaps.szPname[i] ); std::string stringName( nameString ); @@ -2179,7 +2186,7 @@ std::string RtMidiOut :: getPortName( unsigned int portNumber ) // UNICODE (thanks to Eduardo Coutinho!). //std::string stringName = std::string( deviceCaps.szPname ); char nameString[MAXPNAMELEN]; - for( int i=0; i<MAXPNAMELEN; i++ ) + for( int i=0; i<MAXPNAMELEN; ++i ) nameString[i] = (char)( deviceCaps.szPname[i] ); std::string stringName( nameString ); @@ -2284,7 +2291,7 @@ void RtMidiOut :: sendMessage( std::vector<unsigned char> *message ) } // Copy data to buffer. - for ( unsigned int i=0; i<nBytes; i++ ) buffer[i] = message->at(i); + for ( unsigned int i=0; i<nBytes; ++i ) buffer[i] = message->at(i); // Create and prepare MIDIHDR structure. MIDIHDR sysex; @@ -2323,9 +2330,9 @@ void RtMidiOut :: sendMessage( std::vector<unsigned char> *message ) // Pack MIDI bytes into double word. DWORD packet; unsigned char *ptr = (unsigned char *) &packet; - for ( unsigned int i=0; i<nBytes; i++ ) { + for ( unsigned int i=0; i<nBytes; ++i ) { *ptr = message->at(i); - ptr++; + ++ptr; } // Send the message immediately. @@ -8,7 +8,7 @@ RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/ RtMidi: realtime MIDI i/o C++ classes - Copyright (c) 2003-2009 Gary P. Scavone + Copyright (c) 2003-2010 Gary P. Scavone Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -35,7 +35,7 @@ */ /**********************************************************************/ -// RtMidi: Version 1.0.10 +// RtMidi: Version 1.0.11 #ifndef RTMIDI_H #define RTMIDI_H diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile index 0624153..103f24e 100644 --- a/doc/doxygen/Doxyfile +++ b/doc/doxygen/Doxyfile @@ -31,7 +31,7 @@ PROJECT_NAME = RtMidi # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = 1.0.10 +PROJECT_NUMBER = 1.0.11 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. diff --git a/doc/doxygen/footer.html b/doc/doxygen/footer.html index 47f4340..dc3d30f 100644 --- a/doc/doxygen/footer.html +++ b/doc/doxygen/footer.html @@ -1,7 +1,7 @@ <HR>
<table><tr><td><img src="../images/mcgill.gif" width=165></td>
- <td>©2003-2009 Gary P. Scavone, McGill University. All Rights Reserved.<br>
+ <td>©2003-2010 Gary P. Scavone, McGill University. All Rights Reserved.<br>
Maintained by Gary P. Scavone, gary at music.mcgill.ca</td></tr>
</table>
diff --git a/doc/doxygen/tutorial.txt b/doc/doxygen/tutorial.txt index 1104e1a..4984589 100644 --- a/doc/doxygen/tutorial.txt +++ b/doc/doxygen/tutorial.txt @@ -17,7 +17,7 @@ MIDI input and output functionality are separated into two classes, RtMidiIn and \section download Download
-Latest Release (3 June 2009): <A href="http://www.music.mcgill.ca/~gary/rtmidi/release/rtmidi-1.0.10.tar.gz">Version 1.0.10</A>
+Latest Release (29 January 2010): <A href="http://www.music.mcgill.ca/~gary/rtmidi/release/rtmidi-1.0.11.tar.gz">Version 1.0.11</A>
\section start Getting Started
@@ -416,12 +416,15 @@ Many thanks to the following people for providing bug fixes and improvements: <LI>Christoph Eckert (ALSA sysex fixes)</LI>
<LI>Immanuel Litzroth (OS-X sysex fix)</LI>
<LI>Axel Schmidt (client naming)</LI>
+<LI>Bastiaan Verreijt (Windows sysex multi-buffer code)</LI>
+<LI>Jon McCormack (Snow Leopard updates)</LI>
+<LI>Paul Dean (increment optimization)</LI>
</UL>
\section license License
RtMidi: realtime MIDI i/o C++ classes<BR>
- Copyright (c) 2003-2009 Gary P. Scavone
+ Copyright (c) 2003-2010 Gary P. Scavone
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
diff --git a/doc/release.txt b/doc/release.txt index 145a263..abfe577 100644 --- a/doc/release.txt +++ b/doc/release.txt @@ -1,6 +1,12 @@ RtMidi - a set of C++ classes that provides a common API for realtime MIDI input/output across Linux (ALSA), SGI, Macintosh OS X (CoreMidi), and Windows (Multimedia) operating systems.
-By Gary P. Scavone, 2003-2009.
+By Gary P. Scavone, 2003-2010.
+
+v1.0.11: (29 January 2010)
+- added CoreServices/CoreServices.h include for OS-X 10.6 and gcc4.2 compile (thanks to Jon McCormack)
+- various increment optimizations (thanks to Paul Dean)
+- fixed incorrectly located snd_seq_close() function in ALSA API (thanks to Pedro Lopez-Cabanillas)
+- updates to Windows sysex code to better deal with possible delivery problems (thanks to Bastiaan Verreijt)
v1.0.10: (3 June 2009)
- fix adding timestamp to OS-X sendMessage() function (thanks to John Dey)
@@ -1,6 +1,6 @@ RtMidi - a set of C++ classes that provide a common API for realtime MIDI input/output across Linux (ALSA), SGI, Macintosh OS X (CoreMidi), and Windows (Multimedia) operating systems. -By Gary P. Scavone, 2003-2009. +By Gary P. Scavone, 2003-2010. This distribution of RtMidi contains the following: @@ -30,7 +30,7 @@ LEGAL AND ETHICAL: The RtMidi license is similar to the the MIT License, with the added "feature" that modifications be sent to the developer. RtMidi: realtime MIDI i/o C++ classes - Copyright (c) 2003-2009 Gary P. Scavone + Copyright (c) 2003-2010 Gary P. Scavone Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files |
