3445 lines · 109.3 KB · C++
RawDownload
/**********************************************************************//*! \class RtMidi    \brief An abstract base class for realtime MIDI input/output.     This class implements some common functionality for the realtime    MIDI input/output subclasses RtMidiIn and RtMidiOut.     RtMidi GitHub site: https://github.com/thestk/rtmidi    RtMidi WWW site: http://www.music.mcgill.ca/~gary/rtmidi/     RtMidi: realtime MIDI i/o C++ classes    Copyright (c) 2003-2019 Gary P. Scavone     Permission is hereby granted, free of charge, to any person    obtaining a copy of this software and associated documentation files    (the "Software"), to deal in the Software without restriction,    including without limitation the rights to use, copy, modify, merge,    publish, distribute, sublicense, and/or sell copies of the Software,    and to permit persons to whom the Software is furnished to do so,    subject to the following conditions:     The above copyright notice and this permission notice shall be    included in all copies or substantial portions of the Software.     Any person wishing to distribute modifications to the Software is    asked to send the modifications to the original developer so that    they can be incorporated into the canonical version.  This is,    however, not a binding provision of this license.     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.*//**********************************************************************/ #include "RtMidi.h"#include <sstream> #if defined(__MACOSX_CORE__)  #if defined(TARGET_OS_IPHONE)    #define AudioGetCurrentHostTime CAHostTimeBase::GetCurrentTime    #define AudioConvertHostTimeToNanos CAHostTimeBase::ConvertToNanos  #endif#endif // Default for Windows is to add an identifier to the port names; this// flag can be defined (e.g. in your project file) to disable this behaviour.//#define RTMIDI_DO_NOT_ENSURE_UNIQUE_PORTNAMES // **************************************************************** ////// MidiInApi and MidiOutApi subclass prototypes.//// **************************************************************** // #if !defined(__LINUX_ALSA__) && !defined(__UNIX_JACK__) && !defined(__MACOSX_CORE__) && !defined(__WINDOWS_MM__)  #define __RTMIDI_DUMMY__#endif #if defined(__MACOSX_CORE__) class MidiInCore: public MidiInApi{ public:  MidiInCore( const std::string &clientName, unsigned int queueSizeLimit );  ~MidiInCore( void );  RtMidi::Api getCurrentApi( void ) { return RtMidi::MACOSX_CORE; };  void openPort( unsigned int portNumber, const std::string &portName );  void openVirtualPort( const std::string &portName );  void closePort( void );  void setClientName( const std::string &clientName );  void setPortName( const std::string &portName );  unsigned int getPortCount( void );  std::string getPortName( unsigned int portNumber );  protected:  void initialize( const std::string& clientName );}; class MidiOutCore: public MidiOutApi{ public:  MidiOutCore( const std::string &clientName );  ~MidiOutCore( void );  RtMidi::Api getCurrentApi( void ) { return RtMidi::MACOSX_CORE; };  void openPort( unsigned int portNumber, const std::string &portName );  void openVirtualPort( const std::string &portName );  void closePort( void );  void setClientName( const std::string &clientName );  void setPortName( const std::string &portName );  unsigned int getPortCount( void );  std::string getPortName( unsigned int portNumber );  void sendMessage( const unsigned char *message, size_t size );  protected:  void initialize( const std::string& clientName );}; #endif #if defined(__UNIX_JACK__) class MidiInJack: public MidiInApi{ public:  MidiInJack( const std::string &clientName, unsigned int queueSizeLimit );  ~MidiInJack( void );  RtMidi::Api getCurrentApi( void ) { return RtMidi::UNIX_JACK; };  void openPort( unsigned int portNumber, const std::string &portName );  void openVirtualPort( const std::string &portName );  void closePort( void );  void setClientName( const std::string &clientName );  void setPortName( const std::string &portName);  unsigned int getPortCount( void );  std::string getPortName( unsigned int portNumber );  protected:  std::string clientName;   void connect( void );  void initialize( const std::string& clientName );}; class MidiOutJack: public MidiOutApi{ public:  MidiOutJack( const std::string &clientName );  ~MidiOutJack( void );  RtMidi::Api getCurrentApi( void ) { return RtMidi::UNIX_JACK; };  void openPort( unsigned int portNumber, const std::string &portName );  void openVirtualPort( const std::string &portName );  void closePort( void );  void setClientName( const std::string &clientName );  void setPortName( const std::string &portName);  unsigned int getPortCount( void );  std::string getPortName( unsigned int portNumber );  void sendMessage( const unsigned char *message, size_t size );  protected:  std::string clientName;   void connect( void );  void initialize( const std::string& clientName );}; #endif #if defined(__LINUX_ALSA__) class MidiInAlsa: public MidiInApi{ public:  MidiInAlsa( const std::string &clientName, unsigned int queueSizeLimit );  ~MidiInAlsa( void );  RtMidi::Api getCurrentApi( void ) { return RtMidi::LINUX_ALSA; };  void openPort( unsigned int portNumber, const std::string &portName );  void openVirtualPort( const std::string &portName );  void closePort( void );  void setClientName( const std::string &clientName );  void setPortName( const std::string &portName);  unsigned int getPortCount( void );  std::string getPortName( unsigned int portNumber );  protected:  void initialize( const std::string& clientName );}; class MidiOutAlsa: public MidiOutApi{ public:  MidiOutAlsa( const std::string &clientName );  ~MidiOutAlsa( void );  RtMidi::Api getCurrentApi( void ) { return RtMidi::LINUX_ALSA; };  void openPort( unsigned int portNumber, const std::string &portName );  void openVirtualPort( const std::string &portName );  void closePort( void );  void setClientName( const std::string &clientName );  void setPortName( const std::string &portName );  unsigned int getPortCount( void );  std::string getPortName( unsigned int portNumber );  void sendMessage( const unsigned char *message, size_t size );  protected:  void initialize( const std::string& clientName );}; #endif #if defined(__WINDOWS_MM__) class MidiInWinMM: public MidiInApi{ public:  MidiInWinMM( const std::string &clientName, unsigned int queueSizeLimit );  ~MidiInWinMM( void );  RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_MM; };  void openPort( unsigned int portNumber, const std::string &portName );  void openVirtualPort( const std::string &portName );  void closePort( void );  void setClientName( const std::string &clientName );  void setPortName( const std::string &portName );  unsigned int getPortCount( void );  std::string getPortName( unsigned int portNumber );  protected:  void initialize( const std::string& clientName );}; class MidiOutWinMM: public MidiOutApi{ public:  MidiOutWinMM( const std::string &clientName );  ~MidiOutWinMM( void );  RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_MM; };  void openPort( unsigned int portNumber, const std::string &portName );  void openVirtualPort( const std::string &portName );  void closePort( void );  void setClientName( const std::string &clientName );  void setPortName( const std::string &portName );  unsigned int getPortCount( void );  std::string getPortName( unsigned int portNumber );  void sendMessage( const unsigned char *message, size_t size );  protected:  void initialize( const std::string& clientName );}; #endif #if defined(__RTMIDI_DUMMY__) class MidiInDummy: public MidiInApi{ public: 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 ) {}  void setClientName( const std::string &/*clientName*/ ) {};  void setPortName( const std::string &/*portName*/ ) {};  unsigned int getPortCount( void ) { return 0; }  std::string getPortName( unsigned int /*portNumber*/ ) { return ""; }  protected:  void initialize( const std::string& /*clientName*/ ) {}}; class MidiOutDummy: public MidiOutApi{ public:  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 ) {}  void setClientName( const std::string &/*clientName*/ ) {};  void setPortName( const std::string &/*portName*/ ) {};  unsigned int getPortCount( void ) { return 0; }  std::string getPortName( unsigned int /*portNumber*/ ) { return ""; }  void sendMessage( const unsigned char * /*message*/, size_t /*size*/ ) {}  protected:  void initialize( const std::string& /*clientName*/ ) {}}; #endif //*********************************************************************////  RtMidi Definitions//*********************************************************************// RtMidi :: RtMidi()  : rtapi_(0){} RtMidi :: ~RtMidi(){  delete rtapi_;  rtapi_ = 0;} std::string RtMidi :: getVersion( void ) throw(){  return std::string( RTMIDI_VERSION );} // Define API names and display names.// Must be in same order as API enum.extern "C" {const char* rtmidi_api_names[][2] = {  { "unspecified" , "Unknown" },  { "core"        , "CoreMidi" },  { "alsa"        , "ALSA" },  { "jack"        , "Jack" },  { "winmm"       , "Windows MultiMedia" },  { "dummy"       , "Dummy" },};const unsigned int rtmidi_num_api_names =  sizeof(rtmidi_api_names)/sizeof(rtmidi_api_names[0]); // The order here will control the order of RtMidi's API search in// the constructor.extern "C" const RtMidi::Api rtmidi_compiled_apis[] = {#if defined(__MACOSX_CORE__)  RtMidi::MACOSX_CORE,#endif#if defined(__LINUX_ALSA__)  RtMidi::LINUX_ALSA,#endif#if defined(__UNIX_JACK__)  RtMidi::UNIX_JACK,#endif#if defined(__WINDOWS_MM__)  RtMidi::WINDOWS_MM,#endif#if defined(__RTMIDI_DUMMY__)  RtMidi::RTMIDI_DUMMY,#endif  RtMidi::UNSPECIFIED,};extern "C" const unsigned int rtmidi_num_compiled_apis =  sizeof(rtmidi_compiled_apis)/sizeof(rtmidi_compiled_apis[0])-1;} // This is a compile-time check that rtmidi_num_api_names == RtMidi::NUM_APIS.// If the build breaks here, check that they match.template<bool b> class StaticAssert { private: StaticAssert() {} };template<> class StaticAssert<true>{ public: StaticAssert() {} };class StaticAssertions { StaticAssertions() {  StaticAssert<rtmidi_num_api_names == RtMidi::NUM_APIS>();}}; void RtMidi :: getCompiledApi( std::vector<RtMidi::Api> &apis ) throw(){  apis = std::vector<RtMidi::Api>(rtmidi_compiled_apis,                                  rtmidi_compiled_apis + rtmidi_num_compiled_apis);} std::string RtMidi :: getApiName( RtMidi::Api api ){  if (api < 0 || api >= RtMidi::NUM_APIS)    return "";  return rtmidi_api_names[api][0];} std::string RtMidi :: getApiDisplayName( RtMidi::Api api ){  if (api < 0 || api >= RtMidi::NUM_APIS)    return "Unknown";  return rtmidi_api_names[api][1];} RtMidi::Api RtMidi :: getCompiledApiByName( const std::string &name ){  unsigned int i=0;  for (i = 0; i < rtmidi_num_compiled_apis; ++i)    if (name == rtmidi_api_names[rtmidi_compiled_apis[i]][0])      return rtmidi_compiled_apis[i];  return RtMidi::UNSPECIFIED;} void RtMidi :: setClientName( const std::string &clientName ){  rtapi_->setClientName( clientName );} void RtMidi :: setPortName( const std::string &portName ){  rtapi_->setPortName( portName );}  //*********************************************************************////  RtMidiIn Definitions//*********************************************************************// void RtMidiIn :: openMidiApi( RtMidi::Api api, const std::string &clientName, unsigned int queueSizeLimit ){  delete rtapi_;  rtapi_ = 0; #if defined(__UNIX_JACK__)  if ( api == UNIX_JACK )    rtapi_ = new MidiInJack( clientName, queueSizeLimit );#endif#if defined(__LINUX_ALSA__)  if ( api == LINUX_ALSA )    rtapi_ = new MidiInAlsa( clientName, queueSizeLimit );#endif#if defined(__WINDOWS_MM__)  if ( api == WINDOWS_MM )    rtapi_ = new MidiInWinMM( clientName, queueSizeLimit );#endif#if defined(__MACOSX_CORE__)  if ( api == MACOSX_CORE )    rtapi_ = new MidiInCore( clientName, queueSizeLimit );#endif#if defined(__RTMIDI_DUMMY__)  if ( api == RTMIDI_DUMMY )    rtapi_ = new MidiInDummy( clientName, queueSizeLimit );#endif} RTMIDI_DLL_PUBLIC RtMidiIn :: RtMidiIn( RtMidi::Api api, const std::string &clientName, unsigned int queueSizeLimit )  : RtMidi(){  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 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  // one with at least one port or we reach the end of the list.  std::vector< RtMidi::Api > apis;  getCompiledApi( apis );  for ( unsigned int i=0; i<apis.size(); i++ ) {    openMidiApi( apis[i], clientName, queueSizeLimit );    if ( rtapi_ && rtapi_->getPortCount() ) break;  }   if ( rtapi_ ) return;   // 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 throw an error.  std::string errorText = "RtMidiIn: no compiled API support found ... critical error!!";  throw( RtMidiError( errorText, RtMidiError::UNSPECIFIED ) );} RtMidiIn :: ~RtMidiIn() throw(){}  //*********************************************************************////  RtMidiOut Definitions//*********************************************************************// void RtMidiOut :: openMidiApi( RtMidi::Api api, const std::string &clientName ){  delete rtapi_;  rtapi_ = 0; #if defined(__UNIX_JACK__)  if ( api == UNIX_JACK )    rtapi_ = new MidiOutJack( clientName );#endif#if defined(__LINUX_ALSA__)  if ( api == LINUX_ALSA )    rtapi_ = new MidiOutAlsa( clientName );#endif#if defined(__WINDOWS_MM__)  if ( api == WINDOWS_MM )    rtapi_ = new MidiOutWinMM( clientName );#endif#if defined(__MACOSX_CORE__)  if ( api == MACOSX_CORE )    rtapi_ = new MidiOutCore( clientName );#endif#if defined(__RTMIDI_DUMMY__)  if ( api == RTMIDI_DUMMY )    rtapi_ = new MidiOutDummy( clientName );#endif} RTMIDI_DLL_PUBLIC RtMidiOut :: RtMidiOut( RtMidi::Api api, const std::string &clientName){  if ( api != UNSPECIFIED ) {    // Attempt to open the specified API.    openMidiApi( api, clientName );    if ( rtapi_ ) return;     // 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  // one with at least one port or we reach the end of the list.  std::vector< RtMidi::Api > apis;  getCompiledApi( apis );  for ( unsigned int i=0; i<apis.size(); i++ ) {    openMidiApi( apis[i], clientName );    if ( rtapi_ && rtapi_->getPortCount() ) break;  }   if ( rtapi_ ) return; 

Lines 1–500 of 3445.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t