LMMS
Loading...
Searching...
No Matches
juce_AudioDeviceManager.cpp
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
26template <typename Setup>
27static auto getSetupInfo (Setup& s, bool isInput)
28{
29 struct SetupInfo
30 {
31 // double brackets so that we get the expression type, i.e. a (possibly const) reference
32 decltype ((s.inputDeviceName)) name;
33 decltype ((s.inputChannels)) channels;
34 decltype ((s.useDefaultInputChannels)) useDefault;
35 };
36
37 return isInput ? SetupInfo { s.inputDeviceName, s.inputChannels, s.useDefaultInputChannels }
38 : SetupInfo { s.outputDeviceName, s.outputChannels, s.useDefaultOutputChannels };
39}
40
42{
43 return std::tie (s.outputDeviceName,
44 s.inputDeviceName,
45 s.sampleRate,
46 s.bufferSize,
47 s.inputChannels,
48 s.useDefaultInputChannels,
49 s.outputChannels,
50 s.useDefaultOutputChannels);
51}
52
53bool AudioDeviceManager::AudioDeviceSetup::operator== (const AudioDeviceManager::AudioDeviceSetup& other) const
54{
55 return tie (*this) == tie (other);
56}
57
58bool AudioDeviceManager::AudioDeviceSetup::operator!= (const AudioDeviceManager::AudioDeviceSetup& other) const
59{
60 return tie (*this) != tie (other);
61}
62
63//==============================================================================
65 public MidiInputCallback,
67{
68public:
70
71private:
72 void audioDeviceIOCallbackWithContext (const float** ins,
73 int numIns,
74 float** outs,
75 int numOuts,
76 int numSamples,
77 const AudioIODeviceCallbackContext& context) override
78 {
79 owner.audioDeviceIOCallbackInt (ins, numIns, outs, numOuts, numSamples, context);
80 }
81
82 void audioDeviceAboutToStart (AudioIODevice* device) override
83 {
84 owner.audioDeviceAboutToStartInt (device);
85 }
86
87 void audioDeviceStopped() override
88 {
89 owner.audioDeviceStoppedInt();
90 }
91
92 void audioDeviceError (const String& message) override
93 {
94 owner.audioDeviceErrorInt (message);
95 }
96
98 {
99 owner.handleIncomingMidiMessageInt (source, message);
100 }
101
103 {
104 owner.audioDeviceListChanged();
105 }
106
108
110};
111
112//==============================================================================
117
123
124//==============================================================================
126{
127 if (availableDeviceTypes.size() == 0)
128 {
131
132 for (auto* t : types)
133 addAudioDeviceType (std::unique_ptr<AudioIODeviceType> (t));
134
135 types.clear (false);
136
137 for (auto* type : availableDeviceTypes)
138 type->scanForDevices();
139
141 }
142}
143
145{
146 const auto deviceTypeHasDevices = [] (const AudioIODeviceType* ptr)
147 {
148 return ! ptr->getDeviceNames (true) .isEmpty()
149 || ! ptr->getDeviceNames (false).isEmpty();
150 };
151
152 if (auto* type = findType (currentDeviceType))
153 if (deviceTypeHasDevices (type))
154 return;
155
156 const auto iter = std::find_if (availableDeviceTypes.begin(),
158 deviceTypeHasDevices);
159
160 if (iter != availableDeviceTypes.end())
161 currentDeviceType = (*iter)->getTypeName();
162}
163
169
171{
172 if (currentAudioDevice != nullptr)
173 {
174 currentSetup.sampleRate = currentAudioDevice->getCurrentSampleRate();
175 currentSetup.bufferSize = currentAudioDevice->getCurrentBufferSizeSamples();
176 currentSetup.inputChannels = currentAudioDevice->getActiveInputChannels();
177 currentSetup.outputChannels = currentAudioDevice->getActiveOutputChannels();
178 }
179}
180
182{
183 if (currentAudioDevice != nullptr)
184 {
185 auto currentDeviceStillAvailable = [&]
186 {
187 auto currentTypeName = currentAudioDevice->getTypeName();
188 auto currentDeviceName = currentAudioDevice->getName();
189
190 for (auto* deviceType : availableDeviceTypes)
191 {
192 if (currentTypeName == deviceType->getTypeName())
193 {
194 for (auto& deviceName : deviceType->getDeviceNames (true))
195 if (currentDeviceName == deviceName)
196 return true;
197
198 for (auto& deviceName : deviceType->getDeviceNames (false))
199 if (currentDeviceName == deviceName)
200 return true;
201 }
202 }
203
204 return false;
205 }();
206
207 if (! currentDeviceStillAvailable)
208 {
210
211 if (auto e = createStateXml())
213 else
215 }
216
218 }
219
221}
222
223//==============================================================================
225{
226 if (device != nullptr)
227 list.add (device);
228}
229
246
247void AudioDeviceManager::addAudioDeviceType (std::unique_ptr<AudioIODeviceType> newDeviceType)
248{
249 if (newDeviceType != nullptr)
250 {
252
253 availableDeviceTypes.add (newDeviceType.release());
255
256 availableDeviceTypes.getLast()->addListener (callbackHandler.get());
257 }
258}
259
261{
262 if (deviceTypeToRemove != nullptr)
263 {
265
266 auto index = availableDeviceTypes.indexOf (deviceTypeToRemove);
267
268 if (auto removed = std::unique_ptr<AudioIODeviceType> (availableDeviceTypes.removeAndReturn (index)))
269 {
270 removed->removeListener (callbackHandler.get());
271 lastDeviceTypeConfigs.remove (index, true);
272 }
273 }
274}
275
276static bool deviceListContains (AudioIODeviceType* type, bool isInput, const String& name)
277{
278 for (auto& deviceName : type->getDeviceNames (isInput))
279 if (deviceName.trim().equalsIgnoreCase (name.trim()))
280 return true;
281
282 return false;
283}
284
285//==============================================================================
286String AudioDeviceManager::initialise (const int numInputChannelsNeeded,
287 const int numOutputChannelsNeeded,
288 const XmlElement* const xml,
289 const bool selectDefaultDeviceOnFailure,
290 const String& preferredDefaultDeviceName,
291 const AudioDeviceSetup* preferredSetupOptions)
292{
295
296 numInputChansNeeded = numInputChannelsNeeded;
297 numOutputChansNeeded = numOutputChannelsNeeded;
298 preferredDeviceName = preferredDefaultDeviceName;
299
300 if (xml != nullptr && xml->hasTagName ("DEVICESETUP"))
301 return initialiseFromXML (*xml, selectDefaultDeviceOnFailure,
302 preferredDeviceName, preferredSetupOptions);
303
304 return initialiseDefault (preferredDeviceName, preferredSetupOptions);
305}
306
307String AudioDeviceManager::initialiseDefault (const String& preferredDefaultDeviceName,
308 const AudioDeviceSetup* preferredSetupOptions)
309{
310 AudioDeviceSetup setup;
311
312 if (preferredSetupOptions != nullptr)
313 {
314 setup = *preferredSetupOptions;
315 }
316 else if (preferredDefaultDeviceName.isNotEmpty())
317 {
318 const auto nameMatches = [&preferredDefaultDeviceName] (const String& name)
319 {
320 return name.matchesWildcard (preferredDefaultDeviceName, true);
321 };
322
323 struct WildcardMatch
324 {
326 bool successful;
327 };
328
329 const auto getWildcardMatch = [&nameMatches] (const StringArray& names)
330 {
331 const auto iter = std::find_if (names.begin(), names.end(), nameMatches);
332 return WildcardMatch { iter != names.end() ? *iter : String(), iter != names.end() };
333 };
334
335 struct WildcardMatches
336 {
337 WildcardMatch input, output;
338 };
339
340 const auto getMatchesForType = [&getWildcardMatch] (const AudioIODeviceType* type)
341 {
342 return WildcardMatches { getWildcardMatch (type->getDeviceNames (true)),
343 getWildcardMatch (type->getDeviceNames (false)) };
344 };
345
346 struct SearchResult
347 {
348 String type, input, output;
349 };
350
351 const auto result = [&]
352 {
353 // First, look for a device type with an input and output which matches the preferred name
354 for (auto* type : availableDeviceTypes)
355 {
356 const auto matches = getMatchesForType (type);
357
358 if (matches.input.successful && matches.output.successful)
359 return SearchResult { type->getTypeName(), matches.input.value, matches.output.value };
360 }
361
362 // No device type has matching ins and outs, so fall back to a device where either the
363 // input or output match
364 for (auto* type : availableDeviceTypes)
365 {
366 const auto matches = getMatchesForType (type);
367
368 if (matches.input.successful || matches.output.successful)
369 return SearchResult { type->getTypeName(), matches.input.value, matches.output.value };
370 }
371
372 // No devices match the query, so just use the default devices from the current type
373 return SearchResult { currentDeviceType, {}, {} };
374 }();
375
377 setup.inputDeviceName = result.input;
378 setup.outputDeviceName = result.output;
379 }
380
382 return setAudioDeviceSetup (setup, false);
383}
384
386 bool selectDefaultDeviceOnFailure,
387 const String& preferredDefaultDeviceName,
388 const AudioDeviceSetup* preferredSetupOptions)
389{
390 lastExplicitSettings.reset (new XmlElement (xml));
391
393 AudioDeviceSetup setup;
394
395 if (preferredSetupOptions != nullptr)
396 setup = *preferredSetupOptions;
397
398 if (xml.getStringAttribute ("audioDeviceName").isNotEmpty())
399 {
401 = xml.getStringAttribute ("audioDeviceName");
402 }
403 else
404 {
405 setup.inputDeviceName = xml.getStringAttribute ("audioInputDeviceName");
406 setup.outputDeviceName = xml.getStringAttribute ("audioOutputDeviceName");
407 }
408
409 currentDeviceType = xml.getStringAttribute ("deviceType");
410
411 if (findType (currentDeviceType) == nullptr)
412 {
413 if (auto* type = findType (setup.inputDeviceName, setup.outputDeviceName))
414 currentDeviceType = type->getTypeName();
415 else if (auto* firstType = availableDeviceTypes.getFirst())
416 currentDeviceType = firstType->getTypeName();
417 }
418
419 setup.bufferSize = xml.getIntAttribute ("audioDeviceBufferSize", setup.bufferSize);
420 setup.sampleRate = xml.getDoubleAttribute ("audioDeviceRate", setup.sampleRate);
421
422 setup.inputChannels .parseString (xml.getStringAttribute ("audioDeviceInChans", "11"), 2);
423 setup.outputChannels.parseString (xml.getStringAttribute ("audioDeviceOutChans", "11"), 2);
424
425 setup.useDefaultInputChannels = ! xml.hasAttribute ("audioDeviceInChans");
426 setup.useDefaultOutputChannels = ! xml.hasAttribute ("audioDeviceOutChans");
427
428 error = setAudioDeviceSetup (setup, true);
429
430 if (error.isNotEmpty() && selectDefaultDeviceOnFailure)
431 error = initialise (numInputChansNeeded, numOutputChansNeeded, nullptr, false, preferredDefaultDeviceName);
432
434 enabledMidiInputs.clear();
435
436 for (auto* c : xml.getChildWithTagNameIterator ("MIDIINPUT"))
437 midiDeviceInfosFromXml.add ({ c->getStringAttribute ("name"), c->getStringAttribute ("identifier") });
438
439 auto isIdentifierAvailable = [] (const Array<MidiDeviceInfo>& available, const String& identifier)
440 {
441 for (auto& device : available)
442 if (device.identifier == identifier)
443 return true;
444
445 return false;
446 };
447
448 auto getUpdatedIdentifierForName = [&] (const Array<MidiDeviceInfo>& available, const String& name) -> String
449 {
450 for (auto& device : available)
451 if (device.name == name)
452 return device.identifier;
453
454 return {};
455 };
456
457 auto inputs = MidiInput::getAvailableDevices();
458
459 for (auto& info : midiDeviceInfosFromXml)
460 {
461 if (isIdentifierAvailable (inputs, info.identifier))
462 {
463 setMidiInputDeviceEnabled (info.identifier, true);
464 }
465 else
466 {
467 auto identifier = getUpdatedIdentifierForName (inputs, info.name);
468
469 if (identifier.isNotEmpty())
470 setMidiInputDeviceEnabled (identifier, true);
471 }
472 }
473
474 MidiDeviceInfo defaultOutputDeviceInfo (xml.getStringAttribute ("defaultMidiOutput"),
475 xml.getStringAttribute ("defaultMidiOutputDevice"));
476
477 auto outputs = MidiOutput::getAvailableDevices();
478
479 if (isIdentifierAvailable (outputs, defaultOutputDeviceInfo.identifier))
480 {
481 setDefaultMidiOutputDevice (defaultOutputDeviceInfo.identifier);
482 }
483 else
484 {
485 auto identifier = getUpdatedIdentifierForName (outputs, defaultOutputDeviceInfo.name);
486
487 if (identifier.isNotEmpty())
488 setDefaultMidiOutputDevice (identifier);
489 }
490
491 return error;
492}
493
495 int numOutputChannelsNeeded)
496{
497 lastExplicitSettings.reset();
498
499 return initialise (numInputChannelsNeeded, numOutputChannelsNeeded,
500 nullptr, false, {}, nullptr);
501}
502
504{
505 if (auto* type = getCurrentDeviceTypeObject())
506 {
507 for (const auto isInput : { false, true })
508 {
509 const auto numChannelsNeeded = isInput ? numInputChansNeeded : numOutputChansNeeded;
510 const auto info = getSetupInfo (setup, isInput);
511
512 if (numChannelsNeeded > 0 && info.name.isEmpty())
513 info.name = type->getDeviceNames (isInput) [type->getDefaultDeviceIndex (isInput)];
514 }
515 }
516}
517
518std::unique_ptr<XmlElement> AudioDeviceManager::createStateXml() const
519{
520 if (lastExplicitSettings != nullptr)
521 return std::make_unique<XmlElement> (*lastExplicitSettings);
522
523 return {};
524}
525
526//==============================================================================
528{
530 {
531 listNeedsScanning = false;
532
534
535 for (auto* type : availableDeviceTypes)
536 type->scanForDevices();
537 }
538}
539
541{
543
544 for (auto* type : availableDeviceTypes)
545 if (type->getTypeName() == typeName)
546 return type;
547
548 return {};
549}
550
551AudioIODeviceType* AudioDeviceManager::findType (const String& inputName, const String& outputName)
552{
554
555 for (auto* type : availableDeviceTypes)
556 if ((inputName.isNotEmpty() && deviceListContains (type, true, inputName))
557 || (outputName.isNotEmpty() && deviceListContains (type, false, outputName)))
558 return type;
559
560 return {};
561}
562
567
572
574{
575 currentAudioDevice.reset();
576 currentSetup.inputDeviceName.clear();
577 currentSetup.outputDeviceName.clear();
578}
579
580void AudioDeviceManager::setCurrentAudioDeviceType (const String& type, bool treatAsChosenDevice)
581{
582 for (int i = 0; i < availableDeviceTypes.size(); ++i)
583 {
584 if (availableDeviceTypes.getUnchecked(i)->getTypeName() == type
586 {
587 if (currentAudioDevice != nullptr)
588 {
590 Thread::sleep (1500); // allow a moment for OS devices to sort themselves out, to help
591 // avoid things like DirectSound/ASIO clashes
592 }
593
595
596 AudioDeviceSetup s (*lastDeviceTypeConfigs.getUnchecked(i));
598
599 setAudioDeviceSetup (s, treatAsChosenDevice);
600
602 break;
603 }
604 }
605}
606
608{
609 for (auto* type : availableDeviceTypes)
610 if (type->getTypeName() == currentDeviceType)
611 return type;
612
613 return availableDeviceTypes.getFirst();
614}
615
616static void updateSetupChannels (AudioDeviceManager::AudioDeviceSetup& setup, int defaultNumIns, int defaultNumOuts)
617{
618 auto updateChannels = [] (const String& deviceName, BigInteger& channels, int defaultNumChannels)
619 {
620 if (deviceName.isEmpty())
621 {
622 channels.clear();
623 }
624 else if (defaultNumChannels != -1)
625 {
626 channels.clear();
627 channels.setRange (0, defaultNumChannels, true);
628 }
629 };
630
631 updateChannels (setup.inputDeviceName, setup.inputChannels, setup.useDefaultInputChannels ? defaultNumIns : -1);
632 updateChannels (setup.outputDeviceName, setup.outputChannels, setup.useDefaultOutputChannels ? defaultNumOuts : -1);
633}
634
636 bool treatAsChosenDevice)
637{
638 jassert (&newSetup != &currentSetup); // this will have no effect
639
640 if (newSetup != currentSetup)
642 else if (currentAudioDevice != nullptr)
643 return {};
644
645 stopDevice();
646
647 if (getCurrentDeviceTypeObject() == nullptr
648 || (newSetup.inputDeviceName.isEmpty() && newSetup.outputDeviceName.isEmpty()))
649 {
651
652 if (treatAsChosenDevice)
653 updateXml();
654
655 return {};
656 }
657
659
660 const auto needsNewDevice = currentSetup.inputDeviceName != newSetup.inputDeviceName
661 || currentSetup.outputDeviceName != newSetup.outputDeviceName
662 || currentAudioDevice == nullptr;
663
664 if (needsNewDevice)
665 {
668
670
671 for (const auto isInput : { false, true })
672 {
673 const auto name = getSetupInfo (newSetup, isInput).name;
674
675 if (name.isNotEmpty() && ! deviceListContains (type, isInput, name))
676 return "No such device: " + name;
677 }
678
679 currentAudioDevice.reset (type->createDevice (newSetup.outputDeviceName, newSetup.inputDeviceName));
680
681 if (currentAudioDevice == nullptr)
682 error = "Can't open the audio device!\n\n"
683 "This may be because another application is currently using the same device - "
684 "if so, you should close any other applications and try again!";
685 else
686 error = currentAudioDevice->getLastError();
687
688 if (error.isNotEmpty())
689 {
691 return error;
692 }
693 }
694
695 currentSetup = newSetup;
696
697 if (! currentSetup.useDefaultInputChannels) numInputChansNeeded = currentSetup.inputChannels.countNumberOfSetBits();
698 if (! currentSetup.useDefaultOutputChannels) numOutputChansNeeded = currentSetup.outputChannels.countNumberOfSetBits();
699
701
702 if (currentSetup.inputChannels.isZero() && currentSetup.outputChannels.isZero())
703 {
704 if (treatAsChosenDevice)
705 updateXml();
706
707 return {};
708 }
709
710 currentSetup.sampleRate = chooseBestSampleRate (currentSetup.sampleRate);
711 currentSetup.bufferSize = chooseBestBufferSize (currentSetup.bufferSize);
712
713 error = currentAudioDevice->open (currentSetup.inputChannels,
714 currentSetup.outputChannels,
715 currentSetup.sampleRate,
716 currentSetup.bufferSize);
717
718 if (error.isEmpty())
719 {
720 currentDeviceType = currentAudioDevice->getTypeName();
721
722 currentAudioDevice->start (callbackHandler.get());
724
725 for (int i = 0; i < availableDeviceTypes.size(); ++i)
726 if (availableDeviceTypes.getUnchecked (i)->getTypeName() == currentDeviceType)
727 *(lastDeviceTypeConfigs.getUnchecked (i)) = currentSetup;
728
729 if (treatAsChosenDevice)
730 updateXml();
731 }
732 else
733 {
735 }
736
737 return error;
738}
739
741{
742 jassert (currentAudioDevice != nullptr);
743
744 auto rates = currentAudioDevice->getAvailableSampleRates();
745
746 if (rate > 0 && rates.contains (rate))
747 return rate;
748
749 rate = currentAudioDevice->getCurrentSampleRate();
750
751 if (rate > 0 && rates.contains (rate))
752 return rate;
753
754 double lowestAbove44 = 0.0;
755
756 for (int i = rates.size(); --i >= 0;)
757 {
758 auto sr = rates[i];
759
760 if (sr >= 44100.0 && (lowestAbove44 < 1.0 || sr < lowestAbove44))
761 lowestAbove44 = sr;
762 }
763
764 if (lowestAbove44 > 0.0)
765 return lowestAbove44;
766
767 return rates[0];
768}
769
771{
772 jassert (currentAudioDevice != nullptr);
773
774 if (bufferSize > 0 && currentAudioDevice->getAvailableBufferSizes().contains (bufferSize))
775 return bufferSize;
776
777 return currentAudioDevice->getDefaultBufferSize();
778}
779
781{
782 if (currentAudioDevice != nullptr)
783 currentAudioDevice->stop();
784
785 testSound.reset();
786}
787
789{
790 stopDevice();
791 currentAudioDevice.reset();
792 loadMeasurer.reset();
793}
794
796{
797 if (currentAudioDevice == nullptr)
798 {
799 if (currentSetup.inputDeviceName.isEmpty()
800 && currentSetup.outputDeviceName.isEmpty())
801 {
802 // This method will only reload the last device that was running
803 // before closeAudioDevice() was called - you need to actually open
804 // one first, with setAudioDeviceSetup().
806 return;
807 }
808
810 setAudioDeviceSetup (s, false);
811 }
812}
813
815{
816 lastExplicitSettings.reset (new XmlElement ("DEVICESETUP"));
817
818 lastExplicitSettings->setAttribute ("deviceType", currentDeviceType);
819 lastExplicitSettings->setAttribute ("audioOutputDeviceName", currentSetup.outputDeviceName);
820 lastExplicitSettings->setAttribute ("audioInputDeviceName", currentSetup.inputDeviceName);
821
822 if (currentAudioDevice != nullptr)
823 {
824 lastExplicitSettings->setAttribute ("audioDeviceRate", currentAudioDevice->getCurrentSampleRate());
825
826 if (currentAudioDevice->getDefaultBufferSize() != currentAudioDevice->getCurrentBufferSizeSamples())
827 lastExplicitSettings->setAttribute ("audioDeviceBufferSize", currentAudioDevice->getCurrentBufferSizeSamples());
828
829 if (! currentSetup.useDefaultInputChannels)
830 lastExplicitSettings->setAttribute ("audioDeviceInChans", currentSetup.inputChannels.toString (2));
831
832 if (! currentSetup.useDefaultOutputChannels)
833 lastExplicitSettings->setAttribute ("audioDeviceOutChans", currentSetup.outputChannels.toString (2));
834 }
835
836 for (auto& input : enabledMidiInputs)
837 {
838 auto* child = lastExplicitSettings->createNewChildElement ("MIDIINPUT");
839
840 child->setAttribute ("name", input->getName());
841 child->setAttribute ("identifier", input->getIdentifier());
842 }
843
844 if (midiDeviceInfosFromXml.size() > 0)
845 {
846 // Add any midi devices that have been enabled before, but which aren't currently
847 // open because the device has been disconnected.
848 auto availableMidiDevices = MidiInput::getAvailableDevices();
849
850 for (auto& d : midiDeviceInfosFromXml)
851 {
852 if (! availableMidiDevices.contains (d))
853 {
854 auto* child = lastExplicitSettings->createNewChildElement ("MIDIINPUT");
855
856 child->setAttribute ("name", d.name);
857 child->setAttribute ("identifier", d.identifier);
858 }
859 }
860 }
861
863 {
864 lastExplicitSettings->setAttribute ("defaultMidiOutput", defaultMidiOutputDeviceInfo.name);
865 lastExplicitSettings->setAttribute ("defaultMidiOutputDevice", defaultMidiOutputDeviceInfo.identifier);
866 }
867}
868
869//==============================================================================
871{
872 {
873 const ScopedLock sl (audioCallbackLock);
874
875 if (callbacks.contains (newCallback))
876 return;
877 }
878
879 if (currentAudioDevice != nullptr && newCallback != nullptr)
880 newCallback->audioDeviceAboutToStart (currentAudioDevice.get());
881
882 const ScopedLock sl (audioCallbackLock);
883 callbacks.add (newCallback);
884}
885
887{
888 if (callbackToRemove != nullptr)
889 {
890 bool needsDeinitialising = currentAudioDevice != nullptr;
891
892 {
893 const ScopedLock sl (audioCallbackLock);
894
895 needsDeinitialising = needsDeinitialising && callbacks.contains (callbackToRemove);
896 callbacks.removeFirstMatchingValue (callbackToRemove);
897 }
898
899 if (needsDeinitialising)
900 callbackToRemove->audioDeviceStopped();
901 }
902}
903
904void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelData,
905 int numInputChannels,
906 float** outputChannelData,
907 int numOutputChannels,
908 int numSamples,
909 const AudioIODeviceCallbackContext& context)
910{
911 const ScopedLock sl (audioCallbackLock);
912
913 inputLevelGetter->updateLevel (inputChannelData, numInputChannels, numSamples);
914
915 if (callbacks.size() > 0)
916 {
918
919 tempBuffer.setSize (jmax (1, numOutputChannels), jmax (1, numSamples), false, false, true);
920
921 callbacks.getUnchecked(0)->audioDeviceIOCallbackWithContext (inputChannelData,
922 numInputChannels,
923 outputChannelData,
924 numOutputChannels,
925 numSamples,
926 context);
927
928 auto** tempChans = tempBuffer.getArrayOfWritePointers();
929
930 for (int i = callbacks.size(); --i > 0;)
931 {
932 callbacks.getUnchecked(i)->audioDeviceIOCallbackWithContext (inputChannelData,
933 numInputChannels,
934 tempChans,
935 numOutputChannels,
936 numSamples,
937 context);
938
939 for (int chan = 0; chan < numOutputChannels; ++chan)
940 {
941 if (auto* src = tempChans [chan])
942 if (auto* dst = outputChannelData [chan])
943 for (int j = 0; j < numSamples; ++j)
944 dst[j] += src[j];
945 }
946 }
947 }
948 else
949 {
950 for (int i = 0; i < numOutputChannels; ++i)
951 zeromem (outputChannelData[i], (size_t) numSamples * sizeof (float));
952 }
953
954 if (testSound != nullptr)
955 {
956 auto numSamps = jmin (numSamples, testSound->getNumSamples() - testSoundPosition);
957 auto* src = testSound->getReadPointer (0, testSoundPosition);
958
959 for (int i = 0; i < numOutputChannels; ++i)
960 if (auto* dst = outputChannelData [i])
961 for (int j = 0; j < numSamps; ++j)
962 dst[j] += src[j];
963
964 testSoundPosition += numSamps;
965
966 if (testSoundPosition >= testSound->getNumSamples())
967 testSound.reset();
968 }
969
970 outputLevelGetter->updateLevel (const_cast<const float**> (outputChannelData), numOutputChannels, numSamples);
971}
972
974{
975 loadMeasurer.reset (device->getCurrentSampleRate(),
977
979
980 {
981 const ScopedLock sl (audioCallbackLock);
982
983 for (int i = callbacks.size(); --i >= 0;)
984 callbacks.getUnchecked(i)->audioDeviceAboutToStart (device);
985 }
986
988}
989
991{
993
994 const ScopedLock sl (audioCallbackLock);
995
996 loadMeasurer.reset();
997
998 for (int i = callbacks.size(); --i >= 0;)
999 callbacks.getUnchecked(i)->audioDeviceStopped();
1000}
1001
1003{
1004 const ScopedLock sl (audioCallbackLock);
1005
1006 for (int i = callbacks.size(); --i >= 0;)
1007 callbacks.getUnchecked(i)->audioDeviceError (message);
1008}
1009
1011{
1012 return loadMeasurer.getLoadAsProportion();
1013}
1014
1015//==============================================================================
1016void AudioDeviceManager::setMidiInputDeviceEnabled (const String& identifier, bool enabled)
1017{
1018 if (enabled != isMidiInputDeviceEnabled (identifier))
1019 {
1020 if (enabled)
1021 {
1022 if (auto midiIn = MidiInput::openDevice (identifier, callbackHandler.get()))
1023 {
1024 enabledMidiInputs.push_back (std::move (midiIn));
1025 enabledMidiInputs.back()->start();
1026 }
1027 }
1028 else
1029 {
1030 auto removePredicate = [identifier] (const std::unique_ptr<MidiInput>& in) { return in->getIdentifier() == identifier; };
1031 enabledMidiInputs.erase (std::remove_if (std::begin (enabledMidiInputs), std::end (enabledMidiInputs), removePredicate),
1032 std::end (enabledMidiInputs));
1033 }
1034
1035 updateXml();
1037 }
1038}
1039
1041{
1042 for (auto& mi : enabledMidiInputs)
1043 if (mi->getIdentifier() == identifier)
1044 return true;
1045
1046 return false;
1047}
1048
1050{
1051 removeMidiInputDeviceCallback (identifier, callbackToAdd);
1052
1053 if (identifier.isEmpty() || isMidiInputDeviceEnabled (identifier))
1054 {
1055 const ScopedLock sl (midiCallbackLock);
1056 midiCallbacks.add ({ identifier, callbackToAdd });
1057 }
1058}
1059
1061{
1062 for (int i = midiCallbacks.size(); --i >= 0;)
1063 {
1064 auto& mc = midiCallbacks.getReference (i);
1065
1066 if (mc.callback == callbackToRemove && mc.deviceIdentifier == identifier)
1067 {
1068 const ScopedLock sl (midiCallbackLock);
1069 midiCallbacks.remove (i);
1070 }
1071 }
1072}
1073
1075{
1076 if (! message.isActiveSense())
1077 {
1078 const ScopedLock sl (midiCallbackLock);
1079
1080 for (auto& mc : midiCallbacks)
1081 if (mc.deviceIdentifier.isEmpty() || mc.deviceIdentifier == source->getIdentifier())
1082 mc.callback->handleIncomingMidiMessage (source, message);
1083 }
1084}
1085
1086//==============================================================================
1088{
1089 if (defaultMidiOutputDeviceInfo.identifier != identifier)
1090 {
1091 std::unique_ptr<MidiOutput> oldMidiPort;
1092 Array<AudioIODeviceCallback*> oldCallbacks;
1093
1094 {
1095 const ScopedLock sl (audioCallbackLock);
1096 oldCallbacks.swapWith (callbacks);
1097 }
1098
1099 if (currentAudioDevice != nullptr)
1100 for (int i = oldCallbacks.size(); --i >= 0;)
1101 oldCallbacks.getUnchecked (i)->audioDeviceStopped();
1102
1103 std::swap (oldMidiPort, defaultMidiOutput);
1104
1105 if (identifier.isNotEmpty())
1107
1108 if (defaultMidiOutput != nullptr)
1110 else
1112
1113 if (currentAudioDevice != nullptr)
1114 for (auto* c : oldCallbacks)
1115 c->audioDeviceAboutToStart (currentAudioDevice.get());
1116
1117 {
1118 const ScopedLock sl (audioCallbackLock);
1119 oldCallbacks.swapWith (callbacks);
1120 }
1121
1122 updateXml();
1124 }
1125}
1126
1127//==============================================================================
1129
1130void AudioDeviceManager::LevelMeter::updateLevel (const float* const* channelData, int numChannels, int numSamples) noexcept
1131{
1132 if (getReferenceCount() <= 1)
1133 return;
1134
1135 auto localLevel = level.get();
1136
1137 if (numChannels > 0)
1138 {
1139 for (int j = 0; j < numSamples; ++j)
1140 {
1141 float s = 0;
1142
1143 for (int i = 0; i < numChannels; ++i)
1144 s += std::abs (channelData[i][j]);
1145
1146 s /= (float) numChannels;
1147
1148 const float decayFactor = 0.99992f;
1149
1150 if (s > localLevel)
1151 localLevel = s;
1152 else if (localLevel > 0.001f)
1153 localLevel *= decayFactor;
1154 else
1155 localLevel = 0;
1156 }
1157 }
1158 else
1159 {
1160 localLevel = 0;
1161 }
1162
1163 level = localLevel;
1164}
1165
1171
1173{
1174 { // cunningly nested to swap, unlock and delete in that order.
1175 std::unique_ptr<AudioBuffer<float>> oldSound;
1176
1177 {
1178 const ScopedLock sl (audioCallbackLock);
1179 std::swap (oldSound, testSound);
1180 }
1181 }
1182
1184
1185 if (currentAudioDevice != nullptr)
1186 {
1187 auto sampleRate = currentAudioDevice->getCurrentSampleRate();
1188 auto soundLength = (int) sampleRate;
1189
1190 double frequency = 440.0;
1191 float amplitude = 0.5f;
1192
1193 auto phasePerSample = MathConstants<double>::twoPi / (sampleRate / frequency);
1194
1195 std::unique_ptr<AudioBuffer<float>> newSound (new AudioBuffer<float> (1, soundLength));
1196
1197 for (int i = 0; i < soundLength; ++i)
1198 newSound->setSample (0, i, amplitude * (float) std::sin (i * phasePerSample));
1199
1200 newSound->applyGainRamp (0, 0, soundLength / 10, 0.0f, 1.0f);
1201 newSound->applyGainRamp (0, soundLength - soundLength / 4, soundLength / 4, 1.0f, 0.0f);
1202
1203 {
1204 const ScopedLock sl (audioCallbackLock);
1205 std::swap (testSound, newSound);
1206 }
1207 }
1208}
1209
1211{
1212 auto deviceXRuns = (currentAudioDevice != nullptr ? currentAudioDevice->getXRunCount() : -1);
1213 return jmax (0, deviceXRuns) + loadMeasurer.getXRunCount();
1214}
1215
1216//==============================================================================
1217// Deprecated
1218void AudioDeviceManager::setMidiInputEnabled (const String& name, const bool enabled)
1219{
1220 for (auto& device : MidiInput::getAvailableDevices())
1221 {
1222 if (device.name == name)
1223 {
1224 setMidiInputDeviceEnabled (device.identifier, enabled);
1225 return;
1226 }
1227 }
1228}
1229
1231{
1232 for (auto& device : MidiInput::getAvailableDevices())
1233 if (device.name == name)
1234 return isMidiInputDeviceEnabled (device.identifier);
1235
1236 return false;
1237}
1238
1240{
1241 if (name.isEmpty())
1242 {
1243 addMidiInputDeviceCallback ({}, callbackToAdd);
1244 }
1245 else
1246 {
1247 for (auto& device : MidiInput::getAvailableDevices())
1248 {
1249 if (device.name == name)
1250 {
1251 addMidiInputDeviceCallback (device.identifier, callbackToAdd);
1252 return;
1253 }
1254 }
1255 }
1256}
1257
1259{
1260 if (name.isEmpty())
1261 {
1262 removeMidiInputDeviceCallback ({}, callbackToRemove);
1263 }
1264 else
1265 {
1266 for (auto& device : MidiInput::getAvailableDevices())
1267 {
1268 if (device.name == name)
1269 {
1270 removeMidiInputDeviceCallback (device.identifier, callbackToRemove);
1271 return;
1272 }
1273 }
1274 }
1275}
1276
1278{
1279 for (auto& device : MidiOutput::getAvailableDevices())
1280 {
1281 if (device.name == name)
1282 {
1283 setDefaultMidiOutputDevice (device.identifier);
1284 return;
1285 }
1286 }
1287}
1288
1289//==============================================================================
1290//==============================================================================
1291#if JUCE_UNIT_TESTS
1292
1293class AudioDeviceManagerTests : public UnitTest
1294{
1295public:
1296 AudioDeviceManagerTests() : UnitTest ("AudioDeviceManager", UnitTestCategories::audio) {}
1297
1298 void runTest() override
1299 {
1300 beginTest ("When the AudioDeviceSetup has non-empty device names, initialise uses the requested devices");
1301 {
1302 AudioDeviceManager manager;
1303 initialiseManager (manager);
1304
1305 expectEquals (manager.getAvailableDeviceTypes().size(), 2);
1306
1307 AudioDeviceManager::AudioDeviceSetup setup;
1308 setup.outputDeviceName = "z";
1309 setup.inputDeviceName = "c";
1310
1311 expect (manager.initialise (2, 2, nullptr, true, String{}, &setup).isEmpty());
1312
1313 const auto& newSetup = manager.getAudioDeviceSetup();
1314
1315 expectEquals (newSetup.outputDeviceName, setup.outputDeviceName);
1316 expectEquals (newSetup.inputDeviceName, setup.inputDeviceName);
1317
1318 expectEquals (newSetup.outputChannels.countNumberOfSetBits(), 2);
1319 expectEquals (newSetup.inputChannels.countNumberOfSetBits(), 2);
1320 }
1321
1322 beginTest ("When the AudioDeviceSetup has empty device names, initialise picks suitable default devices");
1323 {
1324 AudioDeviceManager manager;
1325 initialiseManager (manager);
1326
1327 AudioDeviceManager::AudioDeviceSetup setup;
1328
1329 expect (manager.initialise (2, 2, nullptr, true, String{}, &setup).isEmpty());
1330
1331 const auto& newSetup = manager.getAudioDeviceSetup();
1332
1333 expectEquals (newSetup.outputDeviceName, String ("x"));
1334 expectEquals (newSetup.inputDeviceName, String ("a"));
1335
1336 expectEquals (newSetup.outputChannels.countNumberOfSetBits(), 2);
1337 expectEquals (newSetup.inputChannels.countNumberOfSetBits(), 2);
1338 }
1339
1340 beginTest ("When the preferred device name matches an input and an output on the same type, that type is used");
1341 {
1342 AudioDeviceManager manager;
1343 initialiseManagerWithDifferentDeviceNames (manager);
1344
1345 expect (manager.initialise (2, 2, nullptr, true, "bar *").isEmpty());
1346
1347 expectEquals (manager.getCurrentAudioDeviceType(), String ("bar"));
1348
1349 const auto& newSetup = manager.getAudioDeviceSetup();
1350
1351 expectEquals (newSetup.outputDeviceName, String ("bar out a"));
1352 expectEquals (newSetup.inputDeviceName, String ("bar in a"));
1353
1354 expectEquals (newSetup.outputChannels.countNumberOfSetBits(), 2);
1355 expectEquals (newSetup.inputChannels.countNumberOfSetBits(), 2);
1356
1357 expect (manager.getCurrentAudioDevice() != nullptr);
1358 }
1359
1360 beginTest ("When the preferred device name matches either an input and an output, but not both, that type is used");
1361 {
1362 AudioDeviceManager manager;
1363 initialiseManagerWithDifferentDeviceNames (manager);
1364
1365 expect (manager.initialise (2, 2, nullptr, true, "bar out b").isEmpty());
1366
1367 expectEquals (manager.getCurrentAudioDeviceType(), String ("bar"));
1368
1369 const auto& newSetup = manager.getAudioDeviceSetup();
1370
1371 expectEquals (newSetup.outputDeviceName, String ("bar out b"));
1372 expectEquals (newSetup.inputDeviceName, String ("bar in a"));
1373
1374 expectEquals (newSetup.outputChannels.countNumberOfSetBits(), 2);
1375 expectEquals (newSetup.inputChannels.countNumberOfSetBits(), 2);
1376
1377 expect (manager.getCurrentAudioDevice() != nullptr);
1378 }
1379
1380 beginTest ("When the preferred device name does not match any inputs or outputs, defaults are used");
1381 {
1382 AudioDeviceManager manager;
1383 initialiseManagerWithDifferentDeviceNames (manager);
1384
1385 expect (manager.initialise (2, 2, nullptr, true, "unmatchable").isEmpty());
1386
1387 expectEquals (manager.getCurrentAudioDeviceType(), String ("foo"));
1388
1389 const auto& newSetup = manager.getAudioDeviceSetup();
1390
1391 expectEquals (newSetup.outputDeviceName, String ("foo out a"));
1392 expectEquals (newSetup.inputDeviceName, String ("foo in a"));
1393
1394 expectEquals (newSetup.outputChannels.countNumberOfSetBits(), 2);
1395 expectEquals (newSetup.inputChannels.countNumberOfSetBits(), 2);
1396
1397 expect (manager.getCurrentAudioDevice() != nullptr);
1398 }
1399
1400 beginTest ("When first device type has no devices, a device type with devices is used instead");
1401 {
1402 AudioDeviceManager manager;
1403 initialiseManagerWithEmptyDeviceType (manager);
1404
1405 AudioDeviceManager::AudioDeviceSetup setup;
1406
1407 expect (manager.initialise (2, 2, nullptr, true, {}, &setup).isEmpty());
1408
1409 const auto& newSetup = manager.getAudioDeviceSetup();
1410
1411 expectEquals (newSetup.outputDeviceName, String ("x"));
1412 expectEquals (newSetup.inputDeviceName, String ("a"));
1413
1414 expectEquals (newSetup.outputChannels.countNumberOfSetBits(), 2);
1415 expectEquals (newSetup.inputChannels.countNumberOfSetBits(), 2);
1416 }
1417
1418 beginTest ("If a device type has been explicitly set to a type with devices, "
1419 "initialisation should respect this choice");
1420 {
1421 AudioDeviceManager manager;
1422 initialiseManagerWithEmptyDeviceType (manager);
1423 manager.setCurrentAudioDeviceType (mockBName, true);
1424
1425 AudioDeviceManager::AudioDeviceSetup setup;
1426 expect (manager.initialise (2, 2, nullptr, true, {}, &setup).isEmpty());
1427
1428 expectEquals (manager.getCurrentAudioDeviceType(), mockBName);
1429 }
1430
1431 beginTest ("If a device type has been explicitly set to a type without devices, "
1432 "initialisation should pick a type with devices instead");
1433 {
1434 AudioDeviceManager manager;
1435 initialiseManagerWithEmptyDeviceType (manager);
1436 manager.setCurrentAudioDeviceType (emptyName, true);
1437
1438 AudioDeviceManager::AudioDeviceSetup setup;
1439 expect (manager.initialise (2, 2, nullptr, true, {}, &setup).isEmpty());
1440
1441 expectEquals (manager.getCurrentAudioDeviceType(), mockAName);
1442 }
1443
1444 beginTest ("Carry out a long sequence of configuration changes");
1445 {
1446 AudioDeviceManager manager;
1447 initialiseManagerWithEmptyDeviceType (manager);
1448 initialiseWithDefaultDevices (manager);
1449 disableInputChannelsButLeaveDeviceOpen (manager);
1450 selectANewInputDevice (manager);
1451 disableInputDevice (manager);
1452 reenableInputDeviceWithNoChannels (manager);
1453 enableInputChannels (manager);
1454 disableInputChannelsButLeaveDeviceOpen (manager);
1455 switchDeviceType (manager);
1456 enableInputChannels (manager);
1457 closeDeviceByRequestingEmptyNames (manager);
1458 }
1459
1460 beginTest ("AudioDeviceManager updates its current settings before notifying callbacks when device restarts itself");
1461 {
1462 AudioDeviceManager manager;
1463 auto deviceType = std::make_unique<MockDeviceType> ("foo",
1464 StringArray { "foo in a", "foo in b" },
1465 StringArray { "foo out a", "foo out b" });
1466 auto* ptr = deviceType.get();
1467 manager.addAudioDeviceType (std::move (deviceType));
1468
1469 AudioDeviceManager::AudioDeviceSetup setup;
1470 setup.sampleRate = 48000.0;
1471 setup.bufferSize = 256;
1472 setup.inputDeviceName = "foo in a";
1473 setup.outputDeviceName = "foo out a";
1474 setup.useDefaultInputChannels = true;
1475 setup.useDefaultOutputChannels = true;
1476 manager.setAudioDeviceSetup (setup, true);
1477
1478 const auto currentSetup = manager.getAudioDeviceSetup();
1479 expectEquals (currentSetup.sampleRate, setup.sampleRate);
1480 expectEquals (currentSetup.bufferSize, setup.bufferSize);
1481
1482 MockCallback callback;
1483 manager.addAudioCallback (&callback);
1484
1485 constexpr auto newSr = 10000.0;
1486 constexpr auto newBs = 1024;
1487 auto numCalls = 0;
1488
1489 // Compilers disagree about whether newSr and newBs need to be captured
1490 callback.aboutToStart = [&]
1491 {
1492 ++numCalls;
1493 const auto current = manager.getAudioDeviceSetup();
1494 expectEquals (current.sampleRate, newSr);
1495 expectEquals (current.bufferSize, newBs);
1496 };
1497
1498 ptr->restartDevices (newSr, newBs);
1499 expectEquals (numCalls, 1);
1500 }
1501 }
1502
1503private:
1504 void initialiseWithDefaultDevices (AudioDeviceManager& manager)
1505 {
1506 manager.initialiseWithDefaultDevices (2, 2);
1507 const auto& setup = manager.getAudioDeviceSetup();
1508
1509 expectEquals (setup.inputChannels.countNumberOfSetBits(), 2);
1510 expectEquals (setup.outputChannels.countNumberOfSetBits(), 2);
1511
1512 expect (setup.useDefaultInputChannels);
1513 expect (setup.useDefaultOutputChannels);
1514
1515 expect (manager.getCurrentAudioDevice() != nullptr);
1516 }
1517
1518 void disableInputChannelsButLeaveDeviceOpen (AudioDeviceManager& manager)
1519 {
1520 auto setup = manager.getAudioDeviceSetup();
1521 setup.inputChannels.clear();
1522 setup.useDefaultInputChannels = false;
1523
1524 expect (manager.setAudioDeviceSetup (setup, true).isEmpty());
1525
1526 const auto newSetup = manager.getAudioDeviceSetup();
1527 expectEquals (newSetup.inputChannels.countNumberOfSetBits(), 0);
1528 expectEquals (newSetup.outputChannels.countNumberOfSetBits(), 2);
1529
1530 expect (! newSetup.useDefaultInputChannels);
1531 expect (newSetup.useDefaultOutputChannels);
1532
1533 expectEquals (newSetup.inputDeviceName, setup.inputDeviceName);
1534 expectEquals (newSetup.outputDeviceName, setup.outputDeviceName);
1535
1536 expect (manager.getCurrentAudioDevice() != nullptr);
1537 }
1538
1539 void selectANewInputDevice (AudioDeviceManager& manager)
1540 {
1541 auto setup = manager.getAudioDeviceSetup();
1542 setup.inputDeviceName = "b";
1543
1544 expect (manager.setAudioDeviceSetup (setup, true).isEmpty());
1545
1546 const auto newSetup = manager.getAudioDeviceSetup();
1547 expectEquals (newSetup.inputChannels.countNumberOfSetBits(), 0);
1548 expectEquals (newSetup.outputChannels.countNumberOfSetBits(), 2);
1549
1550 expect (! newSetup.useDefaultInputChannels);
1551 expect (newSetup.useDefaultOutputChannels);
1552
1553 expectEquals (newSetup.inputDeviceName, setup.inputDeviceName);
1554 expectEquals (newSetup.outputDeviceName, setup.outputDeviceName);
1555
1556 expect (manager.getCurrentAudioDevice() != nullptr);
1557 }
1558
1559 void disableInputDevice (AudioDeviceManager& manager)
1560 {
1561 auto setup = manager.getAudioDeviceSetup();
1562 setup.inputDeviceName = "";
1563
1564 expect (manager.setAudioDeviceSetup (setup, true).isEmpty());
1565
1566 const auto newSetup = manager.getAudioDeviceSetup();
1567 expectEquals (newSetup.inputChannels.countNumberOfSetBits(), 0);
1568 expectEquals (newSetup.outputChannels.countNumberOfSetBits(), 2);
1569
1570 expect (! newSetup.useDefaultInputChannels);
1571 expect (newSetup.useDefaultOutputChannels);
1572
1573 expectEquals (newSetup.inputDeviceName, setup.inputDeviceName);
1574 expectEquals (newSetup.outputDeviceName, setup.outputDeviceName);
1575
1576 expect (manager.getCurrentAudioDevice() != nullptr);
1577 }
1578
1579 void reenableInputDeviceWithNoChannels (AudioDeviceManager& manager)
1580 {
1581 auto setup = manager.getAudioDeviceSetup();
1582 setup.inputDeviceName = "a";
1583
1584 expect (manager.setAudioDeviceSetup (setup, true).isEmpty());
1585
1586 const auto newSetup = manager.getAudioDeviceSetup();
1587 expectEquals (newSetup.inputChannels.countNumberOfSetBits(), 0);
1588 expectEquals (newSetup.outputChannels.countNumberOfSetBits(), 2);
1589
1590 expect (! newSetup.useDefaultInputChannels);
1591 expect (newSetup.useDefaultOutputChannels);
1592
1593 expectEquals (newSetup.inputDeviceName, setup.inputDeviceName);
1594 expectEquals (newSetup.outputDeviceName, setup.outputDeviceName);
1595
1596 expect (manager.getCurrentAudioDevice() != nullptr);
1597 }
1598
1599 void enableInputChannels (AudioDeviceManager& manager)
1600 {
1601 auto setup = manager.getAudioDeviceSetup();
1602 setup.inputDeviceName = manager.getCurrentDeviceTypeObject()->getDeviceNames (true)[0];
1603 setup.inputChannels = 3;
1604 setup.useDefaultInputChannels = false;
1605
1606 expect (manager.setAudioDeviceSetup (setup, true).isEmpty());
1607
1608 const auto newSetup = manager.getAudioDeviceSetup();
1609 expectEquals (newSetup.inputChannels.countNumberOfSetBits(), 2);
1610 expectEquals (newSetup.outputChannels.countNumberOfSetBits(), 2);
1611
1612 expect (! newSetup.useDefaultInputChannels);
1613 expect (newSetup.useDefaultOutputChannels);
1614
1615 expectEquals (newSetup.inputDeviceName, setup.inputDeviceName);
1616 expectEquals (newSetup.outputDeviceName, setup.outputDeviceName);
1617
1618 expect (manager.getCurrentAudioDevice() != nullptr);
1619 }
1620
1621 void switchDeviceType (AudioDeviceManager& manager)
1622 {
1623 const auto oldSetup = manager.getAudioDeviceSetup();
1624
1625 expectEquals (manager.getCurrentAudioDeviceType(), String (mockAName));
1626
1627 manager.setCurrentAudioDeviceType (mockBName, true);
1628
1629 expectEquals (manager.getCurrentAudioDeviceType(), String (mockBName));
1630
1631 const auto newSetup = manager.getAudioDeviceSetup();
1632
1633 expect (newSetup.outputDeviceName.isNotEmpty());
1634 // We had no channels enabled, which means we don't need to open a new input device
1635 expect (newSetup.inputDeviceName.isEmpty());
1636
1637 expectEquals (newSetup.inputChannels.countNumberOfSetBits(), 0);
1638 expectEquals (newSetup.outputChannels.countNumberOfSetBits(), 2);
1639
1640 expect (manager.getCurrentAudioDevice() != nullptr);
1641 }
1642
1643 void closeDeviceByRequestingEmptyNames (AudioDeviceManager& manager)
1644 {
1645 auto setup = manager.getAudioDeviceSetup();
1646 setup.inputDeviceName = "";
1647 setup.outputDeviceName = "";
1648
1649 expect (manager.setAudioDeviceSetup (setup, true).isEmpty());
1650
1651 const auto newSetup = manager.getAudioDeviceSetup();
1652 expectEquals (newSetup.inputChannels.countNumberOfSetBits(), 2);
1653 expectEquals (newSetup.outputChannels.countNumberOfSetBits(), 2);
1654
1655 expect (newSetup.inputDeviceName.isEmpty());
1656 expect (newSetup.outputDeviceName.isEmpty());
1657
1658 expect (manager.getCurrentAudioDevice() == nullptr);
1659 }
1660
1661 const String mockAName = "mockA";
1662 const String mockBName = "mockB";
1663 const String emptyName = "empty";
1664
1665 struct Restartable
1666 {
1667 virtual ~Restartable() = default;
1668 virtual void restart (double newSr, int newBs) = 0;
1669 };
1670
1671 class MockDevice : public AudioIODevice,
1672 private Restartable
1673 {
1674 public:
1675 MockDevice (ListenerList<Restartable>& l, String typeNameIn, String outNameIn, String inNameIn)
1676 : AudioIODevice ("mock", typeNameIn), listeners (l), outName (outNameIn), inName (inNameIn)
1677 {
1678 listeners.add (this);
1679 }
1680
1681 ~MockDevice() override
1682 {
1683 listeners.remove (this);
1684 }
1685
1686 StringArray getOutputChannelNames() override { return { "o1", "o2", "o3" }; }
1687 StringArray getInputChannelNames() override { return { "i1", "i2", "i3" }; }
1688
1689 Array<double> getAvailableSampleRates() override { return { 44100.0, 48000.0 }; }
1690 Array<int> getAvailableBufferSizes() override { return { 128, 256 }; }
1691 int getDefaultBufferSize() override { return 128; }
1692
1693 String open (const BigInteger& inputs, const BigInteger& outputs, double sr, int bs) override
1694 {
1695 inChannels = inputs;
1696 outChannels = outputs;
1697 sampleRate = sr;
1698 blockSize = bs;
1699 on = true;
1700 return {};
1701 }
1702
1703 void close() override { on = false; }
1704 bool isOpen() override { return on; }
1705
1706 void start (AudioIODeviceCallback* c) override
1707 {
1708 callback = c;
1709 callback->audioDeviceAboutToStart (this);
1710 playing = true;
1711 }
1712
1713 void stop() override
1714 {
1715 playing = false;
1716 callback->audioDeviceStopped();
1717 }
1718
1719 bool isPlaying() override { return playing; }
1720
1721 String getLastError() override { return {}; }
1722 int getCurrentBufferSizeSamples() override { return blockSize; }
1723 double getCurrentSampleRate() override { return sampleRate; }
1724 int getCurrentBitDepth() override { return 16; }
1725
1726 BigInteger getActiveOutputChannels() const override { return outChannels; }
1727 BigInteger getActiveInputChannels() const override { return inChannels; }
1728
1729 int getOutputLatencyInSamples() override { return 0; }
1730 int getInputLatencyInSamples() override { return 0; }
1731
1732 private:
1733 void restart (double newSr, int newBs) override
1734 {
1735 stop();
1736 close();
1737 open (inChannels, outChannels, newSr, newBs);
1738 start (callback);
1739 }
1740
1741 ListenerList<Restartable>& listeners;
1742 AudioIODeviceCallback* callback = nullptr;
1743 String outName, inName;
1744 BigInteger outChannels, inChannels;
1745 double sampleRate = 0.0;
1746 int blockSize = 0;
1747 bool on = false, playing = false;
1748 };
1749
1750 class MockDeviceType : public AudioIODeviceType
1751 {
1752 public:
1753 explicit MockDeviceType (String kind)
1754 : MockDeviceType (std::move (kind), { "a", "b", "c" }, { "x", "y", "z" }) {}
1755
1756 MockDeviceType (String kind, StringArray inputNames, StringArray outputNames)
1757 : AudioIODeviceType (std::move (kind)),
1758 inNames (std::move (inputNames)),
1759 outNames (std::move (outputNames)) {}
1760
1761 ~MockDeviceType() override
1762 {
1763 // A Device outlived its DeviceType!
1764 jassert (listeners.isEmpty());
1765 }
1766
1767 void scanForDevices() override {}
1768
1769 StringArray getDeviceNames (bool isInput) const override
1770 {
1771 return getNames (isInput);
1772 }
1773
1774 int getDefaultDeviceIndex (bool) const override { return 0; }
1775
1776 int getIndexOfDevice (AudioIODevice* device, bool isInput) const override
1777 {
1778 return getNames (isInput).indexOf (device->getName());
1779 }
1780
1781 bool hasSeparateInputsAndOutputs() const override { return true; }
1782
1783 AudioIODevice* createDevice (const String& outputName, const String& inputName) override
1784 {
1785 if (inNames.contains (inputName) || outNames.contains (outputName))
1786 return new MockDevice (listeners, getTypeName(), outputName, inputName);
1787
1788 return nullptr;
1789 }
1790
1791 // Call this to emulate the device restarting itself with new settings.
1792 // This might happen e.g. when a user changes the ASIO settings.
1793 void restartDevices (double newSr, int newBs)
1794 {
1795 listeners.call ([&] (auto& l) { return l.restart (newSr, newBs); });
1796 }
1797
1798 private:
1799 const StringArray& getNames (bool isInput) const { return isInput ? inNames : outNames; }
1800
1801 const StringArray inNames, outNames;
1802 ListenerList<Restartable> listeners;
1803 };
1804
1805 class MockCallback : public AudioIODeviceCallback
1806 {
1807 public:
1808 std::function<void()> callback;
1809 std::function<void()> aboutToStart;
1810 std::function<void()> stopped;
1811 std::function<void()> error;
1812
1813 void audioDeviceIOCallback (const float**, int, float**, int, int) override { NullCheckedInvocation::invoke (callback); }
1814 void audioDeviceAboutToStart (AudioIODevice*) override { NullCheckedInvocation::invoke (aboutToStart); }
1815 void audioDeviceStopped() override { NullCheckedInvocation::invoke (stopped); }
1816 void audioDeviceError (const String&) override { NullCheckedInvocation::invoke (error); }
1817 };
1818
1819 void initialiseManager (AudioDeviceManager& manager)
1820 {
1821 manager.addAudioDeviceType (std::make_unique<MockDeviceType> (mockAName));
1822 manager.addAudioDeviceType (std::make_unique<MockDeviceType> (mockBName));
1823 }
1824
1825 void initialiseManagerWithEmptyDeviceType (AudioDeviceManager& manager)
1826 {
1827 manager.addAudioDeviceType (std::make_unique<MockDeviceType> (emptyName, StringArray{}, StringArray{}));
1828 initialiseManager (manager);
1829 }
1830
1831 void initialiseManagerWithDifferentDeviceNames (AudioDeviceManager& manager)
1832 {
1833 manager.addAudioDeviceType (std::make_unique<MockDeviceType> ("foo",
1834 StringArray { "foo in a", "foo in b" },
1835 StringArray { "foo out a", "foo out b" }));
1836
1837 manager.addAudioDeviceType (std::make_unique<MockDeviceType> ("bar",
1838 StringArray { "bar in a", "bar in b" },
1839 StringArray { "bar out a", "bar out b" }));
1840 }
1841};
1842
1843static AudioDeviceManagerTests audioDeviceManagerTests;
1844
1845#endif
1846
1847} // namespace juce
Type jmin(const Type a, const Type b)
Definition MathsFunctions.h:60
Type jmax(const Type a, const Type b)
Definition MathsFunctions.h:48
#define noexcept
Definition DistrhoDefines.h:72
CAdPlugDatabase::CRecord::RecordType type
Definition adplugdb.cpp:93
static void message(int level, const char *fmt,...)
Definition adplugdb.cpp:120
Definition String.h:48
Definition juce_Array.h:56
void swapWith(OtherArrayType &otherArray) noexcept
Definition juce_Array.h:621
ElementType getUnchecked(int index) const
Definition juce_Array.h:252
int size() const noexcept
Definition juce_Array.h:215
Definition juce_AudioSampleBuffer.h:34
Definition juce_AudioDeviceManager.cpp:67
void audioDeviceListChanged() override
Definition juce_AudioDeviceManager.cpp:102
AudioDeviceManager & owner
Definition juce_AudioDeviceManager.cpp:107
void audioDeviceIOCallbackWithContext(const float **ins, int numIns, float **outs, int numOuts, int numSamples, const AudioIODeviceCallbackContext &context) override
Definition juce_AudioDeviceManager.cpp:72
void audioDeviceAboutToStart(AudioIODevice *device) override
Definition juce_AudioDeviceManager.cpp:82
void handleIncomingMidiMessage(MidiInput *source, const MidiMessage &message) override
Definition juce_AudioDeviceManager.cpp:97
CallbackHandler(AudioDeviceManager &adm) noexcept
Definition juce_AudioDeviceManager.cpp:69
void audioDeviceError(const String &message) override
Definition juce_AudioDeviceManager.cpp:92
void audioDeviceStopped() override
Definition juce_AudioDeviceManager.cpp:87
bool isMidiInputDeviceEnabled(const String &deviceIdentifier) const
Definition juce_AudioDeviceManager.cpp:1040
AudioDeviceManager()
Definition juce_AudioDeviceManager.cpp:113
String preferredDeviceName
Definition juce_AudioDeviceManager.h:498
int numInputChansNeeded
Definition juce_AudioDeviceManager.h:497
void handleIncomingMidiMessageInt(MidiInput *, const MidiMessage &)
Definition juce_AudioDeviceManager.cpp:1074
void removeAudioDeviceType(AudioIODeviceType *deviceTypeToRemove)
Definition juce_AudioDeviceManager.cpp:260
Array< MidiDeviceInfo > midiDeviceInfosFromXml
Definition juce_AudioDeviceManager.h:509
AudioDeviceSetup getAudioDeviceSetup() const
Definition juce_AudioDeviceManager.cpp:563
void insertDefaultDeviceNames(AudioDeviceSetup &) const
Definition juce_AudioDeviceManager.cpp:503
std::vector< std::unique_ptr< MidiInput > > enabledMidiInputs
Definition juce_AudioDeviceManager.h:510
void removeMidiInputDeviceCallback(const String &deviceIdentifier, MidiInputCallback *callback)
Definition juce_AudioDeviceManager.cpp:1060
double getCpuUsage() const
Definition juce_AudioDeviceManager.cpp:1010
void createDeviceTypesIfNeeded()
Definition juce_AudioDeviceManager.cpp:125
AudioIODeviceType * getCurrentDeviceTypeObject() const
Definition juce_AudioDeviceManager.cpp:607
void audioDeviceStoppedInt()
Definition juce_AudioDeviceManager.cpp:990
String setAudioDeviceSetup(const AudioDeviceSetup &newSetup, bool treatAsChosenDevice)
Definition juce_AudioDeviceManager.cpp:635
void removeMidiInputCallback(const String &, MidiInputCallback *)
Definition juce_AudioDeviceManager.cpp:1258
void audioDeviceIOCallbackInt(const float **inputChannelData, int totalNumInputChannels, float **outputChannelData, int totalNumOutputChannels, int numSamples, const AudioIODeviceCallbackContext &context)
Definition juce_AudioDeviceManager.cpp:904
AudioDeviceSetup currentSetup
Definition juce_AudioDeviceManager.h:494
bool isMidiInputEnabled(const String &) const
Definition juce_AudioDeviceManager.cpp:1230
MidiDeviceInfo defaultMidiOutputDeviceInfo
Definition juce_AudioDeviceManager.h:513
virtual void createAudioDeviceTypes(OwnedArray< AudioIODeviceType > &types)
Definition juce_AudioDeviceManager.cpp:230
void stopDevice()
Definition juce_AudioDeviceManager.cpp:780
void audioDeviceErrorInt(const String &)
Definition juce_AudioDeviceManager.cpp:1002
void deleteCurrentDevice()
Definition juce_AudioDeviceManager.cpp:573
std::unique_ptr< AudioIODevice > currentAudioDevice
Definition juce_AudioDeviceManager.h:495
std::unique_ptr< CallbackHandler > callbackHandler
Definition juce_AudioDeviceManager.h:527
void setMidiInputEnabled(const String &, bool)
Definition juce_AudioDeviceManager.cpp:1218
void audioDeviceAboutToStartInt(AudioIODevice *)
Definition juce_AudioDeviceManager.cpp:973
void setDefaultMidiOutputDevice(const String &deviceIdentifier)
Definition juce_AudioDeviceManager.cpp:1087
CriticalSection audioCallbackLock
Definition juce_AudioDeviceManager.h:515
void setMidiInputDeviceEnabled(const String &deviceIdentifier, bool enabled)
Definition juce_AudioDeviceManager.cpp:1016
void setDefaultMidiOutput(const String &)
Definition juce_AudioDeviceManager.cpp:1277
void audioDeviceListChanged()
Definition juce_AudioDeviceManager.cpp:181
int getXRunCount() const noexcept
Definition juce_AudioDeviceManager.cpp:1210
void pickCurrentDeviceTypeWithDevices()
Definition juce_AudioDeviceManager.cpp:144
OwnedArray< AudioDeviceSetup > lastDeviceTypeConfigs
Definition juce_AudioDeviceManager.h:492
Array< MidiCallbackInfo > midiCallbacks
Definition juce_AudioDeviceManager.h:511
AudioBuffer< float > tempBuffer
Definition juce_AudioDeviceManager.h:501
LevelMeter::Ptr outputLevelGetter
Definition juce_AudioDeviceManager.h:523
void addMidiInputCallback(const String &, MidiInputCallback *)
Definition juce_AudioDeviceManager.cpp:1239
void addMidiInputDeviceCallback(const String &deviceIdentifier, MidiInputCallback *callback)
Definition juce_AudioDeviceManager.cpp:1049
OwnedArray< AudioIODeviceType > availableDeviceTypes
Definition juce_AudioDeviceManager.h:491
void setCurrentAudioDeviceType(const String &type, bool treatAsChosenDevice)
Definition juce_AudioDeviceManager.cpp:580
void updateCurrentSetup()
Definition juce_AudioDeviceManager.cpp:170
std::unique_ptr< MidiOutput > defaultMidiOutput
Definition juce_AudioDeviceManager.h:514
~AudioDeviceManager() override
Definition juce_AudioDeviceManager.cpp:118
const OwnedArray< AudioIODeviceType > & getAvailableDeviceTypes()
Definition juce_AudioDeviceManager.cpp:164
int numOutputChansNeeded
Definition juce_AudioDeviceManager.h:497
void scanDevicesIfNeeded()
Definition juce_AudioDeviceManager.cpp:527
String initialise(int numInputChannelsNeeded, int numOutputChannelsNeeded, const XmlElement *savedState, bool selectDefaultDeviceOnFailure, const String &preferredDefaultDeviceName=String(), const AudioDeviceSetup *preferredSetupOptions=nullptr)
Definition juce_AudioDeviceManager.cpp:286
void addAudioCallback(AudioIODeviceCallback *newCallback)
Definition juce_AudioDeviceManager.cpp:870
LevelMeter::Ptr inputLevelGetter
Definition juce_AudioDeviceManager.h:522
String currentDeviceType
Definition juce_AudioDeviceManager.h:498
std::unique_ptr< XmlElement > lastExplicitSettings
Definition juce_AudioDeviceManager.h:499
String initialiseWithDefaultDevices(int numInputChannelsNeeded, int numOutputChannelsNeeded)
Definition juce_AudioDeviceManager.cpp:494
void restartLastAudioDevice()
Definition juce_AudioDeviceManager.cpp:795
AudioIODeviceType * findType(const String &inputName, const String &outputName)
Definition juce_AudioDeviceManager.cpp:551
String initialiseDefault(const String &preferredDefaultDeviceName, const AudioDeviceSetup *)
Definition juce_AudioDeviceManager.cpp:307
int testSoundPosition
Definition juce_AudioDeviceManager.h:518
Array< AudioIODeviceCallback * > callbacks
Definition juce_AudioDeviceManager.h:496
void updateXml()
Definition juce_AudioDeviceManager.cpp:814
std::unique_ptr< AudioBuffer< float > > testSound
Definition juce_AudioDeviceManager.h:517
void removeAudioCallback(AudioIODeviceCallback *callback)
Definition juce_AudioDeviceManager.cpp:886
int chooseBestBufferSize(int preferred) const
Definition juce_AudioDeviceManager.cpp:770
CriticalSection midiCallbackLock
Definition juce_AudioDeviceManager.h:515
AudioProcessLoadMeasurer loadMeasurer
Definition juce_AudioDeviceManager.h:520
void playTestSound()
Definition juce_AudioDeviceManager.cpp:1172
double chooseBestSampleRate(double preferred) const
Definition juce_AudioDeviceManager.cpp:740
bool listNeedsScanning
Definition juce_AudioDeviceManager.h:500
void addAudioDeviceType(std::unique_ptr< AudioIODeviceType > newDeviceType)
Definition juce_AudioDeviceManager.cpp:247
String initialiseFromXML(const XmlElement &, bool selectDefaultDeviceOnFailure, const String &preferredDefaultDeviceName, const AudioDeviceSetup *)
Definition juce_AudioDeviceManager.cpp:385
void closeAudioDevice()
Definition juce_AudioDeviceManager.cpp:788
std::unique_ptr< XmlElement > createStateXml() const
Definition juce_AudioDeviceManager.cpp:518
Definition juce_AudioIODevice.h:51
virtual void audioDeviceAboutToStart(AudioIODevice *device)=0
virtual void audioDeviceStopped()=0
Definition juce_AudioIODevice.h:164
virtual double getCurrentSampleRate()=0
virtual int getCurrentBufferSizeSamples()=0
Definition juce_AudioIODeviceType.h:126
Definition juce_AudioIODeviceType.h:62
static AudioIODeviceType * createAudioIODeviceType_WASAPI(WASAPIDeviceMode deviceMode)
Definition juce_AudioIODeviceType.cpp:75
static AudioIODeviceType * createAudioIODeviceType_ASIO()
Definition juce_AudioIODeviceType.cpp:88
static AudioIODeviceType * createAudioIODeviceType_Oboe()
Definition juce_AudioIODeviceType.cpp:143
static AudioIODeviceType * createAudioIODeviceType_JACK()
Definition juce_AudioIODeviceType.cpp:100
static AudioIODeviceType * createAudioIODeviceType_DirectSound()
Definition juce_AudioIODeviceType.cpp:82
static AudioIODeviceType * createAudioIODeviceType_Android()
Definition juce_AudioIODeviceType.cpp:125
static AudioIODeviceType * createAudioIODeviceType_OpenSLES()
Definition juce_AudioIODeviceType.cpp:134
static AudioIODeviceType * createAudioIODeviceType_CoreAudio()
Definition juce_AudioIODeviceType.cpp:48
static AudioIODeviceType * createAudioIODeviceType_Bela()
Definition juce_AudioIODeviceType.cpp:106
static AudioIODeviceType * createAudioIODeviceType_ALSA()
Definition juce_AudioIODeviceType.cpp:94
static AudioIODeviceType * createAudioIODeviceType_iOSAudio()
Definition juce_AudioIODeviceType.cpp:54
Definition juce_BigInteger.h:39
void parseString(StringRef text, int base)
Definition juce_BigInteger.cpp:1128
void sendChangeMessage()
Definition juce_ChangeBroadcaster.cpp:65
void sendSynchronousChangeMessage()
Definition juce_ChangeBroadcaster.cpp:71
Definition juce_MidiDevices.h:195
Definition juce_MidiDevices.h:82
static Array< MidiDeviceInfo > getAvailableDevices()
Definition juce_linux_Bela.cpp:539
static std::unique_ptr< MidiInput > openDevice(const String &deviceIdentifier, MidiInputCallback *callback)
Definition juce_linux_Bela.cpp:549
String getIdentifier() const noexcept
Definition juce_MidiDevices.h:151
Definition juce_MidiMessage.h:35
static std::unique_ptr< MidiOutput > openDevice(const String &deviceIdentifier)
Definition juce_linux_Bela.cpp:594
static Array< MidiDeviceInfo > getAvailableDevices()
Definition juce_linux_Bela.cpp:592
Definition juce_OwnedArray.h:51
void clear(bool deleteObjects=true)
Definition juce_OwnedArray.h:107
int getReferenceCount() const noexcept
Definition juce_ReferenceCountedObject.h:101
Definition juce_StringArray.h:35
Definition juce_String.h:53
bool isEmpty() const noexcept
Definition juce_String.h:310
CharPointerType end() const
Definition juce_String.h:949
bool isNotEmpty() const noexcept
Definition juce_String.h:316
static void JUCE_CALLTYPE sleep(int milliseconds)
Definition juce_posix_SharedCode.h:44
Definition juce_UnitTest.h:70
Definition juce_XmlElement.h:83
double getDoubleAttribute(StringRef attributeName, double defaultReturnValue=0.0) const
Definition juce_XmlElement.cpp:579
Iterator< GetNextElementWithTagName > getChildWithTagNameIterator(StringRef name) const
Definition juce_XmlElement.h:730
bool hasAttribute(StringRef attributeName) const noexcept
Definition juce_XmlElement.cpp:549
bool hasTagName(StringRef possibleTagName) const noexcept
Definition juce_XmlElement.cpp:470
int getIntAttribute(StringRef attributeName, int defaultReturnValue=0) const
Definition juce_XmlElement.cpp:571
const String & getStringAttribute(StringRef attributeName) const noexcept
Definition juce_XmlElement.cpp:555
* e
Definition inflate.c:1404
int * l
Definition inflate.c:1579
struct huft * t
Definition inflate.c:943
register unsigned j
Definition inflate.c:1576
unsigned d
Definition inflate.c:940
register unsigned i
Definition inflate.c:1575
unsigned s
Definition inflate.c:1555
static PuglViewHint int value
Definition pugl.h:1708
static const char * name
Definition pugl.h:1582
virtual ASIOError stop()=0
virtual ASIOError start()=0
struct backing_store_struct * info
Definition jmemsys.h:183
#define jassert(expression)
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
#define jassertfalse
float in
Definition lilv_test.c:1460
Definition juce_UnitTestCategories.h:27
void move(void *from, void *to)
Definition juce_FixedSizeFunction.h:53
Definition carla_juce.cpp:31
CriticalSection::ScopedLockType ScopedLock
Definition juce_CriticalSection.h:186
static void addIfNotNull(OwnedArray< AudioIODeviceType > &list, AudioIODeviceType *const device)
Definition juce_AudioDeviceManager.cpp:224
constexpr Type jmax(Type a, Type b)
Definition juce_MathsFunctions.h:94
static bool deviceListContains(AudioIODeviceType *type, bool isInput, const String &name)
Definition juce_AudioDeviceManager.cpp:276
static auto tie(const AudioDeviceManager::AudioDeviceSetup &s)
Definition juce_AudioDeviceManager.cpp:41
jack_client_t client jack_client_t client jack_client_t client jack_client_t JackInfoShutdownCallback void arg jack_client_t jack_port_t port void func jack_client_t const char const char unsigned long flags const jack_port_t port jack_client_t jack_port_id_t port_id const jack_port_t const char port_name const jack_port_t port void * ptr
Definition juce_linux_JackAudio.cpp:79
static void updateSetupChannels(AudioDeviceManager::AudioDeviceSetup &setup, int defaultNumIns, int defaultNumOuts)
Definition juce_AudioDeviceManager.cpp:616
static auto getSetupInfo(Setup &s, bool isInput)
Definition juce_AudioDeviceManager.cpp:27
@ shared
Definition juce_audio_devices.h:175
@ exclusive
Definition juce_audio_devices.h:176
@ sharedLowLatency
Definition juce_audio_devices.h:177
@ list
Definition juce_AccessibilityRole.h:56
void zeromem(void *memory, size_t numBytes) noexcept
Definition juce_Memory.h:28
Definition juce_AudioDeviceManager.h:91
String outputDeviceName
Definition juce_AudioDeviceManager.h:97
bool useDefaultInputChannels
Definition juce_AudioDeviceManager.h:128
String inputDeviceName
Definition juce_AudioDeviceManager.h:102
BigInteger outputChannels
Definition juce_AudioDeviceManager.h:135
double sampleRate
Definition juce_AudioDeviceManager.h:109
BigInteger inputChannels
Definition juce_AudioDeviceManager.h:122
int bufferSize
Definition juce_AudioDeviceManager.h:115
bool useDefaultOutputChannels
Definition juce_AudioDeviceManager.h:141
double getCurrentLevel() const noexcept
Definition juce_AudioDeviceManager.cpp:1166
void updateLevel(const float *const *, int numChannels, int numSamples) noexcept
Definition juce_AudioDeviceManager.cpp:1130
LevelMeter() noexcept
Definition juce_AudioDeviceManager.cpp:1128
Atomic< float > level
Definition juce_AudioDeviceManager.h:433
Definition juce_AudioIODevice.h:30
Definition juce_AudioProcessLoadMeasurer.h:73
static constexpr FloatType twoPi
Definition juce_MathsFunctions.h:385
Definition juce_MidiDevices.h:37
String name
Definition juce_MidiDevices.h:54
String identifier
Definition juce_MidiDevices.h:61
RECT const char void(* callback)(const char *droppath))) SWELL_API_DEFINE(BOOL
Definition swell-functions.h:1004
return c
Definition crypt.c:175
int error
Definition extract.c:1038
int result
Definition process.c:1455
typedef int(UZ_EXP MsgFn)()
#define void
Definition unzip.h:396
#define const
Definition zconf.h:137