comparison data/midi/rtmidi/RtMidi.h @ 1397:b0533d195c83

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