Mercurial > hg > svcore
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 |