DPF

DISTRHO Plugin Framework
Log | Files | Refs | Submodules | README | LICENSE

RtMidi.h (27068B)


      1 /**********************************************************************/
      2 /*! \class RtMidi
      3     \brief An abstract base class for realtime MIDI input/output.
      4 
      5     This class implements some common functionality for the realtime
      6     MIDI input/output subclasses RtMidiIn and RtMidiOut.
      7 
      8     RtMidi GitHub site: https://github.com/thestk/rtmidi
      9     RtMidi WWW site: http://www.music.mcgill.ca/~gary/rtmidi/
     10 
     11     RtMidi: realtime MIDI i/o C++ classes
     12     Copyright (c) 2003-2021 Gary P. Scavone
     13 
     14     Permission is hereby granted, free of charge, to any person
     15     obtaining a copy of this software and associated documentation files
     16     (the "Software"), to deal in the Software without restriction,
     17     including without limitation the rights to use, copy, modify, merge,
     18     publish, distribute, sublicense, and/or sell copies of the Software,
     19     and to permit persons to whom the Software is furnished to do so,
     20     subject to the following conditions:
     21 
     22     The above copyright notice and this permission notice shall be
     23     included in all copies or substantial portions of the Software.
     24 
     25     Any person wishing to distribute modifications to the Software is
     26     asked to send the modifications to the original developer so that
     27     they can be incorporated into the canonical version.  This is,
     28     however, not a binding provision of this license.
     29 
     30     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     31     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     32     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     33     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
     34     ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
     35     CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     36     WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     37 */
     38 /**********************************************************************/
     39 
     40 /*!
     41   \file RtMidi.h
     42  */
     43 
     44 #ifndef RTMIDI_H
     45 #define RTMIDI_H
     46 
     47 #if defined _WIN32 || defined __CYGWIN__
     48   #if defined(RTMIDI_EXPORT)
     49     #define RTMIDI_DLL_PUBLIC __declspec(dllexport)
     50   #else
     51     #define RTMIDI_DLL_PUBLIC
     52   #endif
     53 #else
     54   #if __GNUC__ >= 4
     55     #define RTMIDI_DLL_PUBLIC __attribute__( (visibility( "default" )) )
     56   #else
     57     #define RTMIDI_DLL_PUBLIC
     58   #endif
     59 #endif
     60 
     61 #define RTMIDI_VERSION "5.0.0"
     62 
     63 #include <exception>
     64 #include <iostream>
     65 #include <string>
     66 #include <vector>
     67 
     68 
     69 /************************************************************************/
     70 /*! \class RtMidiError
     71     \brief Exception handling class for RtMidi.
     72 
     73     The RtMidiError class is quite simple but it does allow errors to be
     74     "caught" by RtMidiError::Type. See the RtMidi documentation to know
     75     which methods can throw an RtMidiError.
     76 */
     77 /************************************************************************/
     78 
     79 class RTMIDI_DLL_PUBLIC RtMidiError : public std::exception
     80 {
     81  public:
     82   //! Defined RtMidiError types.
     83   enum Type {
     84     WARNING,           /*!< A non-critical error. */
     85     DEBUG_WARNING,     /*!< A non-critical error which might be useful for debugging. */
     86     UNSPECIFIED,       /*!< The default, unspecified error type. */
     87     NO_DEVICES_FOUND,  /*!< No devices found on system. */
     88     INVALID_DEVICE,    /*!< An invalid device ID was specified. */
     89     MEMORY_ERROR,      /*!< An error occured during memory allocation. */
     90     INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */
     91     INVALID_USE,       /*!< The function was called incorrectly. */
     92     DRIVER_ERROR,      /*!< A system driver error occured. */
     93     SYSTEM_ERROR,      /*!< A system error occured. */
     94     THREAD_ERROR       /*!< A thread error occured. */
     95   };
     96 
     97   //! The constructor.
     98   RtMidiError( const std::string& message, Type type = RtMidiError::UNSPECIFIED ) throw()
     99     : message_(message), type_(type) {}
    100 
    101   //! The destructor.
    102   virtual ~RtMidiError( void ) throw() {}
    103 
    104   //! Prints thrown error message to stderr.
    105   virtual void printMessage( void ) const throw() { std::cerr << '\n' << message_ << "\n\n"; }
    106 
    107   //! Returns the thrown error message type.
    108   virtual const Type& getType( void ) const throw() { return type_; }
    109 
    110   //! Returns the thrown error message string.
    111   virtual const std::string& getMessage( void ) const throw() { return message_; }
    112 
    113   //! Returns the thrown error message as a c-style string.
    114   virtual const char* what( void ) const throw() { return message_.c_str(); }
    115 
    116  protected:
    117   std::string message_;
    118   Type type_;
    119 };
    120 
    121 //! RtMidi error callback function prototype.
    122 /*!
    123     \param type Type of error.
    124     \param errorText Error description.
    125 
    126     Note that class behaviour is undefined after a critical error (not
    127     a warning) is reported.
    128  */
    129 typedef void (*RtMidiErrorCallback)( RtMidiError::Type type, const std::string &errorText, void *userData );
    130 
    131 class MidiApi;
    132 
    133 class RTMIDI_DLL_PUBLIC RtMidi
    134 {
    135  public:
    136 
    137      RtMidi(RtMidi&& other) noexcept;
    138   //! MIDI API specifier arguments.
    139   enum Api {
    140     UNSPECIFIED,    /*!< Search for a working compiled API. */
    141     MACOSX_CORE,    /*!< Macintosh OS-X CoreMIDI API. */
    142     LINUX_ALSA,     /*!< The Advanced Linux Sound Architecture API. */
    143     UNIX_JACK,      /*!< The JACK Low-Latency MIDI Server API. */
    144     WINDOWS_MM,     /*!< The Microsoft Multimedia MIDI API. */
    145     RTMIDI_DUMMY,   /*!< A compilable but non-functional API. */
    146     WEB_MIDI_API,   /*!< W3C Web MIDI API. */
    147     NUM_APIS        /*!< Number of values in this enum. */
    148   };
    149 
    150   //! A static function to determine the current RtMidi version.
    151   static std::string getVersion( void ) throw();
    152 
    153   //! A static function to determine the available compiled MIDI APIs.
    154   /*!
    155     The values returned in the std::vector can be compared against
    156     the enumerated list values.  Note that there can be more than one
    157     API compiled for certain operating systems.
    158   */
    159   static void getCompiledApi( std::vector<RtMidi::Api> &apis ) throw();
    160 
    161   //! Return the name of a specified compiled MIDI API.
    162   /*!
    163     This obtains a short lower-case name used for identification purposes.
    164     This value is guaranteed to remain identical across library versions.
    165     If the API is unknown, this function will return the empty string.
    166   */
    167   static std::string getApiName( RtMidi::Api api );
    168 
    169   //! Return the display name of a specified compiled MIDI API.
    170   /*!
    171     This obtains a long name used for display purposes.
    172     If the API is unknown, this function will return the empty string.
    173   */
    174   static std::string getApiDisplayName( RtMidi::Api api );
    175 
    176   //! Return the compiled MIDI API having the given name.
    177   /*!
    178     A case insensitive comparison will check the specified name
    179     against the list of compiled APIs, and return the one which
    180     matches. On failure, the function returns UNSPECIFIED.
    181   */
    182   static RtMidi::Api getCompiledApiByName( const std::string &name );
    183 
    184   //! Pure virtual openPort() function.
    185   virtual void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi" ) ) = 0;
    186 
    187   //! Pure virtual openVirtualPort() function.
    188   virtual void openVirtualPort( const std::string &portName = std::string( "RtMidi" ) ) = 0;
    189 
    190   //! Pure virtual getPortCount() function.
    191   virtual unsigned int getPortCount() = 0;
    192 
    193   //! Pure virtual getPortName() function.
    194   virtual std::string getPortName( unsigned int portNumber = 0 ) = 0;
    195 
    196   //! Pure virtual closePort() function.
    197   virtual void closePort( void ) = 0;
    198 
    199   void setClientName( const std::string &clientName );
    200   void setPortName( const std::string &portName );
    201 
    202   //! Returns true if a port is open and false if not.
    203   /*!
    204       Note that this only applies to connections made with the openPort()
    205       function, not to virtual ports.
    206   */
    207   virtual bool isPortOpen( void ) const = 0;
    208 
    209   //! Set an error callback function to be invoked when an error has occured.
    210   /*!
    211     The callback function will be called whenever an error has occured. It is best
    212     to set the error callback function before opening a port.
    213   */
    214   virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 ) = 0;
    215 
    216  protected:
    217   RtMidi();
    218   virtual ~RtMidi();
    219   MidiApi *rtapi_;
    220 
    221   /* Make the class non-copyable */
    222   RtMidi(RtMidi& other) = delete;
    223   RtMidi& operator=(RtMidi& other) = delete;
    224 };
    225 
    226 /**********************************************************************/
    227 /*! \class RtMidiIn
    228     \brief A realtime MIDI input class.
    229 
    230     This class provides a common, platform-independent API for
    231     realtime MIDI input.  It allows access to a single MIDI input
    232     port.  Incoming MIDI messages are either saved to a queue for
    233     retrieval using the getMessage() function or immediately passed to
    234     a user-specified callback function.  Create multiple instances of
    235     this class to connect to more than one MIDI device at the same
    236     time.  With the OS-X, Linux ALSA, and JACK MIDI APIs, it is also
    237     possible to open a virtual input port to which other MIDI software
    238     clients can connect.
    239 */
    240 /**********************************************************************/
    241 
    242 // **************************************************************** //
    243 //
    244 // RtMidiIn and RtMidiOut class declarations.
    245 //
    246 // RtMidiIn / RtMidiOut are "controllers" used to select an available
    247 // MIDI input or output interface.  They present common APIs for the
    248 // user to call but all functionality is implemented by the classes
    249 // MidiInApi, MidiOutApi and their subclasses.  RtMidiIn and RtMidiOut
    250 // each create an instance of a MidiInApi or MidiOutApi subclass based
    251 // on the user's API choice.  If no choice is made, they attempt to
    252 // make a "logical" API selection.
    253 //
    254 // **************************************************************** //
    255 
    256 class RTMIDI_DLL_PUBLIC RtMidiIn : public RtMidi
    257 {
    258  public:
    259   //! User callback function type definition.
    260   typedef void (*RtMidiCallback)( double timeStamp, std::vector<unsigned char> *message, void *userData );
    261 
    262   //! Default constructor that allows an optional api, client name and queue size.
    263   /*!
    264     An exception will be thrown if a MIDI system initialization
    265     error occurs.  The queue size defines the maximum number of
    266     messages that can be held in the MIDI queue (when not using a
    267     callback function).  If the queue size limit is reached,
    268     incoming messages will be ignored.
    269 
    270     If no API argument is specified and multiple API support has been
    271     compiled, the default order of use is ALSA, JACK (Linux) and CORE,
    272     JACK (OS-X).
    273 
    274     \param api        An optional API id can be specified.
    275     \param clientName An optional client name can be specified. This
    276                       will be used to group the ports that are created
    277                       by the application.
    278     \param queueSizeLimit An optional size of the MIDI input queue can be specified.
    279   */
    280   RtMidiIn( RtMidi::Api api=UNSPECIFIED,
    281             const std::string& clientName = "RtMidi Input Client",
    282             unsigned int queueSizeLimit = 100 );
    283 
    284   RtMidiIn(RtMidiIn&& other) noexcept : RtMidi(std::move(other)) { }
    285 
    286   //! If a MIDI connection is still open, it will be closed by the destructor.
    287   ~RtMidiIn ( void ) throw();
    288 
    289   //! Returns the MIDI API specifier for the current instance of RtMidiIn.
    290   RtMidi::Api getCurrentApi( void ) throw();
    291 
    292   //! Open a MIDI input connection given by enumeration number.
    293   /*!
    294     \param portNumber An optional port number greater than 0 can be specified.
    295                       Otherwise, the default or first port found is opened.
    296     \param portName An optional name for the application port that is used to connect to portId can be specified.
    297   */
    298   void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi Input" ) );
    299 
    300   //! Create a virtual input port, with optional name, to allow software connections (OS X, JACK and ALSA only).
    301   /*!
    302     This function creates a virtual MIDI input port to which other
    303     software applications can connect.  This type of functionality
    304     is currently only supported by the Macintosh OS-X, any JACK,
    305     and Linux ALSA APIs (the function returns an error for the other APIs).
    306 
    307     \param portName An optional name for the application port that is
    308                     used to connect to portId can be specified.
    309   */
    310   void openVirtualPort( const std::string &portName = std::string( "RtMidi Input" ) );
    311 
    312   //! Set a callback function to be invoked for incoming MIDI messages.
    313   /*!
    314     The callback function will be called whenever an incoming MIDI
    315     message is received.  While not absolutely necessary, it is best
    316     to set the callback function before opening a MIDI port to avoid
    317     leaving some messages in the queue.
    318 
    319     \param callback A callback function must be given.
    320     \param userData Optionally, a pointer to additional data can be
    321                     passed to the callback function whenever it is called.
    322   */
    323   void setCallback( RtMidiCallback callback, void *userData = 0 );
    324 
    325   //! Cancel use of the current callback function (if one exists).
    326   /*!
    327     Subsequent incoming MIDI messages will be written to the queue
    328     and can be retrieved with the \e getMessage function.
    329   */
    330   void cancelCallback();
    331 
    332   //! Close an open MIDI connection (if one exists).
    333   void closePort( void );
    334 
    335   //! Returns true if a port is open and false if not.
    336   /*!
    337       Note that this only applies to connections made with the openPort()
    338       function, not to virtual ports.
    339   */
    340   virtual bool isPortOpen() const;
    341 
    342   //! Return the number of available MIDI input ports.
    343   /*!
    344     \return This function returns the number of MIDI ports of the selected API.
    345   */
    346   unsigned int getPortCount();
    347 
    348   //! Return a string identifier for the specified MIDI input port number.
    349   /*!
    350     \return The name of the port with the given Id is returned.
    351     \retval An empty string is returned if an invalid port specifier
    352             is provided. User code should assume a UTF-8 encoding.
    353   */
    354   std::string getPortName( unsigned int portNumber = 0 );
    355 
    356   //! Specify whether certain MIDI message types should be queued or ignored during input.
    357   /*!
    358     By default, MIDI timing and active sensing messages are ignored
    359     during message input because of their relative high data rates.
    360     MIDI sysex messages are ignored by default as well.  Variable
    361     values of "true" imply that the respective message type will be
    362     ignored.
    363   */
    364   void ignoreTypes( bool midiSysex = true, bool midiTime = true, bool midiSense = true );
    365 
    366   //! 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.
    367   /*!
    368     This function returns immediately whether a new message is
    369     available or not.  A valid message is indicated by a non-zero
    370     vector size.  An exception is thrown if an error occurs during
    371     message retrieval or an input connection was not previously
    372     established.
    373   */
    374   double getMessage( std::vector<unsigned char> *message );
    375 
    376   //! Set an error callback function to be invoked when an error has occured.
    377   /*!
    378     The callback function will be called whenever an error has occured. It is best
    379     to set the error callback function before opening a port.
    380   */
    381   virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 );
    382 
    383   //! Set maximum expected incoming message size.
    384   /*!
    385     For APIs that require manual buffer management, it can be useful to set the buffer
    386     size and buffer count when expecting to receive large SysEx messages.  Note that
    387     currently this function has no effect when called after openPort().  The default
    388     buffer size is 1024 with a count of 4 buffers, which should be sufficient for most
    389     cases; as mentioned, this does not affect all API backends, since most either support
    390     dynamically scalable buffers or take care of buffer handling themselves.  It is
    391     principally intended for users of the Windows MM backend who must support receiving
    392     especially large messages.
    393   */
    394   virtual void setBufferSize( unsigned int size, unsigned int count );
    395 
    396  protected:
    397   void openMidiApi( RtMidi::Api api, const std::string &clientName, unsigned int queueSizeLimit );
    398 };
    399 
    400 /**********************************************************************/
    401 /*! \class RtMidiOut
    402     \brief A realtime MIDI output class.
    403 
    404     This class provides a common, platform-independent API for MIDI
    405     output.  It allows one to probe available MIDI output ports, to
    406     connect to one such port, and to send MIDI bytes immediately over
    407     the connection.  Create multiple instances of this class to
    408     connect to more than one MIDI device at the same time.  With the
    409     OS-X, Linux ALSA and JACK MIDI APIs, it is also possible to open a
    410     virtual port to which other MIDI software clients can connect.
    411 */
    412 /**********************************************************************/
    413 
    414 class RTMIDI_DLL_PUBLIC RtMidiOut : public RtMidi
    415 {
    416  public:
    417   //! Default constructor that allows an optional client name.
    418   /*!
    419     An exception will be thrown if a MIDI system initialization error occurs.
    420 
    421     If no API argument is specified and multiple API support has been
    422     compiled, the default order of use is ALSA, JACK (Linux) and CORE,
    423     JACK (OS-X).
    424   */
    425   RtMidiOut( RtMidi::Api api=UNSPECIFIED,
    426              const std::string& clientName = "RtMidi Output Client" );
    427 
    428   RtMidiOut(RtMidiOut&& other) noexcept : RtMidi(std::move(other)) { }
    429 
    430   //! The destructor closes any open MIDI connections.
    431   ~RtMidiOut( void ) throw();
    432 
    433   //! Returns the MIDI API specifier for the current instance of RtMidiOut.
    434   RtMidi::Api getCurrentApi( void ) throw();
    435 
    436   //! Open a MIDI output connection.
    437   /*!
    438       An optional port number greater than 0 can be specified.
    439       Otherwise, the default or first port found is opened.  An
    440       exception is thrown if an error occurs while attempting to make
    441       the port connection.
    442   */
    443   void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi Output" ) );
    444 
    445   //! Close an open MIDI connection (if one exists).
    446   void closePort( void );
    447 
    448   //! Returns true if a port is open and false if not.
    449   /*!
    450       Note that this only applies to connections made with the openPort()
    451       function, not to virtual ports.
    452   */
    453   virtual bool isPortOpen() const;
    454 
    455   //! Create a virtual output port, with optional name, to allow software connections (OS X, JACK and ALSA only).
    456   /*!
    457       This function creates a virtual MIDI output port to which other
    458       software applications can connect.  This type of functionality
    459       is currently only supported by the Macintosh OS-X, Linux ALSA
    460       and JACK APIs (the function does nothing with the other APIs).
    461       An exception is thrown if an error occurs while attempting to
    462       create the virtual port.
    463   */
    464   void openVirtualPort( const std::string &portName = std::string( "RtMidi Output" ) );
    465 
    466   //! Return the number of available MIDI output ports.
    467   unsigned int getPortCount( void );
    468 
    469   //! Return a string identifier for the specified MIDI port type and number.
    470   /*!
    471     \return The name of the port with the given Id is returned.
    472     \retval An empty string is returned if an invalid port specifier
    473             is provided. User code should assume a UTF-8 encoding.
    474   */
    475   std::string getPortName( unsigned int portNumber = 0 );
    476 
    477   //! Immediately send a single message out an open MIDI output port.
    478   /*!
    479       An exception is thrown if an error occurs during output or an
    480       output connection was not previously established.
    481   */
    482   void sendMessage( const std::vector<unsigned char> *message );
    483 
    484   //! Immediately send a single message out an open MIDI output port.
    485   /*!
    486       An exception is thrown if an error occurs during output or an
    487       output connection was not previously established.
    488 
    489       \param message A pointer to the MIDI message as raw bytes
    490       \param size    Length of the MIDI message in bytes
    491   */
    492   void sendMessage( const unsigned char *message, size_t size );
    493 
    494   //! Set an error callback function to be invoked when an error has occured.
    495   /*!
    496     The callback function will be called whenever an error has occured. It is best
    497     to set the error callback function before opening a port.
    498   */
    499   virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 );
    500 
    501  protected:
    502   void openMidiApi( RtMidi::Api api, const std::string &clientName );
    503 };
    504 
    505 
    506 // **************************************************************** //
    507 //
    508 // MidiInApi / MidiOutApi class declarations.
    509 //
    510 // Subclasses of MidiInApi and MidiOutApi contain all API- and
    511 // OS-specific code necessary to fully implement the RtMidi API.
    512 //
    513 // Note that MidiInApi and MidiOutApi are abstract base classes and
    514 // cannot be explicitly instantiated.  RtMidiIn and RtMidiOut will
    515 // create instances of a MidiInApi or MidiOutApi subclass.
    516 //
    517 // **************************************************************** //
    518 
    519 class RTMIDI_DLL_PUBLIC MidiApi
    520 {
    521  public:
    522 
    523   MidiApi();
    524   virtual ~MidiApi();
    525   virtual RtMidi::Api getCurrentApi( void ) = 0;
    526   virtual void openPort( unsigned int portNumber, const std::string &portName ) = 0;
    527   virtual void openVirtualPort( const std::string &portName ) = 0;
    528   virtual void closePort( void ) = 0;
    529   virtual void setClientName( const std::string &clientName ) = 0;
    530   virtual void setPortName( const std::string &portName ) = 0;
    531 
    532   virtual unsigned int getPortCount( void ) = 0;
    533   virtual std::string getPortName( unsigned int portNumber ) = 0;
    534 
    535   inline bool isPortOpen() const { return connected_; }
    536   void setErrorCallback( RtMidiErrorCallback errorCallback, void *userData );
    537 
    538   //! A basic error reporting function for RtMidi classes.
    539   void error( RtMidiError::Type type, std::string errorString );
    540 
    541 protected:
    542   virtual void initialize( const std::string& clientName ) = 0;
    543 
    544   void *apiData_;
    545   bool connected_;
    546   std::string errorString_;
    547   RtMidiErrorCallback errorCallback_;
    548   bool firstErrorOccurred_;
    549   void *errorCallbackUserData_;
    550 
    551 };
    552 
    553 class RTMIDI_DLL_PUBLIC MidiInApi : public MidiApi
    554 {
    555  public:
    556 
    557   MidiInApi( unsigned int queueSizeLimit );
    558   virtual ~MidiInApi( void );
    559   void setCallback( RtMidiIn::RtMidiCallback callback, void *userData );
    560   void cancelCallback( void );
    561   virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense );
    562   double getMessage( std::vector<unsigned char> *message );
    563   virtual void setBufferSize( unsigned int size, unsigned int count );
    564 
    565   // A MIDI structure used internally by the class to store incoming
    566   // messages.  Each message represents one and only one MIDI message.
    567   struct MidiMessage {
    568     std::vector<unsigned char> bytes;
    569 
    570     //! Time in seconds elapsed since the previous message
    571     double timeStamp;
    572 
    573     // Default constructor.
    574     MidiMessage()
    575       : bytes(0), timeStamp(0.0) {}
    576   };
    577 
    578   struct MidiQueue {
    579     unsigned int front;
    580     unsigned int back;
    581     unsigned int ringSize;
    582     MidiMessage *ring;
    583 
    584     // Default constructor.
    585     MidiQueue()
    586       : front(0), back(0), ringSize(0), ring(0) {}
    587     bool push( const MidiMessage& );
    588     bool pop( std::vector<unsigned char>*, double* );
    589     unsigned int size( unsigned int *back=0, unsigned int *front=0 );
    590   };
    591 
    592   // The RtMidiInData structure is used to pass private class data to
    593   // the MIDI input handling function or thread.
    594   struct RtMidiInData {
    595     MidiQueue queue;
    596     MidiMessage message;
    597     unsigned char ignoreFlags;
    598     bool doInput;
    599     bool firstMessage;
    600     void *apiData;
    601     bool usingCallback;
    602     RtMidiIn::RtMidiCallback userCallback;
    603     void *userData;
    604     bool continueSysex;
    605     unsigned int bufferSize;
    606     unsigned int bufferCount;
    607 
    608     // Default constructor.
    609     RtMidiInData()
    610       : ignoreFlags(7), doInput(false), firstMessage(true), apiData(0), usingCallback(false),
    611         userCallback(0), userData(0), continueSysex(false), bufferSize(1024), bufferCount(4) {}
    612   };
    613 
    614  protected:
    615   RtMidiInData inputData_;
    616 };
    617 
    618 class RTMIDI_DLL_PUBLIC MidiOutApi : public MidiApi
    619 {
    620  public:
    621 
    622   MidiOutApi( void );
    623   virtual ~MidiOutApi( void );
    624   virtual void sendMessage( const unsigned char *message, size_t size ) = 0;
    625 };
    626 
    627 // **************************************************************** //
    628 //
    629 // Inline RtMidiIn and RtMidiOut definitions.
    630 //
    631 // **************************************************************** //
    632 
    633 inline RtMidi::Api RtMidiIn :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); }
    634 inline void RtMidiIn :: openPort( unsigned int portNumber, const std::string &portName ) { rtapi_->openPort( portNumber, portName ); }
    635 inline void RtMidiIn :: openVirtualPort( const std::string &portName ) { rtapi_->openVirtualPort( portName ); }
    636 inline void RtMidiIn :: closePort( void ) { rtapi_->closePort(); }
    637 inline bool RtMidiIn :: isPortOpen() const { return rtapi_->isPortOpen(); }
    638 inline void RtMidiIn :: setCallback( RtMidiCallback callback, void *userData ) { static_cast<MidiInApi *>(rtapi_)->setCallback( callback, userData ); }
    639 inline void RtMidiIn :: cancelCallback( void ) { static_cast<MidiInApi *>(rtapi_)->cancelCallback(); }
    640 inline unsigned int RtMidiIn :: getPortCount( void ) { return rtapi_->getPortCount(); }
    641 inline std::string RtMidiIn :: getPortName( unsigned int portNumber ) { return rtapi_->getPortName( portNumber ); }
    642 inline void RtMidiIn :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ) { static_cast<MidiInApi *>(rtapi_)->ignoreTypes( midiSysex, midiTime, midiSense ); }
    643 inline double RtMidiIn :: getMessage( std::vector<unsigned char> *message ) { return static_cast<MidiInApi *>(rtapi_)->getMessage( message ); }
    644 inline void RtMidiIn :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); }
    645 inline void RtMidiIn :: setBufferSize( unsigned int size, unsigned int count ) { static_cast<MidiInApi *>(rtapi_)->setBufferSize(size, count); }
    646 
    647 inline RtMidi::Api RtMidiOut :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); }
    648 inline void RtMidiOut :: openPort( unsigned int portNumber, const std::string &portName ) { rtapi_->openPort( portNumber, portName ); }
    649 inline void RtMidiOut :: openVirtualPort( const std::string &portName ) { rtapi_->openVirtualPort( portName ); }
    650 inline void RtMidiOut :: closePort( void ) { rtapi_->closePort(); }
    651 inline bool RtMidiOut :: isPortOpen() const { return rtapi_->isPortOpen(); }
    652 inline unsigned int RtMidiOut :: getPortCount( void ) { return rtapi_->getPortCount(); }
    653 inline std::string RtMidiOut :: getPortName( unsigned int portNumber ) { return rtapi_->getPortName( portNumber ); }
    654 inline void RtMidiOut :: sendMessage( const std::vector<unsigned char> *message ) { static_cast<MidiOutApi *>(rtapi_)->sendMessage( &message->at(0), message->size() ); }
    655 inline void RtMidiOut :: sendMessage( const unsigned char *message, size_t size ) { static_cast<MidiOutApi *>(rtapi_)->sendMessage( message, size ); }
    656 inline void RtMidiOut :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); }
    657 
    658 #endif