Chris@559: /**********************************************************************/
Chris@559: /*! \class RtMidi
Chris@559:     \brief An abstract base class for realtime MIDI input/output.
Chris@559: 
Chris@559:     This class implements some common functionality for the realtime
Chris@559:     MIDI input/output subclasses RtMidiIn and RtMidiOut.
Chris@559: 
Chris@559:     RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/
Chris@559: 
Chris@559:     RtMidi: realtime MIDI i/o C++ classes
Chris@565:     Copyright (c) 2003-2009 Gary P. Scavone
Chris@559: 
Chris@559:     Permission is hereby granted, free of charge, to any person
Chris@559:     obtaining a copy of this software and associated documentation files
Chris@559:     (the "Software"), to deal in the Software without restriction,
Chris@559:     including without limitation the rights to use, copy, modify, merge,
Chris@559:     publish, distribute, sublicense, and/or sell copies of the Software,
Chris@559:     and to permit persons to whom the Software is furnished to do so,
Chris@559:     subject to the following conditions:
Chris@559: 
Chris@559:     The above copyright notice and this permission notice shall be
Chris@559:     included in all copies or substantial portions of the Software.
Chris@559: 
Chris@559:     Any person wishing to distribute modifications to the Software is
Chris@559:     requested to send the modifications to the original developer so that
Chris@559:     they can be incorporated into the canonical version.
Chris@559: 
Chris@559:     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Chris@559:     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Chris@559:     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
Chris@559:     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
Chris@559:     ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
Chris@559:     CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
Chris@559:     WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Chris@559: */
Chris@559: /**********************************************************************/
Chris@559: 
Chris@565: // RtMidi: Version 1.0.8
Chris@559: 
Chris@559: #ifndef RTMIDI_H
Chris@559: #define RTMIDI_H
Chris@559: 
Chris@559: #include "RtError.h"
Chris@559: #include <string>
Chris@559: 
Chris@559: class RtMidi
Chris@559: {
Chris@559:  public:
Chris@559: 
Chris@559:   //! Pure virtual openPort() function.
Chris@565:   virtual void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi" ) ) = 0;
Chris@559: 
Chris@559:   //! Pure virtual openVirtualPort() function.
Chris@559:   virtual void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) = 0;
Chris@559: 
Chris@559:   //! Pure virtual getPortCount() function.
Chris@559:   virtual unsigned int getPortCount() = 0;
Chris@559: 
Chris@559:   //! Pure virtual getPortName() function.
Chris@559:   virtual std::string getPortName( unsigned int portNumber = 0 ) = 0;
Chris@559: 
Chris@559:   //! Pure virtual closePort() function.
Chris@559:   virtual void closePort( void ) = 0;
Chris@559: 
Chris@559:  protected:
Chris@559: 
Chris@559:   RtMidi();
Chris@559:   virtual ~RtMidi() {};
Chris@559: 
Chris@559:   // A basic error reporting function for internal use in the RtMidi
Chris@559:   // subclasses.  The behavior of this function can be modified to
Chris@559:   // suit specific needs.
Chris@559:   void error( RtError::Type type );
Chris@559: 
Chris@559:   void *apiData_;
Chris@559:   bool connected_;
Chris@559:   std::string errorString_;
Chris@559: };
Chris@559: 
Chris@559: /**********************************************************************/
Chris@559: /*! \class RtMidiIn
Chris@559:     \brief A realtime MIDI input class.
Chris@559: 
Chris@559:     This class provides a common, platform-independent API for
Chris@559:     realtime MIDI input.  It allows access to a single MIDI input
Chris@559:     port.  Incoming MIDI messages are either saved to a queue for
Chris@559:     retrieval using the getMessage() function or immediately passed to
Chris@559:     a user-specified callback function.  Create multiple instances of
Chris@559:     this class to connect to more than one MIDI device at the same
Chris@559:     time.  With the OS-X and Linux ALSA MIDI APIs, it is also possible
Chris@559:     to open a virtual input port to which other MIDI software clients
Chris@559:     can connect.
Chris@559: 
Chris@565:     by Gary P. Scavone, 2003-2008.
Chris@559: */
Chris@559: /**********************************************************************/
Chris@559: 
Chris@559: #include <vector>
Chris@559: #include <queue>
Chris@559: 
Chris@559: class RtMidiIn : public RtMidi
Chris@559: {
Chris@559:  public:
Chris@559: 
Chris@559:   //! User callback function type definition.
Chris@559:   typedef void (*RtMidiCallback)( double timeStamp, std::vector<unsigned char> *message, void *userData);
Chris@559: 
Chris@565:   //! Default constructor that allows an optional client name.
Chris@559:   /*!
Chris@559:       An exception will be thrown if a MIDI system initialization error occurs.
Chris@559:   */
Chris@565:   RtMidiIn( const std::string clientName = std::string( "RtMidi Input Client") );
Chris@559: 
Chris@559:   //! If a MIDI connection is still open, it will be closed by the destructor.
Chris@559:   ~RtMidiIn();
Chris@559: 
Chris@559:   //! Open a MIDI input connection.
Chris@559:   /*!
Chris@559:       An optional port number greater than 0 can be specified.
Chris@559:       Otherwise, the default or first port found is opened.
Chris@559:   */
Chris@565:   void openPort( unsigned int portNumber = 0, const std::string Portname = std::string( "RtMidi Input" ) );
Chris@559: 
Chris@559:   //! Create a virtual input port, with optional name, to allow software connections (OS X and ALSA only).
Chris@559:   /*!
Chris@559:       This function creates a virtual MIDI input port to which other
Chris@559:       software applications can connect.  This type of functionality
Chris@559:       is currently only supported by the Macintosh OS-X and Linux ALSA
Chris@559:       APIs (the function does nothing for the other APIs).
Chris@559:   */
Chris@559:   void openVirtualPort( const std::string portName = std::string( "RtMidi Input" ) );
Chris@559: 
Chris@559:   //! Set a callback function to be invoked for incoming MIDI messages.
Chris@559:   /*!
Chris@559:       The callback function will be called whenever an incoming MIDI
Chris@559:       message is received.  While not absolutely necessary, it is best
Chris@559:       to set the callback function before opening a MIDI port to avoid
Chris@559:       leaving some messages in the queue.
Chris@559:   */
Chris@559:   void setCallback( RtMidiCallback callback, void *userData = 0 );
Chris@559: 
Chris@559:   //! Cancel use of the current callback function (if one exists).
Chris@559:   /*!
Chris@559:       Subsequent incoming MIDI messages will be written to the queue
Chris@559:       and can be retrieved with the \e getMessage function.
Chris@559:   */
Chris@559:   void cancelCallback();
Chris@559: 
Chris@559:   //! Close an open MIDI connection (if one exists).
Chris@559:   void closePort( void );
Chris@559: 
Chris@559:   //! Return the number of available MIDI input ports.
Chris@559:   unsigned int getPortCount();
Chris@559: 
Chris@559:   //! Return a string identifier for the specified MIDI input port number.
Chris@559:   /*!
Chris@559:       An exception is thrown if an invalid port specifier is provided.
Chris@559:   */
Chris@559:   std::string getPortName( unsigned int portNumber = 0 );
Chris@559: 
Chris@559:   //! Set the maximum number of MIDI messages to be saved in the queue.
Chris@559:   /*!
Chris@559:       If the queue size limit is reached, incoming messages will be
Chris@559:       ignored.  The default limit is 1024.
Chris@559:   */
Chris@559:   void setQueueSizeLimit( unsigned int queueSize );
Chris@559: 
Chris@559:   //! Specify whether certain MIDI message types should be queued or ignored during input.
Chris@559:   /*!
Chris@559:       By default, MIDI timing and active sensing messages are ignored
Chris@559:       during message input because of their relative high data rates.
Chris@559:       MIDI sysex messages are ignored by default as well.  Variable
Chris@559:       values of "true" imply that the respective message type will be
Chris@559:       ignored.
Chris@559:   */
Chris@559:   void ignoreTypes( bool midiSysex = true, bool midiTime = true, bool midiSense = true );
Chris@559: 
Chris@559:   //! 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.
Chris@559:   /*!
Chris@559:       This function returns immediately whether a new message is
Chris@559:       available or not.  A valid message is indicated by a non-zero
Chris@559:       vector size.  An exception is thrown if an error occurs during
Chris@559:       message retrieval or an input connection was not previously
Chris@559:       established.
Chris@559:   */
Chris@559:   double getMessage( std::vector<unsigned char> *message );
Chris@559: 
Chris@559:   // A MIDI structure used internally by the class to store incoming
Chris@559:   // messages.  Each message represents one and only one MIDI message.
Chris@559:   struct MidiMessage { 
Chris@559:     std::vector<unsigned char> bytes; 
Chris@559:     double timeStamp;
Chris@559: 
Chris@559:     // Default constructor.
Chris@559:     MidiMessage()
Chris@559:       :bytes(3), timeStamp(0.0) {}
Chris@559:   };
Chris@559: 
Chris@559:   // The RtMidiInData structure is used to pass private class data to
Chris@559:   // the MIDI input handling function or thread.
Chris@559:   struct RtMidiInData {
Chris@559:     std::queue<MidiMessage> queue;
Chris@565:     MidiMessage message;
Chris@559:     unsigned int queueLimit;
Chris@559:     unsigned char ignoreFlags;
Chris@559:     bool doInput;
Chris@559:     bool firstMessage;
Chris@559:     void *apiData;
Chris@559:     bool usingCallback;
Chris@559:     void *userCallback;
Chris@559:     void *userData;
Chris@565:     bool continueSysex;
Chris@559: 
Chris@559:     // Default constructor.
Chris@559:     RtMidiInData()
Chris@559:       : queueLimit(1024), ignoreFlags(7), doInput(false), firstMessage(true),
Chris@565:         apiData(0), usingCallback(false), userCallback(0), userData(0),
Chris@565:         continueSysex(false) {}
Chris@559:   };
Chris@559: 
Chris@559:  private:
Chris@559: 
Chris@565:   void initialize( const std::string& clientName );
Chris@559:   RtMidiInData inputData_;
Chris@559: 
Chris@559: };
Chris@559: 
Chris@559: /**********************************************************************/
Chris@559: /*! \class RtMidiOut
Chris@559:     \brief A realtime MIDI output class.
Chris@559: 
Chris@559:     This class provides a common, platform-independent API for MIDI
Chris@559:     output.  It allows one to probe available MIDI output ports, to
Chris@559:     connect to one such port, and to send MIDI bytes immediately over
Chris@559:     the connection.  Create multiple instances of this class to
Chris@559:     connect to more than one MIDI device at the same time.
Chris@559: 
Chris@565:     by Gary P. Scavone, 2003-2008.
Chris@559: */
Chris@559: /**********************************************************************/
Chris@559: 
Chris@559: class RtMidiOut : public RtMidi
Chris@559: {
Chris@559:  public:
Chris@559: 
Chris@565:   //! Default constructor that allows an optional client name.
Chris@559:   /*!
Chris@559:       An exception will be thrown if a MIDI system initialization error occurs.
Chris@559:   */
Chris@565:   RtMidiOut( const std::string clientName = std::string( "RtMidi Output Client" ) );
Chris@559: 
Chris@559:   //! The destructor closes any open MIDI connections.
Chris@559:   ~RtMidiOut();
Chris@559: 
Chris@559:   //! Open a MIDI output connection.
Chris@559:   /*!
Chris@559:       An optional port number greater than 0 can be specified.
Chris@559:       Otherwise, the default or first port found is opened.  An
Chris@559:       exception is thrown if an error occurs while attempting to make
Chris@559:       the port connection.
Chris@559:   */
Chris@565:   void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi Output" ) );
Chris@559: 
Chris@559:   //! Close an open MIDI connection (if one exists).
Chris@559:   void closePort();
Chris@559: 
Chris@559:   //! Create a virtual output port, with optional name, to allow software connections (OS X and ALSA only).
Chris@559:   /*!
Chris@559:       This function creates a virtual MIDI output port to which other
Chris@559:       software applications can connect.  This type of functionality
Chris@559:       is currently only supported by the Macintosh OS-X and Linux ALSA
Chris@559:       APIs (the function does nothing with the other APIs).  An
Chris@559:       exception is thrown if an error occurs while attempting to create
Chris@559:       the virtual port.
Chris@559:   */
Chris@559:   void openVirtualPort( const std::string portName = std::string( "RtMidi Output" ) );
Chris@559: 
Chris@559:   //! Return the number of available MIDI output ports.
Chris@559:   unsigned int getPortCount();
Chris@559: 
Chris@559:   //! Return a string identifier for the specified MIDI port type and number.
Chris@559:   /*!
Chris@559:       An exception is thrown if an invalid port specifier is provided.
Chris@559:   */
Chris@559:   std::string getPortName( unsigned int portNumber = 0 );
Chris@559: 
Chris@559:   //! Immediately send a single message out an open MIDI output port.
Chris@559:   /*!
Chris@559:       An exception is thrown if an error occurs during output or an
Chris@559:       output connection was not previously established.
Chris@559:   */
Chris@559:   void sendMessage( std::vector<unsigned char> *message );
Chris@559: 
Chris@559:  private:
Chris@559: 
Chris@565:   void initialize( const std::string& clientName );
Chris@559: };
Chris@559: 
Chris@559: #endif