659 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			659 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|   | /**********************************************************************/ | ||
|  | /*! \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-2021 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. | ||
|  | */ | ||
|  | /**********************************************************************/ | ||
|  | 
 | ||
|  | /*!
 | ||
|  |   \file RtMidi.h | ||
|  |  */ | ||
|  | 
 | ||
|  | #ifndef RTMIDI_H
 | ||
|  | #define RTMIDI_H
 | ||
|  | 
 | ||
|  | #if defined _WIN32 || defined __CYGWIN__
 | ||
|  |   #if defined(RTMIDI_EXPORT)
 | ||
|  |     #define RTMIDI_DLL_PUBLIC __declspec(dllexport)
 | ||
|  |   #else
 | ||
|  |     #define RTMIDI_DLL_PUBLIC
 | ||
|  |   #endif
 | ||
|  | #else
 | ||
|  |   #if __GNUC__ >= 4
 | ||
|  |     #define RTMIDI_DLL_PUBLIC __attribute__( (visibility( "default" )) )
 | ||
|  |   #else
 | ||
|  |     #define RTMIDI_DLL_PUBLIC
 | ||
|  |   #endif
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #define RTMIDI_VERSION "5.0.0"
 | ||
|  | 
 | ||
|  | #include <exception>
 | ||
|  | #include <iostream>
 | ||
|  | #include <string>
 | ||
|  | #include <vector>
 | ||
|  | 
 | ||
|  | 
 | ||
|  | /************************************************************************/ | ||
|  | /*! \class RtMidiError
 | ||
|  |     \brief Exception handling class for RtMidi. | ||
|  | 
 | ||
|  |     The RtMidiError class is quite simple but it does allow errors to be | ||
|  |     "caught" by RtMidiError::Type. See the RtMidi documentation to know | ||
|  |     which methods can throw an RtMidiError. | ||
|  | */ | ||
|  | /************************************************************************/ | ||
|  | 
 | ||
|  | class RTMIDI_DLL_PUBLIC RtMidiError : public std::exception | ||
|  | { | ||
|  |  public: | ||
|  |   //! Defined RtMidiError types.
 | ||
|  |   enum Type { | ||
|  |     WARNING,           /*!< A non-critical error. */ | ||
|  |     DEBUG_WARNING,     /*!< A non-critical error which might be useful for debugging. */ | ||
|  |     UNSPECIFIED,       /*!< The default, unspecified error type. */ | ||
|  |     NO_DEVICES_FOUND,  /*!< No devices found on system. */ | ||
|  |     INVALID_DEVICE,    /*!< An invalid device ID was specified. */ | ||
|  |     MEMORY_ERROR,      /*!< An error occured during memory allocation. */ | ||
|  |     INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */ | ||
|  |     INVALID_USE,       /*!< The function was called incorrectly. */ | ||
|  |     DRIVER_ERROR,      /*!< A system driver error occured. */ | ||
|  |     SYSTEM_ERROR,      /*!< A system error occured. */ | ||
|  |     THREAD_ERROR       /*!< A thread error occured. */ | ||
|  |   }; | ||
|  | 
 | ||
|  |   //! The constructor.
 | ||
|  |   RtMidiError( const std::string& message, Type type = RtMidiError::UNSPECIFIED ) throw() | ||
|  |     : message_(message), type_(type) {} | ||
|  | 
 | ||
|  |   //! The destructor.
 | ||
|  |   virtual ~RtMidiError( void ) throw() {} | ||
|  | 
 | ||
|  |   //! Prints thrown error message to stderr.
 | ||
|  |   virtual void printMessage( void ) const throw() { std::cerr << '\n' << message_ << "\n\n"; } | ||
|  | 
 | ||
|  |   //! Returns the thrown error message type.
 | ||
|  |   virtual const Type& getType( void ) const throw() { return type_; } | ||
|  | 
 | ||
|  |   //! Returns the thrown error message string.
 | ||
|  |   virtual const std::string& getMessage( void ) const throw() { return message_; } | ||
|  | 
 | ||
|  |   //! Returns the thrown error message as a c-style string.
 | ||
|  |   virtual const char* what( void ) const throw() { return message_.c_str(); } | ||
|  | 
 | ||
|  |  protected: | ||
|  |   std::string message_; | ||
|  |   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, void *userData ); | ||
|  | 
 | ||
|  | class MidiApi; | ||
|  | 
 | ||
|  | class RTMIDI_DLL_PUBLIC RtMidi | ||
|  | { | ||
|  |  public: | ||
|  | 
 | ||
|  |      RtMidi(RtMidi&& other) noexcept; | ||
|  |   //! MIDI API specifier arguments.
 | ||
|  |   enum Api { | ||
|  |     UNSPECIFIED,    /*!< Search for a working compiled API. */ | ||
|  |     MACOSX_CORE,    /*!< Macintosh OS-X CoreMIDI API. */ | ||
|  |     LINUX_ALSA,     /*!< The Advanced Linux Sound Architecture API. */ | ||
|  |     UNIX_JACK,      /*!< The JACK Low-Latency MIDI Server API. */ | ||
|  |     WINDOWS_MM,     /*!< The Microsoft Multimedia MIDI API. */ | ||
|  |     RTMIDI_DUMMY,   /*!< A compilable but non-functional API. */ | ||
|  |     WEB_MIDI_API,   /*!< W3C Web MIDI API. */ | ||
|  |     NUM_APIS        /*!< Number of values in this enum. */ | ||
|  |   }; | ||
|  | 
 | ||
|  |   //! A static function to determine the current RtMidi version.
 | ||
|  |   static std::string getVersion( void ) throw(); | ||
|  | 
 | ||
|  |   //! A static function to determine the available compiled MIDI APIs.
 | ||
|  |   /*!
 | ||
|  |     The values returned in the std::vector can be compared against | ||
|  |     the enumerated list values.  Note that there can be more than one | ||
|  |     API compiled for certain operating systems. | ||
|  |   */ | ||
|  |   static void getCompiledApi( std::vector<RtMidi::Api> &apis ) throw(); | ||
|  | 
 | ||
|  |   //! Return the name of a specified compiled MIDI API.
 | ||
|  |   /*!
 | ||
|  |     This obtains a short lower-case name used for identification purposes. | ||
|  |     This value is guaranteed to remain identical across library versions. | ||
|  |     If the API is unknown, this function will return the empty string. | ||
|  |   */ | ||
|  |   static std::string getApiName( RtMidi::Api api ); | ||
|  | 
 | ||
|  |   //! Return the display name of a specified compiled MIDI API.
 | ||
|  |   /*!
 | ||
|  |     This obtains a long name used for display purposes. | ||
|  |     If the API is unknown, this function will return the empty string. | ||
|  |   */ | ||
|  |   static std::string getApiDisplayName( RtMidi::Api api ); | ||
|  | 
 | ||
|  |   //! Return the compiled MIDI API having the given name.
 | ||
|  |   /*!
 | ||
|  |     A case insensitive comparison will check the specified name | ||
|  |     against the list of compiled APIs, and return the one which | ||
|  |     matches. On failure, the function returns UNSPECIFIED. | ||
|  |   */ | ||
|  |   static RtMidi::Api getCompiledApiByName( const std::string &name ); | ||
|  | 
 | ||
|  |   //! Pure virtual openPort() function.
 | ||
|  |   virtual void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi" ) ) = 0; | ||
|  | 
 | ||
|  |   //! Pure virtual openVirtualPort() function.
 | ||
|  |   virtual void openVirtualPort( const std::string &portName = std::string( "RtMidi" ) ) = 0; | ||
|  | 
 | ||
|  |   //! Pure virtual getPortCount() function.
 | ||
|  |   virtual unsigned int getPortCount() = 0; | ||
|  | 
 | ||
|  |   //! Pure virtual getPortName() function.
 | ||
|  |   virtual std::string getPortName( unsigned int portNumber = 0 ) = 0; | ||
|  | 
 | ||
|  |   //! Pure virtual closePort() function.
 | ||
|  |   virtual void closePort( void ) = 0; | ||
|  | 
 | ||
|  |   void setClientName( const std::string &clientName ); | ||
|  |   void setPortName( const std::string &portName ); | ||
|  | 
 | ||
|  |   //! Returns true if a port is open and false if not.
 | ||
|  |   /*!
 | ||
|  |       Note that this only applies to connections made with the openPort() | ||
|  |       function, not to virtual ports. | ||
|  |   */ | ||
|  |   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, void *userData = 0 ) = 0; | ||
|  | 
 | ||
|  |  protected: | ||
|  |   RtMidi(); | ||
|  |   virtual ~RtMidi(); | ||
|  |   MidiApi *rtapi_; | ||
|  | 
 | ||
|  |   /* Make the class non-copyable */ | ||
|  |   RtMidi(RtMidi& other) = delete; | ||
|  |   RtMidi& operator=(RtMidi& other) = delete; | ||
|  | }; | ||
|  | 
 | ||
|  | /**********************************************************************/ | ||
|  | /*! \class RtMidiIn
 | ||
|  |     \brief A realtime MIDI input class. | ||
|  | 
 | ||
|  |     This class provides a common, platform-independent API for | ||
|  |     realtime MIDI input.  It allows access to a single MIDI input | ||
|  |     port.  Incoming MIDI messages are either saved to a queue for | ||
|  |     retrieval using the getMessage() function or immediately passed to | ||
|  |     a user-specified callback function.  Create multiple instances of | ||
|  |     this class to connect to more than one MIDI device at the same | ||
|  |     time.  With the OS-X, Linux ALSA, and JACK MIDI APIs, it is also | ||
|  |     possible to open a virtual input port to which other MIDI software | ||
|  |     clients can connect. | ||
|  | */ | ||
|  | /**********************************************************************/ | ||
|  | 
 | ||
|  | // **************************************************************** //
 | ||
|  | //
 | ||
|  | // RtMidiIn and RtMidiOut class declarations.
 | ||
|  | //
 | ||
|  | // RtMidiIn / RtMidiOut are "controllers" used to select an available
 | ||
|  | // MIDI input or output interface.  They present common APIs for the
 | ||
|  | // user to call but all functionality is implemented by the classes
 | ||
|  | // MidiInApi, MidiOutApi and their subclasses.  RtMidiIn and RtMidiOut
 | ||
|  | // each create an instance of a MidiInApi or MidiOutApi subclass based
 | ||
|  | // on the user's API choice.  If no choice is made, they attempt to
 | ||
|  | // make a "logical" API selection.
 | ||
|  | //
 | ||
|  | // **************************************************************** //
 | ||
|  | 
 | ||
|  | class RTMIDI_DLL_PUBLIC RtMidiIn : public RtMidi | ||
|  | { | ||
|  |  public: | ||
|  |   //! User callback function type definition.
 | ||
|  |   typedef void (*RtMidiCallback)( double timeStamp, std::vector<unsigned char> *message, void *userData ); | ||
|  | 
 | ||
|  |   //! Default constructor that allows an optional api, client name and queue size.
 | ||
|  |   /*!
 | ||
|  |     An exception will be thrown if a MIDI system initialization | ||
|  |     error occurs.  The queue size defines the maximum number of | ||
|  |     messages that can be held in the MIDI queue (when not using a | ||
|  |     callback function).  If the queue size limit is reached, | ||
|  |     incoming messages will be ignored. | ||
|  | 
 | ||
|  |     If no API argument is specified and multiple API support has been | ||
|  |     compiled, the default order of use is ALSA, JACK (Linux) and CORE, | ||
|  |     JACK (OS-X). | ||
|  | 
 | ||
|  |     \param api        An optional API id can be specified. | ||
|  |     \param clientName An optional client name can be specified. This | ||
|  |                       will be used to group the ports that are created | ||
|  |                       by the application. | ||
|  |     \param queueSizeLimit An optional size of the MIDI input queue can be specified. | ||
|  |   */ | ||
|  |   RtMidiIn( RtMidi::Api api=UNSPECIFIED, | ||
|  |             const std::string& clientName = "RtMidi Input Client", | ||
|  |             unsigned int queueSizeLimit = 100 ); | ||
|  | 
 | ||
|  |   RtMidiIn(RtMidiIn&& other) noexcept : RtMidi(std::move(other)) { } | ||
|  | 
 | ||
|  |   //! If a MIDI connection is still open, it will be closed by the destructor.
 | ||
|  |   ~RtMidiIn ( void ) throw(); | ||
|  | 
 | ||
|  |   //! Returns the MIDI API specifier for the current instance of RtMidiIn.
 | ||
|  |   RtMidi::Api getCurrentApi( void ) throw(); | ||
|  | 
 | ||
|  |   //! Open a MIDI input connection given by enumeration number.
 | ||
|  |   /*!
 | ||
|  |     \param portNumber An optional port number greater than 0 can be specified. | ||
|  |                       Otherwise, the default or first port found is opened. | ||
|  |     \param portName An optional name for the application port that is used to connect to portId can be specified. | ||
|  |   */ | ||
|  |   void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi Input" ) ); | ||
|  | 
 | ||
|  |   //! Create a virtual input port, with optional name, to allow software connections (OS X, JACK and ALSA only).
 | ||
|  |   /*!
 | ||
|  |     This function creates a virtual MIDI input port to which other | ||
|  |     software applications can connect.  This type of functionality | ||
|  |     is currently only supported by the Macintosh OS-X, any JACK, | ||
|  |     and Linux ALSA APIs (the function returns an error for the other APIs). | ||
|  | 
 | ||
|  |     \param portName An optional name for the application port that is | ||
|  |                     used to connect to portId can be specified. | ||
|  |   */ | ||
|  |   void openVirtualPort( const std::string &portName = std::string( "RtMidi Input" ) ); | ||
|  | 
 | ||
|  |   //! Set a callback function to be invoked for incoming MIDI messages.
 | ||
|  |   /*!
 | ||
|  |     The callback function will be called whenever an incoming MIDI | ||
|  |     message is received.  While not absolutely necessary, it is best | ||
|  |     to set the callback function before opening a MIDI port to avoid | ||
|  |     leaving some messages in the queue. | ||
|  | 
 | ||
|  |     \param callback A callback function must be given. | ||
|  |     \param userData Optionally, a pointer to additional data can be | ||
|  |                     passed to the callback function whenever it is called. | ||
|  |   */ | ||
|  |   void setCallback( RtMidiCallback callback, void *userData = 0 ); | ||
|  | 
 | ||
|  |   //! Cancel use of the current callback function (if one exists).
 | ||
|  |   /*!
 | ||
|  |     Subsequent incoming MIDI messages will be written to the queue | ||
|  |     and can be retrieved with the \e getMessage function. | ||
|  |   */ | ||
|  |   void cancelCallback(); | ||
|  | 
 | ||
|  |   //! Close an open MIDI connection (if one exists).
 | ||
|  |   void closePort( void ); | ||
|  | 
 | ||
|  |   //! Returns true if a port is open and false if not.
 | ||
|  |   /*!
 | ||
|  |       Note that this only applies to connections made with the openPort() | ||
|  |       function, not to virtual ports. | ||
|  |   */ | ||
|  |   virtual bool isPortOpen() const; | ||
|  | 
 | ||
|  |   //! Return the number of available MIDI input ports.
 | ||
|  |   /*!
 | ||
|  |     \return This function returns the number of MIDI ports of the selected API. | ||
|  |   */ | ||
|  |   unsigned int getPortCount(); | ||
|  | 
 | ||
|  |   //! Return a string identifier for the specified MIDI input port number.
 | ||
|  |   /*!
 | ||
|  |     \return The name of the port with the given Id is returned. | ||
|  |     \retval An empty string is returned if an invalid port specifier | ||
|  |             is provided. User code should assume a UTF-8 encoding. | ||
|  |   */ | ||
|  |   std::string getPortName( unsigned int portNumber = 0 ); | ||
|  | 
 | ||
|  |   //! Specify whether certain MIDI message types should be queued or ignored during input.
 | ||
|  |   /*!
 | ||
|  |     By default, MIDI timing and active sensing messages are ignored | ||
|  |     during message input because of their relative high data rates. | ||
|  |     MIDI sysex messages are ignored by default as well.  Variable | ||
|  |     values of "true" imply that the respective message type will be | ||
|  |     ignored. | ||
|  |   */ | ||
|  |   void ignoreTypes( bool midiSysex = true, bool midiTime = true, bool midiSense = true ); | ||
|  | 
 | ||
|  |   //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds.
 | ||
|  |   /*!
 | ||
|  |     This function returns immediately whether a new message is | ||
|  |     available or not.  A valid message is indicated by a non-zero | ||
|  |     vector size.  An exception is thrown if an error occurs during | ||
|  |     message retrieval or an input connection was not previously | ||
|  |     established. | ||
|  |   */ | ||
|  |   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, void *userData = 0 ); | ||
|  | 
 | ||
|  |   //! Set maximum expected incoming message size.
 | ||
|  |   /*!
 | ||
|  |     For APIs that require manual buffer management, it can be useful to set the buffer | ||
|  |     size and buffer count when expecting to receive large SysEx messages.  Note that | ||
|  |     currently this function has no effect when called after openPort().  The default | ||
|  |     buffer size is 1024 with a count of 4 buffers, which should be sufficient for most | ||
|  |     cases; as mentioned, this does not affect all API backends, since most either support | ||
|  |     dynamically scalable buffers or take care of buffer handling themselves.  It is | ||
|  |     principally intended for users of the Windows MM backend who must support receiving | ||
|  |     especially large messages. | ||
|  |   */ | ||
|  |   virtual void setBufferSize( unsigned int size, unsigned int count ); | ||
|  | 
 | ||
|  |  protected: | ||
|  |   void openMidiApi( RtMidi::Api api, const std::string &clientName, unsigned int queueSizeLimit ); | ||
|  | }; | ||
|  | 
 | ||
|  | /**********************************************************************/ | ||
|  | /*! \class RtMidiOut
 | ||
|  |     \brief A realtime MIDI output class. | ||
|  | 
 | ||
|  |     This class provides a common, platform-independent API for MIDI | ||
|  |     output.  It allows one to probe available MIDI output ports, to | ||
|  |     connect to one such port, and to send MIDI bytes immediately over | ||
|  |     the connection.  Create multiple instances of this class to | ||
|  |     connect to more than one MIDI device at the same time.  With the | ||
|  |     OS-X, Linux ALSA and JACK MIDI APIs, it is also possible to open a | ||
|  |     virtual port to which other MIDI software clients can connect. | ||
|  | */ | ||
|  | /**********************************************************************/ | ||
|  | 
 | ||
|  | class RTMIDI_DLL_PUBLIC RtMidiOut : public RtMidi | ||
|  | { | ||
|  |  public: | ||
|  |   //! Default constructor that allows an optional client name.
 | ||
|  |   /*!
 | ||
|  |     An exception will be thrown if a MIDI system initialization error occurs. | ||
|  | 
 | ||
|  |     If no API argument is specified and multiple API support has been | ||
|  |     compiled, the default order of use is ALSA, JACK (Linux) and CORE, | ||
|  |     JACK (OS-X). | ||
|  |   */ | ||
|  |   RtMidiOut( RtMidi::Api api=UNSPECIFIED, | ||
|  |              const std::string& clientName = "RtMidi Output Client" ); | ||
|  | 
 | ||
|  |   RtMidiOut(RtMidiOut&& other) noexcept : RtMidi(std::move(other)) { } | ||
|  | 
 | ||
|  |   //! The destructor closes any open MIDI connections.
 | ||
|  |   ~RtMidiOut( void ) throw(); | ||
|  | 
 | ||
|  |   //! Returns the MIDI API specifier for the current instance of RtMidiOut.
 | ||
|  |   RtMidi::Api getCurrentApi( void ) throw(); | ||
|  | 
 | ||
|  |   //! Open a MIDI output connection.
 | ||
|  |   /*!
 | ||
|  |       An optional port number greater than 0 can be specified. | ||
|  |       Otherwise, the default or first port found is opened.  An | ||
|  |       exception is thrown if an error occurs while attempting to make | ||
|  |       the port connection. | ||
|  |   */ | ||
|  |   void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi Output" ) ); | ||
|  | 
 | ||
|  |   //! Close an open MIDI connection (if one exists).
 | ||
|  |   void closePort( void ); | ||
|  | 
 | ||
|  |   //! Returns true if a port is open and false if not.
 | ||
|  |   /*!
 | ||
|  |       Note that this only applies to connections made with the openPort() | ||
|  |       function, not to virtual ports. | ||
|  |   */ | ||
|  |   virtual bool isPortOpen() const; | ||
|  | 
 | ||
|  |   //! Create a virtual output port, with optional name, to allow software connections (OS X, JACK and ALSA only).
 | ||
|  |   /*!
 | ||
|  |       This function creates a virtual MIDI output port to which other | ||
|  |       software applications can connect.  This type of functionality | ||
|  |       is currently only supported by the Macintosh OS-X, Linux ALSA | ||
|  |       and JACK APIs (the function does nothing with the other APIs). | ||
|  |       An exception is thrown if an error occurs while attempting to | ||
|  |       create the virtual port. | ||
|  |   */ | ||
|  |   void openVirtualPort( const std::string &portName = std::string( "RtMidi Output" ) ); | ||
|  | 
 | ||
|  |   //! Return the number of available MIDI output ports.
 | ||
|  |   unsigned int getPortCount( void ); | ||
|  | 
 | ||
|  |   //! Return a string identifier for the specified MIDI port type and number.
 | ||
|  |   /*!
 | ||
|  |     \return The name of the port with the given Id is returned. | ||
|  |     \retval An empty string is returned if an invalid port specifier | ||
|  |             is provided. User code should assume a UTF-8 encoding. | ||
|  |   */ | ||
|  |   std::string getPortName( unsigned int portNumber = 0 ); | ||
|  | 
 | ||
|  |   //! Immediately send a single message out an open MIDI output port.
 | ||
|  |   /*!
 | ||
|  |       An exception is thrown if an error occurs during output or an | ||
|  |       output connection was not previously established. | ||
|  |   */ | ||
|  |   void sendMessage( const std::vector<unsigned char> *message ); | ||
|  | 
 | ||
|  |   //! Immediately send a single message out an open MIDI output port.
 | ||
|  |   /*!
 | ||
|  |       An exception is thrown if an error occurs during output or an | ||
|  |       output connection was not previously established. | ||
|  | 
 | ||
|  |       \param message A pointer to the MIDI message as raw bytes | ||
|  |       \param size    Length of the MIDI message in bytes | ||
|  |   */ | ||
|  |   void sendMessage( const unsigned char *message, size_t size ); | ||
|  | 
 | ||
|  |   //! 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, void *userData = 0 ); | ||
|  | 
 | ||
|  |  protected: | ||
|  |   void openMidiApi( RtMidi::Api api, const std::string &clientName ); | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | // **************************************************************** //
 | ||
|  | //
 | ||
|  | // MidiInApi / MidiOutApi class declarations.
 | ||
|  | //
 | ||
|  | // Subclasses of MidiInApi and MidiOutApi contain all API- and
 | ||
|  | // OS-specific code necessary to fully implement the RtMidi API.
 | ||
|  | //
 | ||
|  | // Note that MidiInApi and MidiOutApi are abstract base classes and
 | ||
|  | // cannot be explicitly instantiated.  RtMidiIn and RtMidiOut will
 | ||
|  | // create instances of a MidiInApi or MidiOutApi subclass.
 | ||
|  | //
 | ||
|  | // **************************************************************** //
 | ||
|  | 
 | ||
|  | class RTMIDI_DLL_PUBLIC MidiApi | ||
|  | { | ||
|  |  public: | ||
|  | 
 | ||
|  |   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; | ||
|  |   virtual void setClientName( const std::string &clientName ) = 0; | ||
|  |   virtual void setPortName( const std::string &portName ) = 0; | ||
|  | 
 | ||
|  |   virtual unsigned int getPortCount( void ) = 0; | ||
|  |   virtual std::string getPortName( unsigned int portNumber ) = 0; | ||
|  | 
 | ||
|  |   inline bool isPortOpen() const { return connected_; } | ||
|  |   void setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ); | ||
|  | 
 | ||
|  |   //! A basic error reporting function for RtMidi classes.
 | ||
|  |   void error( RtMidiError::Type type, std::string errorString ); | ||
|  | 
 | ||
|  | protected: | ||
|  |   virtual void initialize( const std::string& clientName ) = 0; | ||
|  | 
 | ||
|  |   void *apiData_; | ||
|  |   bool connected_; | ||
|  |   std::string errorString_; | ||
|  |   RtMidiErrorCallback errorCallback_; | ||
|  |   bool firstErrorOccurred_; | ||
|  |   void *errorCallbackUserData_; | ||
|  | 
 | ||
|  | }; | ||
|  | 
 | ||
|  | class RTMIDI_DLL_PUBLIC 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 ); | ||
|  |   virtual void setBufferSize( unsigned int size, unsigned int count ); | ||
|  | 
 | ||
|  |   // A MIDI structure used internally by the class to store incoming
 | ||
|  |   // messages.  Each message represents one and only one MIDI message.
 | ||
|  |   struct MidiMessage { | ||
|  |     std::vector<unsigned char> bytes; | ||
|  | 
 | ||
|  |     //! Time in seconds elapsed since the previous message
 | ||
|  |     double timeStamp; | ||
|  | 
 | ||
|  |     // Default constructor.
 | ||
|  |     MidiMessage() | ||
|  |       : bytes(0), timeStamp(0.0) {} | ||
|  |   }; | ||
|  | 
 | ||
|  |   struct MidiQueue { | ||
|  |     unsigned int front; | ||
|  |     unsigned int back; | ||
|  |     unsigned int ringSize; | ||
|  |     MidiMessage *ring; | ||
|  | 
 | ||
|  |     // Default constructor.
 | ||
|  |     MidiQueue() | ||
|  |       : front(0), back(0), ringSize(0), ring(0) {} | ||
|  |     bool push( const MidiMessage& ); | ||
|  |     bool pop( std::vector<unsigned char>*, double* ); | ||
|  |     unsigned int size( unsigned int *back=0, unsigned int *front=0 ); | ||
|  |   }; | ||
|  | 
 | ||
|  |   // The RtMidiInData structure is used to pass private class data to
 | ||
|  |   // the MIDI input handling function or thread.
 | ||
|  |   struct RtMidiInData { | ||
|  |     MidiQueue queue; | ||
|  |     MidiMessage message; | ||
|  |     unsigned char ignoreFlags; | ||
|  |     bool doInput; | ||
|  |     bool firstMessage; | ||
|  |     void *apiData; | ||
|  |     bool usingCallback; | ||
|  |     RtMidiIn::RtMidiCallback userCallback; | ||
|  |     void *userData; | ||
|  |     bool continueSysex; | ||
|  |     unsigned int bufferSize; | ||
|  |     unsigned int bufferCount; | ||
|  | 
 | ||
|  |     // Default constructor.
 | ||
|  |     RtMidiInData() | ||
|  |       : ignoreFlags(7), doInput(false), firstMessage(true), apiData(0), usingCallback(false), | ||
|  |         userCallback(0), userData(0), continueSysex(false), bufferSize(1024), bufferCount(4) {} | ||
|  |   }; | ||
|  | 
 | ||
|  |  protected: | ||
|  |   RtMidiInData inputData_; | ||
|  | }; | ||
|  | 
 | ||
|  | class RTMIDI_DLL_PUBLIC MidiOutApi : public MidiApi | ||
|  | { | ||
|  |  public: | ||
|  | 
 | ||
|  |   MidiOutApi( void ); | ||
|  |   virtual ~MidiOutApi( void ); | ||
|  |   virtual void sendMessage( const unsigned char *message, size_t size ) = 0; | ||
|  | }; | ||
|  | 
 | ||
|  | // **************************************************************** //
 | ||
|  | //
 | ||
|  | // Inline RtMidiIn and RtMidiOut definitions.
 | ||
|  | //
 | ||
|  | // **************************************************************** //
 | ||
|  | 
 | ||
|  | inline RtMidi::Api RtMidiIn :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); } | ||
|  | 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 bool RtMidiIn :: isPortOpen() const { return rtapi_->isPortOpen(); } | ||
|  | inline void RtMidiIn :: setCallback( RtMidiCallback callback, void *userData ) { static_cast<MidiInApi *>(rtapi_)->setCallback( callback, userData ); } | ||
|  | inline void RtMidiIn :: cancelCallback( void ) { static_cast<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 ) { static_cast<MidiInApi *>(rtapi_)->ignoreTypes( midiSysex, midiTime, midiSense ); } | ||
|  | inline double RtMidiIn :: getMessage( std::vector<unsigned char> *message ) { return static_cast<MidiInApi *>(rtapi_)->getMessage( message ); } | ||
|  | inline void RtMidiIn :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); } | ||
|  | inline void RtMidiIn :: setBufferSize( unsigned int size, unsigned int count ) { static_cast<MidiInApi *>(rtapi_)->setBufferSize(size, count); } | ||
|  | 
 | ||
|  | inline RtMidi::Api RtMidiOut :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); } | ||
|  | 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 bool RtMidiOut :: isPortOpen() const { return rtapi_->isPortOpen(); } | ||
|  | 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( const std::vector<unsigned char> *message ) { static_cast<MidiOutApi *>(rtapi_)->sendMessage( &message->at(0), message->size() ); } | ||
|  | inline void RtMidiOut :: sendMessage( const unsigned char *message, size_t size ) { static_cast<MidiOutApi *>(rtapi_)->sendMessage( message, size ); } | ||
|  | inline void RtMidiOut :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); } | ||
|  | 
 | ||
|  | #endif
 |