Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

juce_AudioDeviceManager.cpp 34KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. The code included in this file is provided under the terms of the ISC license
  8. http://www.isc.org/downloads/software-support-policy/isc-license. Permission
  9. To use, copy, modify, and/or distribute this software for any purpose with or
  10. without fee is hereby granted provided that the above copyright notice and
  11. this permission notice appear in all copies.
  12. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  13. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  14. DISCLAIMED.
  15. ==============================================================================
  16. */
  17. namespace juce
  18. {
  19. AudioDeviceManager::AudioDeviceSetup::AudioDeviceSetup()
  20. : sampleRate (0),
  21. bufferSize (0),
  22. useDefaultInputChannels (true),
  23. useDefaultOutputChannels (true)
  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. class AudioDeviceManager::CallbackHandler : public AudioIODeviceCallback,
  39. public MidiInputCallback,
  40. public AudioIODeviceType::Listener
  41. {
  42. public:
  43. CallbackHandler (AudioDeviceManager& adm) noexcept : owner (adm) {}
  44. private:
  45. void audioDeviceIOCallback (const float** ins, int numIns, float** outs, int numOuts, int numSamples) override
  46. {
  47. owner.audioDeviceIOCallbackInt (ins, numIns, outs, numOuts, numSamples);
  48. }
  49. void audioDeviceAboutToStart (AudioIODevice* device) override
  50. {
  51. owner.audioDeviceAboutToStartInt (device);
  52. }
  53. void audioDeviceStopped() override
  54. {
  55. owner.audioDeviceStoppedInt();
  56. }
  57. void audioDeviceError (const String& message) override
  58. {
  59. owner.audioDeviceErrorInt (message);
  60. }
  61. void handleIncomingMidiMessage (MidiInput* source, const MidiMessage& message) override
  62. {
  63. owner.handleIncomingMidiMessageInt (source, message);
  64. }
  65. void audioDeviceListChanged() override
  66. {
  67. owner.audioDeviceListChanged();
  68. }
  69. AudioDeviceManager& owner;
  70. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CallbackHandler)
  71. };
  72. //==============================================================================
  73. AudioDeviceManager::AudioDeviceManager()
  74. : numInputChansNeeded (0),
  75. numOutputChansNeeded (2),
  76. listNeedsScanning (true),
  77. testSoundPosition (0),
  78. cpuUsageMs (0),
  79. timeToCpuScale (0)
  80. {
  81. callbackHandler = new CallbackHandler (*this);
  82. }
  83. AudioDeviceManager::~AudioDeviceManager()
  84. {
  85. currentAudioDevice = nullptr;
  86. defaultMidiOutput = nullptr;
  87. }
  88. //==============================================================================
  89. void AudioDeviceManager::createDeviceTypesIfNeeded()
  90. {
  91. if (availableDeviceTypes.size() == 0)
  92. {
  93. OwnedArray<AudioIODeviceType> types;
  94. createAudioDeviceTypes (types);
  95. for (int i = 0; i < types.size(); ++i)
  96. addAudioDeviceType (types.getUnchecked(i));
  97. types.clear (false);
  98. if (AudioIODeviceType* first = availableDeviceTypes.getFirst())
  99. currentDeviceType = first->getTypeName();
  100. }
  101. }
  102. const OwnedArray<AudioIODeviceType>& AudioDeviceManager::getAvailableDeviceTypes()
  103. {
  104. scanDevicesIfNeeded();
  105. return availableDeviceTypes;
  106. }
  107. void AudioDeviceManager::audioDeviceListChanged()
  108. {
  109. if (currentAudioDevice != nullptr)
  110. {
  111. currentSetup.sampleRate = currentAudioDevice->getCurrentSampleRate();
  112. currentSetup.bufferSize = currentAudioDevice->getCurrentBufferSizeSamples();
  113. currentSetup.inputChannels = currentAudioDevice->getActiveInputChannels();
  114. currentSetup.outputChannels = currentAudioDevice->getActiveOutputChannels();
  115. }
  116. sendChangeMessage();
  117. }
  118. //==============================================================================
  119. static void addIfNotNull (OwnedArray<AudioIODeviceType>& list, AudioIODeviceType* const device)
  120. {
  121. if (device != nullptr)
  122. list.add (device);
  123. }
  124. void AudioDeviceManager::createAudioDeviceTypes (OwnedArray<AudioIODeviceType>& list)
  125. {
  126. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_WASAPI (false));
  127. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_WASAPI (true));
  128. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_DirectSound());
  129. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_ASIO());
  130. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_CoreAudio());
  131. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_iOSAudio());
  132. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_JACK());
  133. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_ALSA());
  134. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_OpenSLES());
  135. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_Android());
  136. }
  137. void AudioDeviceManager::addAudioDeviceType (AudioIODeviceType* newDeviceType)
  138. {
  139. if (newDeviceType != nullptr)
  140. {
  141. jassert (lastDeviceTypeConfigs.size() == availableDeviceTypes.size());
  142. availableDeviceTypes.add (newDeviceType);
  143. lastDeviceTypeConfigs.add (new AudioDeviceSetup());
  144. newDeviceType->addListener (callbackHandler);
  145. }
  146. }
  147. static bool deviceListContains (AudioIODeviceType* type, bool isInput, const String& name)
  148. {
  149. StringArray devices (type->getDeviceNames (isInput));
  150. for (int i = devices.size(); --i >= 0;)
  151. if (devices[i].trim().equalsIgnoreCase (name.trim()))
  152. return true;
  153. return false;
  154. }
  155. //==============================================================================
  156. String AudioDeviceManager::initialise (const int numInputChannelsNeeded,
  157. const int numOutputChannelsNeeded,
  158. const XmlElement* const xml,
  159. const bool selectDefaultDeviceOnFailure,
  160. const String& preferredDefaultDeviceName,
  161. const AudioDeviceSetup* preferredSetupOptions)
  162. {
  163. scanDevicesIfNeeded();
  164. numInputChansNeeded = numInputChannelsNeeded;
  165. numOutputChansNeeded = numOutputChannelsNeeded;
  166. if (xml != nullptr && xml->hasTagName ("DEVICESETUP"))
  167. return initialiseFromXML (*xml, selectDefaultDeviceOnFailure,
  168. preferredDefaultDeviceName, preferredSetupOptions);
  169. return initialiseDefault (preferredDefaultDeviceName, preferredSetupOptions);
  170. }
  171. String AudioDeviceManager::initialiseDefault (const String& preferredDefaultDeviceName,
  172. const AudioDeviceSetup* preferredSetupOptions)
  173. {
  174. AudioDeviceSetup setup;
  175. if (preferredSetupOptions != nullptr)
  176. {
  177. setup = *preferredSetupOptions;
  178. }
  179. else if (preferredDefaultDeviceName.isNotEmpty())
  180. {
  181. for (int j = availableDeviceTypes.size(); --j >= 0;)
  182. {
  183. AudioIODeviceType* const type = availableDeviceTypes.getUnchecked(j);
  184. const StringArray outs (type->getDeviceNames (false));
  185. for (int i = 0; i < outs.size(); ++i)
  186. {
  187. if (outs[i].matchesWildcard (preferredDefaultDeviceName, true))
  188. {
  189. setup.outputDeviceName = outs[i];
  190. break;
  191. }
  192. }
  193. const StringArray ins (type->getDeviceNames (true));
  194. for (int i = 0; i < ins.size(); ++i)
  195. {
  196. if (ins[i].matchesWildcard (preferredDefaultDeviceName, true))
  197. {
  198. setup.inputDeviceName = ins[i];
  199. break;
  200. }
  201. }
  202. }
  203. }
  204. insertDefaultDeviceNames (setup);
  205. return setAudioDeviceSetup (setup, false);
  206. }
  207. String AudioDeviceManager::initialiseFromXML (const XmlElement& xml,
  208. const bool selectDefaultDeviceOnFailure,
  209. const String& preferredDefaultDeviceName,
  210. const AudioDeviceSetup* preferredSetupOptions)
  211. {
  212. lastExplicitSettings = new XmlElement (xml);
  213. String error;
  214. AudioDeviceSetup setup;
  215. if (preferredSetupOptions != nullptr)
  216. setup = *preferredSetupOptions;
  217. if (xml.getStringAttribute ("audioDeviceName").isNotEmpty())
  218. {
  219. setup.inputDeviceName = setup.outputDeviceName
  220. = xml.getStringAttribute ("audioDeviceName");
  221. }
  222. else
  223. {
  224. setup.inputDeviceName = xml.getStringAttribute ("audioInputDeviceName");
  225. setup.outputDeviceName = xml.getStringAttribute ("audioOutputDeviceName");
  226. }
  227. currentDeviceType = xml.getStringAttribute ("deviceType");
  228. if (findType (currentDeviceType) == nullptr)
  229. {
  230. if (AudioIODeviceType* const type = findType (setup.inputDeviceName, setup.outputDeviceName))
  231. currentDeviceType = type->getTypeName();
  232. else if (availableDeviceTypes.size() > 0)
  233. currentDeviceType = availableDeviceTypes.getUnchecked(0)->getTypeName();
  234. }
  235. setup.bufferSize = xml.getIntAttribute ("audioDeviceBufferSize", setup.bufferSize);
  236. setup.sampleRate = xml.getDoubleAttribute ("audioDeviceRate", setup.sampleRate);
  237. setup.inputChannels .parseString (xml.getStringAttribute ("audioDeviceInChans", "11"), 2);
  238. setup.outputChannels.parseString (xml.getStringAttribute ("audioDeviceOutChans", "11"), 2);
  239. setup.useDefaultInputChannels = ! xml.hasAttribute ("audioDeviceInChans");
  240. setup.useDefaultOutputChannels = ! xml.hasAttribute ("audioDeviceOutChans");
  241. error = setAudioDeviceSetup (setup, true);
  242. midiInsFromXml.clear();
  243. forEachXmlChildElementWithTagName (xml, c, "MIDIINPUT")
  244. midiInsFromXml.add (c->getStringAttribute ("name"));
  245. const StringArray allMidiIns (MidiInput::getDevices());
  246. for (int i = allMidiIns.size(); --i >= 0;)
  247. setMidiInputEnabled (allMidiIns[i], midiInsFromXml.contains (allMidiIns[i]));
  248. if (error.isNotEmpty() && selectDefaultDeviceOnFailure)
  249. error = initialise (numInputChansNeeded, numOutputChansNeeded,
  250. nullptr, false, preferredDefaultDeviceName);
  251. setDefaultMidiOutput (xml.getStringAttribute ("defaultMidiOutput"));
  252. return error;
  253. }
  254. String AudioDeviceManager::initialiseWithDefaultDevices (int numInputChannelsNeeded,
  255. int numOutputChannelsNeeded)
  256. {
  257. lastExplicitSettings = nullptr;
  258. return initialise (numInputChannelsNeeded, numOutputChannelsNeeded,
  259. nullptr, false, String(), nullptr);
  260. }
  261. void AudioDeviceManager::insertDefaultDeviceNames (AudioDeviceSetup& setup) const
  262. {
  263. if (AudioIODeviceType* type = getCurrentDeviceTypeObject())
  264. {
  265. if (setup.outputDeviceName.isEmpty())
  266. setup.outputDeviceName = type->getDeviceNames (false) [type->getDefaultDeviceIndex (false)];
  267. if (setup.inputDeviceName.isEmpty())
  268. setup.inputDeviceName = type->getDeviceNames (true) [type->getDefaultDeviceIndex (true)];
  269. }
  270. }
  271. XmlElement* AudioDeviceManager::createStateXml() const
  272. {
  273. return lastExplicitSettings.createCopy();
  274. }
  275. //==============================================================================
  276. void AudioDeviceManager::scanDevicesIfNeeded()
  277. {
  278. if (listNeedsScanning)
  279. {
  280. listNeedsScanning = false;
  281. createDeviceTypesIfNeeded();
  282. for (int i = availableDeviceTypes.size(); --i >= 0;)
  283. availableDeviceTypes.getUnchecked(i)->scanForDevices();
  284. }
  285. }
  286. AudioIODeviceType* AudioDeviceManager::findType (const String& typeName)
  287. {
  288. scanDevicesIfNeeded();
  289. for (int i = availableDeviceTypes.size(); --i >= 0;)
  290. if (availableDeviceTypes.getUnchecked(i)->getTypeName() == typeName)
  291. return availableDeviceTypes.getUnchecked(i);
  292. return nullptr;
  293. }
  294. AudioIODeviceType* AudioDeviceManager::findType (const String& inputName, const String& outputName)
  295. {
  296. scanDevicesIfNeeded();
  297. for (int i = availableDeviceTypes.size(); --i >= 0;)
  298. {
  299. AudioIODeviceType* const type = availableDeviceTypes.getUnchecked(i);
  300. if ((inputName.isNotEmpty() && deviceListContains (type, true, inputName))
  301. || (outputName.isNotEmpty() && deviceListContains (type, false, outputName)))
  302. {
  303. return type;
  304. }
  305. }
  306. return nullptr;
  307. }
  308. void AudioDeviceManager::getAudioDeviceSetup (AudioDeviceSetup& setup) const
  309. {
  310. setup = currentSetup;
  311. }
  312. void AudioDeviceManager::deleteCurrentDevice()
  313. {
  314. currentAudioDevice = nullptr;
  315. currentSetup.inputDeviceName.clear();
  316. currentSetup.outputDeviceName.clear();
  317. }
  318. void AudioDeviceManager::setCurrentAudioDeviceType (const String& type,
  319. const bool treatAsChosenDevice)
  320. {
  321. for (int i = 0; i < availableDeviceTypes.size(); ++i)
  322. {
  323. if (availableDeviceTypes.getUnchecked(i)->getTypeName() == type
  324. && currentDeviceType != type)
  325. {
  326. if (currentAudioDevice != nullptr)
  327. {
  328. closeAudioDevice();
  329. Thread::sleep (1500); // allow a moment for OS devices to sort themselves out, to help
  330. // avoid things like DirectSound/ASIO clashes
  331. }
  332. currentDeviceType = type;
  333. AudioDeviceSetup s (*lastDeviceTypeConfigs.getUnchecked(i));
  334. insertDefaultDeviceNames (s);
  335. setAudioDeviceSetup (s, treatAsChosenDevice);
  336. sendChangeMessage();
  337. break;
  338. }
  339. }
  340. }
  341. AudioIODeviceType* AudioDeviceManager::getCurrentDeviceTypeObject() const
  342. {
  343. for (int i = 0; i < availableDeviceTypes.size(); ++i)
  344. if (availableDeviceTypes.getUnchecked(i)->getTypeName() == currentDeviceType)
  345. return availableDeviceTypes.getUnchecked(i);
  346. return availableDeviceTypes[0];
  347. }
  348. String AudioDeviceManager::setAudioDeviceSetup (const AudioDeviceSetup& newSetup,
  349. const bool treatAsChosenDevice)
  350. {
  351. jassert (&newSetup != &currentSetup); // this will have no effect
  352. if (newSetup == currentSetup && currentAudioDevice != nullptr)
  353. return {};
  354. if (! (newSetup == currentSetup))
  355. sendChangeMessage();
  356. stopDevice();
  357. const String newInputDeviceName (numInputChansNeeded == 0 ? String() : newSetup.inputDeviceName);
  358. const String newOutputDeviceName (numOutputChansNeeded == 0 ? String() : newSetup.outputDeviceName);
  359. String error;
  360. AudioIODeviceType* type = getCurrentDeviceTypeObject();
  361. if (type == nullptr || (newInputDeviceName.isEmpty() && newOutputDeviceName.isEmpty()))
  362. {
  363. deleteCurrentDevice();
  364. if (treatAsChosenDevice)
  365. updateXml();
  366. return {};
  367. }
  368. if (currentSetup.inputDeviceName != newInputDeviceName
  369. || currentSetup.outputDeviceName != newOutputDeviceName
  370. || currentAudioDevice == nullptr)
  371. {
  372. deleteCurrentDevice();
  373. scanDevicesIfNeeded();
  374. if (newOutputDeviceName.isNotEmpty() && ! deviceListContains (type, false, newOutputDeviceName))
  375. return "No such device: " + newOutputDeviceName;
  376. if (newInputDeviceName.isNotEmpty() && ! deviceListContains (type, true, newInputDeviceName))
  377. return "No such device: " + newInputDeviceName;
  378. currentAudioDevice = type->createDevice (newOutputDeviceName, newInputDeviceName);
  379. if (currentAudioDevice == nullptr)
  380. error = "Can't open the audio device!\n\n"
  381. "This may be because another application is currently using the same device - "
  382. "if so, you should close any other applications and try again!";
  383. else
  384. error = currentAudioDevice->getLastError();
  385. if (error.isNotEmpty())
  386. {
  387. deleteCurrentDevice();
  388. return error;
  389. }
  390. if (newSetup.useDefaultInputChannels)
  391. {
  392. inputChannels.clear();
  393. inputChannels.setRange (0, numInputChansNeeded, true);
  394. }
  395. if (newSetup.useDefaultOutputChannels)
  396. {
  397. outputChannels.clear();
  398. outputChannels.setRange (0, numOutputChansNeeded, true);
  399. }
  400. if (newInputDeviceName.isEmpty()) inputChannels.clear();
  401. if (newOutputDeviceName.isEmpty()) outputChannels.clear();
  402. }
  403. if (! newSetup.useDefaultInputChannels) inputChannels = newSetup.inputChannels;
  404. if (! newSetup.useDefaultOutputChannels) outputChannels = newSetup.outputChannels;
  405. currentSetup = newSetup;
  406. currentSetup.sampleRate = chooseBestSampleRate (newSetup.sampleRate);
  407. currentSetup.bufferSize = chooseBestBufferSize (newSetup.bufferSize);
  408. error = currentAudioDevice->open (inputChannels,
  409. outputChannels,
  410. currentSetup.sampleRate,
  411. currentSetup.bufferSize);
  412. if (error.isEmpty())
  413. {
  414. currentDeviceType = currentAudioDevice->getTypeName();
  415. currentAudioDevice->start (callbackHandler);
  416. currentSetup.sampleRate = currentAudioDevice->getCurrentSampleRate();
  417. currentSetup.bufferSize = currentAudioDevice->getCurrentBufferSizeSamples();
  418. currentSetup.inputChannels = currentAudioDevice->getActiveInputChannels();
  419. currentSetup.outputChannels = currentAudioDevice->getActiveOutputChannels();
  420. for (int i = 0; i < availableDeviceTypes.size(); ++i)
  421. if (availableDeviceTypes.getUnchecked (i)->getTypeName() == currentDeviceType)
  422. *(lastDeviceTypeConfigs.getUnchecked (i)) = currentSetup;
  423. if (treatAsChosenDevice)
  424. updateXml();
  425. }
  426. else
  427. {
  428. deleteCurrentDevice();
  429. }
  430. return error;
  431. }
  432. double AudioDeviceManager::chooseBestSampleRate (double rate) const
  433. {
  434. jassert (currentAudioDevice != nullptr);
  435. const Array<double> rates (currentAudioDevice->getAvailableSampleRates());
  436. if (rate > 0 && rates.contains (rate))
  437. return rate;
  438. rate = currentAudioDevice->getCurrentSampleRate();
  439. if (rate > 0 && rates.contains (rate))
  440. return rate;
  441. double lowestAbove44 = 0.0;
  442. for (int i = rates.size(); --i >= 0;)
  443. {
  444. const double sr = rates[i];
  445. if (sr >= 44100.0 && (lowestAbove44 < 1.0 || sr < lowestAbove44))
  446. lowestAbove44 = sr;
  447. }
  448. if (lowestAbove44 > 0.0)
  449. return lowestAbove44;
  450. return rates[0];
  451. }
  452. int AudioDeviceManager::chooseBestBufferSize (int bufferSize) const
  453. {
  454. jassert (currentAudioDevice != nullptr);
  455. if (bufferSize > 0 && currentAudioDevice->getAvailableBufferSizes().contains (bufferSize))
  456. return bufferSize;
  457. return currentAudioDevice->getDefaultBufferSize();
  458. }
  459. void AudioDeviceManager::stopDevice()
  460. {
  461. if (currentAudioDevice != nullptr)
  462. currentAudioDevice->stop();
  463. testSound = nullptr;
  464. }
  465. void AudioDeviceManager::closeAudioDevice()
  466. {
  467. stopDevice();
  468. currentAudioDevice = nullptr;
  469. }
  470. void AudioDeviceManager::restartLastAudioDevice()
  471. {
  472. if (currentAudioDevice == nullptr)
  473. {
  474. if (currentSetup.inputDeviceName.isEmpty()
  475. && currentSetup.outputDeviceName.isEmpty())
  476. {
  477. // This method will only reload the last device that was running
  478. // before closeAudioDevice() was called - you need to actually open
  479. // one first, with setAudioDevice().
  480. jassertfalse;
  481. return;
  482. }
  483. AudioDeviceSetup s (currentSetup);
  484. setAudioDeviceSetup (s, false);
  485. }
  486. }
  487. void AudioDeviceManager::updateXml()
  488. {
  489. lastExplicitSettings = new XmlElement ("DEVICESETUP");
  490. lastExplicitSettings->setAttribute ("deviceType", currentDeviceType);
  491. lastExplicitSettings->setAttribute ("audioOutputDeviceName", currentSetup.outputDeviceName);
  492. lastExplicitSettings->setAttribute ("audioInputDeviceName", currentSetup.inputDeviceName);
  493. if (currentAudioDevice != nullptr)
  494. {
  495. lastExplicitSettings->setAttribute ("audioDeviceRate", currentAudioDevice->getCurrentSampleRate());
  496. if (currentAudioDevice->getDefaultBufferSize() != currentAudioDevice->getCurrentBufferSizeSamples())
  497. lastExplicitSettings->setAttribute ("audioDeviceBufferSize", currentAudioDevice->getCurrentBufferSizeSamples());
  498. if (! currentSetup.useDefaultInputChannels)
  499. lastExplicitSettings->setAttribute ("audioDeviceInChans", currentSetup.inputChannels.toString (2));
  500. if (! currentSetup.useDefaultOutputChannels)
  501. lastExplicitSettings->setAttribute ("audioDeviceOutChans", currentSetup.outputChannels.toString (2));
  502. }
  503. for (int i = 0; i < enabledMidiInputs.size(); ++i)
  504. lastExplicitSettings->createNewChildElement ("MIDIINPUT")
  505. ->setAttribute ("name", enabledMidiInputs[i]->getName());
  506. if (midiInsFromXml.size() > 0)
  507. {
  508. // Add any midi devices that have been enabled before, but which aren't currently
  509. // open because the device has been disconnected.
  510. const StringArray availableMidiDevices (MidiInput::getDevices());
  511. for (int i = 0; i < midiInsFromXml.size(); ++i)
  512. if (! availableMidiDevices.contains (midiInsFromXml[i], true))
  513. lastExplicitSettings->createNewChildElement ("MIDIINPUT")
  514. ->setAttribute ("name", midiInsFromXml[i]);
  515. }
  516. if (defaultMidiOutputName.isNotEmpty())
  517. lastExplicitSettings->setAttribute ("defaultMidiOutput", defaultMidiOutputName);
  518. }
  519. //==============================================================================
  520. void AudioDeviceManager::addAudioCallback (AudioIODeviceCallback* newCallback)
  521. {
  522. {
  523. const ScopedLock sl (audioCallbackLock);
  524. if (callbacks.contains (newCallback))
  525. return;
  526. }
  527. if (currentAudioDevice != nullptr && newCallback != nullptr)
  528. newCallback->audioDeviceAboutToStart (currentAudioDevice);
  529. const ScopedLock sl (audioCallbackLock);
  530. callbacks.add (newCallback);
  531. }
  532. void AudioDeviceManager::removeAudioCallback (AudioIODeviceCallback* callbackToRemove)
  533. {
  534. if (callbackToRemove != nullptr)
  535. {
  536. bool needsDeinitialising = currentAudioDevice != nullptr;
  537. {
  538. const ScopedLock sl (audioCallbackLock);
  539. needsDeinitialising = needsDeinitialising && callbacks.contains (callbackToRemove);
  540. callbacks.removeFirstMatchingValue (callbackToRemove);
  541. }
  542. if (needsDeinitialising)
  543. callbackToRemove->audioDeviceStopped();
  544. }
  545. }
  546. void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelData,
  547. int numInputChannels,
  548. float** outputChannelData,
  549. int numOutputChannels,
  550. int numSamples)
  551. {
  552. const ScopedLock sl (audioCallbackLock);
  553. inputLevelMeter.updateLevel (inputChannelData, numInputChannels, numSamples);
  554. outputLevelMeter.updateLevel (const_cast<const float**> (outputChannelData), numOutputChannels, numSamples);
  555. if (callbacks.size() > 0)
  556. {
  557. const double callbackStartTime = Time::getMillisecondCounterHiRes();
  558. tempBuffer.setSize (jmax (1, numOutputChannels), jmax (1, numSamples), false, false, true);
  559. callbacks.getUnchecked(0)->audioDeviceIOCallback (inputChannelData, numInputChannels,
  560. outputChannelData, numOutputChannels, numSamples);
  561. float** const tempChans = tempBuffer.getArrayOfWritePointers();
  562. for (int i = callbacks.size(); --i > 0;)
  563. {
  564. callbacks.getUnchecked(i)->audioDeviceIOCallback (inputChannelData, numInputChannels,
  565. tempChans, numOutputChannels, numSamples);
  566. for (int chan = 0; chan < numOutputChannels; ++chan)
  567. {
  568. if (const float* const src = tempChans [chan])
  569. if (float* const dst = outputChannelData [chan])
  570. for (int j = 0; j < numSamples; ++j)
  571. dst[j] += src[j];
  572. }
  573. }
  574. const double msTaken = Time::getMillisecondCounterHiRes() - callbackStartTime;
  575. const double filterAmount = 0.2;
  576. cpuUsageMs += filterAmount * (msTaken - cpuUsageMs);
  577. if (msTaken > msPerBlock)
  578. xruns++;
  579. }
  580. else
  581. {
  582. for (int i = 0; i < numOutputChannels; ++i)
  583. zeromem (outputChannelData[i], sizeof (float) * (size_t) numSamples);
  584. }
  585. if (testSound != nullptr)
  586. {
  587. const int numSamps = jmin (numSamples, testSound->getNumSamples() - testSoundPosition);
  588. const float* const src = testSound->getReadPointer (0, testSoundPosition);
  589. for (int i = 0; i < numOutputChannels; ++i)
  590. for (int j = 0; j < numSamps; ++j)
  591. outputChannelData [i][j] += src[j];
  592. testSoundPosition += numSamps;
  593. if (testSoundPosition >= testSound->getNumSamples())
  594. testSound = nullptr;
  595. }
  596. }
  597. void AudioDeviceManager::audioDeviceAboutToStartInt (AudioIODevice* const device)
  598. {
  599. cpuUsageMs = 0;
  600. xruns = 0;
  601. const double sampleRate = device->getCurrentSampleRate();
  602. const int blockSize = device->getCurrentBufferSizeSamples();
  603. if (sampleRate > 0.0 && blockSize > 0)
  604. {
  605. msPerBlock = 1000.0 * blockSize / sampleRate;
  606. timeToCpuScale = (msPerBlock > 0.0) ? (1.0 / msPerBlock) : 0.0;
  607. }
  608. {
  609. const ScopedLock sl (audioCallbackLock);
  610. for (int i = callbacks.size(); --i >= 0;)
  611. callbacks.getUnchecked(i)->audioDeviceAboutToStart (device);
  612. }
  613. sendChangeMessage();
  614. }
  615. void AudioDeviceManager::audioDeviceStoppedInt()
  616. {
  617. cpuUsageMs = 0;
  618. timeToCpuScale = 0;
  619. xruns = 0;
  620. sendChangeMessage();
  621. const ScopedLock sl (audioCallbackLock);
  622. for (int i = callbacks.size(); --i >= 0;)
  623. callbacks.getUnchecked(i)->audioDeviceStopped();
  624. }
  625. void AudioDeviceManager::audioDeviceErrorInt (const String& message)
  626. {
  627. const ScopedLock sl (audioCallbackLock);
  628. for (int i = callbacks.size(); --i >= 0;)
  629. callbacks.getUnchecked(i)->audioDeviceError (message);
  630. }
  631. double AudioDeviceManager::getCpuUsage() const
  632. {
  633. return jlimit (0.0, 1.0, timeToCpuScale * cpuUsageMs);
  634. }
  635. //==============================================================================
  636. void AudioDeviceManager::setMidiInputEnabled (const String& name, const bool enabled)
  637. {
  638. if (enabled != isMidiInputEnabled (name))
  639. {
  640. if (enabled)
  641. {
  642. const int index = MidiInput::getDevices().indexOf (name);
  643. if (index >= 0)
  644. {
  645. if (MidiInput* const midiIn = MidiInput::openDevice (index, callbackHandler))
  646. {
  647. enabledMidiInputs.add (midiIn);
  648. midiIn->start();
  649. }
  650. }
  651. }
  652. else
  653. {
  654. for (int i = enabledMidiInputs.size(); --i >= 0;)
  655. if (enabledMidiInputs[i]->getName() == name)
  656. enabledMidiInputs.remove (i);
  657. }
  658. updateXml();
  659. sendChangeMessage();
  660. }
  661. }
  662. bool AudioDeviceManager::isMidiInputEnabled (const String& name) const
  663. {
  664. for (int i = enabledMidiInputs.size(); --i >= 0;)
  665. if (enabledMidiInputs[i]->getName() == name)
  666. return true;
  667. return false;
  668. }
  669. void AudioDeviceManager::addMidiInputCallback (const String& name, MidiInputCallback* callbackToAdd)
  670. {
  671. removeMidiInputCallback (name, callbackToAdd);
  672. if (name.isEmpty() || isMidiInputEnabled (name))
  673. {
  674. const ScopedLock sl (midiCallbackLock);
  675. MidiCallbackInfo mc;
  676. mc.deviceName = name;
  677. mc.callback = callbackToAdd;
  678. midiCallbacks.add (mc);
  679. }
  680. }
  681. void AudioDeviceManager::removeMidiInputCallback (const String& name, MidiInputCallback* callbackToRemove)
  682. {
  683. for (int i = midiCallbacks.size(); --i >= 0;)
  684. {
  685. const MidiCallbackInfo& mc = midiCallbacks.getReference(i);
  686. if (mc.callback == callbackToRemove && mc.deviceName == name)
  687. {
  688. const ScopedLock sl (midiCallbackLock);
  689. midiCallbacks.remove (i);
  690. }
  691. }
  692. }
  693. void AudioDeviceManager::handleIncomingMidiMessageInt (MidiInput* source, const MidiMessage& message)
  694. {
  695. if (! message.isActiveSense())
  696. {
  697. const ScopedLock sl (midiCallbackLock);
  698. for (int i = 0; i < midiCallbacks.size(); ++i)
  699. {
  700. const MidiCallbackInfo& mc = midiCallbacks.getReference(i);
  701. if (mc.deviceName.isEmpty() || mc.deviceName == source->getName())
  702. mc.callback->handleIncomingMidiMessage (source, message);
  703. }
  704. }
  705. }
  706. //==============================================================================
  707. void AudioDeviceManager::setDefaultMidiOutput (const String& deviceName)
  708. {
  709. if (defaultMidiOutputName != deviceName)
  710. {
  711. Array<AudioIODeviceCallback*> oldCallbacks;
  712. {
  713. const ScopedLock sl (audioCallbackLock);
  714. oldCallbacks.swapWith (callbacks);
  715. }
  716. if (currentAudioDevice != nullptr)
  717. for (int i = oldCallbacks.size(); --i >= 0;)
  718. oldCallbacks.getUnchecked(i)->audioDeviceStopped();
  719. defaultMidiOutput = nullptr;
  720. defaultMidiOutputName = deviceName;
  721. if (deviceName.isNotEmpty())
  722. defaultMidiOutput = MidiOutput::openDevice (MidiOutput::getDevices().indexOf (deviceName));
  723. if (currentAudioDevice != nullptr)
  724. for (int i = oldCallbacks.size(); --i >= 0;)
  725. oldCallbacks.getUnchecked(i)->audioDeviceAboutToStart (currentAudioDevice);
  726. {
  727. const ScopedLock sl (audioCallbackLock);
  728. oldCallbacks.swapWith (callbacks);
  729. }
  730. updateXml();
  731. sendChangeMessage();
  732. }
  733. }
  734. //==============================================================================
  735. AudioDeviceManager::LevelMeter::LevelMeter() noexcept : level() {}
  736. void AudioDeviceManager::LevelMeter::updateLevel (const float* const* channelData, int numChannels, int numSamples) noexcept
  737. {
  738. if (enabled.get() != 0 && numChannels > 0)
  739. {
  740. for (int j = 0; j < numSamples; ++j)
  741. {
  742. float s = 0;
  743. for (int i = 0; i < numChannels; ++i)
  744. s += std::abs (channelData[i][j]);
  745. s /= (float) numChannels;
  746. const double decayFactor = 0.99992;
  747. if (s > level)
  748. level = s;
  749. else if (level > 0.001f)
  750. level *= decayFactor;
  751. else
  752. level = 0;
  753. }
  754. }
  755. else
  756. {
  757. level = 0;
  758. }
  759. }
  760. void AudioDeviceManager::LevelMeter::setEnabled (bool shouldBeEnabled) noexcept
  761. {
  762. enabled.set (shouldBeEnabled ? 1 : 0);
  763. level = 0;
  764. }
  765. double AudioDeviceManager::LevelMeter::getCurrentLevel() const noexcept
  766. {
  767. jassert (enabled.get() != 0); // you need to call setEnabled (true) before using this!
  768. return level;
  769. }
  770. void AudioDeviceManager::playTestSound()
  771. {
  772. { // cunningly nested to swap, unlock and delete in that order.
  773. ScopedPointer<AudioSampleBuffer> oldSound;
  774. {
  775. const ScopedLock sl (audioCallbackLock);
  776. oldSound = testSound;
  777. }
  778. }
  779. testSoundPosition = 0;
  780. if (currentAudioDevice != nullptr)
  781. {
  782. const double sampleRate = currentAudioDevice->getCurrentSampleRate();
  783. const int soundLength = (int) sampleRate;
  784. const double frequency = 440.0;
  785. const float amplitude = 0.5f;
  786. const double phasePerSample = double_Pi * 2.0 / (sampleRate / frequency);
  787. AudioSampleBuffer* const newSound = new AudioSampleBuffer (1, soundLength);
  788. for (int i = 0; i < soundLength; ++i)
  789. newSound->setSample (0, i, amplitude * (float) std::sin (i * phasePerSample));
  790. newSound->applyGainRamp (0, 0, soundLength / 10, 0.0f, 1.0f);
  791. newSound->applyGainRamp (0, soundLength - soundLength / 4, soundLength / 4, 1.0f, 0.0f);
  792. const ScopedLock sl (audioCallbackLock);
  793. testSound = newSound;
  794. }
  795. }
  796. int AudioDeviceManager::getXRunCount() const noexcept
  797. {
  798. auto deviceXRuns = (currentAudioDevice != nullptr ? currentAudioDevice->getXRunCount() : -1);
  799. return (deviceXRuns >= 0 ? deviceXRuns : xruns);
  800. }
  801. double AudioDeviceManager::getCurrentInputLevel() const noexcept { return inputLevelMeter.getCurrentLevel(); }
  802. double AudioDeviceManager::getCurrentOutputLevel() const noexcept { return outputLevelMeter.getCurrentLevel(); }
  803. void AudioDeviceManager::enableInputLevelMeasurement (bool enable) noexcept { inputLevelMeter.setEnabled (enable); }
  804. void AudioDeviceManager::enableOutputLevelMeasurement (bool enable) noexcept { outputLevelMeter.setEnabled (enable); }
  805. } // namespace juce