Tutorial   Class/Enum List   File List   Compound Members  

RtMidi.h
Go to the documentation of this file.
1 /**********************************************************************/
37 /**********************************************************************/
38 
43 #ifndef RTMIDI_H
44 #define RTMIDI_H
45 
46 #define RTMIDI_VERSION "3.0.0"
47 
48 #include <exception>
49 #include <iostream>
50 #include <string>
51 #include <vector>
52 
53 /************************************************************************/
61 /************************************************************************/
62 
63 class RtMidiError : public std::exception
64 {
65  public:
67  enum Type {
79  };
80 
82  RtMidiError( const std::string& message, Type type = RtMidiError::UNSPECIFIED ) throw() : message_(message), type_(type) {}
83 
85  virtual ~RtMidiError( void ) throw() {}
86 
88  virtual void printMessage( void ) const throw() { std::cerr << '\n' << message_ << "\n\n"; }
89 
91  virtual const Type& getType(void) const throw() { return type_; }
92 
94  virtual const std::string& getMessage(void) const throw() { return message_; }
95 
97  virtual const char* what( void ) const throw() { return message_.c_str(); }
98 
99  protected:
100  std::string message_;
101  Type type_;
102 };
103 
105 
112 typedef void (*RtMidiErrorCallback)( RtMidiError::Type type, const std::string &errorText, void *userData );
113 
114 class MidiApi;
115 
116 class RtMidi
117 {
118  public:
119 
121  enum Api {
128  };
129 
131  static std::string getVersion( void ) throw();
132 
134 
139  static void getCompiledApi( std::vector<RtMidi::Api> &apis ) throw();
140 
142  virtual void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi" ) ) = 0;
143 
145  virtual void openVirtualPort( const std::string &portName = std::string( "RtMidi" ) ) = 0;
146 
148  virtual unsigned int getPortCount() = 0;
149 
151  virtual std::string getPortName( unsigned int portNumber = 0 ) = 0;
152 
154  virtual void closePort( void ) = 0;
155 
157 
161  virtual bool isPortOpen( void ) const = 0;
162 
164 
168  virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 ) = 0;
169 
170  protected:
171 
172  RtMidi();
173  virtual ~RtMidi();
174 
175  MidiApi *rtapi_;
176 };
177 
178 /**********************************************************************/
194 /**********************************************************************/
195 
196 // **************************************************************** //
197 //
198 // RtMidiIn and RtMidiOut class declarations.
199 //
200 // RtMidiIn / RtMidiOut are "controllers" used to select an available
201 // MIDI input or output interface. They present common APIs for the
202 // user to call but all functionality is implemented by the classes
203 // MidiInApi, MidiOutApi and their subclasses. RtMidiIn and RtMidiOut
204 // each create an instance of a MidiInApi or MidiOutApi subclass based
205 // on the user's API choice. If no choice is made, they attempt to
206 // make a "logical" API selection.
207 //
208 // **************************************************************** //
209 
210 class RtMidiIn : public RtMidi
211 {
212  public:
213 
215  typedef void (*RtMidiCallback)( double timeStamp, std::vector<unsigned char> *message, void *userData);
216 
218 
236  const std::string& clientName = "RtMidi Input Client",
237  unsigned int queueSizeLimit = 100 );
238 
240  ~RtMidiIn ( void ) throw();
241 
243  RtMidi::Api getCurrentApi( void ) throw();
244 
246 
251  void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi Input" ) );
252 
254 
263  void openVirtualPort( const std::string &portName = std::string( "RtMidi Input" ) );
264 
266 
276  void setCallback( RtMidiCallback callback, void *userData = 0 );
277 
279 
283  void cancelCallback();
284 
286  void closePort( void );
287 
289 
293  virtual bool isPortOpen() const;
294 
296 
299  unsigned int getPortCount();
300 
302 
307  std::string getPortName( unsigned int portNumber = 0 );
308 
310 
317  void ignoreTypes( bool midiSysex = true, bool midiTime = true, bool midiSense = true );
318 
320 
327  double getMessage( std::vector<unsigned char> *message );
328 
330 
334  virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 );
335 
336  protected:
337  void openMidiApi( RtMidi::Api api, const std::string &clientName, unsigned int queueSizeLimit );
338 
339 };
340 
341 /**********************************************************************/
355 /**********************************************************************/
356 
357 class RtMidiOut : public RtMidi
358 {
359  public:
360 
362 
370  const std::string& clientName = "RtMidi Output Client" );
371 
373  ~RtMidiOut( void ) throw();
374 
376  RtMidi::Api getCurrentApi( void ) throw();
377 
379 
385  void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi Output" ) );
386 
388  void closePort( void );
389 
391 
395  virtual bool isPortOpen() const;
396 
398 
406  void openVirtualPort( const std::string &portName = std::string( "RtMidi Output" ) );
407 
409  unsigned int getPortCount( void );
410 
412 
417  std::string getPortName( unsigned int portNumber = 0 );
418 
420 
424  void sendMessage( const std::vector<unsigned char> *message );
425 
427 
434  void sendMessage( const unsigned char *message, size_t size );
435 
437 
441  virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 );
442 
443  protected:
444  void openMidiApi( RtMidi::Api api, const std::string &clientName );
445 };
446 
447 
448 // **************************************************************** //
449 //
450 // MidiInApi / MidiOutApi class declarations.
451 //
452 // Subclasses of MidiInApi and MidiOutApi contain all API- and
453 // OS-specific code necessary to fully implement the RtMidi API.
454 //
455 // Note that MidiInApi and MidiOutApi are abstract base classes and
456 // cannot be explicitly instantiated. RtMidiIn and RtMidiOut will
457 // create instances of a MidiInApi or MidiOutApi subclass.
458 //
459 // **************************************************************** //
460 
461 class MidiApi
462 {
463  public:
464 
465  MidiApi();
466  virtual ~MidiApi();
467  virtual RtMidi::Api getCurrentApi( void ) = 0;
468  virtual void openPort( unsigned int portNumber, const std::string &portName ) = 0;
469  virtual void openVirtualPort( const std::string &portName ) = 0;
470  virtual void closePort( void ) = 0;
471 
472  virtual unsigned int getPortCount( void ) = 0;
473  virtual std::string getPortName( unsigned int portNumber ) = 0;
474 
475  inline bool isPortOpen() const { return connected_; }
476  void setErrorCallback( RtMidiErrorCallback errorCallback, void *userData );
477 
479  void error( RtMidiError::Type type, std::string errorString );
480 
481 protected:
482  virtual void initialize( const std::string& clientName ) = 0;
483 
484  void *apiData_;
485  bool connected_;
486  std::string errorString_;
487  RtMidiErrorCallback errorCallback_;
488  bool firstErrorOccurred_;
489  void *errorCallbackUserData_;
490 };
491 
492 class MidiInApi : public MidiApi
493 {
494  public:
495 
496  MidiInApi( unsigned int queueSizeLimit );
497  virtual ~MidiInApi( void );
498  void setCallback( RtMidiIn::RtMidiCallback callback, void *userData );
499  void cancelCallback( void );
500  virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense );
501  double getMessage( std::vector<unsigned char> *message );
502 
503  // A MIDI structure used internally by the class to store incoming
504  // messages. Each message represents one and only one MIDI message.
505  struct MidiMessage {
506  std::vector<unsigned char> bytes;
507 
509  double timeStamp;
510 
511  // Default constructor.
512  MidiMessage()
513  :bytes(0), timeStamp(0.0) {}
514  };
515 
516  struct MidiQueue {
517  unsigned int front;
518  unsigned int back;
519  unsigned int ringSize;
520  MidiMessage *ring;
521 
522  // Default constructor.
523  MidiQueue()
524  :front(0), back(0), ringSize(0), ring(0) {}
525  bool push(const MidiMessage&);
526  bool pop(std::vector<unsigned char>*, double*);
527  unsigned int size(unsigned int *back=0,
528  unsigned int *front=0);
529  };
530 
531  // The RtMidiInData structure is used to pass private class data to
532  // the MIDI input handling function or thread.
533  struct RtMidiInData {
534  MidiQueue queue;
535  MidiMessage message;
536  unsigned char ignoreFlags;
537  bool doInput;
538  bool firstMessage;
539  void *apiData;
540  bool usingCallback;
541  RtMidiIn::RtMidiCallback userCallback;
542  void *userData;
543  bool continueSysex;
544 
545  // Default constructor.
546  RtMidiInData()
547  : ignoreFlags(7), doInput(false), firstMessage(true),
548  apiData(0), usingCallback(false), userCallback(0), userData(0),
549  continueSysex(false) {}
550  };
551 
552  protected:
553  RtMidiInData inputData_;
554 };
555 
556 class MidiOutApi : public MidiApi
557 {
558  public:
559 
560  MidiOutApi( void );
561  virtual ~MidiOutApi( void );
562  virtual void sendMessage( const unsigned char *message, size_t size ) = 0;
563 };
564 
565 // **************************************************************** //
566 //
567 // Inline RtMidiIn and RtMidiOut definitions.
568 //
569 // **************************************************************** //
570 
571 inline RtMidi::Api RtMidiIn :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); }
572 inline void RtMidiIn :: openPort( unsigned int portNumber, const std::string &portName ) { rtapi_->openPort( portNumber, portName ); }
573 inline void RtMidiIn :: openVirtualPort( const std::string &portName ) { rtapi_->openVirtualPort( portName ); }
574 inline void RtMidiIn :: closePort( void ) { rtapi_->closePort(); }
575 inline bool RtMidiIn :: isPortOpen() const { return rtapi_->isPortOpen(); }
576 inline void RtMidiIn :: setCallback( RtMidiCallback callback, void *userData ) { ((MidiInApi *)rtapi_)->setCallback( callback, userData ); }
577 inline void RtMidiIn :: cancelCallback( void ) { ((MidiInApi *)rtapi_)->cancelCallback(); }
578 inline unsigned int RtMidiIn :: getPortCount( void ) { return rtapi_->getPortCount(); }
579 inline std::string RtMidiIn :: getPortName( unsigned int portNumber ) { return rtapi_->getPortName( portNumber ); }
580 inline void RtMidiIn :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ) { ((MidiInApi *)rtapi_)->ignoreTypes( midiSysex, midiTime, midiSense ); }
581 inline double RtMidiIn :: getMessage( std::vector<unsigned char> *message ) { return ((MidiInApi *)rtapi_)->getMessage( message ); }
582 inline void RtMidiIn :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); }
583 
584 inline RtMidi::Api RtMidiOut :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); }
585 inline void RtMidiOut :: openPort( unsigned int portNumber, const std::string &portName ) { rtapi_->openPort( portNumber, portName ); }
586 inline void RtMidiOut :: openVirtualPort( const std::string &portName ) { rtapi_->openVirtualPort( portName ); }
587 inline void RtMidiOut :: closePort( void ) { rtapi_->closePort(); }
588 inline bool RtMidiOut :: isPortOpen() const { return rtapi_->isPortOpen(); }
589 inline unsigned int RtMidiOut :: getPortCount( void ) { return rtapi_->getPortCount(); }
590 inline std::string RtMidiOut :: getPortName( unsigned int portNumber ) { return rtapi_->getPortName( portNumber ); }
591 inline void RtMidiOut :: sendMessage( const std::vector<unsigned char> *message ) { ((MidiOutApi *)rtapi_)->sendMessage( &message->at(0), message->size() ); }
592 inline void RtMidiOut :: sendMessage( const unsigned char *message, size_t size ) { ((MidiOutApi *)rtapi_)->sendMessage( message, size ); }
593 inline void RtMidiOut :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); }
594 
595 // **************************************************************** //
596 //
597 // MidiInApi and MidiOutApi subclass prototypes.
598 //
599 // **************************************************************** //
600 
601 #if !defined(__LINUX_ALSA__) && !defined(__UNIX_JACK__) && !defined(__MACOSX_CORE__) && !defined(__WINDOWS_MM__)
602  #define __RTMIDI_DUMMY__
603 #endif
604 
605 #if defined(__MACOSX_CORE__)
606 
607 class MidiInCore: public MidiInApi
608 {
609  public:
610  MidiInCore( const std::string &clientName, unsigned int queueSizeLimit );
611  ~MidiInCore( void );
612  RtMidi::Api getCurrentApi( void ) { return RtMidi::MACOSX_CORE; };
613  void openPort( unsigned int portNumber, const std::string &portName );
614  void openVirtualPort( const std::string &portName );
615  void closePort( void );
616  unsigned int getPortCount( void );
617  std::string getPortName( unsigned int portNumber );
618 
619  protected:
620  void initialize( const std::string& clientName );
621 };
622 
623 class MidiOutCore: public MidiOutApi
624 {
625  public:
626  MidiOutCore( const std::string &clientName );
627  ~MidiOutCore( void );
628  RtMidi::Api getCurrentApi( void ) { return RtMidi::MACOSX_CORE; };
629  void openPort( unsigned int portNumber, const std::string &portName );
630  void openVirtualPort( const std::string &portName );
631  void closePort( void );
632  unsigned int getPortCount( void );
633  std::string getPortName( unsigned int portNumber );
634  void sendMessage( const unsigned char *message, size_t size );
635 
636  protected:
637  void initialize( const std::string& clientName );
638 };
639 
640 #endif
641 
642 #if defined(__UNIX_JACK__)
643 
644 class MidiInJack: public MidiInApi
645 {
646  public:
647  MidiInJack( const std::string &clientName, unsigned int queueSizeLimit );
648  ~MidiInJack( void );
649  RtMidi::Api getCurrentApi( void ) { return RtMidi::UNIX_JACK; };
650  void openPort( unsigned int portNumber, const std::string &portName );
651  void openVirtualPort( const std::string &portName );
652  void closePort( void );
653  unsigned int getPortCount( void );
654  std::string getPortName( unsigned int portNumber );
655 
656  protected:
657  std::string clientName;
658 
659  void connect( void );
660  void initialize( const std::string& clientName );
661 };
662 
663 class MidiOutJack: public MidiOutApi
664 {
665  public:
666  MidiOutJack( const std::string &clientName );
667  ~MidiOutJack( void );
668  RtMidi::Api getCurrentApi( void ) { return RtMidi::UNIX_JACK; };
669  void openPort( unsigned int portNumber, const std::string &portName );
670  void openVirtualPort( const std::string &portName );
671  void closePort( void );
672  unsigned int getPortCount( void );
673  std::string getPortName( unsigned int portNumber );
674  void sendMessage( const unsigned char *message, size_t size );
675 
676  protected:
677  std::string clientName;
678 
679  void connect( void );
680  void initialize( const std::string& clientName );
681 };
682 
683 #endif
684 
685 #if defined(__LINUX_ALSA__)
686 
687 class MidiInAlsa: public MidiInApi
688 {
689  public:
690  MidiInAlsa( const std::string &clientName, unsigned int queueSizeLimit );
691  ~MidiInAlsa( void );
692  RtMidi::Api getCurrentApi( void ) { return RtMidi::LINUX_ALSA; };
693  void openPort( unsigned int portNumber, const std::string &portName );
694  void openVirtualPort( const std::string &portName );
695  void closePort( void );
696  unsigned int getPortCount( void );
697  std::string getPortName( unsigned int portNumber );
698 
699  protected:
700  void initialize( const std::string& clientName );
701 };
702 
703 class MidiOutAlsa: public MidiOutApi
704 {
705  public:
706  MidiOutAlsa( const std::string &clientName );
707  ~MidiOutAlsa( void );
708  RtMidi::Api getCurrentApi( void ) { return RtMidi::LINUX_ALSA; };
709  void openPort( unsigned int portNumber, const std::string &portName );
710  void openVirtualPort( const std::string &portName );
711  void closePort( void );
712  unsigned int getPortCount( void );
713  std::string getPortName( unsigned int portNumber );
714  void sendMessage( const unsigned char *message, size_t size );
715 
716  protected:
717  void initialize( const std::string& clientName );
718 };
719 
720 #endif
721 
722 #if defined(__WINDOWS_MM__)
723 
724 class MidiInWinMM: public MidiInApi
725 {
726  public:
727  MidiInWinMM( const std::string &clientName, unsigned int queueSizeLimit );
728  ~MidiInWinMM( void );
729  RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_MM; };
730  void openPort( unsigned int portNumber, const std::string &portName );
731  void openVirtualPort( const std::string &portName );
732  void closePort( void );
733  unsigned int getPortCount( void );
734  std::string getPortName( unsigned int portNumber );
735 
736  protected:
737  void initialize( const std::string& clientName );
738 };
739 
741 {
742  public:
743  MidiOutWinMM( const std::string &clientName );
744  ~MidiOutWinMM( void );
745  RtMidi::Api getCurrentApi( void ) { return RtMidi::WINDOWS_MM; };
746  void openPort( unsigned int portNumber, const std::string &portName );
747  void openVirtualPort( const std::string &portName );
748  void closePort( void );
749  unsigned int getPortCount( void );
750  std::string getPortName( unsigned int portNumber );
751  void sendMessage( const unsigned char *message, size_t size );
752 
753  protected:
754  void initialize( const std::string& clientName );
755 };
756 
757 #endif
758 
759 #if defined(__RTMIDI_DUMMY__)
760 
761 class MidiInDummy: public MidiInApi
762 {
763  public:
764  MidiInDummy( const std::string &/*clientName*/, unsigned int queueSizeLimit ) : MidiInApi( queueSizeLimit ) { errorString_ = "MidiInDummy: This class provides no functionality."; error( RtMidiError::WARNING, errorString_ ); }
765  RtMidi::Api getCurrentApi( void ) { return RtMidi::RTMIDI_DUMMY; }
766  void openPort( unsigned int /*portNumber*/, const std::string &/*portName*/ ) {}
767  void openVirtualPort( const std::string &/*portName*/ ) {}
768  void closePort( void ) {}
769  unsigned int getPortCount( void ) { return 0; }
770  std::string getPortName( unsigned int /*portNumber*/ ) { return ""; }
771 
772  protected:
773  void initialize( const std::string& /*clientName*/ ) {}
774 };
775 
776 class MidiOutDummy: public MidiOutApi
777 {
778  public:
779  MidiOutDummy( const std::string &/*clientName*/ ) { errorString_ = "MidiOutDummy: This class provides no functionality."; error( RtMidiError::WARNING, errorString_ ); }
780  RtMidi::Api getCurrentApi( void ) { return RtMidi::RTMIDI_DUMMY; }
781  void openPort( unsigned int /*portNumber*/, const std::string &/*portName*/ ) {}
782  void openVirtualPort( const std::string &/*portName*/ ) {}
783  void closePort( void ) {}
784  unsigned int getPortCount( void ) { return 0; }
785  std::string getPortName( unsigned int /*portNumber*/ ) { return ""; }
786  void sendMessage( const unsigned char * /*message*/, size_t /*size*/ ) {}
787 
788  protected:
789  void initialize( const std::string& /*clientName*/ ) {}
790 };
791 
792 #endif
793 
794 #endif

©2003-2017 Gary P. Scavone, McGill University. All Rights Reserved.
Maintained by Gary P. Scavone, gary at music.mcgill.ca