1 /* 2 ============================================================================== 3 4 This file is part of the JUCE library. 5 Copyright (c) 2020 - Raw Material Software Limited 6 7 JUCE is an open source library subject to commercial or open-source 8 licensing. 9 10 The code included in this file is provided under the terms of the ISC license 11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission 12 To use, copy, modify, and/or distribute this software for any purpose with or 13 without fee is hereby granted provided that the above copyright notice and 14 this permission notice appear in all copies. 15 16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER 17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE 18 DISCLAIMED. 19 20 ============================================================================== 21 */ 22 23 namespace juce 24 { 25 //============================================================================== 26 /** 27 This struct contains information about a MIDI input or output device. 28 29 You can get one of these structs by calling the static getAvailableDevices() or 30 getDefaultDevice() methods of MidiInput and MidiOutput or by calling getDeviceInfo() 31 on an instance of these classes. Devices can be opened by passing the identifier to 32 the openDevice() method. 33 34 @tags{Audio} 35 */ 36 struct MidiDeviceInfo 37 { 38 MidiDeviceInfo() = default; 39 MidiDeviceInfoMidiDeviceInfo40 MidiDeviceInfo (const String& deviceName, const String& deviceIdentifier) 41 : name (deviceName), identifier (deviceIdentifier) 42 { 43 } 44 45 /** The name of this device. 46 47 This will be provided by the OS unless the device has been created with the 48 createNewDevice() method. 49 50 Note that the name is not guaranteed to be unique and two devices with the 51 same name will be indistinguishable. If you want to address a specific device 52 it is better to use the identifier. 53 */ 54 String name; 55 56 /** The identifier for this device. 57 58 This will be provided by the OS and it's format will differ on different systems 59 e.g. on macOS it will be a number whereas on Windows it will be a long alphanumeric string. 60 */ 61 String identifier; 62 63 //============================================================================== 64 bool operator== (const MidiDeviceInfo& other) const noexcept { return name == other.name && identifier == other.identifier; } 65 bool operator!= (const MidiDeviceInfo& other) const noexcept { return ! operator== (other); } 66 }; 67 68 class MidiInputCallback; 69 70 //============================================================================== 71 /** 72 Represents a midi input device. 73 74 To create one of these, use the static getAvailableDevices() method to find out what 75 inputs are available, and then use the openDevice() method to try to open one. 76 77 @see MidiOutput 78 79 @tags{Audio} 80 */ 81 class JUCE_API MidiInput final 82 { 83 public: 84 //============================================================================== 85 /** Returns a list of the available midi input devices. 86 87 You can open one of the devices by passing its identifier into the openDevice() method. 88 89 @see MidiDeviceInfo, getDevices, getDefaultDeviceIndex, openDevice 90 */ 91 static Array<MidiDeviceInfo> getAvailableDevices(); 92 93 /** Returns the MidiDeviceInfo of the default midi input device to use. */ 94 static MidiDeviceInfo getDefaultDevice(); 95 96 /** Tries to open one of the midi input devices. 97 98 This will return a MidiInput object if it manages to open it, you can then 99 call start() and stop() on this device. 100 101 If the device can't be opened, this will return an empty object. 102 103 @param deviceIdentifier the ID of the device to open - use the getAvailableDevices() method to 104 find the available devices that can be opened 105 @param callback the object that will receive the midi messages from this device 106 107 @see MidiInputCallback, getDevices 108 */ 109 static std::unique_ptr<MidiInput> openDevice (const String& deviceIdentifier, MidiInputCallback* callback); 110 111 #if JUCE_LINUX || JUCE_MAC || JUCE_IOS || DOXYGEN 112 /** This will try to create a new midi input device (only available on Linux, macOS and iOS). 113 114 This will attempt to create a new midi input device with the specified name for other 115 apps to connect to. 116 117 NB - if you are calling this method on iOS you must have enabled the "Audio Background Capability" 118 setting in the iOS exporter otherwise this method will fail. 119 120 Returns an empty object if a device can't be created. 121 122 @param deviceName the name of the device to create 123 @param callback the object that will receive the midi messages from this device 124 */ 125 static std::unique_ptr<MidiInput> createNewDevice (const String& deviceName, MidiInputCallback* callback); 126 #endif 127 128 //============================================================================== 129 /** Destructor. */ 130 ~MidiInput(); 131 132 /** Starts the device running. 133 134 After calling this, the device will start sending midi messages to the MidiInputCallback 135 object that was specified when the openDevice() method was called. 136 137 @see stop 138 */ 139 void start(); 140 141 /** Stops the device running. 142 143 @see start 144 */ 145 void stop(); 146 147 /** Returns the MidiDeviceInfo struct containing some information about this device. */ getDeviceInfo()148 MidiDeviceInfo getDeviceInfo() const noexcept { return deviceInfo; } 149 150 /** Returns the identifier of this device. */ getIdentifier()151 String getIdentifier() const noexcept { return deviceInfo.identifier; } 152 153 /** Returns the name of this device. */ getName()154 String getName() const noexcept { return deviceInfo.name; } 155 156 /** Sets a custom name for the device. */ setName(const String & newName)157 void setName (const String& newName) noexcept { deviceInfo.name = newName; } 158 159 //============================================================================== 160 /** Deprecated. */ 161 static StringArray getDevices(); 162 /** Deprecated. */ 163 static int getDefaultDeviceIndex(); 164 /** Deprecated. */ 165 static std::unique_ptr<MidiInput> openDevice (int, MidiInputCallback*); 166 167 /** @internal */ 168 class Pimpl; 169 170 private: 171 //============================================================================== 172 explicit MidiInput (const String&, const String&); 173 174 MidiDeviceInfo deviceInfo; 175 176 std::unique_ptr<Pimpl> internal; 177 178 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiInput) 179 }; 180 181 //============================================================================== 182 /** 183 Receives incoming messages from a physical MIDI input device. 184 185 This class is overridden to handle incoming midi messages. See the MidiInput 186 class for more details. 187 188 @see MidiInput 189 190 @tags{Audio} 191 */ 192 class JUCE_API MidiInputCallback 193 { 194 public: 195 /** Destructor. */ 196 virtual ~MidiInputCallback() = default; 197 198 /** Receives an incoming message. 199 200 A MidiInput object will call this method when a midi event arrives. It'll be 201 called on a high-priority system thread, so avoid doing anything time-consuming 202 in here, and avoid making any UI calls. You might find the MidiBuffer class helpful 203 for queueing incoming messages for use later. 204 205 @param source the MidiInput object that generated the message 206 @param message the incoming message. The message's timestamp is set to a value 207 equivalent to (Time::getMillisecondCounter() / 1000.0) to specify the 208 time when the message arrived 209 */ 210 virtual void handleIncomingMidiMessage (MidiInput* source, 211 const MidiMessage& message) = 0; 212 213 /** Notification sent each time a packet of a multi-packet sysex message arrives. 214 215 If a long sysex message is broken up into multiple packets, this callback is made 216 for each packet that arrives until the message is finished, at which point 217 the normal handleIncomingMidiMessage() callback will be made with the entire 218 message. 219 220 The message passed in will contain the start of a sysex, but won't be finished 221 with the terminating 0xf7 byte. 222 */ handlePartialSysexMessage(MidiInput * source,const uint8 * messageData,int numBytesSoFar,double timestamp)223 virtual void handlePartialSysexMessage (MidiInput* source, 224 const uint8* messageData, 225 int numBytesSoFar, 226 double timestamp) 227 { 228 ignoreUnused (source, messageData, numBytesSoFar, timestamp); 229 } 230 }; 231 232 //============================================================================== 233 /** 234 Represents a midi output device. 235 236 To create one of these, use the static getAvailableDevices() method to find out what 237 outputs are available, and then use the openDevice() method to try to open one. 238 239 @see MidiInput 240 241 @tags{Audio} 242 */ 243 class JUCE_API MidiOutput final : private Thread 244 { 245 public: 246 //============================================================================== 247 /** Returns a list of the available midi output devices. 248 249 You can open one of the devices by passing its identifier into the openDevice() method. 250 251 @see MidiDeviceInfo, getDevices, getDefaultDeviceIndex, openDevice 252 */ 253 static Array<MidiDeviceInfo> getAvailableDevices(); 254 255 /** Returns the MidiDeviceInfo of the default midi output device to use. */ 256 static MidiDeviceInfo getDefaultDevice(); 257 258 /** Tries to open one of the midi output devices. 259 260 This will return a MidiOutput object if it manages to open it, you can then 261 send messages to this device. 262 263 If the device can't be opened, this will return an empty object. 264 265 @param deviceIdentifier the ID of the device to open - use the getAvailableDevices() method to 266 find the available devices that can be opened 267 @see getDevices 268 */ 269 static std::unique_ptr<MidiOutput> openDevice (const String& deviceIdentifier); 270 271 #if JUCE_LINUX || JUCE_MAC || JUCE_IOS || DOXYGEN 272 /** This will try to create a new midi output device (only available on Linux, macOS and iOS). 273 274 This will attempt to create a new midi output device with the specified name that other 275 apps can connect to and use as their midi input. 276 277 NB - if you are calling this method on iOS you must have enabled the "Audio Background Capability" 278 setting in the iOS exporter otherwise this method will fail. 279 280 Returns an empty object if a device can't be created. 281 282 @param deviceName the name of the device to create 283 */ 284 static std::unique_ptr<MidiOutput> createNewDevice (const String& deviceName); 285 #endif 286 287 //============================================================================== 288 /** Destructor. */ 289 ~MidiOutput() override; 290 291 /** Returns the MidiDeviceInfo struct containing some information about this device. */ getDeviceInfo()292 MidiDeviceInfo getDeviceInfo() const noexcept { return deviceInfo; } 293 294 /** Returns the identifier of this device. */ getIdentifier()295 String getIdentifier() const noexcept { return deviceInfo.identifier; } 296 297 /** Returns the name of this device. */ getName()298 String getName() const noexcept { return deviceInfo.name; } 299 300 /** Sets a custom name for the device. */ setName(const String & newName)301 void setName (const String& newName) noexcept { deviceInfo.name = newName; } 302 303 //============================================================================== 304 /** Sends out a MIDI message immediately. */ 305 void sendMessageNow (const MidiMessage& message); 306 307 /** Sends out a sequence of MIDI messages immediately. */ 308 void sendBlockOfMessagesNow (const MidiBuffer& buffer); 309 310 /** This lets you supply a block of messages that will be sent out at some point 311 in the future. 312 313 The MidiOutput class has an internal thread that can send out timestamped 314 messages - this appends a set of messages to its internal buffer, ready for 315 sending. 316 317 This will only work if you've already started the thread with startBackgroundThread(). 318 319 A time is specified, at which the block of messages should be sent. This time uses 320 the same time base as Time::getMillisecondCounter(), and must be in the future. 321 322 The samplesPerSecondForBuffer parameter indicates the number of samples per second 323 used by the MidiBuffer. Each event in a MidiBuffer has a sample position, and the 324 samplesPerSecondForBuffer value is needed to convert this sample position to a 325 real time. 326 */ 327 void sendBlockOfMessages (const MidiBuffer& buffer, 328 double millisecondCounterToStartAt, 329 double samplesPerSecondForBuffer); 330 331 /** Gets rid of any midi messages that had been added by sendBlockOfMessages(). */ 332 void clearAllPendingMessages(); 333 334 /** Starts up a background thread so that the device can send blocks of data. 335 Call this to get the device ready, before using sendBlockOfMessages(). 336 */ 337 void startBackgroundThread(); 338 339 /** Stops the background thread, and clears any pending midi events. 340 @see startBackgroundThread 341 */ 342 void stopBackgroundThread(); 343 344 /** Returns true if the background thread used to send blocks of data is running. 345 @see startBackgroundThread, stopBackgroundThread 346 */ isBackgroundThreadRunning()347 bool isBackgroundThreadRunning() const noexcept { return isThreadRunning(); } 348 349 //============================================================================== 350 /** Deprecated. */ 351 static StringArray getDevices(); 352 /** Deprecated. */ 353 static int getDefaultDeviceIndex(); 354 /** Deprecated. */ 355 static std::unique_ptr<MidiOutput> openDevice (int); 356 357 /** @internal */ 358 class Pimpl; 359 360 private: 361 //============================================================================== 362 struct PendingMessage 363 { PendingMessagePendingMessage364 PendingMessage (const void* data, int len, double timeStamp) 365 : message (data, len, timeStamp) 366 { 367 } 368 369 MidiMessage message; 370 PendingMessage* next; 371 }; 372 373 //============================================================================== 374 explicit MidiOutput (const String&, const String&); 375 void run() override; 376 377 MidiDeviceInfo deviceInfo; 378 379 std::unique_ptr<Pimpl> internal; 380 381 CriticalSection lock; 382 PendingMessage* firstMessage = nullptr; 383 384 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiOutput) 385 }; 386 387 } // namespace juce 388