The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

998 lines
33KB

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