annotate data/midi/rtmidi/RtMidi.h @ 1825:029d7d3f0a3a

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