1
0
Fork 0
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:
ed 2019-05-22 15:45:15 +01:00
parent f0ea1c00a6
commit e26529d5e9
7 changed files with 250 additions and 113 deletions

View file

@ -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