Tutorial   Class/Enum List   File List   Compound Members   C interface  

RtMidi.h
Go to the documentation of this file.
1/**********************************************************************/
38/**********************************************************************/
39
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_MAJOR 6
62#define RTMIDI_VERSION_MINOR 1
63#define RTMIDI_VERSION_PATCH 0
64#define RTMIDI_VERSION_BETA 0
65
66#define RTMIDI_TOSTRING2(n) #n
67#define RTMIDI_TOSTRING(n) RTMIDI_TOSTRING2(n)
68
69#if RTMIDI_VERSION_BETA > 0
70 #define RTMIDI_VERSION RTMIDI_TOSTRING(RTMIDI_VERSION_MAJOR) \
71 "." RTMIDI_TOSTRING(RTMIDI_VERSION_MINOR) \
72 "." RTMIDI_TOSTRING(RTMIDI_VERSION_PATCH) \
73 "beta" RTMIDI_TOSTRING(RTMIDI_VERSION_BETA)
74#else
75 #define RTMIDI_VERSION RTMIDI_TOSTRING(RTMIDI_VERSION_MAJOR) \
76 "." RTMIDI_TOSTRING(RTMIDI_VERSION_MINOR) \
77 "." RTMIDI_TOSTRING(RTMIDI_VERSION_PATCH)
78#endif
79
80#include <atomic>
81#include <exception>
82#include <iostream>
83#include <string>
84#include <vector>
85
86namespace rt {
87namespace midi {
88
89/************************************************************************/
97/************************************************************************/
98
99class RTMIDI_DLL_PUBLIC RtMidiError : public std::exception
100{
101 public:
117
119 RtMidiError( const std::string& message, Type type = RtMidiError::UNSPECIFIED ) throw()
120 : message_(message), type_(type) {}
121
123 virtual ~RtMidiError( void ) throw() {}
124
126 virtual void printMessage( void ) const throw() { std::cerr << '\n' << message_ << "\n\n"; }
127
129 virtual const Type& getType( void ) const throw() { return type_; }
130
132 virtual const std::string& getMessage( void ) const throw() { return message_; }
133
135 virtual const char* what( void ) const throw() { return message_.c_str(); }
136
137 protected:
138 std::string message_;
139 Type type_;
140};
141
143
150typedef void (*RtMidiErrorCallback)( RtMidiError::Type type, const std::string &errorText, void *userData );
151
152class MidiApi;
153
154class RTMIDI_DLL_PUBLIC RtMidi
155{
156 public:
157
158 RtMidi(RtMidi&& other) noexcept;
173
176 bool available = true;
177 std::string message;
178 std::string installUrl;
179 };
180
182
194
196 static std::string getVersion( void ) throw();
197
199
204 static void getCompiledApi( std::vector<RtMidi::Api> &apis ) throw();
205
207
212 static std::string getApiName( RtMidi::Api api );
213
215
219 static std::string getApiDisplayName( RtMidi::Api api );
220
222
227 static RtMidi::Api getCompiledApiByName( const std::string &name );
228
230 virtual void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi" ) ) = 0;
231
233 virtual void openVirtualPort( const std::string &portName = std::string( "RtMidi" ) ) = 0;
234
236 virtual unsigned int getPortCount() = 0;
237
239 virtual std::string getPortName( unsigned int portNumber = 0 ) = 0;
240
242 virtual void closePort( void ) = 0;
243
244 void setClientName( const std::string &clientName );
245 void setPortName( const std::string &portName );
246
248
252 virtual bool isPortOpen( void ) const = 0;
253
255
265 bool supportsAutoReconnect( void ) const;
266
268
280 void setAutoReconnect( bool enabled );
281 bool isAutoReconnectEnabled( void ) const;
282
284
288 virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 ) = 0;
289
290 protected:
291 RtMidi();
292 virtual ~RtMidi();
293 MidiApi *rtapi_;
294
295 /* Make the class non-copyable */
296 RtMidi(RtMidi& other) = delete;
297 RtMidi& operator=(RtMidi& other) = delete;
298};
299
300/**********************************************************************/
314/**********************************************************************/
315
316// **************************************************************** //
317//
318// RtMidiIn and RtMidiOut class declarations.
319//
320// RtMidiIn / RtMidiOut are "controllers" used to select an available
321// MIDI input or output interface. They present common APIs for the
322// user to call but all functionality is implemented by the classes
323// MidiInApi, MidiOutApi and their subclasses. RtMidiIn and RtMidiOut
324// each create an instance of a MidiInApi or MidiOutApi subclass based
325// on the user's API choice. If no choice is made, they attempt to
326// make a "logical" API selection.
327//
328// **************************************************************** //
329
330class RTMIDI_DLL_PUBLIC RtMidiIn : public RtMidi
331{
332 public:
334 typedef void (*RtMidiCallback)( double timeStamp, std::vector<unsigned char> *message, void *userData );
335
337
362 RtMidiIn( RtMidi::Api api=UNSPECIFIED,
363 const std::string& clientName = "RtMidi Input Client",
364 unsigned int queueSizeLimit = 100 );
365
366 RtMidiIn(RtMidiIn&& other) noexcept : RtMidi(std::move(other)) { }
367
369 ~RtMidiIn ( void ) throw();
370
372 RtMidi::Api getCurrentApi( void ) throw();
373
375
380 void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi Input" ) );
381
383
392 void openVirtualPort( const std::string &portName = std::string( "RtMidi Input" ) );
393
395
405 void setCallback( RtMidiCallback callback, void *userData = 0 );
406
408
417 void cancelCallback();
418
420 void closePort( void );
421
423
427 virtual bool isPortOpen() const;
428
430
433 unsigned int getPortCount();
434
436
441 std::string getPortName( unsigned int portNumber = 0 );
442
444
457 void ignoreTypes( bool midiSysex = true, bool midiTime = true, bool midiSense = true );
458
460
467 double getMessage( std::vector<unsigned char> *message );
468
470
474 virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 );
475
477
489 virtual void setBufferSize( unsigned int size, unsigned int count );
490
491 protected:
492 void openMidiApi( RtMidi::Api api, const std::string &clientName, unsigned int queueSizeLimit );
493};
494
495/**********************************************************************/
507/**********************************************************************/
508
509class RTMIDI_DLL_PUBLIC RtMidiOut : public RtMidi
510{
511 public:
513
522 RtMidiOut( RtMidi::Api api=UNSPECIFIED,
523 const std::string& clientName = "RtMidi Output Client" );
524
525 RtMidiOut(RtMidiOut&& other) noexcept : RtMidi(std::move(other)) { }
526
528 ~RtMidiOut( void ) throw();
529
531 RtMidi::Api getCurrentApi( void ) throw();
532
534
540 void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi Output" ) );
541
543 void closePort( void );
544
546
550 virtual bool isPortOpen() const;
551
553
561 void openVirtualPort( const std::string &portName = std::string( "RtMidi Output" ) );
562
564 unsigned int getPortCount( void );
565
567
572 std::string getPortName( unsigned int portNumber = 0 );
573
575
593 void sendMessage( const std::vector<unsigned char> *message );
594
596
617 void sendMessage( const unsigned char *message, size_t size );
618
620
624 virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 );
625
626 protected:
627 void openMidiApi( RtMidi::Api api, const std::string &clientName );
628};
629
630
631// **************************************************************** //
632//
633// MidiInApi / MidiOutApi class declarations.
634//
635// Subclasses of MidiInApi and MidiOutApi contain all API- and
636// OS-specific code necessary to fully implement the RtMidi API.
637//
638// Note that MidiInApi and MidiOutApi are abstract base classes and
639// cannot be explicitly instantiated. RtMidiIn and RtMidiOut will
640// create instances of a MidiInApi or MidiOutApi subclass.
641//
642// **************************************************************** //
643
644class RTMIDI_DLL_PUBLIC MidiApi
645{
646 public:
647
648 MidiApi();
649 virtual ~MidiApi();
650 virtual RtMidi::Api getCurrentApi( void ) = 0;
651 virtual void openPort( unsigned int portNumber, const std::string &portName ) = 0;
652 virtual void openVirtualPort( const std::string &portName ) = 0;
653 virtual void closePort( void ) = 0;
654 virtual void setClientName( const std::string &clientName ) = 0;
655 virtual void setPortName( const std::string &portName ) = 0;
656
657 virtual unsigned int getPortCount( void ) = 0;
658 virtual std::string getPortName( unsigned int portNumber ) = 0;
659
660 inline bool isPortOpen() const { return connected_; }
661 void setErrorCallback( RtMidiErrorCallback errorCallback, void *userData );
662
664
672 static void setDefaultErrorCallback( RtMidiErrorCallback errorCallback = NULL,
673 void *userData = 0 );
674
676 void error( RtMidiError::Type type, std::string errorString );
677
678 // Non-virtual extensions leave existing backend vtable layouts unchanged.
679 bool supportsAutoReconnect( void ) const;
680 void setAutoReconnect( bool enabled );
681 bool isAutoReconnectEnabled( void ) const;
682
683protected:
684 virtual void initialize( const std::string& clientName ) = 0;
685
686 void *apiData_;
687 bool connected_;
688 std::string errorString_;
689 RtMidiErrorCallback errorCallback_;
690 bool firstErrorOccurred_;
691 void *errorCallbackUserData_;
692
693 // Static, so they add nothing to any object's layout.
694 static RtMidiErrorCallback defaultErrorCallback_;
695 static void *defaultErrorCallbackUserData_;
696
697};
698
699class RTMIDI_DLL_PUBLIC MidiInApi : public MidiApi
700{
701 public:
702
703 MidiInApi( unsigned int queueSizeLimit );
704 virtual ~MidiInApi( void );
705 void setCallback( RtMidiIn::RtMidiCallback callback, void *userData );
706 void cancelCallback( void );
707 virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense );
708 virtual double getMessage( std::vector<unsigned char> *message );
709 virtual void setBufferSize( unsigned int size, unsigned int count );
710
711 // A MIDI structure used internally by the class to store incoming
712 // messages. Each message represents one and only one MIDI message.
713 struct MidiMessage {
714 std::vector<unsigned char> bytes;
715
717 double timeStamp;
718
719 // Default constructor.
721 : bytes(0), timeStamp(0.0) {}
722 };
723
724 // A single-producer, single-consumer ring buffer: the backend's input
725 // thread is the only writer of \c back, and the thread calling
726 // RtMidiIn::getMessage() is the only writer of \c front. The indices are
727 // atomic so that each side sees the other's completed writes: push()
728 // releases \c back after the message is stored, pop() acquires it before
729 // reading, and the same pairing applies to \c front. Without that the
730 // reader may observe a published index before the message it refers to.
731 struct MidiQueue {
732 std::atomic<unsigned int> front;
733 std::atomic<unsigned int> back;
734 unsigned int ringSize;
735 MidiMessage *ring;
736
737 // Default constructor.
738 MidiQueue()
739 : front(0), back(0), ringSize(0), ring(0) {}
740 bool push( const MidiMessage& );
741 bool pop( std::vector<unsigned char>*, double* );
742 unsigned int size( unsigned int *back=0, unsigned int *front=0 );
743 };
744
745 // The RtMidiInData structure is used to pass private class data to
746 // the MIDI input handling function or thread.
748 MidiQueue queue;
749 MidiMessage message;
750 unsigned char ignoreFlags;
751 bool doInput;
752 bool firstMessage;
753 void *apiData;
754 // Read by the input thread while the user may change them; see
755 // callUserCallback(), MidiInApi::setCallback() and cancelCallback().
756 std::atomic<bool> usingCallback;
757 std::atomic<RtMidiIn::RtMidiCallback> userCallback;
758 std::atomic<void *> userData;
759 bool continueSysex;
760 unsigned int bufferSize;
761 unsigned int bufferCount;
762
763 // Default constructor.
765 : ignoreFlags(7), doInput(false), firstMessage(true), apiData(0), usingCallback(false),
766 userCallback(0), userData(0), continueSysex(false), bufferSize(1024), bufferCount(4) {}
767
768 // Called by the backends' input threads: passes the message to the user
769 // callback and returns true, or returns false if none is set (the message
770 // then belongs in the queue). cancelCallback() only clears usingCallback,
771 // so a thread that has just seen it set still reads a valid callback.
772 bool callUserCallback( double timeStamp, std::vector<unsigned char> *bytes )
773 {
774 if ( !usingCallback.load( std::memory_order_acquire ) ) return false;
775 RtMidiIn::RtMidiCallback callback = userCallback.load( std::memory_order_relaxed );
776 callback( timeStamp, bytes, userData.load( std::memory_order_relaxed ) );
777 return true;
778 }
779 };
780
781 protected:
782 RtMidiInData inputData_;
783};
784
785class RTMIDI_DLL_PUBLIC MidiOutApi : public MidiApi
786{
787 public:
788
789 MidiOutApi( void );
790 virtual ~MidiOutApi( void );
791 virtual void sendMessage( const unsigned char *message, size_t size ) = 0;
792};
793
794// **************************************************************** //
795//
796// Inline RtMidiIn and RtMidiOut definitions.
797//
798// **************************************************************** //
799
800inline bool RtMidi :: supportsAutoReconnect( void ) const { return rtapi_->supportsAutoReconnect(); }
801inline void RtMidi :: setAutoReconnect( bool enabled ) { rtapi_->setAutoReconnect( enabled ); }
802inline bool RtMidi :: isAutoReconnectEnabled( void ) const { return rtapi_->isAutoReconnectEnabled(); }
803
804inline RtMidi::Api RtMidiIn :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); }
805inline void RtMidiIn :: openPort( unsigned int portNumber, const std::string &portName ) { rtapi_->openPort( portNumber, portName ); }
806inline void RtMidiIn :: openVirtualPort( const std::string &portName ) { rtapi_->openVirtualPort( portName ); }
807inline void RtMidiIn :: closePort( void ) { rtapi_->closePort(); }
808inline bool RtMidiIn :: isPortOpen() const { return rtapi_->isPortOpen(); }
809inline void RtMidiIn :: setCallback( RtMidiCallback callback, void *userData ) { static_cast<MidiInApi *>(rtapi_)->setCallback( callback, userData ); }
810inline void RtMidiIn :: cancelCallback( void ) { static_cast<MidiInApi *>(rtapi_)->cancelCallback(); }
811inline unsigned int RtMidiIn :: getPortCount( void ) { return rtapi_->getPortCount(); }
812inline std::string RtMidiIn :: getPortName( unsigned int portNumber ) { return rtapi_->getPortName( portNumber ); }
813inline void RtMidiIn :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ) { static_cast<MidiInApi *>(rtapi_)->ignoreTypes( midiSysex, midiTime, midiSense ); }
814inline double RtMidiIn :: getMessage( std::vector<unsigned char> *message ) { return static_cast<MidiInApi *>(rtapi_)->getMessage( message ); }
815inline void RtMidiIn :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); }
816inline void RtMidiIn :: setBufferSize( unsigned int size, unsigned int count ) { static_cast<MidiInApi *>(rtapi_)->setBufferSize(size, count); }
817
818inline RtMidi::Api RtMidiOut :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); }
819inline void RtMidiOut :: openPort( unsigned int portNumber, const std::string &portName ) { rtapi_->openPort( portNumber, portName ); }
820inline void RtMidiOut :: openVirtualPort( const std::string &portName ) { rtapi_->openVirtualPort( portName ); }
821inline void RtMidiOut :: closePort( void ) { rtapi_->closePort(); }
822inline bool RtMidiOut :: isPortOpen() const { return rtapi_->isPortOpen(); }
823inline unsigned int RtMidiOut :: getPortCount( void ) { return rtapi_->getPortCount(); }
824inline std::string RtMidiOut :: getPortName( unsigned int portNumber ) { return rtapi_->getPortName( portNumber ); }
825inline void RtMidiOut :: sendMessage( const std::vector<unsigned char> *message ) { static_cast<MidiOutApi *>(rtapi_)->sendMessage( &message->at(0), message->size() ); }
826inline void RtMidiOut :: sendMessage( const unsigned char *message, size_t size ) { static_cast<MidiOutApi *>(rtapi_)->sendMessage( message, size ); }
827inline void RtMidiOut :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); }
828
829} // namespace midi
830} // namespace rt
831
832#endif
833
834#ifndef RTMIDI_USE_NAMESPACE
835using namespace rt::midi;
836#endif
void(* RtMidiErrorCallback)(RtMidiError::Type type, const std::string &errorText, void *userData)
RtMidi error callback function prototype.
Definition RtMidi.h:150
Definition RtMidi.h:645
static void setDefaultErrorCallback(RtMidiErrorCallback errorCallback=NULL, void *userData=0)
Set a callback for objects that have none of their own.
void error(RtMidiError::Type type, std::string errorString)
A basic error reporting function for RtMidi classes.
Definition RtMidi.h:700
Definition RtMidi.h:786
Exception handling class for RtMidi.
Definition RtMidi.h:100
virtual void printMessage(void) const
Prints thrown error message to stderr.
Definition RtMidi.h:126
virtual const Type & getType(void) const
Returns the thrown error message type.
Definition RtMidi.h:129
virtual const std::string & getMessage(void) const
Returns the thrown error message string.
Definition RtMidi.h:132
RtMidiError(const std::string &message, Type type=RtMidiError::UNSPECIFIED)
The constructor.
Definition RtMidi.h:119
Type
Defined RtMidiError types.
Definition RtMidi.h:103
@ INVALID_PARAMETER
Definition RtMidi.h:110
@ INVALID_USE
Definition RtMidi.h:111
@ NO_DEVICES_FOUND
Definition RtMidi.h:107
@ INVALID_DEVICE
Definition RtMidi.h:108
@ UNSPECIFIED
Definition RtMidi.h:106
@ MEMORY_ERROR
Definition RtMidi.h:109
@ DEBUG_WARNING
Definition RtMidi.h:105
@ THREAD_ERROR
Definition RtMidi.h:114
@ DRIVER_ERROR
Definition RtMidi.h:112
@ WARNING
Definition RtMidi.h:104
@ SYSTEM_ERROR
Definition RtMidi.h:113
virtual ~RtMidiError(void)
The destructor.
Definition RtMidi.h:123
virtual const char * what(void) const
Returns the thrown error message as a c-style string.
Definition RtMidi.h:135
A realtime MIDI input class.
Definition RtMidi.h:331
RtMidiIn(RtMidi::Api api=UNSPECIFIED, const std::string &clientName="RtMidi Input Client", unsigned int queueSizeLimit=100)
Default constructor that allows an optional api, client name and queue size.
~RtMidiIn(void)
If a MIDI connection is still open, it will be closed by the destructor.
void(* RtMidiCallback)(double timeStamp, std::vector< unsigned char > *message, void *userData)
User callback function type definition.
Definition RtMidi.h:334
A realtime MIDI output class.
Definition RtMidi.h:510
RtMidiOut(RtMidi::Api api=UNSPECIFIED, const std::string &clientName="RtMidi Output Client")
Default constructor that allows an optional client name.
~RtMidiOut(void)
The destructor closes any open MIDI connections.
An abstract base class for realtime MIDI input/output.
Definition RtMidi.h:155
virtual void openVirtualPort(const std::string &portName=std::string("RtMidi"))=0
Pure virtual openVirtualPort() function.
Api
MIDI API specifier arguments.
Definition RtMidi.h:160
@ LINUX_ALSA
Definition RtMidi.h:163
@ WINDOWS_MM
Definition RtMidi.h:165
@ ANDROID_AMIDI
Definition RtMidi.h:169
@ UNIX_JACK
Definition RtMidi.h:164
@ WEB_MIDI_API
Definition RtMidi.h:167
@ WINDOWS_UWP
Definition RtMidi.h:168
@ RTMIDI_DUMMY
Definition RtMidi.h:166
@ WINDOWS_MIDI_SERVICES
Definition RtMidi.h:170
@ MACOSX_CORE
Definition RtMidi.h:162
@ UNSPECIFIED
Definition RtMidi.h:161
std::string message
Definition RtMidi.h:177
static RtMidiApiAvailability checkApiAvailability(RtMidi::Api api)
Query whether an API can be used by this build on this system.
static std::string getApiDisplayName(RtMidi::Api api)
Return the display name of a specified compiled MIDI API.
virtual bool isPortOpen(void) const =0
Returns true if a port is open and false if not.
static void getCompiledApi(std::vector< RtMidi::Api > &apis)
A static function to determine the available compiled MIDI APIs.
static std::string getVersion(void)
A static function to determine the current RtMidi version.
virtual void closePort(void)=0
Pure virtual closePort() function.
static std::string getApiName(RtMidi::Api api)
Return the name of a specified compiled MIDI API.
virtual void openPort(unsigned int portNumber=0, const std::string &portName=std::string("RtMidi"))=0
Pure virtual openPort() function.
std::string installUrl
Definition RtMidi.h:178
virtual std::string getPortName(unsigned int portNumber=0)=0
Pure virtual getPortName() function.
virtual void setErrorCallback(RtMidiErrorCallback errorCallback=NULL, void *userData=0)=0
Set an error callback function to be invoked when an error has occurred.
virtual unsigned int getPortCount()=0
Pure virtual getPortCount() function.
static RtMidi::Api getCompiledApiByName(const std::string &name)
Return the compiled MIDI API having the given name.
Result returned by checkApiAvailability().
Definition RtMidi.h:175
Definition RtMidi.h:713
double timeStamp
Time in seconds elapsed since the previous message.
Definition RtMidi.h:717
Definition RtMidi.h:731
Definition RtMidi.h:747

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