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