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 0
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 <exception>
81#include <iostream>
82#include <string>
83#include <vector>
84
85
86/************************************************************************/
94/************************************************************************/
95
96class RTMIDI_DLL_PUBLIC RtMidiError : public std::exception
97{
98 public:
100 enum Type {
111 THREAD_ERROR
112 };
113
115 RtMidiError( const std::string& message, Type type = RtMidiError::UNSPECIFIED ) throw()
116 : message_(message), type_(type) {}
117
119 virtual ~RtMidiError( void ) throw() {}
120
122 virtual void printMessage( void ) const throw() { std::cerr << '\n' << message_ << "\n\n"; }
123
125 virtual const Type& getType( void ) const throw() { return type_; }
126
128 virtual const std::string& getMessage( void ) const throw() { return message_; }
129
131 virtual const char* what( void ) const throw() { return message_.c_str(); }
132
133 protected:
134 std::string message_;
135 Type type_;
136};
137
139
146typedef void (*RtMidiErrorCallback)( RtMidiError::Type type, const std::string &errorText, void *userData );
147
148class MidiApi;
149
150class RTMIDI_DLL_PUBLIC RtMidi
151{
152 public:
153
154 RtMidi(RtMidi&& other) noexcept;
156 enum Api {
166 NUM_APIS
167 };
168
170 static std::string getVersion( void ) throw();
171
173
178 static void getCompiledApi( std::vector<RtMidi::Api> &apis ) throw();
179
181
186 static std::string getApiName( RtMidi::Api api );
187
189
193 static std::string getApiDisplayName( RtMidi::Api api );
194
196
201 static RtMidi::Api getCompiledApiByName( const std::string &name );
202
204 virtual void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi" ) ) = 0;
205
207 virtual void openVirtualPort( const std::string &portName = std::string( "RtMidi" ) ) = 0;
208
210 virtual unsigned int getPortCount() = 0;
211
213 virtual std::string getPortName( unsigned int portNumber = 0 ) = 0;
214
216 virtual void closePort( void ) = 0;
217
218 void setClientName( const std::string &clientName );
219 void setPortName( const std::string &portName );
220
222
226 virtual bool isPortOpen( void ) const = 0;
227
229
233 virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 ) = 0;
234
235 protected:
236 RtMidi();
237 virtual ~RtMidi();
238 MidiApi *rtapi_;
239
240 /* Make the class non-copyable */
241 RtMidi(RtMidi& other) = delete;
242 RtMidi& operator=(RtMidi& other) = delete;
243};
244
245/**********************************************************************/
259/**********************************************************************/
260
261// **************************************************************** //
262//
263// RtMidiIn and RtMidiOut class declarations.
264//
265// RtMidiIn / RtMidiOut are "controllers" used to select an available
266// MIDI input or output interface. They present common APIs for the
267// user to call but all functionality is implemented by the classes
268// MidiInApi, MidiOutApi and their subclasses. RtMidiIn and RtMidiOut
269// each create an instance of a MidiInApi or MidiOutApi subclass based
270// on the user's API choice. If no choice is made, they attempt to
271// make a "logical" API selection.
272//
273// **************************************************************** //
274
275class RTMIDI_DLL_PUBLIC RtMidiIn : public RtMidi
276{
277 public:
279 typedef void (*RtMidiCallback)( double timeStamp, std::vector<unsigned char> *message, void *userData );
280
282
299 RtMidiIn( RtMidi::Api api=UNSPECIFIED,
300 const std::string& clientName = "RtMidi Input Client",
301 unsigned int queueSizeLimit = 100 );
302
303 RtMidiIn(RtMidiIn&& other) noexcept : RtMidi(std::move(other)) { }
304
306 ~RtMidiIn ( void ) throw();
307
309 RtMidi::Api getCurrentApi( void ) throw();
310
312
317 void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi Input" ) );
318
320
329 void openVirtualPort( const std::string &portName = std::string( "RtMidi Input" ) );
330
332
342 void setCallback( RtMidiCallback callback, void *userData = 0 );
343
345
349 void cancelCallback();
350
352 void closePort( void );
353
355
359 virtual bool isPortOpen() const;
360
362
365 unsigned int getPortCount();
366
368
373 std::string getPortName( unsigned int portNumber = 0 );
374
376
383 void ignoreTypes( bool midiSysex = true, bool midiTime = true, bool midiSense = true );
384
386
393 double getMessage( std::vector<unsigned char> *message );
394
396
400 virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 );
401
403
413 virtual void setBufferSize( unsigned int size, unsigned int count );
414
415 protected:
416 void openMidiApi( RtMidi::Api api, const std::string &clientName, unsigned int queueSizeLimit );
417};
418
419/**********************************************************************/
431/**********************************************************************/
432
433class RTMIDI_DLL_PUBLIC RtMidiOut : public RtMidi
434{
435 public:
437
444 RtMidiOut( RtMidi::Api api=UNSPECIFIED,
445 const std::string& clientName = "RtMidi Output Client" );
446
447 RtMidiOut(RtMidiOut&& other) noexcept : RtMidi(std::move(other)) { }
448
450 ~RtMidiOut( void ) throw();
451
453 RtMidi::Api getCurrentApi( void ) throw();
454
456
462 void openPort( unsigned int portNumber = 0, const std::string &portName = std::string( "RtMidi Output" ) );
463
465 void closePort( void );
466
468
472 virtual bool isPortOpen() const;
473
475
483 void openVirtualPort( const std::string &portName = std::string( "RtMidi Output" ) );
484
486 unsigned int getPortCount( void );
487
489
494 std::string getPortName( unsigned int portNumber = 0 );
495
497
501 void sendMessage( const std::vector<unsigned char> *message );
502
504
511 void sendMessage( const unsigned char *message, size_t size );
512
514
518 virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 );
519
520 protected:
521 void openMidiApi( RtMidi::Api api, const std::string &clientName );
522};
523
524
525// **************************************************************** //
526//
527// MidiInApi / MidiOutApi class declarations.
528//
529// Subclasses of MidiInApi and MidiOutApi contain all API- and
530// OS-specific code necessary to fully implement the RtMidi API.
531//
532// Note that MidiInApi and MidiOutApi are abstract base classes and
533// cannot be explicitly instantiated. RtMidiIn and RtMidiOut will
534// create instances of a MidiInApi or MidiOutApi subclass.
535//
536// **************************************************************** //
537
538class RTMIDI_DLL_PUBLIC MidiApi
539{
540 public:
541
542 MidiApi();
543 virtual ~MidiApi();
544 virtual RtMidi::Api getCurrentApi( void ) = 0;
545 virtual void openPort( unsigned int portNumber, const std::string &portName ) = 0;
546 virtual void openVirtualPort( const std::string &portName ) = 0;
547 virtual void closePort( void ) = 0;
548 virtual void setClientName( const std::string &clientName ) = 0;
549 virtual void setPortName( const std::string &portName ) = 0;
550
551 virtual unsigned int getPortCount( void ) = 0;
552 virtual std::string getPortName( unsigned int portNumber ) = 0;
553
554 inline bool isPortOpen() const { return connected_; }
555 void setErrorCallback( RtMidiErrorCallback errorCallback, void *userData );
556
558 void error( RtMidiError::Type type, std::string errorString );
559
560protected:
561 virtual void initialize( const std::string& clientName ) = 0;
562
563 void *apiData_;
564 bool connected_;
565 std::string errorString_;
566 RtMidiErrorCallback errorCallback_;
567 bool firstErrorOccurred_;
568 void *errorCallbackUserData_;
569
570};
571
572class RTMIDI_DLL_PUBLIC MidiInApi : public MidiApi
573{
574 public:
575
576 MidiInApi( unsigned int queueSizeLimit );
577 virtual ~MidiInApi( void );
578 void setCallback( RtMidiIn::RtMidiCallback callback, void *userData );
579 void cancelCallback( void );
580 virtual void ignoreTypes( bool midiSysex, bool midiTime, bool midiSense );
581 virtual double getMessage( std::vector<unsigned char> *message );
582 virtual void setBufferSize( unsigned int size, unsigned int count );
583
584 // A MIDI structure used internally by the class to store incoming
585 // messages. Each message represents one and only one MIDI message.
586 struct MidiMessage {
587 std::vector<unsigned char> bytes;
588
590 double timeStamp;
591
592 // Default constructor.
594 : bytes(0), timeStamp(0.0) {}
595 };
596
597 struct MidiQueue {
598 unsigned int front;
599 unsigned int back;
600 unsigned int ringSize;
601 MidiMessage *ring;
602
603 // Default constructor.
604 MidiQueue()
605 : front(0), back(0), ringSize(0), ring(0) {}
606 bool push( const MidiMessage& );
607 bool pop( std::vector<unsigned char>*, double* );
608 unsigned int size( unsigned int *back=0, unsigned int *front=0 );
609 };
610
611 // The RtMidiInData structure is used to pass private class data to
612 // the MIDI input handling function or thread.
614 MidiQueue queue;
615 MidiMessage message;
616 unsigned char ignoreFlags;
617 bool doInput;
618 bool firstMessage;
619 void *apiData;
620 bool usingCallback;
621 RtMidiIn::RtMidiCallback userCallback;
622 void *userData;
623 bool continueSysex;
624 unsigned int bufferSize;
625 unsigned int bufferCount;
626
627 // Default constructor.
629 : ignoreFlags(7), doInput(false), firstMessage(true), apiData(0), usingCallback(false),
630 userCallback(0), userData(0), continueSysex(false), bufferSize(1024), bufferCount(4) {}
631 };
632
633 protected:
634 RtMidiInData inputData_;
635};
636
637class RTMIDI_DLL_PUBLIC MidiOutApi : public MidiApi
638{
639 public:
640
641 MidiOutApi( void );
642 virtual ~MidiOutApi( void );
643 virtual void sendMessage( const unsigned char *message, size_t size ) = 0;
644};
645
646// **************************************************************** //
647//
648// Inline RtMidiIn and RtMidiOut definitions.
649//
650// **************************************************************** //
651
652inline RtMidi::Api RtMidiIn :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); }
653inline void RtMidiIn :: openPort( unsigned int portNumber, const std::string &portName ) { rtapi_->openPort( portNumber, portName ); }
654inline void RtMidiIn :: openVirtualPort( const std::string &portName ) { rtapi_->openVirtualPort( portName ); }
655inline void RtMidiIn :: closePort( void ) { rtapi_->closePort(); }
656inline bool RtMidiIn :: isPortOpen() const { return rtapi_->isPortOpen(); }
657inline void RtMidiIn :: setCallback( RtMidiCallback callback, void *userData ) { static_cast<MidiInApi *>(rtapi_)->setCallback( callback, userData ); }
658inline void RtMidiIn :: cancelCallback( void ) { static_cast<MidiInApi *>(rtapi_)->cancelCallback(); }
659inline unsigned int RtMidiIn :: getPortCount( void ) { return rtapi_->getPortCount(); }
660inline std::string RtMidiIn :: getPortName( unsigned int portNumber ) { return rtapi_->getPortName( portNumber ); }
661inline void RtMidiIn :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ) { static_cast<MidiInApi *>(rtapi_)->ignoreTypes( midiSysex, midiTime, midiSense ); }
662inline double RtMidiIn :: getMessage( std::vector<unsigned char> *message ) { return static_cast<MidiInApi *>(rtapi_)->getMessage( message ); }
663inline void RtMidiIn :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); }
664inline void RtMidiIn :: setBufferSize( unsigned int size, unsigned int count ) { static_cast<MidiInApi *>(rtapi_)->setBufferSize(size, count); }
665
666inline RtMidi::Api RtMidiOut :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); }
667inline void RtMidiOut :: openPort( unsigned int portNumber, const std::string &portName ) { rtapi_->openPort( portNumber, portName ); }
668inline void RtMidiOut :: openVirtualPort( const std::string &portName ) { rtapi_->openVirtualPort( portName ); }
669inline void RtMidiOut :: closePort( void ) { rtapi_->closePort(); }
670inline bool RtMidiOut :: isPortOpen() const { return rtapi_->isPortOpen(); }
671inline unsigned int RtMidiOut :: getPortCount( void ) { return rtapi_->getPortCount(); }
672inline std::string RtMidiOut :: getPortName( unsigned int portNumber ) { return rtapi_->getPortName( portNumber ); }
673inline void RtMidiOut :: sendMessage( const std::vector<unsigned char> *message ) { static_cast<MidiOutApi *>(rtapi_)->sendMessage( &message->at(0), message->size() ); }
674inline void RtMidiOut :: sendMessage( const unsigned char *message, size_t size ) { static_cast<MidiOutApi *>(rtapi_)->sendMessage( message, size ); }
675inline void RtMidiOut :: setErrorCallback( RtMidiErrorCallback errorCallback, void *userData ) { rtapi_->setErrorCallback(errorCallback, userData); }
676
677#endif
void(* RtMidiErrorCallback)(RtMidiError::Type type, const std::string &errorText, void *userData)
RtMidi error callback function prototype.
Definition RtMidi.h:146
Definition RtMidi.h:539
void error(RtMidiError::Type type, std::string errorString)
A basic error reporting function for RtMidi classes.
Definition RtMidi.h:573
Definition RtMidi.h:638
Exception handling class for RtMidi.
Definition RtMidi.h:97
virtual const std::string & getMessage(void) const
Returns the thrown error message string.
Definition RtMidi.h:128
virtual const Type & getType(void) const
Returns the thrown error message type.
Definition RtMidi.h:125
virtual void printMessage(void) const
Prints thrown error message to stderr.
Definition RtMidi.h:122
Type
Defined RtMidiError types.
Definition RtMidi.h:100
@ INVALID_USE
Definition RtMidi.h:108
@ NO_DEVICES_FOUND
Definition RtMidi.h:104
@ MEMORY_ERROR
Definition RtMidi.h:106
@ INVALID_PARAMETER
Definition RtMidi.h:107
@ WARNING
Definition RtMidi.h:101
@ INVALID_DEVICE
Definition RtMidi.h:105
@ DRIVER_ERROR
Definition RtMidi.h:109
@ UNSPECIFIED
Definition RtMidi.h:103
@ DEBUG_WARNING
Definition RtMidi.h:102
@ SYSTEM_ERROR
Definition RtMidi.h:110
virtual ~RtMidiError(void)
The destructor.
Definition RtMidi.h:119
virtual const char * what(void) const
Returns the thrown error message as a c-style string.
Definition RtMidi.h:131
RtMidiError(const std::string &message, Type type=RtMidiError::UNSPECIFIED)
The constructor.
Definition RtMidi.h:115
A realtime MIDI input class.
Definition RtMidi.h:276
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.
void(* RtMidiCallback)(double timeStamp, std::vector< unsigned char > *message, void *userData)
User callback function type definition.
Definition RtMidi.h:279
~RtMidiIn(void)
If a MIDI connection is still open, it will be closed by the destructor.
A realtime MIDI output class.
Definition RtMidi.h:434
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:151
static void getCompiledApi(std::vector< RtMidi::Api > &apis)
A static function to determine the available compiled MIDI APIs.
virtual void openVirtualPort(const std::string &portName=std::string("RtMidi"))=0
Pure virtual openVirtualPort() function.
virtual void closePort(void)=0
Pure virtual closePort() function.
virtual void openPort(unsigned int portNumber=0, const std::string &portName=std::string("RtMidi"))=0
Pure virtual openPort() function.
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 std::string getApiName(RtMidi::Api api)
Return the name of a specified compiled MIDI API.
virtual std::string getPortName(unsigned int portNumber=0)=0
Pure virtual getPortName() function.
static std::string getVersion(void)
A static function to determine the current RtMidi version.
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.
virtual void setErrorCallback(RtMidiErrorCallback errorCallback=NULL, void *userData=0)=0
Set an error callback function to be invoked when an error has occurred.
Api
MIDI API specifier arguments.
Definition RtMidi.h:156
@ UNIX_JACK
Definition RtMidi.h:160
@ LINUX_ALSA
Definition RtMidi.h:159
@ WEB_MIDI_API
Definition RtMidi.h:163
@ MACOSX_CORE
Definition RtMidi.h:158
@ UNSPECIFIED
Definition RtMidi.h:157
@ RTMIDI_DUMMY
Definition RtMidi.h:162
@ WINDOWS_MM
Definition RtMidi.h:161
@ ANDROID_AMIDI
Definition RtMidi.h:165
@ WINDOWS_UWP
Definition RtMidi.h:164
Definition RtMidi.h:586
double timeStamp
Time in seconds elapsed since the previous message.
Definition RtMidi.h:590
Definition RtMidi.h:597
Definition RtMidi.h:613

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