OpenShot Library | libopenshot-audio  0.2.0
juce_AudioDeviceManager.cpp
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2017 - ROLI Ltd.
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 
23 namespace juce
24 {
25 
26 bool AudioDeviceManager::AudioDeviceSetup::operator== (const AudioDeviceManager::AudioDeviceSetup& other) const
27 {
28  return outputDeviceName == other.outputDeviceName
29  && inputDeviceName == other.inputDeviceName
30  && sampleRate == other.sampleRate
31  && bufferSize == other.bufferSize
32  && inputChannels == other.inputChannels
33  && useDefaultInputChannels == other.useDefaultInputChannels
34  && outputChannels == other.outputChannels
35  && useDefaultOutputChannels == other.useDefaultOutputChannels;
36 }
37 
38 bool AudioDeviceManager::AudioDeviceSetup::operator!= (const AudioDeviceManager::AudioDeviceSetup& other) const
39 {
40  return ! operator== (other);
41 }
42 
43 //==============================================================================
45  public MidiInputCallback,
47 {
48 public:
49  CallbackHandler (AudioDeviceManager& adm) noexcept : owner (adm) {}
50 
51 private:
52  void audioDeviceIOCallback (const float** ins, int numIns, float** outs, int numOuts, int numSamples) override
53  {
54  owner.audioDeviceIOCallbackInt (ins, numIns, outs, numOuts, numSamples);
55  }
56 
57  void audioDeviceAboutToStart (AudioIODevice* device) override
58  {
59  owner.audioDeviceAboutToStartInt (device);
60  }
61 
62  void audioDeviceStopped() override
63  {
64  owner.audioDeviceStoppedInt();
65  }
66 
67  void audioDeviceError (const String& message) override
68  {
69  owner.audioDeviceErrorInt (message);
70  }
71 
72  void handleIncomingMidiMessage (MidiInput* source, const MidiMessage& message) override
73  {
74  owner.handleIncomingMidiMessageInt (source, message);
75  }
76 
77  void audioDeviceListChanged() override
78  {
79  owner.audioDeviceListChanged();
80  }
81 
82  AudioDeviceManager& owner;
83 
84  JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CallbackHandler)
85 };
86 
87 //==============================================================================
89 {
90  callbackHandler.reset (new CallbackHandler (*this));
91 }
92 
94 {
95  currentAudioDevice.reset();
96  defaultMidiOutput.reset();
97 }
98 
99 //==============================================================================
100 void AudioDeviceManager::createDeviceTypesIfNeeded()
101 {
102  if (availableDeviceTypes.size() == 0)
103  {
105  createAudioDeviceTypes (types);
106 
107  for (auto* t : types)
108  addAudioDeviceType (t);
109 
110  types.clear (false);
111 
112  if (auto* first = availableDeviceTypes.getFirst())
113  currentDeviceType = first->getTypeName();
114  }
115 }
116 
118 {
119  scanDevicesIfNeeded();
120  return availableDeviceTypes;
121 }
122 
123 void AudioDeviceManager::audioDeviceListChanged()
124 {
125  if (currentAudioDevice != nullptr)
126  {
127  auto isCurrentDeviceStillAvailable = [&]
128  {
129  for (auto* dt : availableDeviceTypes)
130  if (currentAudioDevice->getTypeName() == dt->getTypeName())
131  for (auto& dn : dt->getDeviceNames())
132  if (currentAudioDevice->getName() == dn)
133  return true;
134 
135  return false;
136  };
137 
138  if (! isCurrentDeviceStillAvailable())
139  {
141 
142  std::unique_ptr<XmlElement> e (createStateXml());
143 
144  if (e == nullptr)
145  initialiseDefault (preferredDeviceName, &currentSetup);
146  else
147  initialiseFromXML (*e, true, preferredDeviceName, &currentSetup);
148  }
149 
150  if (currentAudioDevice != nullptr)
151  {
152  currentSetup.sampleRate = currentAudioDevice->getCurrentSampleRate();
153  currentSetup.bufferSize = currentAudioDevice->getCurrentBufferSizeSamples();
154  currentSetup.inputChannels = currentAudioDevice->getActiveInputChannels();
155  currentSetup.outputChannels = currentAudioDevice->getActiveOutputChannels();
156  }
157  }
158 
160 }
161 
162 //==============================================================================
163 static void addIfNotNull (OwnedArray<AudioIODeviceType>& list, AudioIODeviceType* const device)
164 {
165  if (device != nullptr)
166  list.add (device);
167 }
168 
170 {
171  addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_WASAPI (false));
172  addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_WASAPI (true));
183 }
184 
186 {
187  if (newDeviceType != nullptr)
188  {
189  jassert (lastDeviceTypeConfigs.size() == availableDeviceTypes.size());
190  availableDeviceTypes.add (newDeviceType);
191  lastDeviceTypeConfigs.add (new AudioDeviceSetup());
192 
193  newDeviceType->addListener (callbackHandler.get());
194  }
195 }
196 
197 static bool deviceListContains (AudioIODeviceType* type, bool isInput, const String& name)
198 {
199  for (auto& deviceName : type->getDeviceNames (isInput))
200  if (deviceName.trim().equalsIgnoreCase (name.trim()))
201  return true;
202 
203  return false;
204 }
205 
206 //==============================================================================
207 String AudioDeviceManager::initialise (const int numInputChannelsNeeded,
208  const int numOutputChannelsNeeded,
209  const XmlElement* const xml,
210  const bool selectDefaultDeviceOnFailure,
211  const String& preferredDefaultDeviceName,
212  const AudioDeviceSetup* preferredSetupOptions)
213 {
214  scanDevicesIfNeeded();
215 
216  numInputChansNeeded = numInputChannelsNeeded;
217  numOutputChansNeeded = numOutputChannelsNeeded;
218  preferredDeviceName = preferredDefaultDeviceName;
219 
220  if (xml != nullptr && xml->hasTagName ("DEVICESETUP"))
221  return initialiseFromXML (*xml, selectDefaultDeviceOnFailure,
222  preferredDeviceName, preferredSetupOptions);
223 
224  return initialiseDefault (preferredDeviceName, preferredSetupOptions);
225 }
226 
227 String AudioDeviceManager::initialiseDefault (const String& preferredDefaultDeviceName,
228  const AudioDeviceSetup* preferredSetupOptions)
229 {
230  AudioDeviceSetup setup;
231 
232  if (preferredSetupOptions != nullptr)
233  {
234  setup = *preferredSetupOptions;
235  }
236  else if (preferredDefaultDeviceName.isNotEmpty())
237  {
238  for (auto* type : availableDeviceTypes)
239  {
240  for (auto& out : type->getDeviceNames (false))
241  {
242  if (out.matchesWildcard (preferredDefaultDeviceName, true))
243  {
244  setup.outputDeviceName = out;
245  break;
246  }
247  }
248 
249  for (auto& in : type->getDeviceNames (true))
250  {
251  if (in.matchesWildcard (preferredDefaultDeviceName, true))
252  {
253  setup.inputDeviceName = in;
254  break;
255  }
256  }
257  }
258  }
259 
260  insertDefaultDeviceNames (setup);
261  return setAudioDeviceSetup (setup, false);
262 }
263 
264 String AudioDeviceManager::initialiseFromXML (const XmlElement& xml,
265  bool selectDefaultDeviceOnFailure,
266  const String& preferredDefaultDeviceName,
267  const AudioDeviceSetup* preferredSetupOptions)
268 {
269  lastExplicitSettings.reset (new XmlElement (xml));
270 
271  String error;
272  AudioDeviceSetup setup;
273 
274  if (preferredSetupOptions != nullptr)
275  setup = *preferredSetupOptions;
276 
277  if (xml.getStringAttribute ("audioDeviceName").isNotEmpty())
278  {
279  setup.inputDeviceName = setup.outputDeviceName
280  = xml.getStringAttribute ("audioDeviceName");
281  }
282  else
283  {
284  setup.inputDeviceName = xml.getStringAttribute ("audioInputDeviceName");
285  setup.outputDeviceName = xml.getStringAttribute ("audioOutputDeviceName");
286  }
287 
288  currentDeviceType = xml.getStringAttribute ("deviceType");
289 
290  if (findType (currentDeviceType) == nullptr)
291  {
292  if (auto* type = findType (setup.inputDeviceName, setup.outputDeviceName))
293  currentDeviceType = type->getTypeName();
294  else if (auto* firstType = availableDeviceTypes.getFirst())
295  currentDeviceType = firstType->getTypeName();
296  }
297 
298  setup.bufferSize = xml.getIntAttribute ("audioDeviceBufferSize", setup.bufferSize);
299  setup.sampleRate = xml.getDoubleAttribute ("audioDeviceRate", setup.sampleRate);
300 
301  setup.inputChannels .parseString (xml.getStringAttribute ("audioDeviceInChans", "11"), 2);
302  setup.outputChannels.parseString (xml.getStringAttribute ("audioDeviceOutChans", "11"), 2);
303 
304  setup.useDefaultInputChannels = ! xml.hasAttribute ("audioDeviceInChans");
305  setup.useDefaultOutputChannels = ! xml.hasAttribute ("audioDeviceOutChans");
306 
307  error = setAudioDeviceSetup (setup, true);
308 
309  midiInsFromXml.clear();
310 
311  forEachXmlChildElementWithTagName (xml, c, "MIDIINPUT")
312  midiInsFromXml.add (c->getStringAttribute ("name"));
313 
314  for (auto& m : MidiInput::getDevices())
315  setMidiInputEnabled (m, midiInsFromXml.contains (m));
316 
317  if (error.isNotEmpty() && selectDefaultDeviceOnFailure)
318  error = initialise (numInputChansNeeded, numOutputChansNeeded,
319  nullptr, false, preferredDefaultDeviceName);
320 
321  setDefaultMidiOutput (xml.getStringAttribute ("defaultMidiOutput"));
322 
323  return error;
324 }
325 
327  int numOutputChannelsNeeded)
328 {
329  lastExplicitSettings.reset();
330 
331  return initialise (numInputChannelsNeeded, numOutputChannelsNeeded,
332  nullptr, false, {}, nullptr);
333 }
334 
335 void AudioDeviceManager::insertDefaultDeviceNames (AudioDeviceSetup& setup) const
336 {
337  if (auto* type = getCurrentDeviceTypeObject())
338  {
339  if (numOutputChansNeeded > 0 && setup.outputDeviceName.isEmpty())
340  setup.outputDeviceName = type->getDeviceNames (false) [type->getDefaultDeviceIndex (false)];
341 
342  if (numInputChansNeeded > 0 && setup.inputDeviceName.isEmpty())
343  setup.inputDeviceName = type->getDeviceNames (true) [type->getDefaultDeviceIndex (true)];
344  }
345 }
346 
348 {
349  return createCopyIfNotNull (lastExplicitSettings.get());
350 }
351 
352 //==============================================================================
353 void AudioDeviceManager::scanDevicesIfNeeded()
354 {
355  if (listNeedsScanning)
356  {
357  listNeedsScanning = false;
358 
359  createDeviceTypesIfNeeded();
360 
361  for (auto* type : availableDeviceTypes)
362  type->scanForDevices();
363  }
364 }
365 
366 AudioIODeviceType* AudioDeviceManager::findType (const String& typeName)
367 {
368  scanDevicesIfNeeded();
369 
370  for (auto* type : availableDeviceTypes)
371  if (type->getTypeName() == typeName)
372  return type;
373 
374  return {};
375 }
376 
377 AudioIODeviceType* AudioDeviceManager::findType (const String& inputName, const String& outputName)
378 {
379  scanDevicesIfNeeded();
380 
381  for (auto* type : availableDeviceTypes)
382  if ((inputName.isNotEmpty() && deviceListContains (type, true, inputName))
383  || (outputName.isNotEmpty() && deviceListContains (type, false, outputName)))
384  return type;
385 
386  return {};
387 }
388 
390 {
391  return currentSetup;
392 }
393 
395 {
396  setup = currentSetup;
397 }
398 
399 void AudioDeviceManager::deleteCurrentDevice()
400 {
401  currentAudioDevice.reset();
402  currentSetup.inputDeviceName.clear();
403  currentSetup.outputDeviceName.clear();
404 }
405 
406 void AudioDeviceManager::setCurrentAudioDeviceType (const String& type, bool treatAsChosenDevice)
407 {
408  for (int i = 0; i < availableDeviceTypes.size(); ++i)
409  {
410  if (availableDeviceTypes.getUnchecked(i)->getTypeName() == type
411  && currentDeviceType != type)
412  {
413  if (currentAudioDevice != nullptr)
414  {
416  Thread::sleep (1500); // allow a moment for OS devices to sort themselves out, to help
417  // avoid things like DirectSound/ASIO clashes
418  }
419 
420  currentDeviceType = type;
421 
422  AudioDeviceSetup s (*lastDeviceTypeConfigs.getUnchecked(i));
423  insertDefaultDeviceNames (s);
424 
425  setAudioDeviceSetup (s, treatAsChosenDevice);
426 
428  break;
429  }
430  }
431 }
432 
434 {
435  for (auto* type : availableDeviceTypes)
436  if (type->getTypeName() == currentDeviceType)
437  return type;
438 
439  return availableDeviceTypes.getFirst();
440 }
441 
443  bool treatAsChosenDevice)
444 {
445  jassert (&newSetup != &currentSetup); // this will have no effect
446 
447  if (newSetup == currentSetup && currentAudioDevice != nullptr)
448  return {};
449 
450  if (! (newSetup == currentSetup))
452 
453  stopDevice();
454 
455  if (! newSetup.useDefaultInputChannels)
456  numInputChansNeeded = newSetup.inputChannels.countNumberOfSetBits();
457 
458  if (! newSetup.useDefaultOutputChannels)
459  numOutputChansNeeded = newSetup.outputChannels.countNumberOfSetBits();
460 
461  auto* type = getCurrentDeviceTypeObject();
462 
463  if (type == nullptr)
464  {
465  deleteCurrentDevice();
466 
467  if (treatAsChosenDevice)
468  updateXml();
469 
470  return {};
471  }
472 
473  String error;
474 
475  if (currentSetup.inputDeviceName != newSetup.inputDeviceName
476  || currentSetup.outputDeviceName != newSetup.outputDeviceName
477  || currentAudioDevice == nullptr)
478  {
479  deleteCurrentDevice();
480  scanDevicesIfNeeded();
481 
482  if (newSetup.outputDeviceName.isNotEmpty() && ! deviceListContains (type, false, newSetup.outputDeviceName))
483  return "No such device: " + newSetup.outputDeviceName;
484 
485  if (newSetup.inputDeviceName.isNotEmpty() && ! deviceListContains (type, true, newSetup.inputDeviceName))
486  return "No such device: " + newSetup.inputDeviceName;
487 
488  currentAudioDevice.reset (type->createDevice (newSetup.outputDeviceName, newSetup.inputDeviceName));
489 
490  if (currentAudioDevice == nullptr)
491  error = "Can't open the audio device!\n\n"
492  "This may be because another application is currently using the same device - "
493  "if so, you should close any other applications and try again!";
494  else
495  error = currentAudioDevice->getLastError();
496 
497  if (error.isNotEmpty())
498  {
499  deleteCurrentDevice();
500  return error;
501  }
502 
503  if (newSetup.useDefaultInputChannels)
504  {
505  inputChannels.clear();
506  inputChannels.setRange (0, numInputChansNeeded, true);
507  }
508 
509  if (newSetup.useDefaultOutputChannels)
510  {
511  outputChannels.clear();
512  outputChannels.setRange (0, numOutputChansNeeded, true);
513  }
514 
515  if (newSetup.inputDeviceName.isEmpty()) inputChannels.clear();
516  if (newSetup.outputDeviceName.isEmpty()) outputChannels.clear();
517  }
518 
519  if (! newSetup.useDefaultInputChannels)
520  inputChannels = newSetup.inputChannels;
521 
522  if (! newSetup.useDefaultOutputChannels)
523  outputChannels = newSetup.outputChannels;
524 
525  currentSetup = newSetup;
526 
527  if (inputChannels.isZero() && outputChannels.isZero())
528  {
529  if (treatAsChosenDevice)
530  updateXml();
531 
532  return {};
533  }
534 
535  currentSetup.sampleRate = chooseBestSampleRate (newSetup.sampleRate);
536  currentSetup.bufferSize = chooseBestBufferSize (newSetup.bufferSize);
537 
538  error = currentAudioDevice->open (inputChannels,
539  outputChannels,
540  currentSetup.sampleRate,
541  currentSetup.bufferSize);
542 
543  if (error.isEmpty())
544  {
545  currentDeviceType = currentAudioDevice->getTypeName();
546 
547  currentAudioDevice->start (callbackHandler.get());
548 
549  currentSetup.sampleRate = currentAudioDevice->getCurrentSampleRate();
550  currentSetup.bufferSize = currentAudioDevice->getCurrentBufferSizeSamples();
551  currentSetup.inputChannels = currentAudioDevice->getActiveInputChannels();
552  currentSetup.outputChannels = currentAudioDevice->getActiveOutputChannels();
553 
554  for (int i = 0; i < availableDeviceTypes.size(); ++i)
555  if (availableDeviceTypes.getUnchecked (i)->getTypeName() == currentDeviceType)
556  *(lastDeviceTypeConfigs.getUnchecked (i)) = currentSetup;
557 
558  if (treatAsChosenDevice)
559  updateXml();
560  }
561  else
562  {
563  deleteCurrentDevice();
564  }
565 
566  return error;
567 }
568 
569 double AudioDeviceManager::chooseBestSampleRate (double rate) const
570 {
571  jassert (currentAudioDevice != nullptr);
572 
573  auto rates = currentAudioDevice->getAvailableSampleRates();
574 
575  if (rate > 0 && rates.contains (rate))
576  return rate;
577 
578  rate = currentAudioDevice->getCurrentSampleRate();
579 
580  if (rate > 0 && rates.contains (rate))
581  return rate;
582 
583  double lowestAbove44 = 0.0;
584 
585  for (int i = rates.size(); --i >= 0;)
586  {
587  auto sr = rates[i];
588 
589  if (sr >= 44100.0 && (lowestAbove44 < 1.0 || sr < lowestAbove44))
590  lowestAbove44 = sr;
591  }
592 
593  if (lowestAbove44 > 0.0)
594  return lowestAbove44;
595 
596  return rates[0];
597 }
598 
599 int AudioDeviceManager::chooseBestBufferSize (int bufferSize) const
600 {
601  jassert (currentAudioDevice != nullptr);
602 
603  if (bufferSize > 0 && currentAudioDevice->getAvailableBufferSizes().contains (bufferSize))
604  return bufferSize;
605 
606  return currentAudioDevice->getDefaultBufferSize();
607 }
608 
609 void AudioDeviceManager::stopDevice()
610 {
611  if (currentAudioDevice != nullptr)
612  currentAudioDevice->stop();
613 
614  testSound.reset();
615 }
616 
618 {
619  stopDevice();
620  currentAudioDevice.reset();
621  loadMeasurer.reset();
622 }
623 
625 {
626  if (currentAudioDevice == nullptr)
627  {
628  if (currentSetup.inputDeviceName.isEmpty()
629  && currentSetup.outputDeviceName.isEmpty())
630  {
631  // This method will only reload the last device that was running
632  // before closeAudioDevice() was called - you need to actually open
633  // one first, with setAudioDevice().
634  jassertfalse;
635  return;
636  }
637 
638  AudioDeviceSetup s (currentSetup);
639  setAudioDeviceSetup (s, false);
640  }
641 }
642 
643 void AudioDeviceManager::updateXml()
644 {
645  lastExplicitSettings.reset (new XmlElement ("DEVICESETUP"));
646 
647  lastExplicitSettings->setAttribute ("deviceType", currentDeviceType);
648  lastExplicitSettings->setAttribute ("audioOutputDeviceName", currentSetup.outputDeviceName);
649  lastExplicitSettings->setAttribute ("audioInputDeviceName", currentSetup.inputDeviceName);
650 
651  if (currentAudioDevice != nullptr)
652  {
653  lastExplicitSettings->setAttribute ("audioDeviceRate", currentAudioDevice->getCurrentSampleRate());
654 
655  if (currentAudioDevice->getDefaultBufferSize() != currentAudioDevice->getCurrentBufferSizeSamples())
656  lastExplicitSettings->setAttribute ("audioDeviceBufferSize", currentAudioDevice->getCurrentBufferSizeSamples());
657 
658  if (! currentSetup.useDefaultInputChannels)
659  lastExplicitSettings->setAttribute ("audioDeviceInChans", currentSetup.inputChannels.toString (2));
660 
661  if (! currentSetup.useDefaultOutputChannels)
662  lastExplicitSettings->setAttribute ("audioDeviceOutChans", currentSetup.outputChannels.toString (2));
663  }
664 
665  for (int i = 0; i < enabledMidiInputs.size(); ++i)
666  lastExplicitSettings->createNewChildElement ("MIDIINPUT")
667  ->setAttribute ("name", enabledMidiInputs[i]->getName());
668 
669  if (midiInsFromXml.size() > 0)
670  {
671  // Add any midi devices that have been enabled before, but which aren't currently
672  // open because the device has been disconnected.
673  const StringArray availableMidiDevices (MidiInput::getDevices());
674 
675  for (int i = 0; i < midiInsFromXml.size(); ++i)
676  if (! availableMidiDevices.contains (midiInsFromXml[i], true))
677  lastExplicitSettings->createNewChildElement ("MIDIINPUT")
678  ->setAttribute ("name", midiInsFromXml[i]);
679  }
680 
681  if (defaultMidiOutputName.isNotEmpty())
682  lastExplicitSettings->setAttribute ("defaultMidiOutput", defaultMidiOutputName);
683 }
684 
685 //==============================================================================
687 {
688  {
689  const ScopedLock sl (audioCallbackLock);
690 
691  if (callbacks.contains (newCallback))
692  return;
693  }
694 
695  if (currentAudioDevice != nullptr && newCallback != nullptr)
696  newCallback->audioDeviceAboutToStart (currentAudioDevice.get());
697 
698  const ScopedLock sl (audioCallbackLock);
699  callbacks.add (newCallback);
700 }
701 
703 {
704  if (callbackToRemove != nullptr)
705  {
706  bool needsDeinitialising = currentAudioDevice != nullptr;
707 
708  {
709  const ScopedLock sl (audioCallbackLock);
710 
711  needsDeinitialising = needsDeinitialising && callbacks.contains (callbackToRemove);
712  callbacks.removeFirstMatchingValue (callbackToRemove);
713  }
714 
715  if (needsDeinitialising)
716  callbackToRemove->audioDeviceStopped();
717  }
718 }
719 
720 void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelData,
721  int numInputChannels,
722  float** outputChannelData,
723  int numOutputChannels,
724  int numSamples)
725 {
726  const ScopedLock sl (audioCallbackLock);
727 
728  inputLevelGetter->updateLevel (inputChannelData, numInputChannels, numSamples);
729  outputLevelGetter->updateLevel (const_cast<const float**> (outputChannelData), numOutputChannels, numSamples);
730 
731  if (callbacks.size() > 0)
732  {
733  AudioProcessLoadMeasurer::ScopedTimer timer (loadMeasurer);
734 
735  tempBuffer.setSize (jmax (1, numOutputChannels), jmax (1, numSamples), false, false, true);
736 
737  callbacks.getUnchecked(0)->audioDeviceIOCallback (inputChannelData, numInputChannels,
738  outputChannelData, numOutputChannels, numSamples);
739 
740  auto** tempChans = tempBuffer.getArrayOfWritePointers();
741 
742  for (int i = callbacks.size(); --i > 0;)
743  {
744  callbacks.getUnchecked(i)->audioDeviceIOCallback (inputChannelData, numInputChannels,
745  tempChans, numOutputChannels, numSamples);
746 
747  for (int chan = 0; chan < numOutputChannels; ++chan)
748  {
749  if (auto* src = tempChans [chan])
750  if (auto* dst = outputChannelData [chan])
751  for (int j = 0; j < numSamples; ++j)
752  dst[j] += src[j];
753  }
754  }
755  }
756  else
757  {
758  for (int i = 0; i < numOutputChannels; ++i)
759  zeromem (outputChannelData[i], sizeof (float) * (size_t) numSamples);
760  }
761 
762  if (testSound != nullptr)
763  {
764  auto numSamps = jmin (numSamples, testSound->getNumSamples() - testSoundPosition);
765  auto* src = testSound->getReadPointer (0, testSoundPosition);
766 
767  for (int i = 0; i < numOutputChannels; ++i)
768  for (int j = 0; j < numSamps; ++j)
769  outputChannelData [i][j] += src[j];
770 
771  testSoundPosition += numSamps;
772 
773  if (testSoundPosition >= testSound->getNumSamples())
774  testSound.reset();
775  }
776 }
777 
778 void AudioDeviceManager::audioDeviceAboutToStartInt (AudioIODevice* const device)
779 {
780  loadMeasurer.reset (device->getCurrentSampleRate(),
781  device->getCurrentBufferSizeSamples());
782 
783  {
784  const ScopedLock sl (audioCallbackLock);
785 
786  for (int i = callbacks.size(); --i >= 0;)
787  callbacks.getUnchecked(i)->audioDeviceAboutToStart (device);
788  }
789 
791 }
792 
793 void AudioDeviceManager::audioDeviceStoppedInt()
794 {
796 
797  const ScopedLock sl (audioCallbackLock);
798 
799  loadMeasurer.reset();
800 
801  for (int i = callbacks.size(); --i >= 0;)
802  callbacks.getUnchecked(i)->audioDeviceStopped();
803 }
804 
805 void AudioDeviceManager::audioDeviceErrorInt (const String& message)
806 {
807  const ScopedLock sl (audioCallbackLock);
808 
809  for (int i = callbacks.size(); --i >= 0;)
810  callbacks.getUnchecked(i)->audioDeviceError (message);
811 }
812 
814 {
815  return loadMeasurer.getLoadAsProportion();
816 }
817 
818 //==============================================================================
819 void AudioDeviceManager::setMidiInputEnabled (const String& name, const bool enabled)
820 {
821  if (enabled != isMidiInputEnabled (name))
822  {
823  if (enabled)
824  {
825  auto index = MidiInput::getDevices().indexOf (name);
826 
827  if (index >= 0)
828  {
829  if (auto* midiIn = MidiInput::openDevice (index, callbackHandler.get()))
830  {
831  enabledMidiInputs.add (midiIn);
832  midiIn->start();
833  }
834  }
835  }
836  else
837  {
838  for (int i = enabledMidiInputs.size(); --i >= 0;)
839  if (enabledMidiInputs[i]->getName() == name)
840  enabledMidiInputs.remove (i);
841  }
842 
843  updateXml();
845  }
846 }
847 
849 {
850  for (auto* mi : enabledMidiInputs)
851  if (mi->getName() == name)
852  return true;
853 
854  return false;
855 }
856 
858 {
859  removeMidiInputCallback (name, callbackToAdd);
860 
861  if (name.isEmpty() || isMidiInputEnabled (name))
862  {
863  const ScopedLock sl (midiCallbackLock);
864 
865  MidiCallbackInfo mc;
866  mc.deviceName = name;
867  mc.callback = callbackToAdd;
868  midiCallbacks.add (mc);
869  }
870 }
871 
873 {
874  for (int i = midiCallbacks.size(); --i >= 0;)
875  {
876  auto& mc = midiCallbacks.getReference(i);
877 
878  if (mc.callback == callbackToRemove && mc.deviceName == name)
879  {
880  const ScopedLock sl (midiCallbackLock);
881  midiCallbacks.remove (i);
882  }
883  }
884 }
885 
886 void AudioDeviceManager::handleIncomingMidiMessageInt (MidiInput* source, const MidiMessage& message)
887 {
888  if (! message.isActiveSense())
889  {
890  const ScopedLock sl (midiCallbackLock);
891 
892  for (auto& mc : midiCallbacks)
893  if (mc.deviceName.isEmpty() || mc.deviceName == source->getName())
894  mc.callback->handleIncomingMidiMessage (source, message);
895  }
896 }
897 
898 //==============================================================================
900 {
901  if (defaultMidiOutputName != deviceName)
902  {
903  Array<AudioIODeviceCallback*> oldCallbacks;
904 
905  {
906  const ScopedLock sl (audioCallbackLock);
907  oldCallbacks.swapWith (callbacks);
908  }
909 
910  if (currentAudioDevice != nullptr)
911  for (int i = oldCallbacks.size(); --i >= 0;)
912  oldCallbacks.getUnchecked(i)->audioDeviceStopped();
913 
914  defaultMidiOutput.reset();
915  defaultMidiOutputName = deviceName;
916 
917  if (deviceName.isNotEmpty())
918  defaultMidiOutput.reset (MidiOutput::openDevice (MidiOutput::getDevices().indexOf (deviceName)));
919 
920  if (currentAudioDevice != nullptr)
921  for (auto* c : oldCallbacks)
922  c->audioDeviceAboutToStart (currentAudioDevice.get());
923 
924  {
925  const ScopedLock sl (audioCallbackLock);
926  oldCallbacks.swapWith (callbacks);
927  }
928 
929  updateXml();
931  }
932 }
933 
934 //==============================================================================
935 AudioDeviceManager::LevelMeter::LevelMeter() noexcept : level() {}
936 
937 void AudioDeviceManager::LevelMeter::updateLevel (const float* const* channelData, int numChannels, int numSamples) noexcept
938 {
939  if (getReferenceCount() <= 1)
940  return;
941 
942  auto localLevel = level.get();
943 
944  if (numChannels > 0)
945  {
946  for (int j = 0; j < numSamples; ++j)
947  {
948  float s = 0;
949 
950  for (int i = 0; i < numChannels; ++i)
951  s += std::abs (channelData[i][j]);
952 
953  s /= (float) numChannels;
954 
955  const float decayFactor = 0.99992f;
956 
957  if (s > localLevel)
958  localLevel = s;
959  else if (localLevel > 0.001f)
960  localLevel *= decayFactor;
961  else
962  localLevel = 0;
963  }
964  }
965  else
966  {
967  localLevel = 0;
968  }
969 
970  level = localLevel;
971 }
972 
973 double AudioDeviceManager::LevelMeter::getCurrentLevel() const noexcept
974 {
975  jassert (getReferenceCount() > 1);
976  return level.get();
977 }
978 
980 {
981  { // cunningly nested to swap, unlock and delete in that order.
982  std::unique_ptr<AudioBuffer<float>> oldSound;
983 
984  {
985  const ScopedLock sl (audioCallbackLock);
986  std::swap (oldSound, testSound);
987  }
988  }
989 
990  testSoundPosition = 0;
991 
992  if (currentAudioDevice != nullptr)
993  {
994  auto sampleRate = currentAudioDevice->getCurrentSampleRate();
995  auto soundLength = (int) sampleRate;
996 
997  double frequency = 440.0;
998  float amplitude = 0.5f;
999 
1000  auto phasePerSample = MathConstants<double>::twoPi / (sampleRate / frequency);
1001 
1002  std::unique_ptr<AudioBuffer<float>> newSound (new AudioBuffer<float> (1, soundLength));
1003 
1004  for (int i = 0; i < soundLength; ++i)
1005  newSound->setSample (0, i, amplitude * (float) std::sin (i * phasePerSample));
1006 
1007  newSound->applyGainRamp (0, 0, soundLength / 10, 0.0f, 1.0f);
1008  newSound->applyGainRamp (0, soundLength - soundLength / 4, soundLength / 4, 1.0f, 0.0f);
1009 
1010  {
1011  const ScopedLock sl (audioCallbackLock);
1012  std::swap (testSound, newSound);
1013  }
1014  }
1015 }
1016 
1018 {
1019  auto deviceXRuns = (currentAudioDevice != nullptr ? currentAudioDevice->getXRunCount() : -1);
1020  return jmax (0, deviceXRuns) + loadMeasurer.getXRunCount();
1021 }
1022 
1023 } // namespace juce
juce::AudioDeviceManager::removeAudioCallback
void removeAudioCallback(AudioIODeviceCallback *callback)
Deregisters a previously added callback.
Definition: juce_AudioDeviceManager.cpp:702
juce::AudioIODeviceCallback::audioDeviceStopped
virtual void audioDeviceStopped()=0
Called to indicate that the device has stopped.
juce::AudioProcessLoadMeasurer::getXRunCount
int getXRunCount() const
Returns the number of over- (or under-) runs recorded since the state was reset.
Definition: juce_AudioProcessLoadMeasurer.cpp:67
juce::AudioDeviceManager::setAudioDeviceSetup
String setAudioDeviceSetup(const AudioDeviceSetup &newSetup, bool treatAsChosenDevice)
Changes the current device or its settings.
Definition: juce_AudioDeviceManager.cpp:442
juce::StringArray::indexOf
int indexOf(StringRef stringToLookFor, bool ignoreCase=false, int startIndex=0) const
Searches for a string in the array.
Definition: juce_StringArray.cpp:193
juce::AudioDeviceManager::getCurrentDeviceTypeObject
AudioIODeviceType * getCurrentDeviceTypeObject() const
Returns the currently active audio device type object.
Definition: juce_AudioDeviceManager.cpp:433
juce::AudioDeviceManager
Manages the state of some audio and midi i/o devices.
Definition: juce_AudioDeviceManager.h:70
juce::AudioDeviceManager::addAudioCallback
void addAudioCallback(AudioIODeviceCallback *newCallback)
Registers an audio callback to be used.
Definition: juce_AudioDeviceManager.cpp:686
juce::AudioDeviceManager::AudioDeviceSetup::outputChannels
BigInteger outputChannels
The set of active output channels.
Definition: juce_AudioDeviceManager.h:141
juce::AudioDeviceManager::AudioDeviceSetup::outputDeviceName
String outputDeviceName
The name of the audio device used for output.
Definition: juce_AudioDeviceManager.h:102
juce::AudioDeviceManager::AudioDeviceSetup::sampleRate
double sampleRate
The current sample rate.
Definition: juce_AudioDeviceManager.h:115
juce::AudioBuffer< float >
juce::AudioDeviceManager::AudioDeviceSetup::inputChannels
BigInteger inputChannels
The set of active input channels.
Definition: juce_AudioDeviceManager.h:128
juce::AudioProcessLoadMeasurer::reset
void reset()
Resets the state.
Definition: juce_AudioProcessLoadMeasurer.cpp:33
juce::AudioIODeviceType::addListener
void addListener(Listener *listener)
Adds a listener that will be called when this type of device is added or removed from the system.
Definition: juce_AudioIODeviceType.cpp:36
juce::AudioIODeviceType::createAudioIODeviceType_ALSA
static AudioIODeviceType * createAudioIODeviceType_ALSA()
Creates an ALSA device type if it's available on this platform, or returns null.
Definition: juce_AudioIODeviceType.cpp:66
juce::Array::swapWith
void swapWith(OtherArrayType &otherArray) noexcept
This swaps the contents of this array with those of another array.
Definition: juce_Array.h:578
juce::AudioIODeviceType::createAudioIODeviceType_DirectSound
static AudioIODeviceType * createAudioIODeviceType_DirectSound()
Creates a DirectSound device type if it's available on this platform, or returns null.
Definition: juce_AudioIODeviceType.cpp:58
juce::AudioProcessLoadMeasurer::getLoadAsProportion
double getLoadAsProportion() const
Returns the current load as a proportion 0 to 1.0.
Definition: juce_AudioProcessLoadMeasurer.cpp:64
juce::OwnedArray
An array designed for holding objects.
Definition: juce_OwnedArray.h:54
juce::AudioIODeviceType::createAudioIODeviceType_WASAPI
static AudioIODeviceType * createAudioIODeviceType_WASAPI(bool exclusiveMode)
Creates a WASAPI device type if it's available on this platform, or returns null.
Definition: juce_AudioIODeviceType.cpp:54
juce::Array::size
int size() const noexcept
Returns the current number of elements in the array.
Definition: juce_Array.h:219
juce::MidiInput::openDevice
static MidiInput * openDevice(int deviceIndex, MidiInputCallback *callback)
Tries to open one of the midi input devices.
juce::MidiInput::getDevices
static StringArray getDevices()
Returns a list of the available midi input devices.
juce::String::clear
void clear() noexcept
Resets this string to be empty.
Definition: juce_String.cpp:260
juce::AudioBuffer::setSize
void setSize(int newNumChannels, int newNumSamples, bool keepExistingContent=false, bool clearExtraSpace=false, bool avoidReallocating=false)
Changes the buffer's size or number of channels.
Definition: juce_AudioSampleBuffer.h:335
juce::Array::add
void add(const ElementType &newElement)
Appends a new element at the end of the array.
Definition: juce_Array.h:375
juce::MathConstants
Commonly used mathematical constants.
Definition: juce_MathsFunctions.h:377
juce::AudioDeviceManager::getCpuUsage
double getCpuUsage() const
Returns the average proportion of available CPU being spent inside the audio callbacks.
Definition: juce_AudioDeviceManager.cpp:813
juce::AudioDeviceManager::setDefaultMidiOutput
void setDefaultMidiOutput(const String &deviceName)
Sets a midi output device to use as the default.
Definition: juce_AudioDeviceManager.cpp:899
juce::MidiMessage::isActiveSense
bool isActiveSense() const noexcept
Returns true if this is an active-sense message.
Definition: juce_MidiMessage.cpp:680
juce::AudioDeviceManager::setCurrentAudioDeviceType
void setCurrentAudioDeviceType(const String &type, bool treatAsChosenDevice)
Changes the class of audio device being used.
Definition: juce_AudioDeviceManager.cpp:406
juce::AudioDeviceManager::getAudioDeviceSetup
AudioDeviceSetup getAudioDeviceSetup() const
Returns the current device properties that are in use.
Definition: juce_AudioDeviceManager.cpp:389
juce::Array
Holds a resizable array of primitive or copy-by-value objects.
Definition: juce_Array.h:59
juce::AudioDeviceManager::AudioDeviceSetup::useDefaultOutputChannels
bool useDefaultOutputChannels
If this is true, it indicates that the outputChannels array should be ignored, and instead,...
Definition: juce_AudioDeviceManager.h:147
juce::AudioIODeviceType::getDeviceNames
virtual StringArray getDeviceNames(bool wantInputNames=false) const =0
Returns the list of available devices of this type.
juce::AudioIODeviceType
Represents a type of audio driver, such as DirectSound, ASIO, CoreAudio, etc.
Definition: juce_AudioIODeviceType.h:65
juce::XmlElement
Used to build a tree of elements representing an XML document.
Definition: juce_XmlElement.h:141
juce::MidiInput
Represents a midi input device.
Definition: juce_MidiInput.h:96
juce::AudioDeviceManager::AudioDeviceSetup
This structure holds a set of properties describing the current audio setup.
Definition: juce_AudioDeviceManager.h:94
juce::BigInteger::clear
void clear() noexcept
Resets the value to 0.
Definition: juce_BigInteger.cpp:281
juce::AudioIODeviceType::createAudioIODeviceType_Oboe
static AudioIODeviceType * createAudioIODeviceType_Oboe()
Creates an Oboe device type if it's available on this platform, or returns null.
Definition: juce_AudioIODeviceType.cpp:86
juce::MidiInputCallback
Receives incoming messages from a physical MIDI input device.
Definition: juce_MidiInput.h:44
juce::AudioDeviceManager::AudioDeviceSetup::inputDeviceName
String inputDeviceName
The name of the audio device used for input.
Definition: juce_AudioDeviceManager.h:108
juce::AudioDeviceManager::restartLastAudioDevice
void restartLastAudioDevice()
Tries to reload the last audio device that was running.
Definition: juce_AudioDeviceManager.cpp:624
juce::StringArray::size
int size() const noexcept
Returns the number of strings in the array.
Definition: juce_StringArray.h:139
juce::AudioDeviceManager::getXRunCount
int getXRunCount() const noexcept
Returns the number of under- or over runs reported.
Definition: juce_AudioDeviceManager.cpp:1017
juce::AudioIODeviceType::createAudioIODeviceType_ASIO
static AudioIODeviceType * createAudioIODeviceType_ASIO()
Creates an ASIO device type if it's available on this platform, or returns null.
Definition: juce_AudioIODeviceType.cpp:62
juce::AudioDeviceManager::CallbackHandler
Definition: juce_AudioDeviceManager.cpp:44
juce::MidiInput::getName
const String & getName() const noexcept
Returns the name of this device.
Definition: juce_MidiInput.h:150
juce::AudioIODevice
Base class for an audio device with synchronised input and output channels.
Definition: juce_AudioIODevice.h:140
juce::AudioIODeviceType::scanForDevices
virtual void scanForDevices()=0
Refreshes the object's cached list of known devices.
juce::BigInteger::toString
String toString(int base, int minimumNumCharacters=1) const
Converts the number to a string.
Definition: juce_BigInteger.cpp:1085
juce::Array::getUnchecked
ElementType getUnchecked(int index) const
Returns one of the elements in the array, without checking the index passed in.
Definition: juce_Array.h:256
juce::ChangeBroadcaster::sendChangeMessage
void sendChangeMessage()
Causes an asynchronous change message to be sent to all the registered listeners.
Definition: juce_ChangeBroadcaster.cpp:62
juce::AudioDeviceManager::addAudioDeviceType
void addAudioDeviceType(AudioIODeviceType *newDeviceType)
Adds a new device type to the list of types.
Definition: juce_AudioDeviceManager.cpp:185
juce::AudioIODeviceType::createDevice
virtual AudioIODevice * createDevice(const String &outputDeviceName, const String &inputDeviceName)=0
Creates one of the devices of this type.
juce::MidiMessage
Encapsulates a MIDI message.
Definition: juce_MidiMessage.h:38
juce::AudioIODeviceType::createAudioIODeviceType_Bela
static AudioIODeviceType * createAudioIODeviceType_Bela()
Creates a Bela device type if it's available on this platform, or returns null.
Definition: juce_AudioIODeviceType.cpp:74
juce::AudioProcessLoadMeasurer::ScopedTimer
This class measures the time between its construction and destruction and adds it to an AudioProcessL...
Definition: juce_AudioProcessLoadMeasurer.h:76
juce::MidiOutput::getDevices
static StringArray getDevices()
Returns a list of the available midi output devices.
juce::GenericScopedLock
Automatically locks and unlocks a mutex object.
Definition: juce_ScopedLock.h:58
juce::String::isEmpty
bool isEmpty() const noexcept
Returns true if the string contains no characters.
Definition: juce_String.h:300
juce::AudioDeviceManager::closeAudioDevice
void closeAudioDevice()
Closes the currently-open device.
Definition: juce_AudioDeviceManager.cpp:617
juce::AudioDeviceManager::createStateXml
XmlElement * createStateXml() const
Returns some XML representing the current state of the manager.
Definition: juce_AudioDeviceManager.cpp:347
juce::Array::remove
void remove(int indexToRemove)
Removes an element from the array.
Definition: juce_Array.h:724
juce::AudioIODeviceType::createAudioIODeviceType_CoreAudio
static AudioIODeviceType * createAudioIODeviceType_CoreAudio()
Creates a CoreAudio device type if it's available on this platform, or returns null.
juce::AudioDeviceManager::AudioDeviceSetup::useDefaultInputChannels
bool useDefaultInputChannels
If this is true, it indicates that the inputChannels array should be ignored, and instead,...
Definition: juce_AudioDeviceManager.h:134
juce::AudioIODeviceCallback::audioDeviceAboutToStart
virtual void audioDeviceAboutToStart(AudioIODevice *device)=0
Called to indicate that the device is about to start calling back.
juce::AudioIODeviceCallback
One of these is passed to an AudioIODevice object to stream the audio data in and out.
Definition: juce_AudioIODevice.h:46
juce::AudioDeviceManager::createAudioDeviceTypes
virtual void createAudioDeviceTypes(OwnedArray< AudioIODeviceType > &types)
Creates a list of available types.
Definition: juce_AudioDeviceManager.cpp:169
juce::AudioIODeviceType::createAudioIODeviceType_Android
static AudioIODeviceType * createAudioIODeviceType_Android()
Creates an Android device type if it's available on this platform, or returns null.
juce::String::isNotEmpty
bool isNotEmpty() const noexcept
Returns true if the string contains at least one character.
Definition: juce_String.h:306
juce::AudioDeviceManager::playTestSound
void playTestSound()
Plays a beep through the current audio device.
Definition: juce_AudioDeviceManager.cpp:979
juce::AudioDeviceManager::~AudioDeviceManager
~AudioDeviceManager() override
Destructor.
Definition: juce_AudioDeviceManager.cpp:93
juce::String
The JUCE String class!
Definition: juce_String.h:42
juce::BigInteger::setRange
void setRange(int startBit, int numBits, bool shouldBeSet)
Sets a range of bits to be either on or off.
Definition: juce_BigInteger.cpp:325
juce::BigInteger::isZero
bool isZero() const noexcept
Returns true if no bits are set.
Definition: juce_BigInteger.cpp:340
juce::AudioDeviceManager::AudioDeviceManager
AudioDeviceManager()
Creates a default AudioDeviceManager.
Definition: juce_AudioDeviceManager.cpp:88
juce::AudioIODeviceType::createAudioIODeviceType_JACK
static AudioIODeviceType * createAudioIODeviceType_JACK()
Creates a JACK device type if it's available on this platform, or returns null.
Definition: juce_AudioIODeviceType.cpp:70
juce::AudioDeviceManager::initialise
String initialise(int numInputChannelsNeeded, int numOutputChannelsNeeded, const XmlElement *savedState, bool selectDefaultDeviceOnFailure, const String &preferredDefaultDeviceName=String(), const AudioDeviceSetup *preferredSetupOptions=nullptr)
Opens a set of audio devices ready for use.
Definition: juce_AudioDeviceManager.cpp:207
juce::AudioBuffer::getArrayOfWritePointers
Type ** getArrayOfWritePointers() noexcept
Returns an array of pointers to the channels in the buffer.
Definition: juce_AudioSampleBuffer.h:310
juce::AudioIODeviceType::getDefaultDeviceIndex
virtual int getDefaultDeviceIndex(bool forInput) const =0
Returns the name of the default device.
juce::StringArray::clear
void clear()
Removes all elements from the array.
Definition: juce_StringArray.cpp:111
juce::BigInteger::countNumberOfSetBits
int countNumberOfSetBits() const noexcept
Returns the total number of set bits in the value.
Definition: juce_BigInteger.cpp:369
juce::AudioIODeviceType::getTypeName
const String & getTypeName() const noexcept
Returns the name of this type of driver that this object manages.
Definition: juce_AudioIODeviceType.h:73
juce::AudioIODeviceType::createAudioIODeviceType_iOSAudio
static AudioIODeviceType * createAudioIODeviceType_iOSAudio()
Creates an iOS device type if it's available on this platform, or returns null.
juce::AudioDeviceManager::addMidiInputCallback
void addMidiInputCallback(const String &midiInputDeviceName, MidiInputCallback *callback)
Registers a listener for callbacks when midi events arrive from a midi input.
Definition: juce_AudioDeviceManager.cpp:857
juce::AudioDeviceManager::setMidiInputEnabled
void setMidiInputEnabled(const String &midiInputDeviceName, bool enabled)
Enables or disables a midi input device.
Definition: juce_AudioDeviceManager.cpp:819
juce::AudioIODeviceType::createAudioIODeviceType_OpenSLES
static AudioIODeviceType * createAudioIODeviceType_OpenSLES()
Creates an Android OpenSLES device type if it's available on this platform, or returns null.
Definition: juce_AudioIODeviceType.cpp:82
juce::Array::getReference
ElementType & getReference(int index) const noexcept
Returns a direct reference to one of the elements in the array, without checking the index passed in.
Definition: juce_Array.h:271
juce::XmlElement::hasTagName
bool hasTagName(StringRef possibleTagName) const noexcept
Tests whether this element has a particular tag name.
Definition: juce_XmlElement.cpp:406
juce::AudioDeviceManager::AudioDeviceSetup::bufferSize
int bufferSize
The buffer size, in samples.
Definition: juce_AudioDeviceManager.h:121
juce::String::trim
String trim() const
Returns a copy of this string with any whitespace characters removed from the start and end.
Definition: juce_String.cpp:1662
juce::MidiOutput::openDevice
static MidiOutput * openDevice(int deviceIndex)
Tries to open one of the midi output devices.
juce::AudioIODeviceType::Listener
A class for receiving events when audio devices are inserted or removed.
Definition: juce_AudioIODeviceType.h:130
juce::AudioDeviceManager::isMidiInputEnabled
bool isMidiInputEnabled(const String &midiInputDeviceName) const
Returns true if a given midi input device is being used.
Definition: juce_AudioDeviceManager.cpp:848
juce::AudioDeviceManager::removeMidiInputCallback
void removeMidiInputCallback(const String &midiInputDeviceName, MidiInputCallback *callback)
Removes a listener that was previously registered with addMidiInputCallback().
Definition: juce_AudioDeviceManager.cpp:872
juce::Thread::sleep
static void JUCE_CALLTYPE sleep(int milliseconds)
Suspends the execution of the current thread until the specified timeout period has elapsed (note tha...
juce::AudioDeviceManager::getAvailableDeviceTypes
const OwnedArray< AudioIODeviceType > & getAvailableDeviceTypes()
Returns a list of the types of device supported.
Definition: juce_AudioDeviceManager.cpp:117
juce::AudioDeviceManager::initialiseWithDefaultDevices
String initialiseWithDefaultDevices(int numInputChannelsNeeded, int numOutputChannelsNeeded)
Resets everything to a default device setup, clearing any stored settings.
Definition: juce_AudioDeviceManager.cpp:326