annotate data/midi/rtmidi/RtMidi.h @ 683:f84f147572b9

Avoid crash when generating/processing a very short file
author Chris Cannam
date Wed, 11 May 2011 11:04:02 +0100
parents 3086876472dc
children b0533d195c83
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@565 11 Copyright (c) 2003-2009 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@559 25 requested to send the modifications to the original developer so that
Chris@559 26 they can be incorporated into the canonical version.
Chris@559 27
Chris@559 28 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Chris@559 29 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Chris@559 30 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
Chris@559 31 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
Chris@559 32 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
Chris@559 33 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
Chris@559 34 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Chris@559 35 */
Chris@559 36 /**********************************************************************/
Chris@559 37
Chris@565 38 // RtMidi: Version 1.0.8
Chris@559 39
Chris@559 40 #ifndef RTMIDI_H
Chris@559 41 #define RTMIDI_H
Chris@559 42
Chris@559 43 #include "RtError.h"
Chris@559 44 #include <string>
Chris@559 45
Chris@559 46 class RtMidi
Chris@559 47 {
Chris@559 48 public:
Chris@559 49
Chris@559 50 //! Pure virtual openPort() function.
Chris@565 51 virtual void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi" ) ) = 0;
Chris@559 52
Chris@559 53 //! Pure virtual openVirtualPort() function.
Chris@559 54 virtual void openVirtualPort( const std::string portName = std::string( "RtMidi" ) ) = 0;
Chris@559 55
Chris@559 56 //! Pure virtual getPortCount() function.
Chris@559 57 virtual unsigned int getPortCount() = 0;
Chris@559 58
Chris@559 59 //! Pure virtual getPortName() function.
Chris@559 60 virtual std::string getPortName( unsigned int portNumber = 0 ) = 0;
Chris@559 61
Chris@559 62 //! Pure virtual closePort() function.
Chris@559 63 virtual void closePort( void ) = 0;
Chris@559 64
Chris@559 65 protected:
Chris@559 66
Chris@559 67 RtMidi();
Chris@559 68 virtual ~RtMidi() {};
Chris@559 69
Chris@559 70 // A basic error reporting function for internal use in the RtMidi
Chris@559 71 // subclasses. The behavior of this function can be modified to
Chris@559 72 // suit specific needs.
Chris@559 73 void error( RtError::Type type );
Chris@559 74
Chris@559 75 void *apiData_;
Chris@559 76 bool connected_;
Chris@559 77 std::string errorString_;
Chris@559 78 };
Chris@559 79
Chris@559 80 /**********************************************************************/
Chris@559 81 /*! \class RtMidiIn
Chris@559 82 \brief A realtime MIDI input class.
Chris@559 83
Chris@559 84 This class provides a common, platform-independent API for
Chris@559 85 realtime MIDI input. It allows access to a single MIDI input
Chris@559 86 port. Incoming MIDI messages are either saved to a queue for
Chris@559 87 retrieval using the getMessage() function or immediately passed to
Chris@559 88 a user-specified callback function. Create multiple instances of
Chris@559 89 this class to connect to more than one MIDI device at the same
Chris@559 90 time. With the OS-X and Linux ALSA MIDI APIs, it is also possible
Chris@559 91 to open a virtual input port to which other MIDI software clients
Chris@559 92 can connect.
Chris@559 93
Chris@565 94 by Gary P. Scavone, 2003-2008.
Chris@559 95 */
Chris@559 96 /**********************************************************************/
Chris@559 97
Chris@559 98 #include <vector>
Chris@559 99 #include <queue>
Chris@559 100
Chris@559 101 class RtMidiIn : public RtMidi
Chris@559 102 {
Chris@559 103 public:
Chris@559 104
Chris@559 105 //! User callback function type definition.
Chris@559 106 typedef void (*RtMidiCallback)( double timeStamp, std::vector<unsigned char> *message, void *userData);
Chris@559 107
Chris@565 108 //! Default constructor that allows an optional client name.
Chris@559 109 /*!
Chris@559 110 An exception will be thrown if a MIDI system initialization error occurs.
Chris@559 111 */
Chris@565 112 RtMidiIn( const std::string clientName = std::string( "RtMidi Input Client") );
Chris@559 113
Chris@559 114 //! If a MIDI connection is still open, it will be closed by the destructor.
Chris@559 115 ~RtMidiIn();
Chris@559 116
Chris@559 117 //! Open a MIDI input connection.
Chris@559 118 /*!
Chris@559 119 An optional port number greater than 0 can be specified.
Chris@559 120 Otherwise, the default or first port found is opened.
Chris@559 121 */
Chris@565 122 void openPort( unsigned int portNumber = 0, const std::string Portname = std::string( "RtMidi Input" ) );
Chris@559 123
Chris@559 124 //! Create a virtual input port, with optional name, to allow software connections (OS X and ALSA only).
Chris@559 125 /*!
Chris@559 126 This function creates a virtual MIDI input port to which other
Chris@559 127 software applications can connect. This type of functionality
Chris@559 128 is currently only supported by the Macintosh OS-X and Linux ALSA
Chris@559 129 APIs (the function does nothing for the other APIs).
Chris@559 130 */
Chris@559 131 void openVirtualPort( const std::string portName = std::string( "RtMidi Input" ) );
Chris@559 132
Chris@559 133 //! Set a callback function to be invoked for incoming MIDI messages.
Chris@559 134 /*!
Chris@559 135 The callback function will be called whenever an incoming MIDI
Chris@559 136 message is received. While not absolutely necessary, it is best
Chris@559 137 to set the callback function before opening a MIDI port to avoid
Chris@559 138 leaving some messages in the queue.
Chris@559 139 */
Chris@559 140 void setCallback( RtMidiCallback callback, void *userData = 0 );
Chris@559 141
Chris@559 142 //! Cancel use of the current callback function (if one exists).
Chris@559 143 /*!
Chris@559 144 Subsequent incoming MIDI messages will be written to the queue
Chris@559 145 and can be retrieved with the \e getMessage function.
Chris@559 146 */
Chris@559 147 void cancelCallback();
Chris@559 148
Chris@559 149 //! Close an open MIDI connection (if one exists).
Chris@559 150 void closePort( void );
Chris@559 151
Chris@559 152 //! Return the number of available MIDI input ports.
Chris@559 153 unsigned int getPortCount();
Chris@559 154
Chris@559 155 //! Return a string identifier for the specified MIDI input port number.
Chris@559 156 /*!
Chris@559 157 An exception is thrown if an invalid port specifier is provided.
Chris@559 158 */
Chris@559 159 std::string getPortName( unsigned int portNumber = 0 );
Chris@559 160
Chris@559 161 //! Set the maximum number of MIDI messages to be saved in the queue.
Chris@559 162 /*!
Chris@559 163 If the queue size limit is reached, incoming messages will be
Chris@559 164 ignored. The default limit is 1024.
Chris@559 165 */
Chris@559 166 void setQueueSizeLimit( unsigned int queueSize );
Chris@559 167
Chris@559 168 //! Specify whether certain MIDI message types should be queued or ignored during input.
Chris@559 169 /*!
Chris@559 170 By default, MIDI timing and active sensing messages are ignored
Chris@559 171 during message input because of their relative high data rates.
Chris@559 172 MIDI sysex messages are ignored by default as well. Variable
Chris@559 173 values of "true" imply that the respective message type will be
Chris@559 174 ignored.
Chris@559 175 */
Chris@559 176 void ignoreTypes( bool midiSysex = true, bool midiTime = true, bool midiSense = true );
Chris@559 177
Chris@559 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.
Chris@559 179 /*!
Chris@559 180 This function returns immediately whether a new message is
Chris@559 181 available or not. A valid message is indicated by a non-zero
Chris@559 182 vector size. An exception is thrown if an error occurs during
Chris@559 183 message retrieval or an input connection was not previously
Chris@559 184 established.
Chris@559 185 */
Chris@559 186 double getMessage( std::vector<unsigned char> *message );
Chris@559 187
Chris@559 188 // A MIDI structure used internally by the class to store incoming
Chris@559 189 // messages. Each message represents one and only one MIDI message.
Chris@559 190 struct MidiMessage {
Chris@559 191 std::vector<unsigned char> bytes;
Chris@559 192 double timeStamp;
Chris@559 193
Chris@559 194 // Default constructor.
Chris@559 195 MidiMessage()
Chris@559 196 :bytes(3), timeStamp(0.0) {}
Chris@559 197 };
Chris@559 198
Chris@559 199 // The RtMidiInData structure is used to pass private class data to
Chris@559 200 // the MIDI input handling function or thread.
Chris@559 201 struct RtMidiInData {
Chris@559 202 std::queue<MidiMessage> queue;
Chris@565 203 MidiMessage message;
Chris@559 204 unsigned int queueLimit;
Chris@559 205 unsigned char ignoreFlags;
Chris@559 206 bool doInput;
Chris@559 207 bool firstMessage;
Chris@559 208 void *apiData;
Chris@559 209 bool usingCallback;
Chris@559 210 void *userCallback;
Chris@559 211 void *userData;
Chris@565 212 bool continueSysex;
Chris@559 213
Chris@559 214 // Default constructor.
Chris@559 215 RtMidiInData()
Chris@559 216 : queueLimit(1024), ignoreFlags(7), doInput(false), firstMessage(true),
Chris@565 217 apiData(0), usingCallback(false), userCallback(0), userData(0),
Chris@565 218 continueSysex(false) {}
Chris@559 219 };
Chris@559 220
Chris@559 221 private:
Chris@559 222
Chris@565 223 void initialize( const std::string& clientName );
Chris@559 224 RtMidiInData inputData_;
Chris@559 225
Chris@559 226 };
Chris@559 227
Chris@559 228 /**********************************************************************/
Chris@559 229 /*! \class RtMidiOut
Chris@559 230 \brief A realtime MIDI output class.
Chris@559 231
Chris@559 232 This class provides a common, platform-independent API for MIDI
Chris@559 233 output. It allows one to probe available MIDI output ports, to
Chris@559 234 connect to one such port, and to send MIDI bytes immediately over
Chris@559 235 the connection. Create multiple instances of this class to
Chris@559 236 connect to more than one MIDI device at the same time.
Chris@559 237
Chris@565 238 by Gary P. Scavone, 2003-2008.
Chris@559 239 */
Chris@559 240 /**********************************************************************/
Chris@559 241
Chris@559 242 class RtMidiOut : public RtMidi
Chris@559 243 {
Chris@559 244 public:
Chris@559 245
Chris@565 246 //! Default constructor that allows an optional client name.
Chris@559 247 /*!
Chris@559 248 An exception will be thrown if a MIDI system initialization error occurs.
Chris@559 249 */
Chris@565 250 RtMidiOut( const std::string clientName = std::string( "RtMidi Output Client" ) );
Chris@559 251
Chris@559 252 //! The destructor closes any open MIDI connections.
Chris@559 253 ~RtMidiOut();
Chris@559 254
Chris@559 255 //! Open a MIDI output connection.
Chris@559 256 /*!
Chris@559 257 An optional port number greater than 0 can be specified.
Chris@559 258 Otherwise, the default or first port found is opened. An
Chris@559 259 exception is thrown if an error occurs while attempting to make
Chris@559 260 the port connection.
Chris@559 261 */
Chris@565 262 void openPort( unsigned int portNumber = 0, const std::string portName = std::string( "RtMidi Output" ) );
Chris@559 263
Chris@559 264 //! Close an open MIDI connection (if one exists).
Chris@559 265 void closePort();
Chris@559 266
Chris@559 267 //! Create a virtual output port, with optional name, to allow software connections (OS X and ALSA only).
Chris@559 268 /*!
Chris@559 269 This function creates a virtual MIDI output port to which other
Chris@559 270 software applications can connect. This type of functionality
Chris@559 271 is currently only supported by the Macintosh OS-X and Linux ALSA
Chris@559 272 APIs (the function does nothing with the other APIs). An
Chris@559 273 exception is thrown if an error occurs while attempting to create
Chris@559 274 the virtual port.
Chris@559 275 */
Chris@559 276 void openVirtualPort( const std::string portName = std::string( "RtMidi Output" ) );
Chris@559 277
Chris@559 278 //! Return the number of available MIDI output ports.
Chris@559 279 unsigned int getPortCount();
Chris@559 280
Chris@559 281 //! Return a string identifier for the specified MIDI port type and number.
Chris@559 282 /*!
Chris@559 283 An exception is thrown if an invalid port specifier is provided.
Chris@559 284 */
Chris@559 285 std::string getPortName( unsigned int portNumber = 0 );
Chris@559 286
Chris@559 287 //! Immediately send a single message out an open MIDI output port.
Chris@559 288 /*!
Chris@559 289 An exception is thrown if an error occurs during output or an
Chris@559 290 output connection was not previously established.
Chris@559 291 */
Chris@559 292 void sendMessage( std::vector<unsigned char> *message );
Chris@559 293
Chris@559 294 private:
Chris@559 295
Chris@565 296 void initialize( const std::string& clientName );
Chris@559 297 };
Chris@559 298
Chris@559 299 #endif