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
 |