| @@ -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); | |||
| } | |||
| @@ -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); | |||
| } | |||
| @@ -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<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; | |||
| } | |||
| @@ -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<MidiInput>& 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<AudioIODeviceCallback*> 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 | |||
| @@ -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<AudioIODeviceType>& 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<AudioIODeviceType> availableDeviceTypes; | |||
| @@ -477,15 +494,15 @@ private: | |||
| struct MidiCallbackInfo | |||
| { | |||
| String deviceName; | |||
| String deviceIdentifier; | |||
| MidiInputCallback* callback; | |||
| }; | |||
| StringArray midiInsFromXml; | |||
| OwnedArray<MidiInput> enabledMidiInputs; | |||
| Array<MidiDeviceInfo> midiDeviceInfosFromXml; | |||
| std::vector<std::unique_ptr<MidiInput>> enabledMidiInputs; | |||
| Array<MidiCallbackInfo> midiCallbacks; | |||
| String defaultMidiOutputName; | |||
| MidiDeviceInfo defaultMidiOutputDeviceInfo; | |||
| std::unique_ptr<MidiOutput> defaultMidiOutput; | |||
| CriticalSection audioCallbackLock, midiCallbackLock; | |||
| @@ -411,7 +411,7 @@ public: | |||
| bool autoOpenMidiDevices; | |||
| std::unique_ptr<AudioDeviceManager::AudioDeviceSetup> options; | |||
| StringArray lastMidiDevices; | |||
| Array<MidiDeviceInfo> 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; | |||
| } | |||
| } | |||
| @@ -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<MidiDeviceInfo> 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(); | |||
| @@ -111,6 +111,7 @@ private: | |||
| const bool hideAdvancedOptionsWithButton; | |||
| class MidiInputSelectorComponentListBox; | |||
| Array<MidiDeviceInfo> currentMidiOutputs; | |||
| std::unique_ptr<MidiInputSelectorComponentListBox> midiInputsList; | |||
| std::unique_ptr<ComboBox> midiOutputSelector; | |||
| std::unique_ptr<Label> midiInputsLabel, midiOutputLabel; | |||