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 39KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171
  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2020 - Raw Material Software Limited
  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. bool AudioDeviceManager::AudioDeviceSetup::operator== (const AudioDeviceManager::AudioDeviceSetup& other) const
  20. {
  21. return outputDeviceName == other.outputDeviceName
  22. && inputDeviceName == other.inputDeviceName
  23. && sampleRate == other.sampleRate
  24. && bufferSize == other.bufferSize
  25. && inputChannels == other.inputChannels
  26. && useDefaultInputChannels == other.useDefaultInputChannels
  27. && outputChannels == other.outputChannels
  28. && useDefaultOutputChannels == other.useDefaultOutputChannels;
  29. }
  30. bool AudioDeviceManager::AudioDeviceSetup::operator!= (const AudioDeviceManager::AudioDeviceSetup& other) const
  31. {
  32. return ! operator== (other);
  33. }
  34. //==============================================================================
  35. class AudioDeviceManager::CallbackHandler : public AudioIODeviceCallback,
  36. public MidiInputCallback,
  37. public AudioIODeviceType::Listener
  38. {
  39. public:
  40. CallbackHandler (AudioDeviceManager& adm) noexcept : owner (adm) {}
  41. private:
  42. void audioDeviceIOCallback (const float** ins, int numIns, float** outs, int numOuts, int numSamples) override
  43. {
  44. owner.audioDeviceIOCallbackInt (ins, numIns, outs, numOuts, numSamples);
  45. }
  46. void audioDeviceAboutToStart (AudioIODevice* device) override
  47. {
  48. owner.audioDeviceAboutToStartInt (device);
  49. }
  50. void audioDeviceStopped() override
  51. {
  52. owner.audioDeviceStoppedInt();
  53. }
  54. void audioDeviceError (const String& message) override
  55. {
  56. owner.audioDeviceErrorInt (message);
  57. }
  58. void handleIncomingMidiMessage (MidiInput* source, const MidiMessage& message) override
  59. {
  60. owner.handleIncomingMidiMessageInt (source, message);
  61. }
  62. void audioDeviceListChanged() override
  63. {
  64. owner.audioDeviceListChanged();
  65. }
  66. AudioDeviceManager& owner;
  67. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CallbackHandler)
  68. };
  69. //==============================================================================
  70. AudioDeviceManager::AudioDeviceManager()
  71. {
  72. callbackHandler.reset (new CallbackHandler (*this));
  73. }
  74. AudioDeviceManager::~AudioDeviceManager()
  75. {
  76. currentAudioDevice.reset();
  77. defaultMidiOutput.reset();
  78. }
  79. //==============================================================================
  80. void AudioDeviceManager::createDeviceTypesIfNeeded()
  81. {
  82. if (availableDeviceTypes.size() == 0)
  83. {
  84. OwnedArray<AudioIODeviceType> types;
  85. createAudioDeviceTypes (types);
  86. for (auto* t : types)
  87. addAudioDeviceType (std::unique_ptr<AudioIODeviceType> (t));
  88. types.clear (false);
  89. if (auto* first = availableDeviceTypes.getFirst())
  90. currentDeviceType = first->getTypeName();
  91. }
  92. }
  93. const OwnedArray<AudioIODeviceType>& AudioDeviceManager::getAvailableDeviceTypes()
  94. {
  95. scanDevicesIfNeeded();
  96. return availableDeviceTypes;
  97. }
  98. void AudioDeviceManager::audioDeviceListChanged()
  99. {
  100. if (currentAudioDevice != nullptr)
  101. {
  102. auto currentDeviceStillAvailable = [&]
  103. {
  104. auto currentTypeName = currentAudioDevice->getTypeName();
  105. auto currentDeviceName = currentAudioDevice->getName();
  106. for (auto* deviceType : availableDeviceTypes)
  107. {
  108. if (currentTypeName == deviceType->getTypeName())
  109. {
  110. for (auto& deviceName : deviceType->getDeviceNames (true))
  111. if (currentDeviceName == deviceName)
  112. return true;
  113. for (auto& deviceName : deviceType->getDeviceNames (false))
  114. if (currentDeviceName == deviceName)
  115. return true;
  116. }
  117. }
  118. return false;
  119. }();
  120. if (! currentDeviceStillAvailable)
  121. {
  122. closeAudioDevice();
  123. if (auto e = createStateXml())
  124. initialiseFromXML (*e, true, preferredDeviceName, &currentSetup);
  125. else
  126. initialiseDefault (preferredDeviceName, &currentSetup);
  127. }
  128. if (currentAudioDevice != nullptr)
  129. {
  130. currentSetup.sampleRate = currentAudioDevice->getCurrentSampleRate();
  131. currentSetup.bufferSize = currentAudioDevice->getCurrentBufferSizeSamples();
  132. currentSetup.inputChannels = currentAudioDevice->getActiveInputChannels();
  133. currentSetup.outputChannels = currentAudioDevice->getActiveOutputChannels();
  134. }
  135. }
  136. sendChangeMessage();
  137. }
  138. //==============================================================================
  139. static void addIfNotNull (OwnedArray<AudioIODeviceType>& list, AudioIODeviceType* const device)
  140. {
  141. if (device != nullptr)
  142. list.add (device);
  143. }
  144. void AudioDeviceManager::createAudioDeviceTypes (OwnedArray<AudioIODeviceType>& list)
  145. {
  146. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_WASAPI (WASAPIDeviceMode::shared));
  147. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_WASAPI (WASAPIDeviceMode::exclusive));
  148. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_WASAPI (WASAPIDeviceMode::sharedLowLatency));
  149. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_DirectSound());
  150. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_ASIO());
  151. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_CoreAudio());
  152. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_iOSAudio());
  153. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_Bela());
  154. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_JACK());
  155. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_ALSA());
  156. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_Oboe());
  157. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_OpenSLES());
  158. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_Android());
  159. }
  160. void AudioDeviceManager::addAudioDeviceType (std::unique_ptr<AudioIODeviceType> newDeviceType)
  161. {
  162. if (newDeviceType != nullptr)
  163. {
  164. jassert (lastDeviceTypeConfigs.size() == availableDeviceTypes.size());
  165. availableDeviceTypes.add (newDeviceType.release());
  166. lastDeviceTypeConfigs.add (new AudioDeviceSetup());
  167. availableDeviceTypes.getLast()->addListener (callbackHandler.get());
  168. }
  169. }
  170. void AudioDeviceManager::removeAudioDeviceType (AudioIODeviceType* deviceTypeToRemove)
  171. {
  172. if (deviceTypeToRemove != nullptr)
  173. {
  174. jassert (lastDeviceTypeConfigs.size() == availableDeviceTypes.size());
  175. auto index = availableDeviceTypes.indexOf (deviceTypeToRemove);
  176. if (auto removed = std::unique_ptr<AudioIODeviceType> (availableDeviceTypes.removeAndReturn (index)))
  177. {
  178. removed->removeListener (callbackHandler.get());
  179. lastDeviceTypeConfigs.remove (index, true);
  180. }
  181. }
  182. }
  183. static bool deviceListContains (AudioIODeviceType* type, bool isInput, const String& name)
  184. {
  185. for (auto& deviceName : type->getDeviceNames (isInput))
  186. if (deviceName.trim().equalsIgnoreCase (name.trim()))
  187. return true;
  188. return false;
  189. }
  190. //==============================================================================
  191. String AudioDeviceManager::initialise (const int numInputChannelsNeeded,
  192. const int numOutputChannelsNeeded,
  193. const XmlElement* const xml,
  194. const bool selectDefaultDeviceOnFailure,
  195. const String& preferredDefaultDeviceName,
  196. const AudioDeviceSetup* preferredSetupOptions)
  197. {
  198. scanDevicesIfNeeded();
  199. numInputChansNeeded = numInputChannelsNeeded;
  200. numOutputChansNeeded = numOutputChannelsNeeded;
  201. preferredDeviceName = preferredDefaultDeviceName;
  202. if (xml != nullptr && xml->hasTagName ("DEVICESETUP"))
  203. return initialiseFromXML (*xml, selectDefaultDeviceOnFailure,
  204. preferredDeviceName, preferredSetupOptions);
  205. return initialiseDefault (preferredDeviceName, preferredSetupOptions);
  206. }
  207. String AudioDeviceManager::initialiseDefault (const String& preferredDefaultDeviceName,
  208. const AudioDeviceSetup* preferredSetupOptions)
  209. {
  210. AudioDeviceSetup setup;
  211. if (preferredSetupOptions != nullptr)
  212. {
  213. setup = *preferredSetupOptions;
  214. }
  215. else if (preferredDefaultDeviceName.isNotEmpty())
  216. {
  217. for (auto* type : availableDeviceTypes)
  218. {
  219. for (auto& out : type->getDeviceNames (false))
  220. {
  221. if (out.matchesWildcard (preferredDefaultDeviceName, true))
  222. {
  223. setup.outputDeviceName = out;
  224. break;
  225. }
  226. }
  227. for (auto& in : type->getDeviceNames (true))
  228. {
  229. if (in.matchesWildcard (preferredDefaultDeviceName, true))
  230. {
  231. setup.inputDeviceName = in;
  232. break;
  233. }
  234. }
  235. }
  236. }
  237. insertDefaultDeviceNames (setup);
  238. return setAudioDeviceSetup (setup, false);
  239. }
  240. String AudioDeviceManager::initialiseFromXML (const XmlElement& xml,
  241. bool selectDefaultDeviceOnFailure,
  242. const String& preferredDefaultDeviceName,
  243. const AudioDeviceSetup* preferredSetupOptions)
  244. {
  245. lastExplicitSettings.reset (new XmlElement (xml));
  246. String error;
  247. AudioDeviceSetup setup;
  248. if (preferredSetupOptions != nullptr)
  249. setup = *preferredSetupOptions;
  250. if (xml.getStringAttribute ("audioDeviceName").isNotEmpty())
  251. {
  252. setup.inputDeviceName = setup.outputDeviceName
  253. = xml.getStringAttribute ("audioDeviceName");
  254. }
  255. else
  256. {
  257. setup.inputDeviceName = xml.getStringAttribute ("audioInputDeviceName");
  258. setup.outputDeviceName = xml.getStringAttribute ("audioOutputDeviceName");
  259. }
  260. currentDeviceType = xml.getStringAttribute ("deviceType");
  261. if (findType (currentDeviceType) == nullptr)
  262. {
  263. if (auto* type = findType (setup.inputDeviceName, setup.outputDeviceName))
  264. currentDeviceType = type->getTypeName();
  265. else if (auto* firstType = availableDeviceTypes.getFirst())
  266. currentDeviceType = firstType->getTypeName();
  267. }
  268. setup.bufferSize = xml.getIntAttribute ("audioDeviceBufferSize", setup.bufferSize);
  269. setup.sampleRate = xml.getDoubleAttribute ("audioDeviceRate", setup.sampleRate);
  270. setup.inputChannels .parseString (xml.getStringAttribute ("audioDeviceInChans", "11"), 2);
  271. setup.outputChannels.parseString (xml.getStringAttribute ("audioDeviceOutChans", "11"), 2);
  272. setup.useDefaultInputChannels = ! xml.hasAttribute ("audioDeviceInChans");
  273. setup.useDefaultOutputChannels = ! xml.hasAttribute ("audioDeviceOutChans");
  274. error = setAudioDeviceSetup (setup, true);
  275. if (error.isNotEmpty() && selectDefaultDeviceOnFailure)
  276. error = initialise (numInputChansNeeded, numOutputChansNeeded, nullptr, false, preferredDefaultDeviceName);
  277. midiDeviceInfosFromXml.clear();
  278. enabledMidiInputs.clear();
  279. forEachXmlChildElementWithTagName (xml, c, "MIDIINPUT")
  280. midiDeviceInfosFromXml.add ({ c->getStringAttribute ("name"), c->getStringAttribute ("identifier") });
  281. auto isIdentifierAvailable = [] (const Array<MidiDeviceInfo>& available, const String& identifier)
  282. {
  283. for (auto& device : available)
  284. if (device.identifier == identifier)
  285. return true;
  286. return false;
  287. };
  288. auto getUpdatedIdentifierForName = [&] (const Array<MidiDeviceInfo>& available, const String& name) -> String
  289. {
  290. for (auto& device : available)
  291. if (device.name == name)
  292. return device.identifier;
  293. return {};
  294. };
  295. auto inputs = MidiInput::getAvailableDevices();
  296. for (auto& info : midiDeviceInfosFromXml)
  297. {
  298. if (isIdentifierAvailable (inputs, info.identifier))
  299. {
  300. setMidiInputDeviceEnabled (info.identifier, true);
  301. }
  302. else
  303. {
  304. auto identifier = getUpdatedIdentifierForName (inputs, info.name);
  305. if (identifier.isNotEmpty())
  306. setMidiInputDeviceEnabled (identifier, true);
  307. }
  308. }
  309. MidiDeviceInfo defaultOutputDeviceInfo (xml.getStringAttribute ("defaultMidiOutput"),
  310. xml.getStringAttribute ("defaultMidiOutputDevice"));
  311. auto outputs = MidiOutput::getAvailableDevices();
  312. if (isIdentifierAvailable (outputs, defaultOutputDeviceInfo.identifier))
  313. {
  314. setDefaultMidiOutputDevice (defaultOutputDeviceInfo.identifier);
  315. }
  316. else
  317. {
  318. auto identifier = getUpdatedIdentifierForName (outputs, defaultOutputDeviceInfo.name);
  319. if (identifier.isNotEmpty())
  320. setDefaultMidiOutputDevice (identifier);
  321. }
  322. return error;
  323. }
  324. String AudioDeviceManager::initialiseWithDefaultDevices (int numInputChannelsNeeded,
  325. int numOutputChannelsNeeded)
  326. {
  327. lastExplicitSettings.reset();
  328. return initialise (numInputChannelsNeeded, numOutputChannelsNeeded,
  329. nullptr, false, {}, nullptr);
  330. }
  331. void AudioDeviceManager::insertDefaultDeviceNames (AudioDeviceSetup& setup) const
  332. {
  333. if (auto* type = getCurrentDeviceTypeObject())
  334. {
  335. if (numOutputChansNeeded > 0 && setup.outputDeviceName.isEmpty())
  336. setup.outputDeviceName = type->getDeviceNames (false) [type->getDefaultDeviceIndex (false)];
  337. if (numInputChansNeeded > 0 && setup.inputDeviceName.isEmpty())
  338. setup.inputDeviceName = type->getDeviceNames (true) [type->getDefaultDeviceIndex (true)];
  339. }
  340. }
  341. std::unique_ptr<XmlElement> AudioDeviceManager::createStateXml() const
  342. {
  343. if (lastExplicitSettings != nullptr)
  344. return std::make_unique<XmlElement> (*lastExplicitSettings);
  345. return {};
  346. }
  347. //==============================================================================
  348. void AudioDeviceManager::scanDevicesIfNeeded()
  349. {
  350. if (listNeedsScanning)
  351. {
  352. listNeedsScanning = false;
  353. createDeviceTypesIfNeeded();
  354. for (auto* type : availableDeviceTypes)
  355. type->scanForDevices();
  356. }
  357. }
  358. AudioIODeviceType* AudioDeviceManager::findType (const String& typeName)
  359. {
  360. scanDevicesIfNeeded();
  361. for (auto* type : availableDeviceTypes)
  362. if (type->getTypeName() == typeName)
  363. return type;
  364. return {};
  365. }
  366. AudioIODeviceType* AudioDeviceManager::findType (const String& inputName, const String& outputName)
  367. {
  368. scanDevicesIfNeeded();
  369. for (auto* type : availableDeviceTypes)
  370. if ((inputName.isNotEmpty() && deviceListContains (type, true, inputName))
  371. || (outputName.isNotEmpty() && deviceListContains (type, false, outputName)))
  372. return type;
  373. return {};
  374. }
  375. AudioDeviceManager::AudioDeviceSetup AudioDeviceManager::getAudioDeviceSetup() const
  376. {
  377. return currentSetup;
  378. }
  379. void AudioDeviceManager::getAudioDeviceSetup (AudioDeviceSetup& setup) const
  380. {
  381. setup = currentSetup;
  382. }
  383. void AudioDeviceManager::deleteCurrentDevice()
  384. {
  385. currentAudioDevice.reset();
  386. currentSetup.inputDeviceName.clear();
  387. currentSetup.outputDeviceName.clear();
  388. }
  389. void AudioDeviceManager::setCurrentAudioDeviceType (const String& type, bool treatAsChosenDevice)
  390. {
  391. for (int i = 0; i < availableDeviceTypes.size(); ++i)
  392. {
  393. if (availableDeviceTypes.getUnchecked(i)->getTypeName() == type
  394. && currentDeviceType != type)
  395. {
  396. if (currentAudioDevice != nullptr)
  397. {
  398. closeAudioDevice();
  399. Thread::sleep (1500); // allow a moment for OS devices to sort themselves out, to help
  400. // avoid things like DirectSound/ASIO clashes
  401. }
  402. currentDeviceType = type;
  403. AudioDeviceSetup s (*lastDeviceTypeConfigs.getUnchecked(i));
  404. insertDefaultDeviceNames (s);
  405. setAudioDeviceSetup (s, treatAsChosenDevice);
  406. sendChangeMessage();
  407. break;
  408. }
  409. }
  410. }
  411. AudioIODeviceType* AudioDeviceManager::getCurrentDeviceTypeObject() const
  412. {
  413. for (auto* type : availableDeviceTypes)
  414. if (type->getTypeName() == currentDeviceType)
  415. return type;
  416. return availableDeviceTypes.getFirst();
  417. }
  418. static void updateSetupChannels (AudioDeviceManager::AudioDeviceSetup& setup, int defaultNumIns, int defaultNumOuts)
  419. {
  420. auto updateChannels = [] (const String& deviceName, BigInteger& channels, int defaultNumChannels)
  421. {
  422. if (deviceName.isEmpty())
  423. {
  424. channels.clear();
  425. }
  426. else if (defaultNumChannels != -1)
  427. {
  428. channels.clear();
  429. channels.setRange (0, defaultNumChannels, true);
  430. }
  431. };
  432. updateChannels (setup.inputDeviceName, setup.inputChannels, setup.useDefaultInputChannels ? defaultNumIns : -1);
  433. updateChannels (setup.outputDeviceName, setup.outputChannels, setup.useDefaultOutputChannels ? defaultNumOuts : -1);
  434. }
  435. String AudioDeviceManager::setAudioDeviceSetup (const AudioDeviceSetup& newSetup,
  436. bool treatAsChosenDevice)
  437. {
  438. jassert (&newSetup != &currentSetup); // this will have no effect
  439. if (newSetup != currentSetup)
  440. sendChangeMessage();
  441. else if (currentAudioDevice != nullptr)
  442. return {};
  443. stopDevice();
  444. if (getCurrentDeviceTypeObject() == nullptr
  445. || (newSetup.inputDeviceName.isEmpty() && newSetup.outputDeviceName.isEmpty()))
  446. {
  447. deleteCurrentDevice();
  448. if (treatAsChosenDevice)
  449. updateXml();
  450. return {};
  451. }
  452. String error;
  453. if (currentSetup.inputDeviceName != newSetup.inputDeviceName
  454. || currentSetup.outputDeviceName != newSetup.outputDeviceName
  455. || currentAudioDevice == nullptr)
  456. {
  457. deleteCurrentDevice();
  458. scanDevicesIfNeeded();
  459. auto* type = getCurrentDeviceTypeObject();
  460. if (newSetup.outputDeviceName.isNotEmpty() && ! deviceListContains (type, false, newSetup.outputDeviceName))
  461. return "No such device: " + newSetup.outputDeviceName;
  462. if (newSetup.inputDeviceName.isNotEmpty() && ! deviceListContains (type, true, newSetup.inputDeviceName))
  463. return "No such device: " + newSetup.inputDeviceName;
  464. currentAudioDevice.reset (type->createDevice (newSetup.outputDeviceName, newSetup.inputDeviceName));
  465. if (currentAudioDevice == nullptr)
  466. error = "Can't open the audio device!\n\n"
  467. "This may be because another application is currently using the same device - "
  468. "if so, you should close any other applications and try again!";
  469. else
  470. error = currentAudioDevice->getLastError();
  471. if (error.isNotEmpty())
  472. {
  473. deleteCurrentDevice();
  474. return error;
  475. }
  476. }
  477. currentSetup = newSetup;
  478. if (! currentSetup.useDefaultInputChannels) numInputChansNeeded = currentSetup.inputChannels.countNumberOfSetBits();
  479. if (! currentSetup.useDefaultOutputChannels) numOutputChansNeeded = currentSetup.outputChannels.countNumberOfSetBits();
  480. updateSetupChannels (currentSetup, numInputChansNeeded, numOutputChansNeeded);
  481. if (currentSetup.inputChannels.isZero() && currentSetup.outputChannels.isZero())
  482. {
  483. if (treatAsChosenDevice)
  484. updateXml();
  485. return {};
  486. }
  487. currentSetup.sampleRate = chooseBestSampleRate (currentSetup.sampleRate);
  488. currentSetup.bufferSize = chooseBestBufferSize (currentSetup.bufferSize);
  489. error = currentAudioDevice->open (currentSetup.inputChannels,
  490. currentSetup.outputChannels,
  491. currentSetup.sampleRate,
  492. currentSetup.bufferSize);
  493. if (error.isEmpty())
  494. {
  495. currentDeviceType = currentAudioDevice->getTypeName();
  496. currentAudioDevice->start (callbackHandler.get());
  497. currentSetup.sampleRate = currentAudioDevice->getCurrentSampleRate();
  498. currentSetup.bufferSize = currentAudioDevice->getCurrentBufferSizeSamples();
  499. currentSetup.inputChannels = currentAudioDevice->getActiveInputChannels();
  500. currentSetup.outputChannels = currentAudioDevice->getActiveOutputChannels();
  501. for (int i = 0; i < availableDeviceTypes.size(); ++i)
  502. if (availableDeviceTypes.getUnchecked (i)->getTypeName() == currentDeviceType)
  503. *(lastDeviceTypeConfigs.getUnchecked (i)) = currentSetup;
  504. if (treatAsChosenDevice)
  505. updateXml();
  506. }
  507. else
  508. {
  509. deleteCurrentDevice();
  510. }
  511. return error;
  512. }
  513. double AudioDeviceManager::chooseBestSampleRate (double rate) const
  514. {
  515. jassert (currentAudioDevice != nullptr);
  516. auto rates = currentAudioDevice->getAvailableSampleRates();
  517. if (rate > 0 && rates.contains (rate))
  518. return rate;
  519. rate = currentAudioDevice->getCurrentSampleRate();
  520. if (rate > 0 && rates.contains (rate))
  521. return rate;
  522. double lowestAbove44 = 0.0;
  523. for (int i = rates.size(); --i >= 0;)
  524. {
  525. auto sr = rates[i];
  526. if (sr >= 44100.0 && (lowestAbove44 < 1.0 || sr < lowestAbove44))
  527. lowestAbove44 = sr;
  528. }
  529. if (lowestAbove44 > 0.0)
  530. return lowestAbove44;
  531. return rates[0];
  532. }
  533. int AudioDeviceManager::chooseBestBufferSize (int bufferSize) const
  534. {
  535. jassert (currentAudioDevice != nullptr);
  536. if (bufferSize > 0 && currentAudioDevice->getAvailableBufferSizes().contains (bufferSize))
  537. return bufferSize;
  538. return currentAudioDevice->getDefaultBufferSize();
  539. }
  540. void AudioDeviceManager::stopDevice()
  541. {
  542. if (currentAudioDevice != nullptr)
  543. currentAudioDevice->stop();
  544. testSound.reset();
  545. }
  546. void AudioDeviceManager::closeAudioDevice()
  547. {
  548. stopDevice();
  549. currentAudioDevice.reset();
  550. loadMeasurer.reset();
  551. }
  552. void AudioDeviceManager::restartLastAudioDevice()
  553. {
  554. if (currentAudioDevice == nullptr)
  555. {
  556. if (currentSetup.inputDeviceName.isEmpty()
  557. && currentSetup.outputDeviceName.isEmpty())
  558. {
  559. // This method will only reload the last device that was running
  560. // before closeAudioDevice() was called - you need to actually open
  561. // one first, with setAudioDevice().
  562. jassertfalse;
  563. return;
  564. }
  565. AudioDeviceSetup s (currentSetup);
  566. setAudioDeviceSetup (s, false);
  567. }
  568. }
  569. void AudioDeviceManager::updateXml()
  570. {
  571. lastExplicitSettings.reset (new XmlElement ("DEVICESETUP"));
  572. lastExplicitSettings->setAttribute ("deviceType", currentDeviceType);
  573. lastExplicitSettings->setAttribute ("audioOutputDeviceName", currentSetup.outputDeviceName);
  574. lastExplicitSettings->setAttribute ("audioInputDeviceName", currentSetup.inputDeviceName);
  575. if (currentAudioDevice != nullptr)
  576. {
  577. lastExplicitSettings->setAttribute ("audioDeviceRate", currentAudioDevice->getCurrentSampleRate());
  578. if (currentAudioDevice->getDefaultBufferSize() != currentAudioDevice->getCurrentBufferSizeSamples())
  579. lastExplicitSettings->setAttribute ("audioDeviceBufferSize", currentAudioDevice->getCurrentBufferSizeSamples());
  580. if (! currentSetup.useDefaultInputChannels)
  581. lastExplicitSettings->setAttribute ("audioDeviceInChans", currentSetup.inputChannels.toString (2));
  582. if (! currentSetup.useDefaultOutputChannels)
  583. lastExplicitSettings->setAttribute ("audioDeviceOutChans", currentSetup.outputChannels.toString (2));
  584. }
  585. for (auto& input : enabledMidiInputs)
  586. {
  587. auto* child = lastExplicitSettings->createNewChildElement ("MIDIINPUT");
  588. child->setAttribute ("name", input->getName());
  589. child->setAttribute ("identifier", input->getIdentifier());
  590. }
  591. if (midiDeviceInfosFromXml.size() > 0)
  592. {
  593. // Add any midi devices that have been enabled before, but which aren't currently
  594. // open because the device has been disconnected.
  595. auto availableMidiDevices = MidiInput::getAvailableDevices();
  596. for (auto& d : midiDeviceInfosFromXml)
  597. {
  598. if (! availableMidiDevices.contains (d))
  599. {
  600. auto* child = lastExplicitSettings->createNewChildElement ("MIDIINPUT");
  601. child->setAttribute ("name", d.name);
  602. child->setAttribute ("identifier", d.identifier);
  603. }
  604. }
  605. }
  606. if (defaultMidiOutputDeviceInfo != MidiDeviceInfo())
  607. {
  608. lastExplicitSettings->setAttribute ("defaultMidiOutput", defaultMidiOutputDeviceInfo.name);
  609. lastExplicitSettings->setAttribute ("defaultMidiOutputDevice", defaultMidiOutputDeviceInfo.identifier);
  610. }
  611. }
  612. //==============================================================================
  613. void AudioDeviceManager::addAudioCallback (AudioIODeviceCallback* newCallback)
  614. {
  615. {
  616. const ScopedLock sl (audioCallbackLock);
  617. if (callbacks.contains (newCallback))
  618. return;
  619. }
  620. if (currentAudioDevice != nullptr && newCallback != nullptr)
  621. newCallback->audioDeviceAboutToStart (currentAudioDevice.get());
  622. const ScopedLock sl (audioCallbackLock);
  623. callbacks.add (newCallback);
  624. }
  625. void AudioDeviceManager::removeAudioCallback (AudioIODeviceCallback* callbackToRemove)
  626. {
  627. if (callbackToRemove != nullptr)
  628. {
  629. bool needsDeinitialising = currentAudioDevice != nullptr;
  630. {
  631. const ScopedLock sl (audioCallbackLock);
  632. needsDeinitialising = needsDeinitialising && callbacks.contains (callbackToRemove);
  633. callbacks.removeFirstMatchingValue (callbackToRemove);
  634. }
  635. if (needsDeinitialising)
  636. callbackToRemove->audioDeviceStopped();
  637. }
  638. }
  639. void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelData,
  640. int numInputChannels,
  641. float** outputChannelData,
  642. int numOutputChannels,
  643. int numSamples)
  644. {
  645. const ScopedLock sl (audioCallbackLock);
  646. inputLevelGetter->updateLevel (inputChannelData, numInputChannels, numSamples);
  647. outputLevelGetter->updateLevel (const_cast<const float**> (outputChannelData), numOutputChannels, numSamples);
  648. if (callbacks.size() > 0)
  649. {
  650. AudioProcessLoadMeasurer::ScopedTimer timer (loadMeasurer);
  651. tempBuffer.setSize (jmax (1, numOutputChannels), jmax (1, numSamples), false, false, true);
  652. callbacks.getUnchecked(0)->audioDeviceIOCallback (inputChannelData, numInputChannels,
  653. outputChannelData, numOutputChannels, numSamples);
  654. auto** tempChans = tempBuffer.getArrayOfWritePointers();
  655. for (int i = callbacks.size(); --i > 0;)
  656. {
  657. callbacks.getUnchecked(i)->audioDeviceIOCallback (inputChannelData, numInputChannels,
  658. tempChans, numOutputChannels, numSamples);
  659. for (int chan = 0; chan < numOutputChannels; ++chan)
  660. {
  661. if (auto* src = tempChans [chan])
  662. if (auto* dst = outputChannelData [chan])
  663. for (int j = 0; j < numSamples; ++j)
  664. dst[j] += src[j];
  665. }
  666. }
  667. }
  668. else
  669. {
  670. for (int i = 0; i < numOutputChannels; ++i)
  671. zeromem (outputChannelData[i], (size_t) numSamples * sizeof (float));
  672. }
  673. if (testSound != nullptr)
  674. {
  675. auto numSamps = jmin (numSamples, testSound->getNumSamples() - testSoundPosition);
  676. auto* src = testSound->getReadPointer (0, testSoundPosition);
  677. for (int i = 0; i < numOutputChannels; ++i)
  678. for (int j = 0; j < numSamps; ++j)
  679. outputChannelData [i][j] += src[j];
  680. testSoundPosition += numSamps;
  681. if (testSoundPosition >= testSound->getNumSamples())
  682. testSound.reset();
  683. }
  684. }
  685. void AudioDeviceManager::audioDeviceAboutToStartInt (AudioIODevice* const device)
  686. {
  687. loadMeasurer.reset (device->getCurrentSampleRate(),
  688. device->getCurrentBufferSizeSamples());
  689. {
  690. const ScopedLock sl (audioCallbackLock);
  691. for (int i = callbacks.size(); --i >= 0;)
  692. callbacks.getUnchecked(i)->audioDeviceAboutToStart (device);
  693. }
  694. sendChangeMessage();
  695. }
  696. void AudioDeviceManager::audioDeviceStoppedInt()
  697. {
  698. sendChangeMessage();
  699. const ScopedLock sl (audioCallbackLock);
  700. loadMeasurer.reset();
  701. for (int i = callbacks.size(); --i >= 0;)
  702. callbacks.getUnchecked(i)->audioDeviceStopped();
  703. }
  704. void AudioDeviceManager::audioDeviceErrorInt (const String& message)
  705. {
  706. const ScopedLock sl (audioCallbackLock);
  707. for (int i = callbacks.size(); --i >= 0;)
  708. callbacks.getUnchecked(i)->audioDeviceError (message);
  709. }
  710. double AudioDeviceManager::getCpuUsage() const
  711. {
  712. return loadMeasurer.getLoadAsProportion();
  713. }
  714. //==============================================================================
  715. void AudioDeviceManager::setMidiInputDeviceEnabled (const String& identifier, bool enabled)
  716. {
  717. if (enabled != isMidiInputDeviceEnabled (identifier))
  718. {
  719. if (enabled)
  720. {
  721. if (auto midiIn = MidiInput::openDevice (identifier, callbackHandler.get()))
  722. {
  723. enabledMidiInputs.push_back (std::move (midiIn));
  724. enabledMidiInputs.back()->start();
  725. }
  726. }
  727. else
  728. {
  729. auto removePredicate = [identifier] (const std::unique_ptr<MidiInput>& in) { return in->getIdentifier() == identifier; };
  730. enabledMidiInputs.erase (std::remove_if (std::begin (enabledMidiInputs), std::end (enabledMidiInputs), removePredicate),
  731. std::end (enabledMidiInputs));
  732. }
  733. updateXml();
  734. sendChangeMessage();
  735. }
  736. }
  737. bool AudioDeviceManager::isMidiInputDeviceEnabled (const String& identifier) const
  738. {
  739. for (auto& mi : enabledMidiInputs)
  740. if (mi->getIdentifier() == identifier)
  741. return true;
  742. return false;
  743. }
  744. void AudioDeviceManager::addMidiInputDeviceCallback (const String& identifier, MidiInputCallback* callbackToAdd)
  745. {
  746. removeMidiInputDeviceCallback (identifier, callbackToAdd);
  747. if (identifier.isEmpty() || isMidiInputDeviceEnabled (identifier))
  748. {
  749. const ScopedLock sl (midiCallbackLock);
  750. midiCallbacks.add ({ identifier, callbackToAdd });
  751. }
  752. }
  753. void AudioDeviceManager::removeMidiInputDeviceCallback (const String& identifier, MidiInputCallback* callbackToRemove)
  754. {
  755. for (int i = midiCallbacks.size(); --i >= 0;)
  756. {
  757. auto& mc = midiCallbacks.getReference (i);
  758. if (mc.callback == callbackToRemove && mc.deviceIdentifier == identifier)
  759. {
  760. const ScopedLock sl (midiCallbackLock);
  761. midiCallbacks.remove (i);
  762. }
  763. }
  764. }
  765. void AudioDeviceManager::handleIncomingMidiMessageInt (MidiInput* source, const MidiMessage& message)
  766. {
  767. if (! message.isActiveSense())
  768. {
  769. const ScopedLock sl (midiCallbackLock);
  770. for (auto& mc : midiCallbacks)
  771. if (mc.deviceIdentifier.isEmpty() || mc.deviceIdentifier == source->getIdentifier())
  772. mc.callback->handleIncomingMidiMessage (source, message);
  773. }
  774. }
  775. //==============================================================================
  776. void AudioDeviceManager::setDefaultMidiOutputDevice (const String& identifier)
  777. {
  778. if (defaultMidiOutputDeviceInfo.identifier != identifier)
  779. {
  780. Array<AudioIODeviceCallback*> oldCallbacks;
  781. {
  782. const ScopedLock sl (audioCallbackLock);
  783. oldCallbacks.swapWith (callbacks);
  784. }
  785. if (currentAudioDevice != nullptr)
  786. for (int i = oldCallbacks.size(); --i >= 0;)
  787. oldCallbacks.getUnchecked (i)->audioDeviceStopped();
  788. defaultMidiOutput.reset();
  789. if (identifier.isNotEmpty())
  790. defaultMidiOutput = MidiOutput::openDevice (identifier);
  791. if (defaultMidiOutput != nullptr)
  792. defaultMidiOutputDeviceInfo = defaultMidiOutput->getDeviceInfo();
  793. else
  794. defaultMidiOutputDeviceInfo = {};
  795. if (currentAudioDevice != nullptr)
  796. for (auto* c : oldCallbacks)
  797. c->audioDeviceAboutToStart (currentAudioDevice.get());
  798. {
  799. const ScopedLock sl (audioCallbackLock);
  800. oldCallbacks.swapWith (callbacks);
  801. }
  802. updateXml();
  803. sendChangeMessage();
  804. }
  805. }
  806. //==============================================================================
  807. AudioDeviceManager::LevelMeter::LevelMeter() noexcept : level() {}
  808. void AudioDeviceManager::LevelMeter::updateLevel (const float* const* channelData, int numChannels, int numSamples) noexcept
  809. {
  810. if (getReferenceCount() <= 1)
  811. return;
  812. auto localLevel = level.get();
  813. if (numChannels > 0)
  814. {
  815. for (int j = 0; j < numSamples; ++j)
  816. {
  817. float s = 0;
  818. for (int i = 0; i < numChannels; ++i)
  819. s += std::abs (channelData[i][j]);
  820. s /= (float) numChannels;
  821. const float decayFactor = 0.99992f;
  822. if (s > localLevel)
  823. localLevel = s;
  824. else if (localLevel > 0.001f)
  825. localLevel *= decayFactor;
  826. else
  827. localLevel = 0;
  828. }
  829. }
  830. else
  831. {
  832. localLevel = 0;
  833. }
  834. level = localLevel;
  835. }
  836. double AudioDeviceManager::LevelMeter::getCurrentLevel() const noexcept
  837. {
  838. jassert (getReferenceCount() > 1);
  839. return level.get();
  840. }
  841. void AudioDeviceManager::playTestSound()
  842. {
  843. { // cunningly nested to swap, unlock and delete in that order.
  844. std::unique_ptr<AudioBuffer<float>> oldSound;
  845. {
  846. const ScopedLock sl (audioCallbackLock);
  847. std::swap (oldSound, testSound);
  848. }
  849. }
  850. testSoundPosition = 0;
  851. if (currentAudioDevice != nullptr)
  852. {
  853. auto sampleRate = currentAudioDevice->getCurrentSampleRate();
  854. auto soundLength = (int) sampleRate;
  855. double frequency = 440.0;
  856. float amplitude = 0.5f;
  857. auto phasePerSample = MathConstants<double>::twoPi / (sampleRate / frequency);
  858. std::unique_ptr<AudioBuffer<float>> newSound (new AudioBuffer<float> (1, soundLength));
  859. for (int i = 0; i < soundLength; ++i)
  860. newSound->setSample (0, i, amplitude * (float) std::sin (i * phasePerSample));
  861. newSound->applyGainRamp (0, 0, soundLength / 10, 0.0f, 1.0f);
  862. newSound->applyGainRamp (0, soundLength - soundLength / 4, soundLength / 4, 1.0f, 0.0f);
  863. {
  864. const ScopedLock sl (audioCallbackLock);
  865. std::swap (testSound, newSound);
  866. }
  867. }
  868. }
  869. int AudioDeviceManager::getXRunCount() const noexcept
  870. {
  871. auto deviceXRuns = (currentAudioDevice != nullptr ? currentAudioDevice->getXRunCount() : -1);
  872. return jmax (0, deviceXRuns) + loadMeasurer.getXRunCount();
  873. }
  874. //==============================================================================
  875. // Deprecated
  876. void AudioDeviceManager::setMidiInputEnabled (const String& name, const bool enabled)
  877. {
  878. for (auto& device : MidiInput::getAvailableDevices())
  879. {
  880. if (device.name == name)
  881. {
  882. setMidiInputDeviceEnabled (device.identifier, enabled);
  883. return;
  884. }
  885. }
  886. }
  887. bool AudioDeviceManager::isMidiInputEnabled (const String& name) const
  888. {
  889. for (auto& device : MidiInput::getAvailableDevices())
  890. if (device.name == name)
  891. return isMidiInputDeviceEnabled (device.identifier);
  892. return false;
  893. }
  894. void AudioDeviceManager::addMidiInputCallback (const String& name, MidiInputCallback* callbackToAdd)
  895. {
  896. if (name.isEmpty())
  897. {
  898. addMidiInputDeviceCallback ({}, callbackToAdd);
  899. }
  900. else
  901. {
  902. for (auto& device : MidiInput::getAvailableDevices())
  903. {
  904. if (device.name == name)
  905. {
  906. addMidiInputDeviceCallback (device.identifier, callbackToAdd);
  907. return;
  908. }
  909. }
  910. }
  911. }
  912. void AudioDeviceManager::removeMidiInputCallback (const String& name, MidiInputCallback* callbackToRemove)
  913. {
  914. for (auto& device : MidiInput::getAvailableDevices())
  915. {
  916. if (device.name == name)
  917. {
  918. removeMidiInputDeviceCallback (device.identifier, callbackToRemove);
  919. return;
  920. }
  921. }
  922. }
  923. void AudioDeviceManager::setDefaultMidiOutput (const String& name)
  924. {
  925. for (auto& device : MidiOutput::getAvailableDevices())
  926. {
  927. if (device.name == name)
  928. {
  929. setDefaultMidiOutputDevice (device.identifier);
  930. return;
  931. }
  932. }
  933. }
  934. } // namespace juce