26bool AudioDeviceManager::AudioDeviceSetup::operator== (
const AudioDeviceManager::AudioDeviceSetup& other)
const
38bool AudioDeviceManager::AudioDeviceSetup::operator!= (
const AudioDeviceManager::AudioDeviceSetup& other)
const
40 return ! operator== (other);
44class AudioDeviceManager::CallbackHandler :
public AudioIODeviceCallback,
45 public MidiInputCallback,
46 public AudioIODeviceType::Listener
49 CallbackHandler (AudioDeviceManager& adm) noexcept : owner (adm) {}
52 void audioDeviceIOCallback (
const float** ins,
int numIns,
float** outs,
int numOuts,
int numSamples)
override
54 owner.audioDeviceIOCallbackInt (ins, numIns, outs, numOuts, numSamples);
57 void audioDeviceAboutToStart (AudioIODevice* device)
override
59 owner.audioDeviceAboutToStartInt (device);
62 void audioDeviceStopped()
override
64 owner.audioDeviceStoppedInt();
67 void audioDeviceError (
const String& message)
override
69 owner.audioDeviceErrorInt (message);
72 void handleIncomingMidiMessage (MidiInput* source,
const MidiMessage& message)
override
74 owner.handleIncomingMidiMessageInt (source, message);
77 void audioDeviceListChanged()
override
79 owner.audioDeviceListChanged();
82 AudioDeviceManager& owner;
84 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CallbackHandler)
90 callbackHandler.reset (
new CallbackHandler (*
this));
95 currentAudioDevice.reset();
96 defaultMidiOutput.reset();
100void AudioDeviceManager::createDeviceTypesIfNeeded()
102 if (availableDeviceTypes.
size() == 0)
107 for (
auto*
t : types)
112 if (
auto* first = availableDeviceTypes.
getFirst())
113 currentDeviceType = first->getTypeName();
119 scanDevicesIfNeeded();
120 return availableDeviceTypes;
123void AudioDeviceManager::audioDeviceListChanged()
125 if (currentAudioDevice !=
nullptr)
129 for (
auto*
dt : availableDeviceTypes)
130 if (currentAudioDevice->getTypeName() ==
dt->getTypeName())
132 if (currentAudioDevice->getName() ==
dn)
138 if (! isCurrentDeviceStillAvailable())
143 initialiseFromXML (*e,
true, preferredDeviceName, ¤tSetup);
145 initialiseDefault (preferredDeviceName, ¤tSetup);
148 if (currentAudioDevice !=
nullptr)
150 currentSetup.
sampleRate = currentAudioDevice->getCurrentSampleRate();
151 currentSetup.
bufferSize = currentAudioDevice->getCurrentBufferSizeSamples();
152 currentSetup.
inputChannels = currentAudioDevice->getActiveInputChannels();
153 currentSetup.
outputChannels = currentAudioDevice->getActiveOutputChannels();
161static void addIfNotNull (OwnedArray<AudioIODeviceType>& list, AudioIODeviceType*
const device)
163 if (device !=
nullptr)
187 jassert (lastDeviceTypeConfigs.
size() == availableDeviceTypes.
size());
192 availableDeviceTypes.
getLast()->addListener (callbackHandler.get());
200 jassert (lastDeviceTypeConfigs.
size() == availableDeviceTypes.
size());
206 removed->removeListener (callbackHandler.get());
207 lastDeviceTypeConfigs.
remove (index,
true);
229 scanDevicesIfNeeded();
235 if (xml !=
nullptr && xml->
hasTagName (
"DEVICESETUP"))
245 AudioDeviceSetup
setup;
251 else if (preferredDefaultDeviceName.
isNotEmpty())
253 for (
auto* type : availableDeviceTypes)
255 for (
auto& out : type->getDeviceNames (false))
257 if (out.matchesWildcard (preferredDefaultDeviceName,
true))
259 setup.outputDeviceName = out;
264 for (
auto& in : type->getDeviceNames (true))
266 if (in.matchesWildcard (preferredDefaultDeviceName,
true))
268 setup.inputDeviceName = in;
275 insertDefaultDeviceNames (setup);
279String AudioDeviceManager::initialiseFromXML (
const XmlElement& xml,
280 bool selectDefaultDeviceOnFailure,
281 const String& preferredDefaultDeviceName,
282 const AudioDeviceSetup* preferredSetupOptions)
284 lastExplicitSettings.reset (
new XmlElement (xml));
287 AudioDeviceSetup setup;
289 if (preferredSetupOptions !=
nullptr)
290 setup = *preferredSetupOptions;
292 if (xml.getStringAttribute (
"audioDeviceName").isNotEmpty())
294 setup.inputDeviceName = setup.outputDeviceName
295 = xml.getStringAttribute (
"audioDeviceName");
299 setup.inputDeviceName = xml.getStringAttribute (
"audioInputDeviceName");
300 setup.outputDeviceName = xml.getStringAttribute (
"audioOutputDeviceName");
303 currentDeviceType = xml.getStringAttribute (
"deviceType");
305 if (findType (currentDeviceType) ==
nullptr)
307 if (
auto* type = findType (setup.inputDeviceName, setup.outputDeviceName))
309 else if (
auto* firstType = availableDeviceTypes.
getFirst())
310 currentDeviceType = firstType->getTypeName();
313 setup.bufferSize = xml.getIntAttribute (
"audioDeviceBufferSize", setup.bufferSize);
314 setup.sampleRate = xml.getDoubleAttribute (
"audioDeviceRate", setup.sampleRate);
316 setup.inputChannels .parseString (xml.getStringAttribute (
"audioDeviceInChans",
"11"), 2);
317 setup.outputChannels.parseString (xml.getStringAttribute (
"audioDeviceOutChans",
"11"), 2);
319 setup.useDefaultInputChannels = ! xml.hasAttribute (
"audioDeviceInChans");
320 setup.useDefaultOutputChannels = ! xml.hasAttribute (
"audioDeviceOutChans");
324 if (error.isNotEmpty() && selectDefaultDeviceOnFailure)
325 error =
initialise (numInputChansNeeded, numOutputChansNeeded,
nullptr,
false, preferredDefaultDeviceName);
327 midiDeviceInfosFromXml.
clear();
328 enabledMidiInputs.clear();
330 forEachXmlChildElementWithTagName (xml, c,
"MIDIINPUT")
331 midiDeviceInfosFromXml.add ({ c->getStringAttribute (
"name"), c->getStringAttribute (
"identifier") });
333 auto isIdentifierAvailable = [] (
const Array<MidiDeviceInfo>& available,
const String& identifier)
335 for (
auto& device : available)
336 if (device.identifier == identifier)
342 auto getUpdatedIdentifierForName = [&] (
const Array<MidiDeviceInfo>& available,
const String& name) -> String
344 for (
auto& device : available)
345 if (device.name == name)
346 return device.identifier;
353 for (
auto& info : midiDeviceInfosFromXml)
355 if (isIdentifierAvailable (inputs, info.identifier))
361 auto identifier = getUpdatedIdentifierForName (inputs, info.name);
363 if (identifier.isNotEmpty())
368 MidiDeviceInfo defaultOutputDeviceInfo (xml.getStringAttribute (
"defaultMidiOutput"),
369 xml.getStringAttribute (
"defaultMidiOutputDevice"));
373 if (isIdentifierAvailable (outputs, defaultOutputDeviceInfo.identifier))
379 auto identifier = getUpdatedIdentifierForName (outputs, defaultOutputDeviceInfo.name);
381 if (identifier.isNotEmpty())
391 lastExplicitSettings.reset();
394 nullptr,
false, {},
nullptr);
397void AudioDeviceManager::insertDefaultDeviceNames (AudioDeviceSetup&
setup)
const
401 if (numOutputChansNeeded > 0 &&
setup.outputDeviceName.
isEmpty())
404 if (numInputChansNeeded > 0 &&
setup.inputDeviceName.
isEmpty())
411 if (lastExplicitSettings !=
nullptr)
412 return std::make_unique<XmlElement> (*lastExplicitSettings);
418void AudioDeviceManager::scanDevicesIfNeeded()
420 if (listNeedsScanning)
422 listNeedsScanning =
false;
424 createDeviceTypesIfNeeded();
426 for (
auto* type : availableDeviceTypes)
427 type->scanForDevices();
431AudioIODeviceType* AudioDeviceManager::findType (
const String& typeName)
433 scanDevicesIfNeeded();
435 for (
auto* type : availableDeviceTypes)
436 if (type->getTypeName() == typeName)
442AudioIODeviceType* AudioDeviceManager::findType (
const String& inputName,
const String& outputName)
444 scanDevicesIfNeeded();
446 for (
auto* type : availableDeviceTypes)
447 if ((inputName.isNotEmpty() && deviceListContains (type, true, inputName))
448 || (outputName.isNotEmpty() && deviceListContains (type, false, outputName)))
461 setup = currentSetup;
464void AudioDeviceManager::deleteCurrentDevice()
466 currentAudioDevice.reset();
473 for (
int i = 0; i < availableDeviceTypes.
size(); ++i)
475 if (availableDeviceTypes.
getUnchecked(i)->getTypeName() == type
476 && currentDeviceType != type)
478 if (currentAudioDevice !=
nullptr)
485 currentDeviceType = type;
488 insertDefaultDeviceNames (s);
500 for (
auto* type : availableDeviceTypes)
504 return availableDeviceTypes.
getFirst();
515 else if (defaultNumChannels != -1)
518 channels.setRange (0, defaultNumChannels,
true);
529 jassert (&
newSetup != ¤tSetup);
533 else if (currentAudioDevice !=
nullptr)
539 deleteCurrentDevice();
553 || currentAudioDevice ==
nullptr)
555 deleteCurrentDevice();
556 scanDevicesIfNeeded();
560 if (
newSetup.outputDeviceName.isNotEmpty() && ! deviceListContains (type,
false,
newSetup.outputDeviceName))
561 return "No such device: " +
newSetup.outputDeviceName;
563 if (
newSetup.inputDeviceName.isNotEmpty() && ! deviceListContains (type,
true,
newSetup.inputDeviceName))
564 return "No such device: " +
newSetup.inputDeviceName;
568 if (currentAudioDevice ==
nullptr)
569 error =
"Can't open the audio device!\n\n"
570 "This may be because another application is currently using the same device - "
571 "if so, you should close any other applications and try again!";
573 error = currentAudioDevice->getLastError();
577 deleteCurrentDevice();
587 updateSetupChannels (currentSetup, numInputChansNeeded, numOutputChansNeeded);
600 error = currentAudioDevice->open (currentSetup.
inputChannels,
607 currentDeviceType = currentAudioDevice->getTypeName();
609 currentAudioDevice->start (callbackHandler.get());
611 currentSetup.
sampleRate = currentAudioDevice->getCurrentSampleRate();
612 currentSetup.
bufferSize = currentAudioDevice->getCurrentBufferSizeSamples();
613 currentSetup.
inputChannels = currentAudioDevice->getActiveInputChannels();
614 currentSetup.
outputChannels = currentAudioDevice->getActiveOutputChannels();
616 for (
int i = 0; i < availableDeviceTypes.
size(); ++i)
617 if (availableDeviceTypes.
getUnchecked (i)->getTypeName() == currentDeviceType)
618 *(lastDeviceTypeConfigs.
getUnchecked (i)) = currentSetup;
625 deleteCurrentDevice();
631double AudioDeviceManager::chooseBestSampleRate (
double rate)
const
633 jassert (currentAudioDevice !=
nullptr);
635 auto rates = currentAudioDevice->getAvailableSampleRates();
640 rate = currentAudioDevice->getCurrentSampleRate();
655 if (lowestAbove44 > 0.0)
656 return lowestAbove44;
661int AudioDeviceManager::chooseBestBufferSize (
int bufferSize)
const
663 jassert (currentAudioDevice !=
nullptr);
665 if (bufferSize > 0 && currentAudioDevice->getAvailableBufferSizes().contains (bufferSize))
668 return currentAudioDevice->getDefaultBufferSize();
671void AudioDeviceManager::stopDevice()
673 if (currentAudioDevice !=
nullptr)
674 currentAudioDevice->stop();
682 currentAudioDevice.reset();
683 loadMeasurer.
reset();
688 if (currentAudioDevice ==
nullptr)
705void AudioDeviceManager::updateXml()
707 lastExplicitSettings.reset (
new XmlElement (
"DEVICESETUP"));
709 lastExplicitSettings->setAttribute (
"deviceType", currentDeviceType);
710 lastExplicitSettings->setAttribute (
"audioOutputDeviceName", currentSetup.
outputDeviceName);
711 lastExplicitSettings->setAttribute (
"audioInputDeviceName", currentSetup.
inputDeviceName);
713 if (currentAudioDevice !=
nullptr)
715 lastExplicitSettings->setAttribute (
"audioDeviceRate", currentAudioDevice->getCurrentSampleRate());
717 if (currentAudioDevice->getDefaultBufferSize() != currentAudioDevice->getCurrentBufferSizeSamples())
718 lastExplicitSettings->setAttribute (
"audioDeviceBufferSize", currentAudioDevice->getCurrentBufferSizeSamples());
727 for (
auto& input : enabledMidiInputs)
729 auto* child = lastExplicitSettings->createNewChildElement (
"MIDIINPUT");
731 child->setAttribute (
"name", input->getName());
732 child->setAttribute (
"identifier", input->getIdentifier());
735 if (midiDeviceInfosFromXml.
size() > 0)
741 for (
auto& d : midiDeviceInfosFromXml)
743 if (! availableMidiDevices.contains (d))
745 auto* child = lastExplicitSettings->createNewChildElement (
"MIDIINPUT");
747 child->setAttribute (
"name", d.name);
748 child->setAttribute (
"identifier", d.identifier);
753 if (defaultMidiOutputDeviceInfo != MidiDeviceInfo())
755 lastExplicitSettings->setAttribute (
"defaultMidiOutput", defaultMidiOutputDeviceInfo.
name);
756 lastExplicitSettings->setAttribute (
"defaultMidiOutputDevice", defaultMidiOutputDeviceInfo.
identifier);
770 if (currentAudioDevice !=
nullptr &&
newCallback !=
nullptr)
771 newCallback->audioDeviceAboutToStart (currentAudioDevice.get());
795void AudioDeviceManager::audioDeviceIOCallbackInt (
const float**
inputChannelData,
806 if (callbacks.
size() > 0)
817 for (
int i = callbacks.
size(); --i > 0;)
826 for (
int j = 0;
j < numSamples; ++
j)
833 for (
int i = 0; i < numOutputChannels; ++i)
834 zeromem (outputChannelData[i], (
size_t) numSamples *
sizeof (float));
837 if (testSound !=
nullptr)
839 auto numSamps = jmin (numSamples, testSound->getNumSamples() - testSoundPosition);
840 auto* src = testSound->getReadPointer (0, testSoundPosition);
842 for (
int i = 0; i < numOutputChannels; ++i)
843 for (
int j = 0; j < numSamps; ++j)
844 outputChannelData [i][j] += src[j];
846 testSoundPosition += numSamps;
848 if (testSoundPosition >= testSound->getNumSamples())
853void AudioDeviceManager::audioDeviceAboutToStartInt (AudioIODevice*
const device)
855 loadMeasurer.
reset (device->getCurrentSampleRate(),
856 device->getCurrentBufferSizeSamples());
859 const ScopedLock sl (audioCallbackLock);
861 for (
int i = callbacks.
size(); --i >= 0;)
862 callbacks.
getUnchecked(i)->audioDeviceAboutToStart (device);
868void AudioDeviceManager::audioDeviceStoppedInt()
872 const ScopedLock sl (audioCallbackLock);
874 loadMeasurer.
reset();
876 for (
int i = callbacks.
size(); --i >= 0;)
880void AudioDeviceManager::audioDeviceErrorInt (
const String& message)
882 const ScopedLock sl (audioCallbackLock);
884 for (
int i = callbacks.
size(); --i >= 0;)
902 enabledMidiInputs.push_back (std::move (
midiIn));
903 enabledMidiInputs.back()->start();
908 auto removePredicate = [identifier] (
const std::unique_ptr<MidiInput>&
in) {
return in->getIdentifier() == identifier; };
909 enabledMidiInputs.erase (std::remove_if (std::begin (enabledMidiInputs), std::end (enabledMidiInputs),
removePredicate),
910 std::end (enabledMidiInputs));
920 for (
auto&
mi : enabledMidiInputs)
921 if (
mi->getIdentifier() == identifier)
940 for (
int i = midiCallbacks.
size(); --i >= 0;)
952void AudioDeviceManager::handleIncomingMidiMessageInt (
MidiInput* source,
const MidiMessage& message)
958 for (
auto&
mc : midiCallbacks)
959 if (
mc.deviceIdentifier.isEmpty() ||
mc.deviceIdentifier == source->getIdentifier())
960 mc.callback->handleIncomingMidiMessage (source, message);
967 if (defaultMidiOutputDeviceInfo.
identifier != identifier)
976 if (currentAudioDevice !=
nullptr)
980 defaultMidiOutput.reset();
985 if (defaultMidiOutput !=
nullptr)
986 defaultMidiOutputDeviceInfo = defaultMidiOutput->getDeviceInfo();
988 defaultMidiOutputDeviceInfo = {};
990 if (currentAudioDevice !=
nullptr)
992 c->audioDeviceAboutToStart (currentAudioDevice.get());
1005AudioDeviceManager::LevelMeter::LevelMeter()
noexcept : level() {}
1007void AudioDeviceManager::LevelMeter::updateLevel (
const float*
const* channelData,
int numChannels,
int numSamples)
noexcept
1009 if (getReferenceCount() <= 1)
1012 auto localLevel = level.get();
1014 if (numChannels > 0)
1016 for (
int j = 0; j < numSamples; ++j)
1020 for (
int i = 0; i < numChannels; ++i)
1021 s += std::abs (channelData[i][j]);
1023 s /= (float) numChannels;
1025 const float decayFactor = 0.99992f;
1029 else if (localLevel > 0.001f)
1030 localLevel *= decayFactor;
1043double AudioDeviceManager::LevelMeter::getCurrentLevel() const noexcept
1045 jassert (getReferenceCount() > 1);
1052 std::unique_ptr<AudioBuffer<float>>
oldSound;
1060 testSoundPosition = 0;
1062 if (currentAudioDevice !=
nullptr)
1064 auto sampleRate = currentAudioDevice->getCurrentSampleRate();
1067 double frequency = 440.0;
1068 float amplitude = 0.5f;
1075 newSound->setSample (0, i, amplitude * (
float) std::sin (i * phasePerSample));
1089 auto deviceXRuns = (currentAudioDevice !=
nullptr ? currentAudioDevice->getXRunCount() : -1);
void swapWith(OtherArrayType &otherArray) noexcept
ElementType getUnchecked(int index) const
bool isEmpty() const noexcept
int size() const noexcept
void removeFirstMatchingValue(ParameterType valueToRemove)
void remove(int indexToRemove)
ElementType getFirst() const noexcept
int indexOf(ParameterType elementToLookFor) const
void add(const ElementType &newElement)
ElementType removeAndReturn(int indexToRemove)
bool contains(ParameterType elementToLookFor) const
ElementType & getReference(int index) noexcept
ElementType getLast() const noexcept
void setSize(int newNumChannels, int newNumSamples, bool keepExistingContent=false, bool clearExtraSpace=false, bool avoidReallocating=false)
Type ** getArrayOfWritePointers() noexcept
bool isMidiInputDeviceEnabled(const String &deviceIdentifier) const
void removeAudioDeviceType(AudioIODeviceType *deviceTypeToRemove)
AudioDeviceSetup getAudioDeviceSetup() const
void removeMidiInputDeviceCallback(const String &deviceIdentifier, MidiInputCallback *callback)
double getCpuUsage() const
AudioIODeviceType * getCurrentDeviceTypeObject() const
String setAudioDeviceSetup(const AudioDeviceSetup &newSetup, bool treatAsChosenDevice)
void removeMidiInputCallback(const String &, MidiInputCallback *)
bool isMidiInputEnabled(const String &) const
virtual void createAudioDeviceTypes(OwnedArray< AudioIODeviceType > &types)
void setMidiInputEnabled(const String &, bool)
void setDefaultMidiOutputDevice(const String &deviceIdentifier)
void setMidiInputDeviceEnabled(const String &deviceIdentifier, bool enabled)
void setDefaultMidiOutput(const String &)
int getXRunCount() const noexcept
void addMidiInputCallback(const String &, MidiInputCallback *)
void addMidiInputDeviceCallback(const String &deviceIdentifier, MidiInputCallback *callback)
void setCurrentAudioDeviceType(const String &type, bool treatAsChosenDevice)
~AudioDeviceManager() override
const OwnedArray< AudioIODeviceType > & getAvailableDeviceTypes()
String initialise(int numInputChannelsNeeded, int numOutputChannelsNeeded, const XmlElement *savedState, bool selectDefaultDeviceOnFailure, const String &preferredDefaultDeviceName=String(), const AudioDeviceSetup *preferredSetupOptions=nullptr)
void addAudioCallback(AudioIODeviceCallback *newCallback)
String initialiseWithDefaultDevices(int numInputChannelsNeeded, int numOutputChannelsNeeded)
void restartLastAudioDevice()
void removeAudioCallback(AudioIODeviceCallback *callback)
void addAudioDeviceType(std::unique_ptr< AudioIODeviceType > newDeviceType)
std::unique_ptr< XmlElement > createStateXml() const
virtual int getDefaultDeviceIndex(bool forInput) const =0
static AudioIODeviceType * createAudioIODeviceType_ASIO()
static AudioIODeviceType * createAudioIODeviceType_Oboe()
static AudioIODeviceType * createAudioIODeviceType_JACK()
static AudioIODeviceType * createAudioIODeviceType_DirectSound()
static AudioIODeviceType * createAudioIODeviceType_Android()
static AudioIODeviceType * createAudioIODeviceType_OpenSLES()
static AudioIODeviceType * createAudioIODeviceType_WASAPI(bool exclusiveMode)
static AudioIODeviceType * createAudioIODeviceType_CoreAudio()
virtual StringArray getDeviceNames(bool wantInputNames=false) const =0
const String & getTypeName() const noexcept
static AudioIODeviceType * createAudioIODeviceType_Bela()
static AudioIODeviceType * createAudioIODeviceType_ALSA()
virtual AudioIODevice * createDevice(const String &outputDeviceName, const String &inputDeviceName)=0
static AudioIODeviceType * createAudioIODeviceType_iOSAudio()
double getLoadAsProportion() const
String toString(int base, int minimumNumCharacters=1) const
bool isZero() const noexcept
int countNumberOfSetBits() const noexcept
bool isActiveSense() const noexcept
static std::unique_ptr< MidiOutput > openDevice(const String &deviceIdentifier)
static Array< MidiDeviceInfo > getAvailableDevices()
bool isEmpty() const noexcept
bool isNotEmpty() const noexcept
static void JUCE_CALLTYPE sleep(int milliseconds)
bool hasTagName(StringRef possibleTagName) const noexcept
bool useDefaultInputChannels
BigInteger outputChannels
bool useDefaultOutputChannels