From e26529d5e9dc55f72ce70759d4bbfd41ddef4300 Mon Sep 17 00:00:00 2001 From: ed Date: Wed, 22 May 2019 15:45:15 +0100 Subject: [PATCH] Added identifier-based MIDI input/output methods to AudioDeviceManager and deprecated the old name-based methods --- examples/Audio/AudioSynthesiserDemo.h | 4 +- examples/Audio/MPEDemo.h | 4 +- .../audio_io/juce_AudioDeviceManager.cpp | 220 +++++++++++++----- .../audio_io/juce_AudioDeviceManager.h | 79 ++++--- .../Standalone/juce_StandaloneFilterWindow.h | 14 +- .../gui/juce_AudioDeviceSelectorComponent.cpp | 39 ++-- .../gui/juce_AudioDeviceSelectorComponent.h | 1 + 7 files changed, 249 insertions(+), 112 deletions(-) diff --git a/examples/Audio/AudioSynthesiserDemo.h b/examples/Audio/AudioSynthesiserDemo.h index 58bb4513a7..a646adc2db 100644 --- a/examples/Audio/AudioSynthesiserDemo.h +++ b/examples/Audio/AudioSynthesiserDemo.h @@ -270,7 +270,7 @@ public: #endif audioDeviceManager.addAudioCallback (&audioSourcePlayer); - audioDeviceManager.addMidiInputCallback ({}, &(synthAudioSource.midiCollector)); + audioDeviceManager.addMidiInputDeviceCallback ({}, &(synthAudioSource.midiCollector)); setOpaque (true); setSize (640, 480); @@ -279,7 +279,7 @@ public: ~AudioSynthesiserDemo() { audioSourcePlayer.setSource (nullptr); - audioDeviceManager.removeMidiInputCallback ({}, &(synthAudioSource.midiCollector)); + audioDeviceManager.removeMidiInputDeviceCallback ({}, &(synthAudioSource.midiCollector)); audioDeviceManager.removeAudioCallback (&audioSourcePlayer); audioDeviceManager.removeAudioCallback (&liveAudioDisplayComp); } diff --git a/examples/Audio/MPEDemo.h b/examples/Audio/MPEDemo.h index eede466d1a..f7e445bf96 100644 --- a/examples/Audio/MPEDemo.h +++ b/examples/Audio/MPEDemo.h @@ -879,7 +879,7 @@ public: audioDeviceManager.initialise (0, 2, 0, true, {}, 0); #endif - audioDeviceManager.addMidiInputCallback ({}, this); + audioDeviceManager.addMidiInputDeviceCallback ({}, this); audioDeviceManager.addAudioCallback (this); addAndMakeVisible (audioSetupComp); @@ -904,7 +904,7 @@ public: ~MPEDemo() { - audioDeviceManager.removeMidiInputCallback ({}, this); + audioDeviceManager.removeMidiInputDeviceCallback ({}, this); audioDeviceManager.removeAudioCallback (this); } diff --git a/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp b/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp index a6fd50ee0d..70d096218c 100644 --- a/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp +++ b/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp @@ -304,19 +304,66 @@ String AudioDeviceManager::initialiseFromXML (const XmlElement& xml, 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") - midiInsFromXml.add (c->getStringAttribute ("name")); + midiDeviceInfosFromXml.add ({ c->getStringAttribute ("name"), c->getStringAttribute ("identifier") }); + + auto isIdentifierAvailable = [] (const Array& 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& 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; } @@ -660,24 +707,37 @@ void AudioDeviceManager::updateXml() 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 // 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) { - 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 { - for (int i = enabledMidiInputs.size(); --i >= 0;) - if (enabledMidiInputs[i]->getName() == name) - enabledMidiInputs.remove (i); + auto removePredicate = [identifier] (const std::unique_ptr& in) { return in->getIdentifier() == identifier; }; + enabledMidiInputs.erase (std::remove_if (std::begin (enabledMidiInputs), std::end (enabledMidiInputs), removePredicate), + std::end (enabledMidiInputs)); } 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 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); - - 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;) { - 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); midiCallbacks.remove (i); @@ -888,15 +939,15 @@ void AudioDeviceManager::handleIncomingMidiMessageInt (MidiInput* source, const const ScopedLock sl (midiCallbackLock); 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); } } //============================================================================== -void AudioDeviceManager::setDefaultMidiOutput (const String& deviceName) +void AudioDeviceManager::setDefaultMidiOutputDevice (const String& identifier) { - if (defaultMidiOutputName != deviceName) + if (defaultMidiOutputDeviceInfo.identifier != identifier) { Array oldCallbacks; @@ -907,13 +958,17 @@ void AudioDeviceManager::setDefaultMidiOutput (const String& deviceName) if (currentAudioDevice != nullptr) for (int i = oldCallbacks.size(); --i >= 0;) - oldCallbacks.getUnchecked(i)->audioDeviceStopped(); + oldCallbacks.getUnchecked (i)->audioDeviceStopped(); 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) for (auto* c : oldCallbacks) @@ -1018,4 +1073,63 @@ int AudioDeviceManager::getXRunCount() const noexcept 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 diff --git a/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h b/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h index a253228167..83b49c1e51 100644 --- a/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h +++ b/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h @@ -307,12 +307,12 @@ public: //============================================================================== /** 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 - 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 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 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. - @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. - 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 - 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. */ - 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. - 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 getDefaultMidiOutput() method. 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. - @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(); } + //============================================================================== /** Returns a list of the types of device supported. */ const OwnedArray& getAvailableDeviceTypes(); - //============================================================================== /** Creates a list of available types. This will add a set of new AudioIODeviceType objects to the specified list, to @@ -461,6 +464,20 @@ public: */ 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: //============================================================================== OwnedArray availableDeviceTypes; @@ -477,15 +494,15 @@ private: struct MidiCallbackInfo { - String deviceName; + String deviceIdentifier; MidiInputCallback* callback; }; - StringArray midiInsFromXml; - OwnedArray enabledMidiInputs; + Array midiDeviceInfosFromXml; + std::vector> enabledMidiInputs; Array midiCallbacks; - String defaultMidiOutputName; + MidiDeviceInfo defaultMidiOutputDeviceInfo; std::unique_ptr defaultMidiOutput; CriticalSection audioCallbackLock, midiCallbackLock; diff --git a/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h b/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h index f92ea84115..a0c22651c7 100644 --- a/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h +++ b/modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h @@ -411,7 +411,7 @@ public: bool autoOpenMidiDevices; std::unique_ptr options; - StringArray lastMidiDevices; + Array lastMidiDevices; private: //============================================================================== @@ -526,7 +526,7 @@ private: const AudioDeviceManager::AudioDeviceSetup* preferredSetupOptions) { deviceManager.addAudioCallback (this); - deviceManager.addMidiInputCallback ({}, &player); + deviceManager.addMidiInputDeviceCallback ({}, &player); reloadAudioDeviceState (enableAudioInput, preferredDefaultDeviceName, preferredSetupOptions); } @@ -535,23 +535,25 @@ private: { saveAudioDeviceState(); - deviceManager.removeMidiInputCallback ({}, &player); + deviceManager.removeMidiInputDeviceCallback ({}, &player); deviceManager.removeAudioCallback (this); } void timerCallback() override { - auto newMidiDevices = MidiInput::getDevices(); + auto newMidiDevices = MidiInput::getAvailableDevices(); if (newMidiDevices != lastMidiDevices) { for (auto& oldDevice : lastMidiDevices) if (! newMidiDevices.contains (oldDevice)) - deviceManager.setMidiInputEnabled (oldDevice, false); + deviceManager.setMidiInputDeviceEnabled (oldDevice.identifier, false); for (auto& newDevice : newMidiDevices) if (! lastMidiDevices.contains (newDevice)) - deviceManager.setMidiInputEnabled (newDevice, true); + deviceManager.setMidiInputDeviceEnabled (newDevice.identifier, true); + + lastMidiDevices = newMidiDevices; } } diff --git a/modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.cpp b/modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.cpp index 920330474f..9dfc3df28c 100644 --- a/modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.cpp +++ b/modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.cpp @@ -90,7 +90,7 @@ public: void updateDevices() { - items = MidiInput::getDevices(); + items = MidiInput::getAvailableDevices(); } int getNumRows() override @@ -107,7 +107,7 @@ public: .withMultipliedAlpha (0.3f)); auto item = items[row]; - bool enabled = deviceManager.isMidiInputEnabled (item); + bool enabled = deviceManager.isMidiInputDeviceEnabled (item.identifier); auto x = getTickX(); auto tickW = height * 0.75f; @@ -117,7 +117,7 @@ public: g.setFont (height * 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; const String noItemsMessage; - StringArray items; + Array items; void flipEnablement (const int row) { 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() { - 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*) @@ -1168,20 +1168,23 @@ void AudioDeviceSelectorComponent::updateAllControls() { midiOutputSelector->clear(); - auto midiOuts = MidiOutput::getDevices(); + currentMidiOutputs = MidiOutput::getAvailableDevices(); midiOutputSelector->addItem (getNoDeviceString(), -1); 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(); diff --git a/modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.h b/modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.h index 25ff141107..b323bbadae 100644 --- a/modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.h +++ b/modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.h @@ -111,6 +111,7 @@ private: const bool hideAdvancedOptionsWithButton; class MidiInputSelectorComponentListBox; + Array currentMidiOutputs; std::unique_ptr midiInputsList; std::unique_ptr midiOutputSelector; std::unique_ptr