mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Added identifier-based MIDI input/output methods to AudioDeviceManager and deprecated the old name-based methods
This commit is contained in:
parent
f0ea1c00a6
commit
e26529d5e9
7 changed files with 250 additions and 113 deletions
|
|
@ -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") });
|
||||
|
||||
for (auto& m : MidiInput::getDevices())
|
||||
setMidiInputEnabled (m, midiInsFromXml.contains (m));
|
||||
auto isIdentifierAvailable = [] (const Array<MidiDeviceInfo>& available, const String& identifier)
|
||||
{
|
||||
for (auto& device : available)
|
||||
if (device.identifier == identifier)
|
||||
return true;
|
||||
|
||||
if (error.isNotEmpty() && selectDefaultDeviceOnFailure)
|
||||
error = initialise (numInputChansNeeded, numOutputChansNeeded,
|
||||
nullptr, false, preferredDefaultDeviceName);
|
||||
return false;
|
||||
};
|
||||
|
||||
setDefaultMidiOutput (xml.getStringAttribute ("defaultMidiOutput"));
|
||||
auto getUpdatedIdentifierForName = [&] (const Array<MidiDeviceInfo>& available, const String& name) -> String
|
||||
{
|
||||
for (auto& device : available)
|
||||
if (device.name == name)
|
||||
return device.identifier;
|
||||
|
||||
return {};
|
||||
};
|
||||
|
||||
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 (int i = 0; i < midiInsFromXml.size(); ++i)
|
||||
if (! availableMidiDevices.contains (midiInsFromXml[i], true))
|
||||
lastExplicitSettings->createNewChildElement ("MIDIINPUT")
|
||||
->setAttribute ("name", midiInsFromXml[i]);
|
||||
for (auto& d : midiDeviceInfosFromXml)
|
||||
{
|
||||
if (! availableMidiDevices.contains (d))
|
||||
{
|
||||
auto* child = lastExplicitSettings->createNewChildElement ("MIDIINPUT");
|
||||
|
||||
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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue