To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.
root / CollidoscopeApp / include / RtMidi.h @ 0:02467299402e
History | View | Annotate | Download (28.3 KB)
| 1 | 0:02467299402e | f | /**********************************************************************/
|
|---|---|---|---|
| 2 | /*! \class RtMidi
|
||
| 3 | \brief An abstract base class for realtime MIDI input/output.
|
||
| 4 | |||
| 5 | This class implements some common functionality for the realtime
|
||
| 6 | MIDI input/output subclasses RtMidiIn and RtMidiOut.
|
||
| 7 | |||
| 8 | RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/
|
||
| 9 | |||
| 10 | RtMidi: realtime MIDI i/o C++ classes
|
||
| 11 | Copyright (c) 2003-2016 Gary P. Scavone
|
||
| 12 | |||
| 13 | Permission is hereby granted, free of charge, to any person
|
||
| 14 | obtaining a copy of this software and associated documentation files
|
||
| 15 | (the "Software"), to deal in the Software without restriction,
|
||
| 16 | including without limitation the rights to use, copy, modify, merge,
|
||
| 17 | publish, distribute, sublicense, and/or sell copies of the Software,
|
||
| 18 | and to permit persons to whom the Software is furnished to do so,
|
||
| 19 | subject to the following conditions:
|
||
| 20 | |||
| 21 | The above copyright notice and this permission notice shall be
|
||
| 22 | included in all copies or substantial portions of the Software.
|
||
| 23 | |||
| 24 | Any person wishing to distribute modifications to the Software is
|
||
| 25 | asked to send the modifications to the original developer so that
|
||
| 26 | they can be incorporated into the canonical version. This is,
|
||
| 27 | however, not a binding provision of this license.
|
||
| 28 | |||
| 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||
| 30 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||
| 31 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||
| 32 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||
| 33 | ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||
| 34 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||
| 35 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
| 36 | */
|
||
| 37 | /**********************************************************************/
|
||
| 38 | |||
| 39 | /*!
|
||
| 40 | \file RtMidi.h
|
||
| 41 | */
|
||
| 42 | |||
| 43 | #ifndef RTMIDI_H
|
||
| 44 | #define RTMIDI_H
|
||
| 45 | |||
| 46 | #define RTMIDI_VERSION "2.1.1" |
||
| 47 | |||
| 48 | #include <exception> |
||
| 49 | #include <iostream> |
||
| 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; |
||
| 115 | |||
| 116 | class RtMidi |
||
| 117 | {
|
||
| 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(); |
||
| 140 | |||
| 141 | //! Pure virtual openPort() function.
|
||
| 142 | virtual void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi" ) ) = 0; |
||
| 143 | |||
| 144 | //! Pure virtual openVirtualPort() function.
|
||
| 145 | virtual void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) = 0; |
||
| 146 | |||
| 147 | //! Pure virtual getPortCount() function.
|
||
| 148 | virtual unsigned int getPortCount() = 0; |
||
| 149 | |||
| 150 | //! Pure virtual getPortName() function.
|
||
| 151 | virtual std::string getPortName( unsigned int portNumber = 0 ) = 0; |
||
| 152 | |||
| 153 | //! Pure virtual closePort() function.
|
||
| 154 | virtual void closePort( void ) = 0; |
||
| 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 | |||
| 166 | protected:
|
||
| 167 | |||
| 168 | RtMidi(); |
||
| 169 | virtual ~RtMidi(); |
||
| 170 | |||
| 171 | MidiApi *rtapi_; |
||
| 172 | }; |
||
| 173 | |||
| 174 | /**********************************************************************/
|
||
| 175 | /*! \class RtMidiIn
|
||
| 176 | \brief A realtime MIDI input class.
|
||
| 177 | |||
| 178 | This class provides a common, platform-independent API for
|
||
| 179 | realtime MIDI input. It allows access to a single MIDI input
|
||
| 180 | port. Incoming MIDI messages are either saved to a queue for
|
||
| 181 | retrieval using the getMessage() function or immediately passed to
|
||
| 182 | a user-specified callback function. Create multiple instances of
|
||
| 183 | this class to connect to more than one MIDI device at the same
|
||
| 184 | time. With the OS-X, Linux ALSA, and JACK MIDI APIs, it is also
|
||
| 185 | possible to open a virtual input port to which other MIDI software
|
||
| 186 | clients can connect.
|
||
| 187 | |||
| 188 | by Gary P. Scavone, 2003-2014.
|
||
| 189 | */
|
||
| 190 | /**********************************************************************/
|
||
| 191 | |||
| 192 | // **************************************************************** //
|
||
| 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 | // **************************************************************** //
|
||
| 205 | |||
| 206 | class RtMidiIn : public RtMidi |
||
| 207 | {
|
||
| 208 | public:
|
||
| 209 | |||
| 210 | //! User callback function type definition.
|
||
| 211 | typedef void (*RtMidiCallback)( double timeStamp, std::vector<unsigned char> *message, void *userData); |
||
| 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 | |||
| 352 | //! Default constructor that allows an optional client name.
|
||
| 353 | /*!
|
||
| 354 | An exception will be thrown if a MIDI system initialization error occurs.
|
||
| 355 | |||
| 356 | If no API argument is specified and multiple API support has been
|
||
| 357 | compiled, the default order of use is ALSA, JACK (Linux) and CORE,
|
||
| 358 | JACK (OS-X).
|
||
| 359 | */
|
||
| 360 | RtMidiOut( RtMidi::Api api=UNSPECIFIED, |
||
| 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.
|
||
| 370 | /*!
|
||
| 371 | An optional port number greater than 0 can be specified.
|
||
| 372 | Otherwise, the default or first port found is opened. An
|
||
| 373 | exception is thrown if an error occurs while attempting to make
|
||
| 374 | the port connection.
|
||
| 375 | */
|
||
| 376 | void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi Output" ) ); |
||
| 377 | |||
| 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
|
||
| 387 | software applications can connect. This type of functionality
|
||
| 388 | is currently only supported by the Macintosh OS-X, Linux ALSA
|
||
| 389 | and JACK APIs (the function does nothing with the other APIs).
|
||
| 390 | An exception is thrown if an error occurs while attempting to
|
||
| 391 | create the virtual port.
|
||
| 392 | */
|
||
| 393 | void openVirtualPort( const std::string portName = std::string( "RtMidi Output" ) ); |
||
| 394 | |||
| 395 | //! Return the number of available MIDI output ports.
|
||
| 396 | unsigned int getPortCount( void ); |
||
| 397 | |||
| 398 | //! Return a string identifier for the specified MIDI port type and number.
|
||
| 399 | /*!
|
||
| 400 | An empty string is returned if an invalid port specifier is provided.
|
||
| 401 | */
|
||
| 402 | std::string getPortName( unsigned int portNumber = 0 ); |
||
| 403 | |||
| 404 | //! Immediately send a single message out an open MIDI output port.
|
||
| 405 | /*!
|
||
| 406 | An exception is thrown if an error occurs during output or an
|
||
| 407 | output connection was not previously established.
|
||
| 408 | */
|
||
| 409 | void sendMessage( std::vector<unsigned char> *message ); |
||
| 410 | |||
| 411 | //! Set an error callback function to be invoked when an error has occured.
|
||
| 412 | /*!
|
||
| 413 | The callback function will be called whenever an error has occured. It is best
|
||
| 414 | to set the error callback function before opening a port.
|
||
| 415 | */
|
||
| 416 | virtual void setErrorCallback( RtMidiErrorCallback errorCallback = NULL, void *userData = 0 ); |
||
| 417 | |||
| 418 | protected:
|
||
| 419 | void openMidiApi( RtMidi::Api api, const std::string clientName ); |
||
| 420 | }; |
||
| 421 | |||
| 422 | |||
| 423 | // **************************************************************** //
|
||
| 424 | //
|
||
| 425 | // MidiInApi / MidiOutApi class declarations.
|
||
| 426 | //
|
||
| 427 | // Subclasses of MidiInApi and MidiOutApi contain all API- and
|
||
| 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 ); |
||
| 476 | double getMessage( std::vector<unsigned char> *message ); |
||
| 477 | |||
| 478 | // A MIDI structure used internally by the class to store incoming
|
||
| 479 | // messages. Each message represents one and only one MIDI message.
|
||
| 480 | struct MidiMessage {
|
||
| 481 | std::vector<unsigned char> bytes; |
||
| 482 | double timeStamp;
|
||
| 483 | |||
| 484 | // Default constructor.
|
||
| 485 | MidiMessage() |
||
| 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) {} |
||
| 499 | }; |
||
| 500 | |||
| 501 | // The RtMidiInData structure is used to pass private class data to
|
||
| 502 | // the MIDI input handling function or thread.
|
||
| 503 | struct RtMidiInData {
|
||
| 504 | MidiQueue queue; |
||
| 505 | MidiMessage message; |
||
| 506 | unsigned char ignoreFlags; |
||
| 507 | bool doInput;
|
||
| 508 | bool firstMessage;
|
||
| 509 | void *apiData;
|
||
| 510 | bool usingCallback;
|
||
| 511 | RtMidiIn::RtMidiCallback userCallback; |
||
| 512 | void *userData;
|
||
| 513 | bool continueSysex;
|
||
| 514 | |||
| 515 | // Default constructor.
|
||
| 516 | RtMidiInData() |
||
| 517 | : ignoreFlags(7), doInput(false), firstMessage(true), |
||
| 518 | apiData(0), usingCallback(false), userCallback(0), userData(0), |
||
| 519 | continueSysex(false) {}
|
||
| 520 | }; |
||
| 521 | |||
| 522 | protected:
|
||
| 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:
|
||
| 589 | void initialize( const std::string& clientName ); |
||
| 590 | }; |
||
| 591 | |||
| 592 | class MidiOutCore: public MidiOutApi |
||
| 593 | {
|
||
| 594 | public:
|
||
| 595 | MidiOutCore( const std::string clientName );
|
||
| 596 | ~MidiOutCore( void );
|
||
| 597 | RtMidi::Api getCurrentApi( void ) { return RtMidi::MACOSX_CORE; }; |
||
| 598 | void openPort( unsigned int portNumber, const std::string portName ); |
||
| 599 | void openVirtualPort( const std::string portName ); |
||
| 600 | void closePort( void ); |
||
| 601 | unsigned int getPortCount( void ); |
||
| 602 | std::string getPortName( unsigned int portNumber ); |
||
| 603 | void sendMessage( std::vector<unsigned char> *message ); |
||
| 604 | |||
| 605 | protected:
|
||
| 606 | void initialize( const std::string& clientName ); |
||
| 607 | }; |
||
| 608 | |||
| 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 |