diff options
| author | Gary Scavone <gary@music.mcgill.ca> | 2014-03-14 11:34:21 -0400 |
|---|---|---|
| committer | Gary Scavone <gary@music.mcgill.ca> | 2014-03-14 11:34:21 -0400 |
| commit | 112baabce3f4a0ef5968097e986896d098dacc36 (patch) | |
| tree | 65c4f122c49f01550254657498bc38ba7ba46024 | |
| parent | c5a8f3a85c567068777841fc3c60ed0e20641b07 (diff) | |
Updates from Mogilevskiy to add error hook, isPortOpen() function, and UNICODE windows name fix.
| -rw-r--r-- | RtMidi.cpp | 410 | ||||
| -rw-r--r-- | RtMidi.h | 171 | ||||
| -rw-r--r-- | doc/release.txt | 3 |
3 files changed, 365 insertions, 219 deletions
@@ -43,6 +43,18 @@ // RtMidi Definitions //*********************************************************************// +RtMidi :: RtMidi() + : rtapi_(0) +{ +} + +RtMidi :: ~RtMidi() +{ + if ( rtapi_ ) + delete rtapi_; + rtapi_ = 0; +} + std::string RtMidi :: getVersion( void ) throw() { return std::string( RTMIDI_VERSION ); @@ -74,22 +86,6 @@ void RtMidi :: getCompiledApi( std::vector<RtMidi::Api> &apis ) throw() #endif } -void RtMidi :: error( RtMidiError::Type type, std::string &errorString ) -{ - if (type == RtMidiError::WARNING) { - std::cerr << '\n' << errorString << "\n\n"; - } - else if (type == RtMidiError::DEBUG_WARNING) { -#if defined(__RTMIDI_DEBUG__) - std::cerr << '\n' << errorString << "\n\n"; -#endif - } - else { - std::cerr << '\n' << errorString << "\n\n"; - throw RtMidiError( errorString, type ); - } -} - //*********************************************************************// // RtMidiIn Definitions //*********************************************************************// @@ -127,18 +123,16 @@ void RtMidiIn :: openMidiApi( RtMidi::Api api, const std::string clientName, uns } RtMidiIn :: RtMidiIn( RtMidi::Api api, const std::string clientName, unsigned int queueSizeLimit ) + : RtMidi() { - rtapi_ = 0; - if ( api != UNSPECIFIED ) { // Attempt to open the specified API. openMidiApi( api, clientName, queueSizeLimit ); if ( rtapi_ ) return; - // No compiled support for specified API value. Issue a debug - // warning and continue as if no API was specified. - std::string errormsg = "RtMidiIn: no compiled support for specified API argument!"; - RtMidi::error( RtMidiError::WARNING, errormsg ); + // No compiled support for specified API value. Issue a warning + // and continue as if no API was specified. + std::cerr << "\nRtMidiIn: no compiled support for specified API argument!\n\n" << std::endl; } // Iterate through the compiled APIs and return as soon as we find @@ -155,15 +149,13 @@ RtMidiIn :: RtMidiIn( RtMidi::Api api, const std::string clientName, unsigned in // It should not be possible to get here because the preprocessor // definition __RTMIDI_DUMMY__ is automatically defined if no // API-specific definitions are passed to the compiler. But just in - // case something weird happens, we'll print out an error message. - std::string errormsg = "RtMidiIn: no compiled API support found ... critical error!!"; - RtMidi::error( RtMidiError::UNSPECIFIED, errormsg ); + // case something weird happens, we'll throw an error. + std::string errorText = "RtMidiIn: no compiled API support found ... critical error!!"; + throw( RtMidiError( errorText, RtMidiError::UNSPECIFIED ) ); } RtMidiIn :: ~RtMidiIn() throw() { - if ( rtapi_ ) - delete rtapi_; } @@ -205,17 +197,14 @@ void RtMidiOut :: openMidiApi( RtMidi::Api api, const std::string clientName ) RtMidiOut :: RtMidiOut( RtMidi::Api api, const std::string clientName ) { - rtapi_ = 0; - if ( api != UNSPECIFIED ) { // Attempt to open the specified API. openMidiApi( api, clientName ); if ( rtapi_ ) return; - // No compiled support for specified API value. Issue a debug - // warning and continue as if no API was specified. - std::string errormsg = "RtMidiOut: no compiled support for specified API argument!"; - RtMidi::error( RtMidiError::WARNING, errormsg ); + // No compiled support for specified API value. Issue a warning + // and continue as if no API was specified. + std::cerr << "\nRtMidiOut: no compiled support for specified API argument!\n\n" << std::endl; } // Iterate through the compiled APIs and return as soon as we find @@ -232,15 +221,66 @@ RtMidiOut :: RtMidiOut( RtMidi::Api api, const std::string clientName ) // It should not be possible to get here because the preprocessor // definition __RTMIDI_DUMMY__ is automatically defined if no // API-specific definitions are passed to the compiler. But just in - // case something weird happens, we'll print out an error message. - std::string errormsg = "RtMidiOut: no compiled API support found ... critical error!!"; - RtMidi::error( RtMidiError::UNSPECIFIED, errormsg ); + // case something weird happens, we'll thrown an error. + std::string errorText = "RtMidiOut: no compiled API support found ... critical error!!"; + throw( RtMidiError( errorText, RtMidiError::UNSPECIFIED ) ); } RtMidiOut :: ~RtMidiOut() throw() { - if ( rtapi_ ) - delete rtapi_; +} + +//*********************************************************************// +// Common MidiApi Definitions +//*********************************************************************// + +MidiApi :: MidiApi( void ) + : apiData_( 0 ), connected_( false ), errorCallback_(0) +{ +} + +MidiApi :: ~MidiApi( void ) +{ +} + +bool MidiApi :: isPortOpen() const +{ + return connected_; +} + +void MidiApi :: setErrorCallback( RtMidiErrorCallback errorCallback ) +{ + errorCallback_ = errorCallback; +} + +void MidiApi :: error( RtError::Type type, std::string errorString ) +{ + if ( errorCallback_ ) { + static bool firstErrorOccured = false; + + if ( firstErrorOccured ) + return; + + firstErrorOccured = true; + const std::string errorMessage = errorString; + + errorCallback_( type, errorMessage ); + firstErrorOccured = false; + return; + } + + if ( type == RtError::WARNING ) { + std::cerr << '\n' << errorString << "\n\n"; + } + else if ( type == RtError::DEBUG_WARNING ) { +#if defined(__RTMIDI_DEBUG__) + std::cerr << '\n' << errorString << "\n\n"; +#endif + } + else { + std::cerr << '\n' << errorString << "\n\n"; + throw RtError( errorString, type ); + } } //*********************************************************************// @@ -248,7 +288,7 @@ RtMidiOut :: ~RtMidiOut() throw() //*********************************************************************// MidiInApi :: MidiInApi( unsigned int queueSizeLimit ) - : apiData_( 0 ), connected_( false ) + : MidiApi() { // Allocate the MIDI queue. inputData_.queue.ringSize = queueSizeLimit; @@ -266,13 +306,13 @@ void MidiInApi :: setCallback( RtMidiIn::RtMidiCallback callback, void *userData { if ( inputData_.usingCallback ) { errorString_ = "MidiInApi::setCallback: a callback function is already set!"; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return; } if ( !callback ) { errorString_ = "RtMidiIn::setCallback: callback function value is invalid!"; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return; } @@ -285,7 +325,7 @@ void MidiInApi :: cancelCallback() { if ( !inputData_.usingCallback ) { errorString_ = "RtMidiIn::cancelCallback: no callback function was set!"; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return; } @@ -308,7 +348,7 @@ double MidiInApi :: getMessage( std::vector<unsigned char> *message ) if ( inputData_.usingCallback ) { errorString_ = "RtMidiIn::getNextMessage: a user callback is currently set for this port."; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return 0.0; } @@ -331,7 +371,7 @@ double MidiInApi :: getMessage( std::vector<unsigned char> *message ) //*********************************************************************// MidiOutApi :: MidiOutApi( void ) - : apiData_( 0 ), connected_( false ) + : MidiApi() { } @@ -546,7 +586,8 @@ void MidiInCore :: initialize( const std::string& clientName ) OSStatus result = MIDIClientCreate( CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ), NULL, NULL, &client ); if ( result != noErr ) { errorString_ = "MidiInCore::initialize: error creating OS-X MIDI client object."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } // Save our api-specific connection information. @@ -561,7 +602,7 @@ void MidiInCore :: openPort( unsigned int portNumber, const std::string portName { if ( connected_ ) { errorString_ = "MidiInCore::openPort: a valid connection already exists!"; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return; } @@ -569,14 +610,16 @@ void MidiInCore :: openPort( unsigned int portNumber, const std::string portName unsigned int nSrc = MIDIGetNumberOfSources(); if (nSrc < 1) { errorString_ = "MidiInCore::openPort: no MIDI input sources found!"; - RtMidi::error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); + error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); + return; } if ( portNumber >= nSrc ) { std::ostringstream ost; ost << "MidiInCore::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); - RtMidi::error( RtMidiError::INVALID_PARAMETER, errorString_ ); + error( RtMidiError::INVALID_PARAMETER, errorString_ ); + return; } MIDIPortRef port; @@ -587,7 +630,8 @@ void MidiInCore :: openPort( unsigned int portNumber, const std::string portName if ( result != noErr ) { MIDIClientDispose( data->client ); errorString_ = "MidiInCore::openPort: error creating OS-X MIDI input port."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } // Get the desired input source identifier. @@ -596,7 +640,8 @@ void MidiInCore :: openPort( unsigned int portNumber, const std::string portName MIDIPortDispose( port ); MIDIClientDispose( data->client ); errorString_ = "MidiInCore::openPort: error getting MIDI input source reference."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } // Make the connection. @@ -605,7 +650,8 @@ void MidiInCore :: openPort( unsigned int portNumber, const std::string portName MIDIPortDispose( port ); MIDIClientDispose( data->client ); errorString_ = "MidiInCore::openPort: error connecting OS-X MIDI input port."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } // Save our api-specific port information. @@ -625,7 +671,8 @@ void MidiInCore :: openVirtualPort( const std::string portName ) midiInputCallback, (void *)&inputData_, &endpoint ); if ( result != noErr ) { errorString_ = "MidiInCore::openVirtualPort: error creating virtual OS-X MIDI destination."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } // Save our api-specific connection information. @@ -783,7 +830,7 @@ std::string MidiInCore :: getPortName( unsigned int portNumber ) std::ostringstream ost; ost << "MidiInCore::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return stringName; } @@ -824,7 +871,8 @@ void MidiOutCore :: initialize( const std::string& clientName ) OSStatus result = MIDIClientCreate( CFStringCreateWithCString( NULL, clientName.c_str(), kCFStringEncodingASCII ), NULL, NULL, &client ); if ( result != noErr ) { errorString_ = "MidiOutCore::initialize: error creating OS-X MIDI client object."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } // Save our api-specific connection information. @@ -852,7 +900,7 @@ std::string MidiOutCore :: getPortName( unsigned int portNumber ) std::ostringstream ost; ost << "MidiOutCore::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return stringName; } @@ -868,7 +916,7 @@ void MidiOutCore :: openPort( unsigned int portNumber, const std::string portNam { if ( connected_ ) { errorString_ = "MidiOutCore::openPort: a valid connection already exists!"; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return; } @@ -876,14 +924,16 @@ void MidiOutCore :: openPort( unsigned int portNumber, const std::string portNam unsigned int nDest = MIDIGetNumberOfDestinations(); if (nDest < 1) { errorString_ = "MidiOutCore::openPort: no MIDI output destinations found!"; - RtMidi::error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); + error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); + return; } if ( portNumber >= nDest ) { std::ostringstream ost; ost << "MidiOutCore::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); - RtMidi::error( RtMidiError::INVALID_PARAMETER, errorString_ ); + error( RtMidiError::INVALID_PARAMETER, errorString_ ); + return; } MIDIPortRef port; @@ -894,7 +944,8 @@ void MidiOutCore :: openPort( unsigned int portNumber, const std::string portNam if ( result != noErr ) { MIDIClientDispose( data->client ); errorString_ = "MidiOutCore::openPort: error creating OS-X MIDI output port."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } // Get the desired output port identifier. @@ -903,7 +954,8 @@ void MidiOutCore :: openPort( unsigned int portNumber, const std::string portNam MIDIPortDispose( port ); MIDIClientDispose( data->client ); errorString_ = "MidiOutCore::openPort: error getting MIDI output destination reference."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } // Save our api-specific connection information. @@ -927,7 +979,7 @@ void MidiOutCore :: openVirtualPort( std::string portName ) if ( data->endpoint ) { errorString_ = "MidiOutCore::openVirtualPort: a virtual output port already exists!"; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return; } @@ -938,7 +990,8 @@ void MidiOutCore :: openVirtualPort( std::string portName ) &endpoint ); if ( result != noErr ) { errorString_ = "MidiOutCore::initialize: error creating OS-X virtual MIDI source."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } // Save our api-specific connection information. @@ -961,7 +1014,7 @@ void MidiOutCore :: sendMessage( std::vector<unsigned char> *message ) unsigned int nBytes = message->size(); if ( nBytes == 0 ) { errorString_ = "MidiOutCore::sendMessage: no data in message argument!"; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return; } @@ -978,7 +1031,8 @@ void MidiOutCore :: sendMessage( std::vector<unsigned char> *message ) sysexBuffer = new char[nBytes]; if ( sysexBuffer == NULL ) { errorString_ = "MidiOutCore::sendMessage: error allocating sysex message memory!"; - RtMidi::error( RtMidiError::MEMORY_ERROR, errorString_ ); + error( RtMidiError::MEMORY_ERROR, errorString_ ); + return; } // Copy data to buffer. @@ -994,13 +1048,14 @@ void MidiOutCore :: sendMessage( std::vector<unsigned char> *message ) result = MIDISendSysex( &(data->sysexreq) ); if ( result != noErr ) { errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations."; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); + return; } return; } else if ( nBytes > 3 ) { errorString_ = "MidiOutCore::sendMessage: message format problem ... not sysex but > 3 bytes?"; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return; } @@ -1009,7 +1064,8 @@ void MidiOutCore :: sendMessage( std::vector<unsigned char> *message ) packet = MIDIPacketListAdd( &packetList, sizeof(packetList), packet, timeStamp, nBytes, (const Byte *) &message->at( 0 ) ); if ( !packet ) { errorString_ = "MidiOutCore::sendMessage: could not allocate packet list"; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } // Send to any destinations that may have connected to us. @@ -1017,7 +1073,7 @@ void MidiOutCore :: sendMessage( std::vector<unsigned char> *message ) result = MIDIReceived( data->endpoint, &packetList ); if ( result != noErr ) { errorString_ = "MidiOutCore::sendMessage: error sending MIDI to virtual destinations."; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); } } @@ -1026,10 +1082,9 @@ void MidiOutCore :: sendMessage( std::vector<unsigned char> *message ) result = MIDISend( data->port, data->destinationId, &packetList ); if ( result != noErr ) { errorString_ = "MidiOutCore::sendMessage: error sending MIDI message to port."; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); } } - } #endif // __MACOSX_CORE__ @@ -1313,7 +1368,8 @@ void MidiInAlsa :: initialize( const std::string& clientName ) int result = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); if ( result < 0 ) { errorString_ = "MidiInAlsa::initialize: error creating ALSA sequencer client object."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } // Set client name. @@ -1334,7 +1390,8 @@ void MidiInAlsa :: initialize( const std::string& clientName ) if ( pipe(data->trigger_fds) == -1 ) { errorString_ = "MidiInAlsa::initialize: error creating pipe objects."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } // Create the input queue @@ -1413,7 +1470,7 @@ std::string MidiInAlsa :: getPortName( unsigned int portNumber ) // If we get here, we didn't find a match. errorString_ = "MidiInAlsa::getPortName: error looking for port name!"; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return stringName; } @@ -1421,14 +1478,15 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName { if ( connected_ ) { errorString_ = "MidiInAlsa::openPort: a valid connection already exists!"; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return; } unsigned int nSrc = this->getPortCount(); if ( nSrc < 1 ) { errorString_ = "MidiInAlsa::openPort: no MIDI input sources found!"; - RtMidi::error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); + error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); + return; } snd_seq_port_info_t *pinfo; @@ -1438,7 +1496,8 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName std::ostringstream ost; ost << "MidiInAlsa::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); - RtMidi::error( RtMidiError::INVALID_PARAMETER, errorString_ ); + error( RtMidiError::INVALID_PARAMETER, errorString_ ); + return; } snd_seq_addr_t sender, receiver; @@ -1465,7 +1524,8 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName if ( data->vport < 0 ) { errorString_ = "MidiInAlsa::openPort: ALSA error creating input port."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } data->vport = snd_seq_port_info_get_port(pinfo); } @@ -1476,7 +1536,8 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName // Make subscription if (snd_seq_port_subscribe_malloc( &data->subscription ) < 0) { errorString_ = "MidiInAlsa::openPort: ALSA error allocation port subscription."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } snd_seq_port_subscribe_set_sender(data->subscription, &sender); snd_seq_port_subscribe_set_dest(data->subscription, &receiver); @@ -1484,7 +1545,8 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName snd_seq_port_subscribe_free( data->subscription ); data->subscription = 0; errorString_ = "MidiInAlsa::openPort: ALSA error making port connection."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } } @@ -1509,7 +1571,8 @@ void MidiInAlsa :: openPort( unsigned int portNumber, const std::string portName data->subscription = 0; inputData_.doInput = false; errorString_ = "MidiInAlsa::openPort: error starting MIDI input thread!"; - RtMidi::error( RtMidiError::THREAD_ERROR, errorString_ ); + error( RtMidiError::THREAD_ERROR, errorString_ ); + return; } } @@ -1539,7 +1602,8 @@ void MidiInAlsa :: openVirtualPort( std::string portName ) if ( data->vport < 0 ) { errorString_ = "MidiInAlsa::openVirtualPort: ALSA error creating virtual port."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } } @@ -1570,7 +1634,8 @@ void MidiInAlsa :: openVirtualPort( std::string portName ) } inputData_.doInput = false; errorString_ = "MidiInAlsa::openPort: error starting MIDI input thread!"; - RtMidi::error( RtMidiError::THREAD_ERROR, errorString_ ); + error( RtMidiError::THREAD_ERROR, errorString_ ); + return; } } } @@ -1634,7 +1699,8 @@ void MidiOutAlsa :: initialize( const std::string& clientName ) int result1 = snd_seq_open( &seq, "default", SND_SEQ_OPEN_OUTPUT, SND_SEQ_NONBLOCK ); if ( result1 < 0 ) { errorString_ = "MidiOutAlsa::initialize: error creating ALSA sequencer client object."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } // Set client name. @@ -1652,13 +1718,15 @@ void MidiOutAlsa :: initialize( const std::string& clientName ) if ( result < 0 ) { delete data; errorString_ = "MidiOutAlsa::initialize: error initializing MIDI event parser!\n\n"; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } data->buffer = (unsigned char *) malloc( data->bufferSize ); if ( data->buffer == NULL ) { delete data; errorString_ = "MidiOutAlsa::initialize: error allocating buffer memory!\n\n"; - RtMidi::error( RtMidiError::MEMORY_ERROR, errorString_ ); + error( RtMidiError::MEMORY_ERROR, errorString_ ); + return; } snd_midi_event_init( data->coder ); apiData_ = (void *) data; @@ -1697,8 +1765,7 @@ std::string MidiOutAlsa :: getPortName( unsigned int portNumber ) // If we get here, we didn't find a match. errorString_ = "MidiOutAlsa::getPortName: error looking for port name!"; - //RtMidi::error( RtMidiError::INVALID_PARAMETER, errorString_ ); - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return stringName; } @@ -1706,14 +1773,15 @@ void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string portNam { if ( connected_ ) { errorString_ = "MidiOutAlsa::openPort: a valid connection already exists!"; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return; } unsigned int nSrc = this->getPortCount(); if (nSrc < 1) { errorString_ = "MidiOutAlsa::openPort: no MIDI output sources found!"; - RtMidi::error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); + error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); + return; } snd_seq_port_info_t *pinfo; @@ -1723,7 +1791,8 @@ void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string portNam std::ostringstream ost; ost << "MidiOutAlsa::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); - RtMidi::error( RtMidiError::INVALID_PARAMETER, errorString_ ); + error( RtMidiError::INVALID_PARAMETER, errorString_ ); + return; } snd_seq_addr_t sender, receiver; @@ -1737,7 +1806,8 @@ void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string portNam SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION ); if ( data->vport < 0 ) { errorString_ = "MidiOutAlsa::openPort: ALSA error creating output port."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } } @@ -1746,8 +1816,9 @@ void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string portNam // Make subscription if (snd_seq_port_subscribe_malloc( &data->subscription ) < 0) { snd_seq_port_subscribe_free( data->subscription ); - errorString_ = "MidiOutAlsa::openPort: error allocation port subscribtion."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + errorString_ = "MidiOutAlsa::openPort: error allocating port subscription."; + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } snd_seq_port_subscribe_set_sender(data->subscription, &sender); snd_seq_port_subscribe_set_dest(data->subscription, &receiver); @@ -1756,7 +1827,8 @@ void MidiOutAlsa :: openPort( unsigned int portNumber, const std::string portNam if ( snd_seq_subscribe_port(data->seq, data->subscription) ) { snd_seq_port_subscribe_free( data->subscription ); errorString_ = "MidiOutAlsa::openPort: ALSA error making port connection."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } connected_ = true; @@ -1782,7 +1854,7 @@ void MidiOutAlsa :: openVirtualPort( std::string portName ) if ( data->vport < 0 ) { errorString_ = "MidiOutAlsa::openVirtualPort: ALSA error creating virtual port."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); } } } @@ -1797,13 +1869,15 @@ void MidiOutAlsa :: sendMessage( std::vector<unsigned char> *message ) result = snd_midi_event_resize_buffer ( data->coder, nBytes); if ( result != 0 ) { errorString_ = "MidiOutAlsa::sendMessage: ALSA error resizing MIDI event buffer."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } free (data->buffer); data->buffer = (unsigned char *) malloc( data->bufferSize ); if ( data->buffer == NULL ) { errorString_ = "MidiOutAlsa::initialize: error allocating buffer memory!\n\n"; - RtMidi::error( RtMidiError::MEMORY_ERROR, errorString_ ); + error( RtMidiError::MEMORY_ERROR, errorString_ ); + return; } } @@ -1816,7 +1890,7 @@ void MidiOutAlsa :: sendMessage( std::vector<unsigned char> *message ) result = snd_midi_event_encode( data->coder, data->buffer, (long)nBytes, &ev ); if ( result < (int)nBytes ) { errorString_ = "MidiOutAlsa::sendMessage: event parsing error!"; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return; } @@ -1824,7 +1898,8 @@ void MidiOutAlsa :: sendMessage( std::vector<unsigned char> *message ) result = snd_seq_event_output(data->seq, &ev); if ( result < 0 ) { errorString_ = "MidiOutAlsa::sendMessage: error sending MIDI message to port."; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); + return; } snd_seq_drain_output(data->seq); } @@ -1988,7 +2063,7 @@ void MidiInWinMM :: initialize( const std::string& /*clientName*/ ) unsigned int nDevices = midiInGetNumDevs(); if ( nDevices == 0 ) { errorString_ = "MidiInWinMM::initialize: no MIDI input devices currently available."; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); } // Save our api-specific connection information. @@ -2002,21 +2077,23 @@ void MidiInWinMM :: openPort( unsigned int portNumber, const std::string /*portN { if ( connected_ ) { errorString_ = "MidiInWinMM::openPort: a valid connection already exists!"; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return; } unsigned int nDevices = midiInGetNumDevs(); if (nDevices == 0) { errorString_ = "MidiInWinMM::openPort: no MIDI input sources found!"; - RtMidi::error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); + error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); + return; } if ( portNumber >= nDevices ) { std::ostringstream ost; ost << "MidiInWinMM::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); - RtMidi::error( RtMidiError::INVALID_PARAMETER, errorString_ ); + error( RtMidiError::INVALID_PARAMETER, errorString_ ); + return; } WinMidiData *data = static_cast<WinMidiData *> (apiData_); @@ -2027,7 +2104,8 @@ void MidiInWinMM :: openPort( unsigned int portNumber, const std::string /*portN CALLBACK_FUNCTION ); if ( result != MMSYSERR_NOERROR ) { errorString_ = "MidiInWinMM::openPort: error creating Windows MM MIDI input port."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } // Allocate and init the sysex buffers. @@ -2042,7 +2120,8 @@ void MidiInWinMM :: openPort( unsigned int portNumber, const std::string /*portN if ( result != MMSYSERR_NOERROR ) { midiInClose( data->inHandle ); errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (PrepareHeader)."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } // Register the buffer. @@ -2050,7 +2129,8 @@ void MidiInWinMM :: openPort( unsigned int portNumber, const std::string /*portN if ( result != MMSYSERR_NOERROR ) { midiInClose( data->inHandle ); errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port (AddBuffer)."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } } @@ -2058,7 +2138,8 @@ void MidiInWinMM :: openPort( unsigned int portNumber, const std::string /*portN if ( result != MMSYSERR_NOERROR ) { midiInClose( data->inHandle ); errorString_ = "MidiInWinMM::openPort: error starting Windows MM MIDI input port."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } connected_ = true; @@ -2068,7 +2149,7 @@ void MidiInWinMM :: openVirtualPort( std::string portName ) { // This function cannot be implemented for the Windows MM MIDI API. errorString_ = "MidiInWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!"; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); } void MidiInWinMM :: closePort( void ) @@ -2085,7 +2166,8 @@ void MidiInWinMM :: closePort( void ) if ( result != MMSYSERR_NOERROR ) { midiInClose( data->inHandle ); errorString_ = "MidiInWinMM::openPort: error closing Windows MM MIDI input port (midiInUnprepareHeader)."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } } @@ -2107,7 +2189,7 @@ std::string MidiInWinMM :: getPortName( unsigned int portNumber ) std::ostringstream ost; ost << "MidiInWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return stringName; } @@ -2116,8 +2198,8 @@ std::string MidiInWinMM :: getPortName( unsigned int portNumber ) #if defined( UNICODE ) || defined( _UNICODE ) int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL) - 1; - stringName.assign( length, 0 ); - length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, wcslen(deviceCaps.szPname), &stringName[0], length, NULL, NULL); + stringName.resize( --length ); + length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, static_cast<int>(wcslen(deviceCaps.szPname)), &stringName[0], length, NULL, NULL); #else stringName = std::string( deviceCaps.szPname ); #endif @@ -2160,7 +2242,7 @@ void MidiOutWinMM :: initialize( const std::string& /*clientName*/ ) unsigned int nDevices = midiOutGetNumDevs(); if ( nDevices == 0 ) { errorString_ = "MidiOutWinMM::initialize: no MIDI output devices currently available."; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); } // Save our api-specific connection information. @@ -2181,7 +2263,7 @@ std::string MidiOutWinMM :: getPortName( unsigned int portNumber ) std::ostringstream ost; ost << "MidiOutWinMM::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return stringName; } @@ -2190,8 +2272,8 @@ std::string MidiOutWinMM :: getPortName( unsigned int portNumber ) #if defined( UNICODE ) || defined( _UNICODE ) int length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, -1, NULL, 0, NULL, NULL) - 1; - stringName.assign( length, 0 ); - length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, wcslen(deviceCaps.szPname), &stringName[0], length, NULL, NULL); + stringName.resize( --length ); + length = WideCharToMultiByte(CP_UTF8, 0, deviceCaps.szPname, static_cast<int>(wcslen(deviceCaps.szPname)), &stringName[0], length, NULL, NULL); #else stringName = std::string( deviceCaps.szPname ); #endif @@ -2203,21 +2285,23 @@ void MidiOutWinMM :: openPort( unsigned int portNumber, const std::string /*port { if ( connected_ ) { errorString_ = "MidiOutWinMM::openPort: a valid connection already exists!"; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return; } unsigned int nDevices = midiOutGetNumDevs(); if (nDevices < 1) { errorString_ = "MidiOutWinMM::openPort: no MIDI output destinations found!"; - RtMidi::error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); + error( RtMidiError::NO_DEVICES_FOUND, errorString_ ); + return; } if ( portNumber >= nDevices ) { std::ostringstream ost; ost << "MidiOutWinMM::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); - RtMidi::error( RtMidiError::INVALID_PARAMETER, errorString_ ); + error( RtMidiError::INVALID_PARAMETER, errorString_ ); + return; } WinMidiData *data = static_cast<WinMidiData *> (apiData_); @@ -2228,7 +2312,8 @@ void MidiOutWinMM :: openPort( unsigned int portNumber, const std::string /*port CALLBACK_NULL ); if ( result != MMSYSERR_NOERROR ) { errorString_ = "MidiOutWinMM::openPort: error creating Windows MM MIDI output port."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } connected_ = true; @@ -2248,7 +2333,7 @@ void MidiOutWinMM :: openVirtualPort( std::string portName ) { // This function cannot be implemented for the Windows MM MIDI API. errorString_ = "MidiOutWinMM::openVirtualPort: cannot be implemented in Windows MM MIDI API!"; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); } void MidiOutWinMM :: sendMessage( std::vector<unsigned char> *message ) @@ -2256,7 +2341,7 @@ void MidiOutWinMM :: sendMessage( std::vector<unsigned char> *message ) unsigned int nBytes = static_cast<unsigned int>(message->size()); if ( nBytes == 0 ) { errorString_ = "MidiOutWinMM::sendMessage: message argument is empty!"; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return; } @@ -2268,7 +2353,8 @@ void MidiOutWinMM :: sendMessage( std::vector<unsigned char> *message ) char *buffer = (char *) malloc( nBytes ); if ( buffer == NULL ) { errorString_ = "MidiOutWinMM::sendMessage: error allocating sysex message memory!"; - RtMidi::error( RtMidiError::MEMORY_ERROR, errorString_ ); + error( RtMidiError::MEMORY_ERROR, errorString_ ); + return; } // Copy data to buffer. @@ -2283,7 +2369,8 @@ void MidiOutWinMM :: sendMessage( std::vector<unsigned char> *message ) if ( result != MMSYSERR_NOERROR ) { free( buffer ); errorString_ = "MidiOutWinMM::sendMessage: error preparing sysex header."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } // Send the message. @@ -2291,7 +2378,8 @@ void MidiOutWinMM :: sendMessage( std::vector<unsigned char> *message ) if ( result != MMSYSERR_NOERROR ) { free( buffer ); errorString_ = "MidiOutWinMM::sendMessage: error sending sysex message."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } // Unprepare the buffer and MIDIHDR. @@ -2304,7 +2392,7 @@ void MidiOutWinMM :: sendMessage( std::vector<unsigned char> *message ) // Make sure the message size isn't too big. if ( nBytes > 3 ) { errorString_ = "MidiOutWinMM::sendMessage: message size is greater than 3 bytes (and not sysex)!"; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return; } @@ -2320,7 +2408,7 @@ void MidiOutWinMM :: sendMessage( std::vector<unsigned char> *message ) result = midiOutShortMsg( data->outHandle, packet ); if ( result != MMSYSERR_NOERROR ) { errorString_ = "MidiOutWinMM::sendMessage: error sending MIDI message."; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); } } } @@ -3133,7 +3221,8 @@ void MidiInWinKS :: openPort( unsigned int portNumber, const std::string portNam std::stringstream ost; ost << "MidiInWinKS::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); + return; } CKsMidiCapFilter* pFilter = data->m_pCaptureEnum->m_Filters[portNumber]; @@ -3143,7 +3232,8 @@ void MidiInWinKS :: openPort( unsigned int portNumber, const std::string portNam std::stringstream ost; ost << "MidiInWinKS::openPort: KS error opening port (could not create pin)"; errorString_ = ost.str(); - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); + return; } data->m_pPin->SetState(KSSTATE_RUN); @@ -3152,9 +3242,10 @@ void MidiInWinKS :: openPort( unsigned int portNumber, const std::string portNam data->m_hInputThread = ::CreateThread(NULL, 0, &midiKsInputThread, &inputData_, 0, &threadId); if ( data->m_hInputThread == NULL ) { std::stringstream ost; - ost << "MidiInWinKS::initialize: Could not create input thread : Windows error " << GetLastError() << std::endl;; + ost << "MidiInWinKS::openPort: Could not create input thread : Windows error " << GetLastError() << std::endl;; errorString_ = ost.str(); - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); + return; } connected_ = true; @@ -3164,7 +3255,7 @@ void MidiInWinKS :: openVirtualPort( const std::string portName ) { // This function cannot be implemented for the Windows KS MIDI API. errorString_ = "MidiInWinKS::openVirtualPort: cannot be implemented in Windows KS MIDI API!"; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); } unsigned int MidiInWinKS :: getPortCount() @@ -3177,11 +3268,12 @@ std::string MidiInWinKS :: getPortName(unsigned int portNumber) { WindowsKsData* data = static_cast<WindowsKsData*>(apiData_); - if(portNumber < 0 || portNumber >= data->m_pCaptureEnum->m_Filters.size()) { + if (portNumber < 0 || portNumber >= data->m_pCaptureEnum->m_Filters.size()) { std::stringstream ost; ost << "MidiInWinKS::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); + return; } CKsMidiCapFilter* pFilter = data->m_pCaptureEnum->m_Filters[portNumber]; @@ -3193,12 +3285,12 @@ void MidiInWinKS :: closePort() WindowsKsData* data = static_cast<WindowsKsData*>(apiData_); connected_ = false; - if(data->m_hInputThread) { + if (data->m_hInputThread) { ::SignalObjectAndWait(data->m_hExitEvent, data->m_hInputThread, INFINITE, FALSE); ::CloseHandle(data->m_hInputThread); } - if(data->m_pPin) { + if (data->m_pPin) { data->m_pPin->SetState(KSSTATE_PAUSE); data->m_pPin->SetState(KSSTATE_STOP); data->m_pPin->ClosePin(); @@ -3245,21 +3337,23 @@ void MidiOutWinKS :: openPort( unsigned int portNumber, const std::string portNa { WindowsKsData* data = static_cast<WindowsKsData*>(apiData_); - if(portNumber < 0 || portNumber >= data->m_pRenderEnum->m_Filters.size()) { + if (portNumber < 0 || portNumber >= data->m_pRenderEnum->m_Filters.size()) { std::stringstream ost; ost << "MidiOutWinKS::openPort: the 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); + return; } CKsMidiRenFilter* pFilter = data->m_pRenderEnum->m_Filters[portNumber]; data->m_pPin = pFilter->CreateRenderPin(); - if(data->m_pPin == NULL) { + if (data->m_pPin == NULL) { std::stringstream ost; ost << "MidiOutWinKS::openPort: KS error opening port (could not create pin)"; errorString_ = ost.str(); - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); + return; } data->m_pPin->SetState(KSSTATE_RUN); @@ -3270,13 +3364,12 @@ void MidiOutWinKS :: openVirtualPort( const std::string portName ) { // This function cannot be implemented for the Windows KS MIDI API. errorString_ = "MidiOutWinKS::openVirtualPort: cannot be implemented in Windows KS MIDI API!"; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); } unsigned int MidiOutWinKS :: getPortCount() { WindowsKsData* data = static_cast<WindowsKsData*>(apiData_); - return (unsigned int)data->m_pRenderEnum->m_Filters.size(); } @@ -3288,7 +3381,8 @@ std::string MidiOutWinKS :: getPortName( unsigned int portNumber ) std::stringstream ost; ost << "MidiOutWinKS::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); + return; } CKsMidiRenFilter* pFilter = data->m_pRenderEnum->m_Filters[portNumber]; @@ -3326,14 +3420,16 @@ void MidiOutWinKS :: sendMessage(std::vector<unsigned char>* pMessage) std::stringstream ost; ost << "KsMidiInput::Write: MIDI buffer too small. Required " << pos + iNumMidiBytes << " bytes, only has " << data->m_Buffer.size(); errorString_ = ost.str(); - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); + return; } if ( data->m_pPin == NULL ) { std::stringstream ost; ost << "MidiOutWinKS::sendMessage: port is not open"; errorString_ = ost.str(); - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); + return; } memcpy(&data->m_Buffer[pos], &msg[0], iNumMidiBytes); @@ -3465,7 +3561,7 @@ void MidiInJack :: connect() // Initialize JACK client if (( data->client = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { errorString_ = "MidiInJack::initialize: JACK server not running?"; - RtMidi::error( RtError::WARNING, errorString_ ); + error( RtError::WARNING, errorString_ ); return; } @@ -3496,7 +3592,8 @@ void MidiInJack :: openPort( unsigned int portNumber, const std::string portName if ( data->port == NULL) { errorString_ = "MidiInJack::openVirtualPort: JACK error creating virtual port"; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } // Connecting to the output @@ -3515,7 +3612,7 @@ void MidiInJack :: openVirtualPort( const std::string portName ) if ( data->port == NULL ) { errorString_ = "MidiInJack::openVirtualPort: JACK error creating virtual port"; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); } } @@ -3553,7 +3650,7 @@ std::string MidiInJack :: getPortName( unsigned int portNumber ) // Check port validity if ( ports == NULL ) { errorString_ = "MidiInJack::getPortName: no ports available!"; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return retStr; } @@ -3561,12 +3658,11 @@ std::string MidiInJack :: getPortName( unsigned int portNumber ) std::ostringstream ost; ost << "MidiInJack::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); } else retStr.assign( ports[portNumber] ); free( ports ); - return retStr; } @@ -3633,7 +3729,7 @@ void MidiOutJack :: connect() // Initialize JACK client if (( data->client = jack_client_open( clientName.c_str(), JackNoStartServer, NULL )) == 0) { errorString_ = "MidiOutJack::initialize: JACK server not running?"; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return; } @@ -3671,7 +3767,8 @@ void MidiOutJack :: openPort( unsigned int portNumber, const std::string portNam if ( data->port == NULL ) { errorString_ = "MidiOutJack::openVirtualPort: JACK error creating virtual port"; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); + return; } // Connecting to the output @@ -3690,7 +3787,7 @@ void MidiOutJack :: openVirtualPort( const std::string portName ) if ( data->port == NULL ) { errorString_ = "MidiOutJack::openVirtualPort: JACK error creating virtual port"; - RtMidi::error( RtMidiError::DRIVER_ERROR, errorString_ ); + error( RtMidiError::DRIVER_ERROR, errorString_ ); } } @@ -3729,7 +3826,7 @@ std::string MidiOutJack :: getPortName( unsigned int portNumber ) // Check port validity if ( ports == NULL) { errorString_ = "MidiOutJack::getPortName: no ports available!"; - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); return retStr; } @@ -3737,12 +3834,11 @@ std::string MidiOutJack :: getPortName( unsigned int portNumber ) std::ostringstream ost; ost << "MidiOutJack::getPortName: the 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); - RtMidi::error( RtMidiError::WARNING, errorString_ ); + error( RtMidiError::WARNING, errorString_ ); } else retStr.assign( ports[portNumber] ); free( ports ); - return retStr; } @@ -101,6 +101,18 @@ class RtMidiError : public std::exception Type type_; }; +//! RtMidi error callback function prototype. +/*! + \param type Type of error. + \param errorText Error description. + + Note that class behaviour is undefined after a critical error (not + a warning) is reported. + */ +typedef void (*RtMidiErrorCallback)( RtMidiError::Type type, const std::string &errorText ); + +class MidiApi; + class RtMidi { public: @@ -143,12 +155,24 @@ class RtMidi virtual void closePort( void ) = 0; //! A basic error reporting function for RtMidi classes. - static void error( RtMidiError::Type type, std::string &errorString ); + // static void error( RtMidiError::Type type, std::string &errorString ); + + //! Returns true if a port is open and false if not. + virtual bool isPortOpen( void ) const = 0; + + //! Set an error callback function to be invoked when an error has occured. + /*! + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. + */ + virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL ) = 0; protected: - RtMidi() {}; - virtual ~RtMidi() {}; + RtMidi(); + virtual ~RtMidi(); + + MidiApi *rtapi_; }; /**********************************************************************/ @@ -165,7 +189,7 @@ class RtMidi to open a virtual input port to which other MIDI software clients can connect. - by Gary P. Scavone, 2003-2012. + by Gary P. Scavone, 2003-2014. */ /**********************************************************************/ @@ -183,9 +207,6 @@ class RtMidi // // **************************************************************** // -class MidiInApi; -class MidiOutApi; - class RtMidiIn : public RtMidi { public: @@ -250,6 +271,9 @@ class RtMidiIn : public RtMidi //! Close an open MIDI connection (if one exists). void closePort( void ); + //! Returns true if a port is open and false if not. + virtual bool isPortOpen() const; + //! Return the number of available MIDI input ports. unsigned int getPortCount(); @@ -279,9 +303,15 @@ class RtMidiIn : public RtMidi */ double getMessage( std::vector<unsigned char> *message ); + //! Set an error callback function to be invoked when an error has occured. + /*! + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. + */ + virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL ); + protected: void openMidiApi( RtMidi::Api api, const std::string clientName, unsigned int queueSizeLimit ); - MidiInApi *rtapi_; }; @@ -297,7 +327,7 @@ class RtMidiIn : public RtMidi OS-X and Linux ALSA MIDI APIs, it is also possible to open a virtual port to which other MIDI software clients can connect. - by Gary P. Scavone, 2003-2012. + by Gary P. Scavone, 2003-2014. */ /**********************************************************************/ @@ -334,6 +364,9 @@ class RtMidiOut : public RtMidi //! Close an open MIDI connection (if one exists). void closePort( void ); + //! Returns true if a port is open and false if not. + virtual bool isPortOpen() const; + //! Create a virtual output port, with optional name, to allow software connections (OS X and ALSA only). /*! This function creates a virtual MIDI output port to which other @@ -361,9 +394,15 @@ class RtMidiOut : public RtMidi */ void sendMessage( std::vector<unsigned char> *message ); + //! Set an error callback function to be invoked when an error has occured. + /*! + The callback function will be called whenever an error has occured. It is best + to set the error callback function before opening a port. + */ + virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL ); + protected: void openMidiApi( RtMidi::Api api, const std::string clientName ); - MidiOutApi *rtapi_; }; @@ -380,22 +419,46 @@ class RtMidiOut : public RtMidi // // **************************************************************** // -class MidiInApi +class MidiApi { public: - MidiInApi( unsigned int queueSizeLimit ); - virtual ~MidiInApi( void ); + MidiApi(); + virtual ~MidiApi(); virtual RtMidi::Api getCurrentApi( void ) = 0; virtual void openPort( unsigned int portNumber, const std::string portName ) = 0; virtual void openVirtualPort( const std::string portName ) = 0; virtual void closePort( void ) = 0; - void setCallback( RtMidiIn::RtMidiCallback callback, void *userData ); - void cancelCallback( void ); + virtual unsigned int getPortCount( void ) = 0; virtual std::string getPortName( unsigned int portNumber ) = 0; + + bool isPortOpened() const; + void setErrorCallback( RtMidiErrorCallback errorCallback ); + + //! A basic error reporting function for RtMidi classes. + void error( RtError::Type type, std::string errorString ); + +protected: + virtual void initialize( const std::string& clientName ) = 0; + + void *apiData_; + bool connected_; + std::string errorString_; + RtMidiErrorCallback errorCallback_; +} + +class MidiInApi : public MidiApi +{ + public: + + MidiInApi( unsigned int queueSizeLimit ); + virtual ~MidiInApi( void ); + void setCallback( RtMidiIn::RtMidiCallback callback, void *userData ); + void cancelCallback( void ); virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ); double getMessage( std::vector<unsigned char> *message ); + inline bool isPortOpen() const { return connected_; } // A MIDI structure used internally by the class to store incoming // messages. Each message represents one and only one MIDI message. @@ -442,34 +505,16 @@ class MidiInApi }; protected: - virtual void initialize( const std::string& clientName ) = 0; RtMidiInData inputData_; - - void *apiData_; - bool connected_; - std::string errorString_; }; -class MidiOutApi +class MidiOutApi : public MidiApi { public: MidiOutApi( void ); virtual ~MidiOutApi( void ); - virtual RtMidi::Api getCurrentApi( void ) = 0; - virtual void openPort( unsigned int portNumber, const std::string portName ) = 0; - virtual void openVirtualPort( const std::string portName ) = 0; - virtual void closePort( void ) = 0; - virtual unsigned int getPortCount( void ) = 0; - virtual std::string getPortName( unsigned int portNumber ) = 0; virtual void sendMessage( std::vector<unsigned char> *message ) = 0; - - protected: - virtual void initialize( const std::string& clientName ) = 0; - - void *apiData_; - bool connected_; - std::string errorString_; }; // **************************************************************** // @@ -479,23 +524,25 @@ class MidiOutApi // **************************************************************** // inline RtMidi::Api RtMidiIn :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); } -inline void RtMidiIn :: openPort( unsigned int portNumber, const std::string portName ) { return rtapi_->openPort( portNumber, portName ); } -inline void RtMidiIn :: openVirtualPort( const std::string portName ) { return rtapi_->openVirtualPort( portName ); } -inline void RtMidiIn :: closePort( void ) { return rtapi_->closePort(); } -inline void RtMidiIn :: setCallback( RtMidiCallback callback, void *userData ) { return rtapi_->setCallback( callback, userData ); } -inline void RtMidiIn :: cancelCallback( void ) { return rtapi_->cancelCallback(); } +inline void RtMidiIn :: openPort( unsigned int portNumber, const std::string portName ) { rtapi_->openPort( portNumber, portName ); } +inline void RtMidiIn :: openVirtualPort( const std::string portName ) { rtapi_->openVirtualPort( portName ); } +inline void RtMidiIn :: closePort( void ) { rtapi_->closePort(); } +inline void RtMidiIn :: setCallback( RtMidiCallback callback, void *userData ) { ((MidiInApi *)rtapi_)->setCallback( callback, userData ); } +inline void RtMidiIn :: cancelCallback( void ) { ((MidiInApi *)rtapi_)->cancelCallback(); } inline unsigned int RtMidiIn :: getPortCount( void ) { return rtapi_->getPortCount(); } inline std::string RtMidiIn :: getPortName( unsigned int portNumber ) { return rtapi_->getPortName( portNumber ); } -inline void RtMidiIn :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ) { return rtapi_->ignoreTypes( midiSysex, midiTime, midiSense ); } -inline double RtMidiIn :: getMessage( std::vector<unsigned char> *message ) { return rtapi_->getMessage( message ); } +inline void RtMidiIn :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ) { ((MidiInApi *)rtapi_)->ignoreTypes( midiSysex, midiTime, midiSense ); } +inline double RtMidiIn :: getMessage( std::vector<unsigned char> *message ) { return ((MidiInApi *)rtapi_)->getMessage( message ); } +inline void RtMidiIn :: setErrorCallback( RtMidiErrorCallback errorCallback ) { rtapi_->setErrorCallback(errorCallback); } inline RtMidi::Api RtMidiOut :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); } -inline void RtMidiOut :: openPort( unsigned int portNumber, const std::string portName ) { return rtapi_->openPort( portNumber, portName ); } -inline void RtMidiOut :: openVirtualPort( const std::string portName ) { return rtapi_->openVirtualPort( portName ); } -inline void RtMidiOut :: closePort( void ) { return rtapi_->closePort(); } +inline void RtMidiOut :: openPort( unsigned int portNumber, const std::string portName ) { rtapi_->openPort( portNumber, portName ); } +inline void RtMidiOut :: openVirtualPort( const std::string portName ) { rtapi_->openVirtualPort( portName ); } +inline void RtMidiOut :: closePort( void ) { rtapi_->closePort(); } inline unsigned int RtMidiOut :: getPortCount( void ) { return rtapi_->getPortCount(); } inline std::string RtMidiOut :: getPortName( unsigned int portNumber ) { return rtapi_->getPortName( portNumber ); } -inline void RtMidiOut :: sendMessage( std::vector<unsigned char> *message ) { return rtapi_->sendMessage( message ); } +inline void RtMidiOut :: sendMessage( std::vector<unsigned char> *message ) { ((MidiOutApi *)rtapi_)->sendMessage( message ); } +inline void RtMidiOut :: setErrorCallback( RtMidiErrorCallback errorCallback ) { rtapi_->setErrorCallback(errorCallback); } // **************************************************************** // // @@ -703,32 +750,32 @@ class MidiOutWinKS: public MidiOutApi class MidiInDummy: public MidiInApi { public: - MidiInDummy( const std::string clientName, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { errorString_ = "MidiInDummy: This class provides no functionality."; RtMidi::error( RtMidiError::WARNING, errorString_ ); }; - RtMidi::Api getCurrentApi( void ) { return RtMidi::RTMIDI_DUMMY; }; - void openPort( unsigned int portNumber, const std::string portName ) {}; - void openVirtualPort( const std::string portName ) {}; - void closePort( void ) {}; - unsigned int getPortCount( void ) { return 0; }; - std::string getPortName( unsigned int portNumber ) { return ""; }; + MidiInDummy( const std::string /*clientName*/, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { errorString_ = "MidiInDummy: This class provides no functionality."; error( RtMidiError::WARNING, errorString_ ); } + RtMidi::Api getCurrentApi( void ) { return RtMidi::RTMIDI_DUMMY; } + void openPort( unsigned int /*portNumber*/, const std::string /*portName*/ ) {} + void openVirtualPort( const std::string /*portName*/ ) {} + void closePort( void ) {} + unsigned int getPortCount( void ) { return 0; } + std::string getPortName( unsigned int portNumber ) { return ""; } protected: - void initialize( const std::string& clientName ) {}; + void initialize( const std::string& /*clientName*/ ) {} }; class MidiOutDummy: public MidiOutApi { public: - MidiOutDummy( const std::string clientName ) { errorString_ = "MidiOutDummy: This class provides no functionality."; RtMidi::error( RtMidiError::WARNING, errorString_ ); }; - RtMidi::Api getCurrentApi( void ) { return RtMidi::RTMIDI_DUMMY; }; - void openPort( unsigned int portNumber, const std::string portName ) {}; - void openVirtualPort( const std::string portName ) {}; - void closePort( void ) {}; - unsigned int getPortCount( void ) { return 0; }; - std::string getPortName( unsigned int portNumber ) { return ""; }; - void sendMessage( std::vector<unsigned char> *message ) {}; + MidiOutDummy( const std::string /*clientName*/ ) { errorString_ = "MidiOutDummy: This class provides no functionality."; error( RtMidiError::WARNING, errorString_ ); } + RtMidi::Api getCurrentApi( void ) { return RtMidi::RTMIDI_DUMMY; } + void openPort( unsigned int /*portNumber*/, const std::string /*portName*/ ) {} + void openVirtualPort( const std::string /*portName*/ ) {} + void closePort( void ) {} + unsigned int getPortCount( void ) { return 0; } + std::string getPortName( unsigned int /*portNumber*/ ) { return ""; } + void sendMessage( std::vector<unsigned char> * /*message*/ ) {} protected: - void initialize( const std::string& clientName ) {}; + void initialize( const std::string& /*clientName*/ ) {} }; #endif diff --git a/doc/release.txt b/doc/release.txt index e5aa3d5..7eefe46 100644 --- a/doc/release.txt +++ b/doc/release.txt @@ -10,6 +10,9 @@ v2.1.0: (?? 2014) - fix for ALSA incorrect use of snd_seq_create_port() function (Tobias Schlemmer)
- fix for international character support in CoreMidi (Martin Finke)
- fix for unicode conversion in WinMM (Dan Wilcox)
+- 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
v2.0.1: (26 July 2012)
- small fixes for problems reported by Chris Arndt (scoping, preprocessor, and include)
|
