| @@ -270,7 +270,7 @@ public: | |||||
| #endif | #endif | ||||
| audioDeviceManager.addAudioCallback (&audioSourcePlayer); | audioDeviceManager.addAudioCallback (&audioSourcePlayer); | ||||
| audioDeviceManager.addMidiInputCallback ({}, &(synthAudioSource.midiCollector)); | |||||
| audioDeviceManager.addMidiInputDeviceCallback ({}, &(synthAudioSource.midiCollector)); | |||||
| setOpaque (true); | setOpaque (true); | ||||
| setSize (640, 480); | setSize (640, 480); | ||||
| @@ -279,7 +279,7 @@ public: | |||||
| ~AudioSynthesiserDemo() | ~AudioSynthesiserDemo() | ||||
| { | { | ||||
| audioSourcePlayer.setSource (nullptr); | audioSourcePlayer.setSource (nullptr); | ||||
| audioDeviceManager.removeMidiInputCallback ({}, &(synthAudioSource.midiCollector)); | |||||
| audioDeviceManager.removeMidiInputDeviceCallback ({}, &(synthAudioSource.midiCollector)); | |||||
| audioDeviceManager.removeAudioCallback (&audioSourcePlayer); | audioDeviceManager.removeAudioCallback (&audioSourcePlayer); | ||||
| audioDeviceManager.removeAudioCallback (&liveAudioDisplayComp); | audioDeviceManager.removeAudioCallback (&liveAudioDisplayComp); | ||||
| } | } | ||||
| @@ -879,7 +879,7 @@ public: | |||||
| audioDeviceManager.initialise (0, 2, 0, true, {}, 0); | audioDeviceManager.initialise (0, 2, 0, true, {}, 0); | ||||
| #endif | #endif | ||||
| audioDeviceManager.addMidiInputCallback ({}, this); | |||||
| audioDeviceManager.addMidiInputDeviceCallback ({}, this); | |||||
| audioDeviceManager.addAudioCallback (this); | audioDeviceManager.addAudioCallback (this); | ||||
| addAndMakeVisible (audioSetupComp); | addAndMakeVisible (audioSetupComp); | ||||
| @@ -904,7 +904,7 @@ public: | |||||
| ~MPEDemo() | ~MPEDemo() | ||||
| { | { | ||||
| audioDeviceManager.removeMidiInputCallback ({}, this); | |||||
| audioDeviceManager.removeMidiInputDeviceCallback ({}, this); | |||||
| audioDeviceManager.removeAudioCallback (this); | audioDeviceManager.removeAudioCallback (this); | ||||
| } | } | ||||
| @@ -304,19 +304,66 @@ String AudioDeviceManager::initialiseFromXML (const XmlElement& xml, | |||||
| error = setAudioDeviceSetup (setup, true); | error = setAudioDeviceSetup (setup, true); | ||||
| midiInsFromXml.clear(); | |||||
| if (error.isNotEmpty() && selectDefaultDeviceOnFailure) | |||||
| error = initialise (numInputChansNeeded, numOutputChansNeeded, nullptr, false, preferredDefaultDeviceName); | |||||
| midiDeviceInfosFromXml.clear(); | |||||
| enabledMidiInputs.clear(); | |||||
| forEachXmlChildElementWithTagName (xml, c, "MIDIINPUT") | forEachXmlChildElementWithTagName (xml, c, "MIDIINPUT") | ||||
| midiInsFromXml.add (c->getStringAttribute ("name")); | |||||
| midiDeviceInfosFromXml.add ({ c->getStringAttribute ("name"), c->getStringAttribute ("identifier") }); | |||||
| auto isIdentifierAvailable = [] (const Array<MidiDeviceInfo>& available, const String& identifier) | |||||
| { | |||||
| for (auto& device : available) | |||||
| if (device.identifier == identifier) | |||||
| return true; | |||||
| for (auto& m : MidiInput::getDevices()) | |||||
| setMidiInputEnabled (m, midiInsFromXml.contains (m)); | |||||
| return false; | |||||
| }; | |||||
| if (error.isNotEmpty() && selectDefaultDeviceOnFailure) | |||||
| error = initialise (numInputChansNeeded, numOutputChansNeeded, | |||||
| nullptr, false, preferredDefaultDeviceName); | |||||
| auto getUpdatedIdentifierForName = [&] (const Array<MidiDeviceInfo>& available, const String& name) -> String | |||||
| { | |||||
| for (auto& device : available) | |||||
| if (device.name == name) | |||||
| return device.identifier; | |||||
| return {}; | |||||
| }; | |||||
| setDefaultMidiOutput (xml.getStringAttribute ("defaultMidiOutput")); | |||||
| auto inputs = MidiInput::getAvailableDevices(); | |||||
| for (auto& info : midiDeviceInfosFromXml) | |||||
| { | |||||
| if (isIdentifierAvailable (inputs, info.identifier)) | |||||
| { | |||||
| setMidiInputDeviceEnabled (info.identifier, true); | |||||
| } | |||||
| else | |||||
| { | |||||
| auto identifier = getUpdatedIdentifierForName (inputs, info.name); | |||||
| if (identifier.isNotEmpty()) | |||||
| setMidiInputDeviceEnabled (identifier, true); | |||||
| } | |||||
| } | |||||
| MidiDeviceInfo defaultOutputDeviceInfo (xml.getStringAttribute ("defaultMidiOutput"), | |||||
| xml.getStringAttribute ("defaultMidiOutputDevice")); | |||||
| auto outputs = MidiOutput::getAvailableDevices(); | |||||
| if (isIdentifierAvailable (outputs, defaultOutputDeviceInfo.identifier)) | |||||
| { | |||||
| setDefaultMidiOutputDevice (defaultOutputDeviceInfo.identifier); | |||||
| } | |||||
| else | |||||
| { | |||||
| auto identifier = getUpdatedIdentifierForName (outputs, defaultOutputDeviceInfo.name); | |||||
| if (identifier.isNotEmpty()) | |||||
| setDefaultMidiOutputDevice (identifier); | |||||
| } | |||||
| return error; | return error; | ||||
| } | } | ||||
| @@ -660,24 +707,37 @@ void AudioDeviceManager::updateXml() | |||||
| lastExplicitSettings->setAttribute ("audioDeviceOutChans", currentSetup.outputChannels.toString (2)); | lastExplicitSettings->setAttribute ("audioDeviceOutChans", currentSetup.outputChannels.toString (2)); | ||||
| } | } | ||||
| for (int i = 0; i < enabledMidiInputs.size(); ++i) | |||||
| lastExplicitSettings->createNewChildElement ("MIDIINPUT") | |||||
| ->setAttribute ("name", enabledMidiInputs[i]->getName()); | |||||
| for (auto& input : enabledMidiInputs) | |||||
| { | |||||
| auto* child = lastExplicitSettings->createNewChildElement ("MIDIINPUT"); | |||||
| if (midiInsFromXml.size() > 0) | |||||
| child->setAttribute ("name", input->getName()); | |||||
| child->setAttribute ("identifier", input->getIdentifier()); | |||||
| } | |||||
| if (midiDeviceInfosFromXml.size() > 0) | |||||
| { | { | ||||
| // Add any midi devices that have been enabled before, but which aren't currently | // Add any midi devices that have been enabled before, but which aren't currently | ||||
| // open because the device has been disconnected. | // open because the device has been disconnected. | ||||
| const StringArray availableMidiDevices (MidiInput::getDevices()); | |||||
| auto availableMidiDevices = MidiInput::getAvailableDevices(); | |||||
| for (auto& d : midiDeviceInfosFromXml) | |||||
| { | |||||
| if (! availableMidiDevices.contains (d)) | |||||
| { | |||||
| auto* child = lastExplicitSettings->createNewChildElement ("MIDIINPUT"); | |||||
| for (int i = 0; i < midiInsFromXml.size(); ++i) | |||||
| if (! availableMidiDevices.contains (midiInsFromXml[i], true)) | |||||
| lastExplicitSettings->createNewChildElement ("MIDIINPUT") | |||||
| ->setAttribute ("name", midiInsFromXml[i]); | |||||
| child->setAttribute ("name", d.name); | |||||
| child->setAttribute ("identifier", d.identifier); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| if (defaultMidiOutputName.isNotEmpty()) | |||||
| lastExplicitSettings->setAttribute ("defaultMidiOutput", defaultMidiOutputName); | |||||
| if (defaultMidiOutputDeviceInfo != MidiDeviceInfo()) | |||||
| { | |||||
| lastExplicitSettings->setAttribute ("defaultMidiOutput", defaultMidiOutputDeviceInfo.name); | |||||
| lastExplicitSettings->setAttribute ("defaultMidiOutputDevice", defaultMidiOutputDeviceInfo.identifier); | |||||
| } | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -814,28 +874,23 @@ double AudioDeviceManager::getCpuUsage() const | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| void AudioDeviceManager::setMidiInputEnabled (const String& name, const bool enabled) | |||||
| void AudioDeviceManager::setMidiInputDeviceEnabled (const String& identifier, bool enabled) | |||||
| { | { | ||||
| if (enabled != isMidiInputEnabled (name)) | |||||
| if (enabled != isMidiInputDeviceEnabled (identifier)) | |||||
| { | { | ||||
| if (enabled) | if (enabled) | ||||
| { | { | ||||
| auto index = MidiInput::getDevices().indexOf (name); | |||||
| if (index >= 0) | |||||
| if (auto midiIn = MidiInput::openDevice (identifier, callbackHandler.get())) | |||||
| { | { | ||||
| if (auto* midiIn = MidiInput::openDevice (index, callbackHandler.get())) | |||||
| { | |||||
| enabledMidiInputs.add (midiIn); | |||||
| midiIn->start(); | |||||
| } | |||||
| enabledMidiInputs.push_back (std::move (midiIn)); | |||||
| enabledMidiInputs.back()->start(); | |||||
| } | } | ||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| for (int i = enabledMidiInputs.size(); --i >= 0;) | |||||
| if (enabledMidiInputs[i]->getName() == name) | |||||
| enabledMidiInputs.remove (i); | |||||
| auto removePredicate = [identifier] (const std::unique_ptr<MidiInput>& in) { return in->getIdentifier() == identifier; }; | |||||
| enabledMidiInputs.erase (std::remove_if (std::begin (enabledMidiInputs), std::end (enabledMidiInputs), removePredicate), | |||||
| std::end (enabledMidiInputs)); | |||||
| } | } | ||||
| updateXml(); | updateXml(); | ||||
| @@ -843,37 +898,33 @@ void AudioDeviceManager::setMidiInputEnabled (const String& name, const bool ena | |||||
| } | } | ||||
| } | } | ||||
| bool AudioDeviceManager::isMidiInputEnabled (const String& name) const | |||||
| bool AudioDeviceManager::isMidiInputDeviceEnabled (const String& identifier) const | |||||
| { | { | ||||
| for (auto* mi : enabledMidiInputs) | |||||
| if (mi->getName() == name) | |||||
| for (auto& mi : enabledMidiInputs) | |||||
| if (mi->getIdentifier() == identifier) | |||||
| return true; | return true; | ||||
| return false; | return false; | ||||
| } | } | ||||
| void AudioDeviceManager::addMidiInputCallback (const String& name, MidiInputCallback* callbackToAdd) | |||||
| void AudioDeviceManager::addMidiInputDeviceCallback (const String& identifier, MidiInputCallback* callbackToAdd) | |||||
| { | { | ||||
| removeMidiInputCallback (name, callbackToAdd); | |||||
| removeMidiInputDeviceCallback (identifier, callbackToAdd); | |||||
| if (name.isEmpty() || isMidiInputEnabled (name)) | |||||
| if (identifier.isEmpty() || isMidiInputDeviceEnabled (identifier)) | |||||
| { | { | ||||
| const ScopedLock sl (midiCallbackLock); | const ScopedLock sl (midiCallbackLock); | ||||
| MidiCallbackInfo mc; | |||||
| mc.deviceName = name; | |||||
| mc.callback = callbackToAdd; | |||||
| midiCallbacks.add (mc); | |||||
| midiCallbacks.add ({ identifier, callbackToAdd }); | |||||
| } | } | ||||
| } | } | ||||
| void AudioDeviceManager::removeMidiInputCallback (const String& name, MidiInputCallback* callbackToRemove) | |||||
| void AudioDeviceManager::removeMidiInputDeviceCallback (const String& identifier, MidiInputCallback* callbackToRemove) | |||||
| { | { | ||||
| for (int i = midiCallbacks.size(); --i >= 0;) | for (int i = midiCallbacks.size(); --i >= 0;) | ||||
| { | { | ||||
| auto& mc = midiCallbacks.getReference(i); | |||||
| auto& mc = midiCallbacks.getReference (i); | |||||
| if (mc.callback == callbackToRemove && mc.deviceName == name) | |||||
| if (mc.callback == callbackToRemove && mc.deviceIdentifier == identifier) | |||||
| { | { | ||||
| const ScopedLock sl (midiCallbackLock); | const ScopedLock sl (midiCallbackLock); | ||||
| midiCallbacks.remove (i); | midiCallbacks.remove (i); | ||||
| @@ -888,15 +939,15 @@ void AudioDeviceManager::handleIncomingMidiMessageInt (MidiInput* source, const | |||||
| const ScopedLock sl (midiCallbackLock); | const ScopedLock sl (midiCallbackLock); | ||||
| for (auto& mc : midiCallbacks) | for (auto& mc : midiCallbacks) | ||||
| if (mc.deviceName.isEmpty() || mc.deviceName == source->getName()) | |||||
| if (mc.deviceIdentifier.isEmpty() || mc.deviceIdentifier == source->getIdentifier()) | |||||
| mc.callback->handleIncomingMidiMessage (source, message); | mc.callback->handleIncomingMidiMessage (source, message); | ||||
| } | } | ||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| void AudioDeviceManager::setDefaultMidiOutput (const String& deviceName) | |||||
| void AudioDeviceManager::setDefaultMidiOutputDevice (const String& identifier) | |||||
| { | { | ||||
| if (defaultMidiOutputName != deviceName) | |||||
| if (defaultMidiOutputDeviceInfo.identifier != identifier) | |||||
| { | { | ||||
| Array<AudioIODeviceCallback*> oldCallbacks; | Array<AudioIODeviceCallback*> oldCallbacks; | ||||
| @@ -907,13 +958,17 @@ void AudioDeviceManager::setDefaultMidiOutput (const String& deviceName) | |||||
| if (currentAudioDevice != nullptr) | if (currentAudioDevice != nullptr) | ||||
| for (int i = oldCallbacks.size(); --i >= 0;) | for (int i = oldCallbacks.size(); --i >= 0;) | ||||
| oldCallbacks.getUnchecked(i)->audioDeviceStopped(); | |||||
| oldCallbacks.getUnchecked (i)->audioDeviceStopped(); | |||||
| defaultMidiOutput.reset(); | defaultMidiOutput.reset(); | ||||
| defaultMidiOutputName = deviceName; | |||||
| if (deviceName.isNotEmpty()) | |||||
| defaultMidiOutput.reset (MidiOutput::openDevice (MidiOutput::getDevices().indexOf (deviceName))); | |||||
| if (identifier.isNotEmpty()) | |||||
| defaultMidiOutput = MidiOutput::openDevice (identifier); | |||||
| if (defaultMidiOutput != nullptr) | |||||
| defaultMidiOutputDeviceInfo = defaultMidiOutput->getDeviceInfo(); | |||||
| else | |||||
| defaultMidiOutputDeviceInfo = {}; | |||||
| if (currentAudioDevice != nullptr) | if (currentAudioDevice != nullptr) | ||||
| for (auto* c : oldCallbacks) | for (auto* c : oldCallbacks) | ||||
| @@ -1018,4 +1073,63 @@ int AudioDeviceManager::getXRunCount() const noexcept | |||||
| return jmax (0, deviceXRuns) + loadMeasurer.getXRunCount(); | return jmax (0, deviceXRuns) + loadMeasurer.getXRunCount(); | ||||
| } | } | ||||
| //============================================================================== | |||||
| // Deprecated | |||||
| void AudioDeviceManager::setMidiInputEnabled (const String& name, const bool enabled) | |||||
| { | |||||
| for (auto& device : MidiInput::getAvailableDevices()) | |||||
| { | |||||
| if (device.name == name) | |||||
| { | |||||
| setMidiInputDeviceEnabled (device.identifier, enabled); | |||||
| return; | |||||
| } | |||||
| } | |||||
| } | |||||
| bool AudioDeviceManager::isMidiInputEnabled (const String& name) const | |||||
| { | |||||
| for (auto& device : MidiInput::getAvailableDevices()) | |||||
| if (device.name == name) | |||||
| return isMidiInputDeviceEnabled (device.identifier); | |||||
| return false; | |||||
| } | |||||
| void AudioDeviceManager::addMidiInputCallback (const String& name, MidiInputCallback* callbackToAdd) | |||||
| { | |||||
| for (auto& device : MidiInput::getAvailableDevices()) | |||||
| { | |||||
| if (device.name == name) | |||||
| { | |||||
| addMidiInputDeviceCallback (device.identifier, callbackToAdd); | |||||
| return; | |||||
| } | |||||
| } | |||||
| } | |||||
| void AudioDeviceManager::removeMidiInputCallback (const String& name, MidiInputCallback* callbackToRemove) | |||||
| { | |||||
| for (auto& device : MidiInput::getAvailableDevices()) | |||||
| { | |||||
| if (device.name == name) | |||||
| { | |||||
| removeMidiInputDeviceCallback (device.identifier, callbackToRemove); | |||||
| return; | |||||
| } | |||||
| } | |||||
| } | |||||
| void AudioDeviceManager::setDefaultMidiOutput (const String& name) | |||||
| { | |||||
| for (auto& device : MidiOutput::getAvailableDevices()) | |||||
| { | |||||
| if (device.name == name) | |||||
| { | |||||
| setDefaultMidiOutputDevice (device.identifier); | |||||
| return; | |||||
| } | |||||
| } | |||||
| } | |||||
| } // namespace juce | } // namespace juce | ||||
| @@ -307,12 +307,12 @@ public: | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Enables or disables a midi input device. | /** Enables or disables a midi input device. | ||||
| The list of devices can be obtained with the MidiInput::getDevices() method. | |||||
| The list of devices can be obtained with the MidiInput::getAvailableDevices() method. | |||||
| Any incoming messages from enabled input devices will be forwarded on to all the | Any incoming messages from enabled input devices will be forwarded on to all the | ||||
| listeners that have been registered with the addMidiInputCallback() method. They | |||||
| can either register for messages from a particular device, or from just the | |||||
| "default" midi input. | |||||
| listeners that have been registered with the addMidiInputDeviceCallback() method. They | |||||
| can either register for messages from a particular device, or from just the "default" | |||||
| midi input. | |||||
| Routing the midi input via an AudioDeviceManager means that when a listener | Routing the midi input via an AudioDeviceManager means that when a listener | ||||
| registers for the default midi input, this default device can be changed by the | registers for the default midi input, this default device can be changed by the | ||||
| @@ -322,62 +322,65 @@ public: | |||||
| or not present, so that when the input is re-enabled, the listener will start | or not present, so that when the input is re-enabled, the listener will start | ||||
| receiving messages again. | receiving messages again. | ||||
| @see addMidiInputCallback, isMidiInputEnabled | |||||
| @see addMidiInputDeviceCallback, isMidiInputDeviceEnabled | |||||
| */ | */ | ||||
| void setMidiInputEnabled (const String& midiInputDeviceName, bool enabled); | |||||
| void setMidiInputDeviceEnabled (const String& deviceIdentifier, bool enabled); | |||||
| /** Returns true if a given midi input device is being used. | /** Returns true if a given midi input device is being used. | ||||
| @see setMidiInputEnabled | |||||
| @see setMidiInputDeviceEnabled | |||||
| */ | */ | ||||
| bool isMidiInputEnabled (const String& midiInputDeviceName) const; | |||||
| bool isMidiInputDeviceEnabled (const String& deviceIdentifier) const; | |||||
| /** Registers a listener for callbacks when midi events arrive from a midi input. | /** Registers a listener for callbacks when midi events arrive from a midi input. | ||||
| The device name can be empty to indicate that it wants to receive all incoming | |||||
| events from all the enabled MIDI inputs. Or it can be the name of one of the | |||||
| The device identifier can be empty to indicate that it wants to receive all incoming | |||||
| events from all the enabled MIDI inputs. Or it can be the identifier of one of the | |||||
| MIDI input devices if it just wants the events from that device. (see | MIDI input devices if it just wants the events from that device. (see | ||||
| MidiInput::getDevices() for the list of device names). | |||||
| MidiInput::getAvailableDevices() for the list of devices). | |||||
| Only devices which are enabled (see the setMidiInputEnabled() method) will have their | |||||
| Only devices which are enabled (see the setMidiInputDeviceEnabled() method) will have their | |||||
| events forwarded on to listeners. | events forwarded on to listeners. | ||||
| */ | */ | ||||
| void addMidiInputCallback (const String& midiInputDeviceName, | |||||
| MidiInputCallback* callback); | |||||
| void addMidiInputDeviceCallback (const String& deviceIdentifier, | |||||
| MidiInputCallback* callback); | |||||
| /** Removes a listener that was previously registered with addMidiInputCallback(). */ | |||||
| void removeMidiInputCallback (const String& midiInputDeviceName, | |||||
| MidiInputCallback* callback); | |||||
| /** Removes a listener that was previously registered with addMidiInputDeviceCallback(). */ | |||||
| void removeMidiInputDeviceCallback (const String& deviceIdentifier, | |||||
| MidiInputCallback* callback); | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Sets a midi output device to use as the default. | /** Sets a midi output device to use as the default. | ||||
| The list of devices can be obtained with the MidiOutput::getDevices() method. | |||||
| The list of devices can be obtained with the MidiOutput::getAvailableDevices() method. | |||||
| The specified device will be opened automatically and can be retrieved with the | The specified device will be opened automatically and can be retrieved with the | ||||
| getDefaultMidiOutput() method. | getDefaultMidiOutput() method. | ||||
| Pass in an empty string to deselect all devices. For the default device, you | Pass in an empty string to deselect all devices. For the default device, you | ||||
| can use MidiOutput::getDevices() [MidiOutput::getDefaultDeviceIndex()]. | |||||
| can use MidiOutput::getDefaultDevice(). | |||||
| @see getDefaultMidiOutput, getDefaultMidiOutputName | |||||
| @see getDefaultMidiOutput, getDefaultMidiOutputIdentifier | |||||
| */ | */ | ||||
| void setDefaultMidiOutput (const String& deviceName); | |||||
| void setDefaultMidiOutputDevice (const String& deviceIdentifier); | |||||
| /** Returns the name of the default midi output. | /** Returns the name of the default midi output. | ||||
| @see setDefaultMidiOutput, getDefaultMidiOutput | |||||
| @see setDefaultMidiOutputDevice, getDefaultMidiOutput | |||||
| */ | */ | ||||
| const String& getDefaultMidiOutputName() const noexcept { return defaultMidiOutputName; } | |||||
| const String& getDefaultMidiOutputIdentifier() const noexcept { return defaultMidiOutputDeviceInfo.identifier; } | |||||
| /** Returns the current default midi output device. | |||||
| If no device has been selected, or the device can't be opened, this will return nullptr. | |||||
| @see getDefaultMidiOutputName | |||||
| /** Returns the current default midi output device. If no device has been selected, or the | |||||
| device can't be opened, this will return nullptr. | |||||
| @see getDefaultMidiOutputIdentifier | |||||
| */ | */ | ||||
| MidiOutput* getDefaultMidiOutput() const noexcept { return defaultMidiOutput.get(); } | MidiOutput* getDefaultMidiOutput() const noexcept { return defaultMidiOutput.get(); } | ||||
| //============================================================================== | |||||
| /** Returns a list of the types of device supported. */ | /** Returns a list of the types of device supported. */ | ||||
| const OwnedArray<AudioIODeviceType>& getAvailableDeviceTypes(); | const OwnedArray<AudioIODeviceType>& getAvailableDeviceTypes(); | ||||
| //============================================================================== | |||||
| /** Creates a list of available types. | /** Creates a list of available types. | ||||
| This will add a set of new AudioIODeviceType objects to the specified list, to | This will add a set of new AudioIODeviceType objects to the specified list, to | ||||
| @@ -461,6 +464,20 @@ public: | |||||
| */ | */ | ||||
| int getXRunCount() const noexcept; | int getXRunCount() const noexcept; | ||||
| //============================================================================== | |||||
| /** Deprecated. */ | |||||
| void setMidiInputEnabled (const String&, bool); | |||||
| /** Deprecated. */ | |||||
| bool isMidiInputEnabled (const String&) const; | |||||
| /** Deprecated. */ | |||||
| void addMidiInputCallback (const String&, MidiInputCallback*); | |||||
| /** Deprecated. */ | |||||
| void removeMidiInputCallback (const String&, MidiInputCallback*); | |||||
| /** Deprecated. */ | |||||
| void setDefaultMidiOutput (const String&); | |||||
| /** Deprecated. */ | |||||
| const String& getDefaultMidiOutputName() const noexcept { return defaultMidiOutputDeviceInfo.name; } | |||||
| private: | private: | ||||
| //============================================================================== | //============================================================================== | ||||
| OwnedArray<AudioIODeviceType> availableDeviceTypes; | OwnedArray<AudioIODeviceType> availableDeviceTypes; | ||||
| @@ -477,15 +494,15 @@ private: | |||||
| struct MidiCallbackInfo | struct MidiCallbackInfo | ||||
| { | { | ||||
| String deviceName; | |||||
| String deviceIdentifier; | |||||
| MidiInputCallback* callback; | MidiInputCallback* callback; | ||||
| }; | }; | ||||
| StringArray midiInsFromXml; | |||||
| OwnedArray<MidiInput> enabledMidiInputs; | |||||
| Array<MidiDeviceInfo> midiDeviceInfosFromXml; | |||||
| std::vector<std::unique_ptr<MidiInput>> enabledMidiInputs; | |||||
| Array<MidiCallbackInfo> midiCallbacks; | Array<MidiCallbackInfo> midiCallbacks; | ||||
| String defaultMidiOutputName; | |||||
| MidiDeviceInfo defaultMidiOutputDeviceInfo; | |||||
| std::unique_ptr<MidiOutput> defaultMidiOutput; | std::unique_ptr<MidiOutput> defaultMidiOutput; | ||||
| CriticalSection audioCallbackLock, midiCallbackLock; | CriticalSection audioCallbackLock, midiCallbackLock; | ||||
| @@ -411,7 +411,7 @@ public: | |||||
| bool autoOpenMidiDevices; | bool autoOpenMidiDevices; | ||||
| std::unique_ptr<AudioDeviceManager::AudioDeviceSetup> options; | std::unique_ptr<AudioDeviceManager::AudioDeviceSetup> options; | ||||
| StringArray lastMidiDevices; | |||||
| Array<MidiDeviceInfo> lastMidiDevices; | |||||
| private: | private: | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -526,7 +526,7 @@ private: | |||||
| const AudioDeviceManager::AudioDeviceSetup* preferredSetupOptions) | const AudioDeviceManager::AudioDeviceSetup* preferredSetupOptions) | ||||
| { | { | ||||
| deviceManager.addAudioCallback (this); | deviceManager.addAudioCallback (this); | ||||
| deviceManager.addMidiInputCallback ({}, &player); | |||||
| deviceManager.addMidiInputDeviceCallback ({}, &player); | |||||
| reloadAudioDeviceState (enableAudioInput, preferredDefaultDeviceName, preferredSetupOptions); | reloadAudioDeviceState (enableAudioInput, preferredDefaultDeviceName, preferredSetupOptions); | ||||
| } | } | ||||
| @@ -535,23 +535,25 @@ private: | |||||
| { | { | ||||
| saveAudioDeviceState(); | saveAudioDeviceState(); | ||||
| deviceManager.removeMidiInputCallback ({}, &player); | |||||
| deviceManager.removeMidiInputDeviceCallback ({}, &player); | |||||
| deviceManager.removeAudioCallback (this); | deviceManager.removeAudioCallback (this); | ||||
| } | } | ||||
| void timerCallback() override | void timerCallback() override | ||||
| { | { | ||||
| auto newMidiDevices = MidiInput::getDevices(); | |||||
| auto newMidiDevices = MidiInput::getAvailableDevices(); | |||||
| if (newMidiDevices != lastMidiDevices) | if (newMidiDevices != lastMidiDevices) | ||||
| { | { | ||||
| for (auto& oldDevice : lastMidiDevices) | for (auto& oldDevice : lastMidiDevices) | ||||
| if (! newMidiDevices.contains (oldDevice)) | if (! newMidiDevices.contains (oldDevice)) | ||||
| deviceManager.setMidiInputEnabled (oldDevice, false); | |||||
| deviceManager.setMidiInputDeviceEnabled (oldDevice.identifier, false); | |||||
| for (auto& newDevice : newMidiDevices) | for (auto& newDevice : newMidiDevices) | ||||
| if (! lastMidiDevices.contains (newDevice)) | if (! lastMidiDevices.contains (newDevice)) | ||||
| deviceManager.setMidiInputEnabled (newDevice, true); | |||||
| deviceManager.setMidiInputDeviceEnabled (newDevice.identifier, true); | |||||
| lastMidiDevices = newMidiDevices; | |||||
| } | } | ||||
| } | } | ||||
| @@ -90,7 +90,7 @@ public: | |||||
| void updateDevices() | void updateDevices() | ||||
| { | { | ||||
| items = MidiInput::getDevices(); | |||||
| items = MidiInput::getAvailableDevices(); | |||||
| } | } | ||||
| int getNumRows() override | int getNumRows() override | ||||
| @@ -107,7 +107,7 @@ public: | |||||
| .withMultipliedAlpha (0.3f)); | .withMultipliedAlpha (0.3f)); | ||||
| auto item = items[row]; | auto item = items[row]; | ||||
| bool enabled = deviceManager.isMidiInputEnabled (item); | |||||
| bool enabled = deviceManager.isMidiInputDeviceEnabled (item.identifier); | |||||
| auto x = getTickX(); | auto x = getTickX(); | ||||
| auto tickW = height * 0.75f; | auto tickW = height * 0.75f; | ||||
| @@ -117,7 +117,7 @@ public: | |||||
| g.setFont (height * 0.6f); | g.setFont (height * 0.6f); | ||||
| g.setColour (findColour (ListBox::textColourId, true).withMultipliedAlpha (enabled ? 1.0f : 0.6f)); | g.setColour (findColour (ListBox::textColourId, true).withMultipliedAlpha (enabled ? 1.0f : 0.6f)); | ||||
| g.drawText (item, x + 5, 0, width - x - 5, height, Justification::centredLeft, true); | |||||
| g.drawText (item.name, x + 5, 0, width - x - 5, height, Justification::centredLeft, true); | |||||
| } | } | ||||
| } | } | ||||
| @@ -166,14 +166,14 @@ private: | |||||
| //============================================================================== | //============================================================================== | ||||
| AudioDeviceManager& deviceManager; | AudioDeviceManager& deviceManager; | ||||
| const String noItemsMessage; | const String noItemsMessage; | ||||
| StringArray items; | |||||
| Array<MidiDeviceInfo> items; | |||||
| void flipEnablement (const int row) | void flipEnablement (const int row) | ||||
| { | { | ||||
| if (isPositiveAndBelow (row, items.size())) | if (isPositiveAndBelow (row, items.size())) | ||||
| { | { | ||||
| auto item = items[row]; | |||||
| deviceManager.setMidiInputEnabled (item, ! deviceManager.isMidiInputEnabled (item)); | |||||
| auto identifier = items[row].identifier; | |||||
| deviceManager.setMidiInputDeviceEnabled (identifier, ! deviceManager.isMidiInputDeviceEnabled (identifier)); | |||||
| } | } | ||||
| } | } | ||||
| @@ -1115,12 +1115,12 @@ void AudioDeviceSelectorComponent::updateDeviceType() | |||||
| void AudioDeviceSelectorComponent::updateMidiOutput() | void AudioDeviceSelectorComponent::updateMidiOutput() | ||||
| { | { | ||||
| auto midiDeviceName = midiOutputSelector->getText(); | |||||
| if (midiDeviceName == getNoDeviceString()) | |||||
| midiDeviceName = {}; | |||||
| auto selectedId = midiOutputSelector->getSelectedId(); | |||||
| deviceManager.setDefaultMidiOutput (midiDeviceName); | |||||
| if (selectedId == -1) | |||||
| deviceManager.setDefaultMidiOutputDevice ({}); | |||||
| else | |||||
| deviceManager.setDefaultMidiOutputDevice (currentMidiOutputs[selectedId - 1].identifier); | |||||
| } | } | ||||
| void AudioDeviceSelectorComponent::changeListenerCallback (ChangeBroadcaster*) | void AudioDeviceSelectorComponent::changeListenerCallback (ChangeBroadcaster*) | ||||
| @@ -1168,20 +1168,23 @@ void AudioDeviceSelectorComponent::updateAllControls() | |||||
| { | { | ||||
| midiOutputSelector->clear(); | midiOutputSelector->clear(); | ||||
| auto midiOuts = MidiOutput::getDevices(); | |||||
| currentMidiOutputs = MidiOutput::getAvailableDevices(); | |||||
| midiOutputSelector->addItem (getNoDeviceString(), -1); | midiOutputSelector->addItem (getNoDeviceString(), -1); | ||||
| midiOutputSelector->addSeparator(); | midiOutputSelector->addSeparator(); | ||||
| for (int i = 0; i < midiOuts.size(); ++i) | |||||
| midiOutputSelector->addItem (midiOuts[i], i + 1); | |||||
| auto defaultOutputIdentifier = deviceManager.getDefaultMidiOutputIdentifier(); | |||||
| int i = 0; | |||||
| int current = -1; | |||||
| for (auto& out : currentMidiOutputs) | |||||
| { | |||||
| midiOutputSelector->addItem (out.name, i + 1); | |||||
| if (deviceManager.getDefaultMidiOutput() != nullptr) | |||||
| current = 1 + midiOuts.indexOf (deviceManager.getDefaultMidiOutputName()); | |||||
| if (defaultOutputIdentifier.isNotEmpty() && out.identifier == defaultOutputIdentifier) | |||||
| midiOutputSelector->setSelectedId (i + 1); | |||||
| midiOutputSelector->setSelectedId (current, dontSendNotification); | |||||
| ++i; | |||||
| } | |||||
| } | } | ||||
| resized(); | resized(); | ||||
| @@ -111,6 +111,7 @@ private: | |||||
| const bool hideAdvancedOptionsWithButton; | const bool hideAdvancedOptionsWithButton; | ||||
| class MidiInputSelectorComponentListBox; | class MidiInputSelectorComponentListBox; | ||||
| Array<MidiDeviceInfo> currentMidiOutputs; | |||||
| std::unique_ptr<MidiInputSelectorComponentListBox> midiInputsList; | std::unique_ptr<MidiInputSelectorComponentListBox> midiInputsList; | ||||
| std::unique_ptr<ComboBox> midiOutputSelector; | std::unique_ptr<ComboBox> midiOutputSelector; | ||||
| std::unique_ptr<Label> midiInputsLabel, midiOutputLabel; | std::unique_ptr<Label> midiInputsLabel, midiOutputLabel; | ||||