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