|
|
|
@@ -114,7 +114,7 @@ void AudioDeviceManager::createDeviceTypesIfNeeded() |
|
|
|
{
|
|
|
|
if (availableDeviceTypes.size() == 0)
|
|
|
|
{
|
|
|
|
OwnedArray <AudioIODeviceType> types;
|
|
|
|
OwnedArray<AudioIODeviceType> types;
|
|
|
|
createAudioDeviceTypes (types);
|
|
|
|
|
|
|
|
for (int i = 0; i < types.size(); ++i)
|
|
|
|
@@ -127,7 +127,7 @@ void AudioDeviceManager::createDeviceTypesIfNeeded() |
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const OwnedArray <AudioIODeviceType>& AudioDeviceManager::getAvailableDeviceTypes()
|
|
|
|
const OwnedArray<AudioIODeviceType>& AudioDeviceManager::getAvailableDeviceTypes()
|
|
|
|
{
|
|
|
|
scanDevicesIfNeeded();
|
|
|
|
return availableDeviceTypes;
|
|
|
|
@@ -147,13 +147,13 @@ void AudioDeviceManager::audioDeviceListChanged() |
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
static void addIfNotNull (OwnedArray <AudioIODeviceType>& list, AudioIODeviceType* const device)
|
|
|
|
static void addIfNotNull (OwnedArray<AudioIODeviceType>& list, AudioIODeviceType* const device)
|
|
|
|
{
|
|
|
|
if (device != nullptr)
|
|
|
|
list.add (device);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AudioDeviceManager::createAudioDeviceTypes (OwnedArray <AudioIODeviceType>& list)
|
|
|
|
void AudioDeviceManager::createAudioDeviceTypes (OwnedArray<AudioIODeviceType>& list)
|
|
|
|
{
|
|
|
|
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_WASAPI());
|
|
|
|
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_DirectSound());
|
|
|
|
@@ -181,7 +181,7 @@ void AudioDeviceManager::addAudioDeviceType (AudioIODeviceType* newDeviceType) |
|
|
|
//==============================================================================
|
|
|
|
String AudioDeviceManager::initialise (const int numInputChannelsNeeded,
|
|
|
|
const int numOutputChannelsNeeded,
|
|
|
|
const XmlElement* const e,
|
|
|
|
const XmlElement* const xml,
|
|
|
|
const bool selectDefaultDeviceOnFailure,
|
|
|
|
const String& preferredDefaultDeviceName,
|
|
|
|
const AudioDeviceSetup* preferredSetupOptions)
|
|
|
|
@@ -191,106 +191,127 @@ String AudioDeviceManager::initialise (const int numInputChannelsNeeded, |
|
|
|
numInputChansNeeded = numInputChannelsNeeded;
|
|
|
|
numOutputChansNeeded = numOutputChannelsNeeded;
|
|
|
|
|
|
|
|
if (e != nullptr && e->hasTagName ("DEVICESETUP"))
|
|
|
|
{
|
|
|
|
lastExplicitSettings = new XmlElement (*e);
|
|
|
|
if (xml != nullptr && xml->hasTagName ("DEVICESETUP"))
|
|
|
|
return initialiseFromXML (*xml, selectDefaultDeviceOnFailure,
|
|
|
|
preferredDefaultDeviceName, preferredSetupOptions);
|
|
|
|
|
|
|
|
String error;
|
|
|
|
AudioDeviceSetup setup;
|
|
|
|
return initialiseDefault (preferredDefaultDeviceName, preferredSetupOptions);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (preferredSetupOptions != nullptr)
|
|
|
|
setup = *preferredSetupOptions;
|
|
|
|
String AudioDeviceManager::initialiseDefault (const String& preferredDefaultDeviceName,
|
|
|
|
const AudioDeviceSetup* preferredSetupOptions)
|
|
|
|
{
|
|
|
|
AudioDeviceSetup setup;
|
|
|
|
|
|
|
|
if (e->getStringAttribute ("audioDeviceName").isNotEmpty())
|
|
|
|
{
|
|
|
|
setup.inputDeviceName = setup.outputDeviceName
|
|
|
|
= e->getStringAttribute ("audioDeviceName");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (preferredSetupOptions != nullptr)
|
|
|
|
{
|
|
|
|
setup = *preferredSetupOptions;
|
|
|
|
}
|
|
|
|
else if (preferredDefaultDeviceName.isNotEmpty())
|
|
|
|
{
|
|
|
|
for (int j = availableDeviceTypes.size(); --j >= 0;)
|
|
|
|
{
|
|
|
|
setup.inputDeviceName = e->getStringAttribute ("audioInputDeviceName");
|
|
|
|
setup.outputDeviceName = e->getStringAttribute ("audioOutputDeviceName");
|
|
|
|
}
|
|
|
|
AudioIODeviceType* const type = availableDeviceTypes.getUnchecked(j);
|
|
|
|
|
|
|
|
currentDeviceType = e->getStringAttribute ("deviceType");
|
|
|
|
const StringArray outs (type->getDeviceNames (false));
|
|
|
|
|
|
|
|
if (findType (currentDeviceType) == nullptr)
|
|
|
|
{
|
|
|
|
if (AudioIODeviceType* const type = findType (setup.inputDeviceName, setup.outputDeviceName))
|
|
|
|
currentDeviceType = type->getTypeName();
|
|
|
|
else if (availableDeviceTypes.size() > 0)
|
|
|
|
currentDeviceType = availableDeviceTypes.getUnchecked(0)->getTypeName();
|
|
|
|
for (int i = 0; i < outs.size(); ++i)
|
|
|
|
{
|
|
|
|
if (outs[i].matchesWildcard (preferredDefaultDeviceName, true))
|
|
|
|
{
|
|
|
|
setup.outputDeviceName = outs[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const StringArray ins (type->getDeviceNames (true));
|
|
|
|
|
|
|
|
for (int i = 0; i < ins.size(); ++i)
|
|
|
|
{
|
|
|
|
if (ins[i].matchesWildcard (preferredDefaultDeviceName, true))
|
|
|
|
{
|
|
|
|
setup.inputDeviceName = ins[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
setup.bufferSize = e->getIntAttribute ("audioDeviceBufferSize");
|
|
|
|
setup.sampleRate = e->getDoubleAttribute ("audioDeviceRate");
|
|
|
|
insertDefaultDeviceNames (setup);
|
|
|
|
return setAudioDeviceSetup (setup, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
setup.inputChannels .parseString (e->getStringAttribute ("audioDeviceInChans", "11"), 2);
|
|
|
|
setup.outputChannels.parseString (e->getStringAttribute ("audioDeviceOutChans", "11"), 2);
|
|
|
|
String AudioDeviceManager::initialiseFromXML (const XmlElement& xml,
|
|
|
|
const bool selectDefaultDeviceOnFailure,
|
|
|
|
const String& preferredDefaultDeviceName,
|
|
|
|
const AudioDeviceSetup* preferredSetupOptions)
|
|
|
|
{
|
|
|
|
lastExplicitSettings = new XmlElement (xml);
|
|
|
|
|
|
|
|
setup.useDefaultInputChannels = ! e->hasAttribute ("audioDeviceInChans");
|
|
|
|
setup.useDefaultOutputChannels = ! e->hasAttribute ("audioDeviceOutChans");
|
|
|
|
String error;
|
|
|
|
AudioDeviceSetup setup;
|
|
|
|
|
|
|
|
error = setAudioDeviceSetup (setup, true);
|
|
|
|
if (preferredSetupOptions != nullptr)
|
|
|
|
setup = *preferredSetupOptions;
|
|
|
|
|
|
|
|
midiInsFromXml.clear();
|
|
|
|
forEachXmlChildElementWithTagName (*e, c, "MIDIINPUT")
|
|
|
|
midiInsFromXml.add (c->getStringAttribute ("name"));
|
|
|
|
if (xml.getStringAttribute ("audioDeviceName").isNotEmpty())
|
|
|
|
{
|
|
|
|
setup.inputDeviceName = setup.outputDeviceName
|
|
|
|
= xml.getStringAttribute ("audioDeviceName");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
setup.inputDeviceName = xml.getStringAttribute ("audioInputDeviceName");
|
|
|
|
setup.outputDeviceName = xml.getStringAttribute ("audioOutputDeviceName");
|
|
|
|
}
|
|
|
|
|
|
|
|
const StringArray allMidiIns (MidiInput::getDevices());
|
|
|
|
currentDeviceType = xml.getStringAttribute ("deviceType");
|
|
|
|
|
|
|
|
for (int i = allMidiIns.size(); --i >= 0;)
|
|
|
|
setMidiInputEnabled (allMidiIns[i], midiInsFromXml.contains (allMidiIns[i]));
|
|
|
|
if (findType (currentDeviceType) == nullptr)
|
|
|
|
{
|
|
|
|
if (AudioIODeviceType* const type = findType (setup.inputDeviceName, setup.outputDeviceName))
|
|
|
|
currentDeviceType = type->getTypeName();
|
|
|
|
else if (availableDeviceTypes.size() > 0)
|
|
|
|
currentDeviceType = availableDeviceTypes.getUnchecked(0)->getTypeName();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (error.isNotEmpty() && selectDefaultDeviceOnFailure)
|
|
|
|
error = initialise (numInputChannelsNeeded, numOutputChannelsNeeded, 0,
|
|
|
|
false, preferredDefaultDeviceName);
|
|
|
|
setup.bufferSize = xml.getIntAttribute ("audioDeviceBufferSize");
|
|
|
|
setup.sampleRate = xml.getDoubleAttribute ("audioDeviceRate");
|
|
|
|
|
|
|
|
setDefaultMidiOutput (e->getStringAttribute ("defaultMidiOutput"));
|
|
|
|
setup.inputChannels .parseString (xml.getStringAttribute ("audioDeviceInChans", "11"), 2);
|
|
|
|
setup.outputChannels.parseString (xml.getStringAttribute ("audioDeviceOutChans", "11"), 2);
|
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
AudioDeviceSetup setup;
|
|
|
|
setup.useDefaultInputChannels = ! xml.hasAttribute ("audioDeviceInChans");
|
|
|
|
setup.useDefaultOutputChannels = ! xml.hasAttribute ("audioDeviceOutChans");
|
|
|
|
|
|
|
|
if (preferredSetupOptions != nullptr)
|
|
|
|
{
|
|
|
|
setup = *preferredSetupOptions;
|
|
|
|
}
|
|
|
|
else if (preferredDefaultDeviceName.isNotEmpty())
|
|
|
|
{
|
|
|
|
for (int j = availableDeviceTypes.size(); --j >= 0;)
|
|
|
|
{
|
|
|
|
AudioIODeviceType* const type = availableDeviceTypes.getUnchecked(j);
|
|
|
|
error = setAudioDeviceSetup (setup, true);
|
|
|
|
|
|
|
|
const StringArray outs (type->getDeviceNames (false));
|
|
|
|
midiInsFromXml.clear();
|
|
|
|
|
|
|
|
for (int i = 0; i < outs.size(); ++i)
|
|
|
|
{
|
|
|
|
if (outs[i].matchesWildcard (preferredDefaultDeviceName, true))
|
|
|
|
{
|
|
|
|
setup.outputDeviceName = outs[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
forEachXmlChildElementWithTagName (xml, c, "MIDIINPUT")
|
|
|
|
midiInsFromXml.add (c->getStringAttribute ("name"));
|
|
|
|
|
|
|
|
const StringArray ins (type->getDeviceNames (true));
|
|
|
|
const StringArray allMidiIns (MidiInput::getDevices());
|
|
|
|
|
|
|
|
for (int i = 0; i < ins.size(); ++i)
|
|
|
|
{
|
|
|
|
if (ins[i].matchesWildcard (preferredDefaultDeviceName, true))
|
|
|
|
{
|
|
|
|
setup.inputDeviceName = ins[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int i = allMidiIns.size(); --i >= 0;)
|
|
|
|
setMidiInputEnabled (allMidiIns[i], midiInsFromXml.contains (allMidiIns[i]));
|
|
|
|
|
|
|
|
insertDefaultDeviceNames (setup);
|
|
|
|
return setAudioDeviceSetup (setup, false);
|
|
|
|
}
|
|
|
|
if (error.isNotEmpty() && selectDefaultDeviceOnFailure)
|
|
|
|
error = initialise (numInputChansNeeded, numOutputChansNeeded,
|
|
|
|
nullptr, false, preferredDefaultDeviceName);
|
|
|
|
|
|
|
|
setDefaultMidiOutput (xml.getStringAttribute ("defaultMidiOutput"));
|
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
String AudioDeviceManager::initialiseWithDefaultDevices (int numInputChannelsNeeded,
|
|
|
|
int numOutputChannelsNeeded)
|
|
|
|
{
|
|
|
|
lastExplicitSettings = nullptr;
|
|
|
|
|
|
|
|
return initialise (numInputChannelsNeeded, numOutputChannelsNeeded,
|
|
|
|
nullptr, false, String(), nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AudioDeviceManager::insertDefaultDeviceNames (AudioDeviceSetup& setup) const
|
|
|
|
@@ -880,7 +901,7 @@ void AudioDeviceManager::setDefaultMidiOutput (const String& deviceName) |
|
|
|
{
|
|
|
|
if (defaultMidiOutputName != deviceName)
|
|
|
|
{
|
|
|
|
Array <AudioIODeviceCallback*> oldCallbacks;
|
|
|
|
Array<AudioIODeviceCallback*> oldCallbacks;
|
|
|
|
|
|
|
|
{
|
|
|
|
const ScopedLock sl (audioCallbackLock);
|
|
|
|
@@ -915,7 +936,7 @@ void AudioDeviceManager::setDefaultMidiOutput (const String& deviceName) |
|
|
|
void AudioDeviceManager::playTestSound()
|
|
|
|
{
|
|
|
|
{ // cunningly nested to swap, unlock and delete in that order.
|
|
|
|
ScopedPointer <AudioSampleBuffer> oldSound;
|
|
|
|
ScopedPointer<AudioSampleBuffer> oldSound;
|
|
|
|
|
|
|
|
{
|
|
|
|
const ScopedLock sl (audioCallbackLock);
|
|
|
|
|