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.

1138 lines
35KB

  1. /*
  2. * Carla Plugin Host
  3. * Copyright (C) 2011-2020 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the GPL.txt file
  16. */
  17. #include "CarlaEngineGraph.hpp"
  18. #include "CarlaEngineInit.hpp"
  19. #include "CarlaEngineInternal.hpp"
  20. #include "CarlaBackendUtils.hpp"
  21. #include "CarlaStringList.hpp"
  22. #include "RtLinkedList.hpp"
  23. #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
  24. # pragma GCC diagnostic push
  25. # pragma GCC diagnostic ignored "-Wdouble-promotion"
  26. # pragma GCC diagnostic ignored "-Weffc++"
  27. # pragma GCC diagnostic ignored "-Wfloat-equal"
  28. #endif
  29. #include "AppConfig.h"
  30. #include "juce_audio_devices/juce_audio_devices.h"
  31. #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
  32. # pragma GCC diagnostic pop
  33. #endif
  34. CARLA_BACKEND_START_NAMESPACE
  35. // -------------------------------------------------------------------------------------------------------------------
  36. struct MidiInPort {
  37. juce::MidiInput* port;
  38. char name[STR_MAX];
  39. char identifier[STR_MAX];
  40. };
  41. struct MidiOutPort {
  42. juce::MidiOutput* port;
  43. char name[STR_MAX];
  44. char identifier[STR_MAX];
  45. };
  46. struct RtMidiEvent {
  47. uint64_t time; // needs to compare to internal time
  48. uint8_t size;
  49. uint8_t data[EngineMidiEvent::kDataSize];
  50. };
  51. // -------------------------------------------------------------------------------------------------------------------
  52. // Fallback data
  53. static const MidiInPort kMidiInPortFallback = { nullptr, { '\0' }, { '\0' } };
  54. static /* */ MidiInPort kMidiInPortFallbackNC = { nullptr, { '\0' }, { '\0' } };
  55. static const MidiOutPort kMidiOutPortFallback = { nullptr, { '\0' }, { '\0' } };
  56. static /* */ MidiOutPort kMidiOutPortFallbackNC = { nullptr, { '\0' }, { '\0' } };
  57. static const RtMidiEvent kRtMidiEventFallback = { 0, 0, { 0 } };
  58. // -------------------------------------------------------------------------------------------------------------------
  59. // Global static data
  60. static CharStringListPtr gDeviceNames;
  61. static juce::OwnedArray<juce::AudioIODeviceType> gDeviceTypes;
  62. struct JuceCleanup : public juce::DeletedAtShutdown {
  63. JuceCleanup() noexcept {}
  64. ~JuceCleanup()
  65. {
  66. gDeviceTypes.clear(true);
  67. }
  68. };
  69. // -------------------------------------------------------------------------------------------------------------------
  70. // Cleanup
  71. struct AudioIODeviceTypeComparator
  72. {
  73. static int compareElements (const juce::AudioIODeviceType* d1, const juce::AudioIODeviceType* d2) noexcept
  74. {
  75. return d1->getTypeName().compareNatural (d2->getTypeName());
  76. }
  77. };
  78. static void initJuceDevicesIfNeeded()
  79. {
  80. static juce::AudioDeviceManager sDeviceManager;
  81. if (gDeviceTypes.size() != 0)
  82. return;
  83. sDeviceManager.createAudioDeviceTypes(gDeviceTypes);
  84. CARLA_SAFE_ASSERT_RETURN(gDeviceTypes.size() != 0,);
  85. new JuceCleanup();
  86. // remove JACK from device list
  87. for (int i=0, count=gDeviceTypes.size(); i < count; ++i)
  88. {
  89. if (gDeviceTypes[i]->getTypeName() == "JACK")
  90. {
  91. gDeviceTypes.remove(i, true);
  92. break;
  93. }
  94. }
  95. AudioIODeviceTypeComparator comp;
  96. gDeviceTypes.sort(comp);
  97. }
  98. // -------------------------------------------------------------------------------------------------------------------
  99. // Juce Engine
  100. class CarlaEngineJuce : public CarlaEngine,
  101. public juce::AudioIODeviceCallback,
  102. public juce::MidiInputCallback
  103. {
  104. public:
  105. CarlaEngineJuce(juce::AudioIODeviceType* const devType)
  106. : CarlaEngine(),
  107. juce::AudioIODeviceCallback(),
  108. fDevice(),
  109. fDeviceType(devType),
  110. fMidiIns(),
  111. fMidiInEvents(),
  112. fMidiOuts(),
  113. fMidiOutMutex()
  114. {
  115. carla_debug("CarlaEngineJuce::CarlaEngineJuce(%p)", devType);
  116. // just to make sure
  117. pData->options.transportMode = ENGINE_TRANSPORT_MODE_INTERNAL;
  118. }
  119. ~CarlaEngineJuce() override
  120. {
  121. carla_debug("CarlaEngineJuce::~CarlaEngineJuce()");
  122. }
  123. // -------------------------------------
  124. bool init(const char* const clientName) override
  125. {
  126. CARLA_SAFE_ASSERT_RETURN(clientName != nullptr && clientName[0] != '\0', false);
  127. carla_debug("CarlaEngineJuce::init(\"%s\")", clientName);
  128. if (pData->options.processMode != ENGINE_PROCESS_MODE_CONTINUOUS_RACK && pData->options.processMode != ENGINE_PROCESS_MODE_PATCHBAY)
  129. {
  130. setLastError("Invalid process mode");
  131. return false;
  132. }
  133. juce::String deviceName;
  134. if (pData->options.audioDevice != nullptr && pData->options.audioDevice[0] != '\0')
  135. {
  136. deviceName = pData->options.audioDevice;
  137. }
  138. else
  139. {
  140. const int defaultIndex = fDeviceType->getDefaultDeviceIndex(false);
  141. juce::StringArray deviceNames(fDeviceType->getDeviceNames());
  142. if (defaultIndex >= 0 && defaultIndex < deviceNames.size())
  143. deviceName = deviceNames[defaultIndex];
  144. }
  145. if (deviceName.isEmpty())
  146. {
  147. setLastError("Audio device has not been selected yet and a default one is not available");
  148. return false;
  149. }
  150. fDevice = fDeviceType->createDevice(deviceName, deviceName);
  151. if (fDevice == nullptr)
  152. {
  153. setLastError("Failed to create device");
  154. return false;
  155. }
  156. juce::StringArray inputNames(fDevice->getInputChannelNames());
  157. juce::StringArray outputNames(fDevice->getOutputChannelNames());
  158. if (inputNames.size() < 0 || outputNames.size() <= 0)
  159. {
  160. setLastError("Selected device does not have any outputs");
  161. return false;
  162. }
  163. juce::BigInteger inputChannels;
  164. inputChannels.setRange(0, inputNames.size(), true);
  165. juce::BigInteger outputChannels;
  166. outputChannels.setRange(0, outputNames.size(), true);
  167. juce::String error = fDevice->open(inputChannels, outputChannels, pData->options.audioSampleRate, static_cast<int>(pData->options.audioBufferSize));
  168. if (error.isNotEmpty())
  169. {
  170. setLastError(error.toUTF8());
  171. fDevice = nullptr;
  172. return false;
  173. }
  174. if (! pData->init(clientName))
  175. {
  176. close();
  177. setLastError("Failed to init internal data");
  178. return false;
  179. }
  180. pData->bufferSize = static_cast<uint32_t>(fDevice->getCurrentBufferSizeSamples());
  181. pData->sampleRate = fDevice->getCurrentSampleRate();
  182. pData->initTime(pData->options.transportExtra);
  183. pData->graph.create(static_cast<uint32_t>(inputNames.size()),
  184. static_cast<uint32_t>(outputNames.size()),
  185. 0, 0);
  186. fDevice->start(this);
  187. patchbayRefresh(true, false, false);
  188. if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
  189. refreshExternalGraphPorts<PatchbayGraph>(pData->graph.getPatchbayGraph(), false, false);
  190. callback(true, true,
  191. ENGINE_CALLBACK_ENGINE_STARTED,
  192. 0,
  193. pData->options.processMode,
  194. pData->options.transportMode,
  195. static_cast<int>(pData->bufferSize),
  196. static_cast<float>(pData->sampleRate),
  197. getCurrentDriverName());
  198. return true;
  199. }
  200. bool close() override
  201. {
  202. carla_debug("CarlaEngineJuce::close()");
  203. bool hasError = false;
  204. // stop stream first
  205. if (fDevice != nullptr && fDevice->isPlaying())
  206. fDevice->stop();
  207. // clear engine data
  208. CarlaEngine::close();
  209. pData->graph.destroy();
  210. for (LinkedList<MidiInPort>::Itenerator it = fMidiIns.begin2(); it.valid(); it.next())
  211. {
  212. MidiInPort& inPort(it.getValue(kMidiInPortFallbackNC));
  213. CARLA_SAFE_ASSERT_CONTINUE(inPort.port != nullptr);
  214. inPort.port->stop();
  215. delete inPort.port;
  216. }
  217. fMidiIns.clear();
  218. fMidiInEvents.clear();
  219. fMidiOutMutex.lock();
  220. for (LinkedList<MidiOutPort>::Itenerator it = fMidiOuts.begin2(); it.valid(); it.next())
  221. {
  222. MidiOutPort& outPort(it.getValue(kMidiOutPortFallbackNC));
  223. CARLA_SAFE_ASSERT_CONTINUE(outPort.port != nullptr);
  224. outPort.port->stopBackgroundThread();
  225. delete outPort.port;
  226. }
  227. fMidiOuts.clear();
  228. fMidiOutMutex.unlock();
  229. // close stream
  230. if (fDevice != nullptr)
  231. {
  232. if (fDevice->isOpen())
  233. fDevice->close();
  234. fDevice = nullptr;
  235. }
  236. return !hasError;
  237. }
  238. bool isRunning() const noexcept override
  239. {
  240. return fDevice != nullptr && fDevice->isOpen();
  241. }
  242. bool isOffline() const noexcept override
  243. {
  244. return false;
  245. }
  246. EngineType getType() const noexcept override
  247. {
  248. return kEngineTypeJuce;
  249. }
  250. const char* getCurrentDriverName() const noexcept override
  251. {
  252. return fDeviceType->getTypeName().toRawUTF8();
  253. }
  254. /*
  255. float getDSPLoad() const noexcept override
  256. {
  257. return 0.0f;
  258. }
  259. */
  260. uint32_t getTotalXruns() const noexcept override
  261. {
  262. const int xruns = fDevice->getXRunCount();
  263. if (xruns <= 0)
  264. return 0;
  265. const uint uxruns = static_cast<uint>(xruns);
  266. if (uxruns <= pData->xruns)
  267. return 0;
  268. return uxruns - pData->xruns;
  269. }
  270. void clearXruns() const noexcept override
  271. {
  272. const int xruns = fDevice->getXRunCount();
  273. pData->xruns = xruns > 0 ? static_cast<uint32_t>(xruns) : 0;
  274. }
  275. bool setBufferSizeAndSampleRate(const uint bufferSize, const double sampleRate) override
  276. {
  277. CARLA_SAFE_ASSERT_RETURN(fDevice != nullptr, false);
  278. juce::StringArray inputNames(fDevice->getInputChannelNames());
  279. juce::StringArray outputNames(fDevice->getOutputChannelNames());
  280. if (inputNames.size() < 0 || outputNames.size() <= 0)
  281. {
  282. setLastError("Selected device does not have any outputs");
  283. return false;
  284. }
  285. juce::BigInteger inputChannels;
  286. inputChannels.setRange(0, inputNames.size(), true);
  287. juce::BigInteger outputChannels;
  288. outputChannels.setRange(0, outputNames.size(), true);
  289. // stop stream first
  290. if (fDevice->isPlaying())
  291. fDevice->stop();
  292. if (fDevice->isOpen())
  293. fDevice->close();
  294. juce::String error = fDevice->open(inputChannels, outputChannels, sampleRate, static_cast<int>(bufferSize));
  295. if (error.isNotEmpty())
  296. {
  297. setLastError(error.toUTF8());
  298. // try to roll back
  299. error = fDevice->open(inputChannels, outputChannels, pData->sampleRate, static_cast<int>(pData->bufferSize));
  300. // if we failed, we are screwed...
  301. if (error.isNotEmpty())
  302. {
  303. fDevice = nullptr;
  304. close();
  305. }
  306. return false;
  307. }
  308. const uint32_t newBufferSize = static_cast<uint32_t>(fDevice->getCurrentBufferSizeSamples());
  309. const double newSampleRate = fDevice->getCurrentSampleRate();
  310. if (carla_isNotEqual(pData->sampleRate, newSampleRate))
  311. {
  312. pData->sampleRate = newSampleRate;
  313. sampleRateChanged(newSampleRate);
  314. }
  315. if (pData->bufferSize != newBufferSize)
  316. {
  317. pData->bufferSize = newBufferSize;
  318. bufferSizeChanged(newBufferSize);
  319. }
  320. fDevice->start(this);
  321. return true;
  322. }
  323. bool showDeviceControlPanel() const noexcept override
  324. {
  325. try {
  326. return fDevice->showControlPanel();
  327. } CARLA_SAFE_EXCEPTION_RETURN("showDeviceControlPanel", false);
  328. }
  329. // -------------------------------------------------------------------
  330. // Patchbay
  331. template<class Graph>
  332. bool refreshExternalGraphPorts(Graph* const graph, const bool sendHost, const bool sendOSC)
  333. {
  334. CARLA_SAFE_ASSERT_RETURN(graph != nullptr, false);
  335. char strBuf[STR_MAX];
  336. ExternalGraph& extGraph(graph->extGraph);
  337. // ---------------------------------------------------------------
  338. // clear last ports
  339. extGraph.clear();
  340. // ---------------------------------------------------------------
  341. // fill in new ones
  342. // Audio In
  343. {
  344. juce::StringArray inputNames(fDevice->getInputChannelNames());
  345. for (int i=0, count=inputNames.size(); i<count; ++i)
  346. {
  347. PortNameToId portNameToId;
  348. portNameToId.setData(kExternalGraphGroupAudioIn, uint(i+1), inputNames[i].toRawUTF8(), "");
  349. extGraph.audioPorts.ins.append(portNameToId);
  350. }
  351. }
  352. // Audio Out
  353. {
  354. juce::StringArray outputNames(fDevice->getOutputChannelNames());
  355. for (int i=0, count=outputNames.size(); i<count; ++i)
  356. {
  357. PortNameToId portNameToId;
  358. portNameToId.setData(kExternalGraphGroupAudioOut, uint(i+1), outputNames[i].toRawUTF8(), "");
  359. extGraph.audioPorts.outs.append(portNameToId);
  360. }
  361. }
  362. // MIDI In
  363. {
  364. juce::Array<juce::MidiDeviceInfo> midiIns(juce::MidiInput::getAvailableDevices());
  365. for (int i=0, count=midiIns.size(); i<count; ++i)
  366. {
  367. const juce::MidiDeviceInfo devInfo(midiIns[i]);
  368. if (devInfo.name == "a2jmidid - port")
  369. continue;
  370. PortNameToId portNameToId;
  371. portNameToId.setDataWithIdentifier(kExternalGraphGroupMidiIn, static_cast<uint>(i + 1),
  372. devInfo.name.toRawUTF8(), devInfo.identifier.toRawUTF8());
  373. extGraph.midiPorts.ins.append(portNameToId);
  374. }
  375. }
  376. // MIDI Out
  377. {
  378. juce::Array<juce::MidiDeviceInfo> midiOuts(juce::MidiOutput::getAvailableDevices());
  379. for (int i=0, count=midiOuts.size(); i<count; ++i)
  380. {
  381. const juce::MidiDeviceInfo devInfo(midiOuts[i]);
  382. if (devInfo.name == "a2jmidid - port")
  383. continue;
  384. PortNameToId portNameToId;
  385. portNameToId.setDataWithIdentifier(kExternalGraphGroupMidiOut, static_cast<uint>(i + 1),
  386. devInfo.name.toRawUTF8(), devInfo.identifier.toRawUTF8());
  387. extGraph.midiPorts.outs.append(portNameToId);
  388. }
  389. }
  390. // ---------------------------------------------------------------
  391. // now refresh
  392. if (sendHost || sendOSC)
  393. {
  394. juce::String deviceName(fDevice->getName());
  395. if (deviceName.isNotEmpty())
  396. deviceName = deviceName.dropLastCharacters(deviceName.fromFirstOccurrenceOf(", ", true, false).length());
  397. graph->refresh(sendHost, sendOSC, true, deviceName.toRawUTF8());
  398. }
  399. // ---------------------------------------------------------------
  400. // add midi connections
  401. for (LinkedList<MidiInPort>::Itenerator it=fMidiIns.begin2(); it.valid(); it.next())
  402. {
  403. const MidiInPort& inPort(it.getValue(kMidiInPortFallback));
  404. CARLA_SAFE_ASSERT_CONTINUE(inPort.port != nullptr);
  405. bool ok;
  406. const uint portId = extGraph.midiPorts.getPortIdFromIdentifier(true, inPort.identifier, &ok);
  407. CARLA_SAFE_ASSERT_UINT_CONTINUE(ok, portId);
  408. ConnectionToId connectionToId;
  409. connectionToId.setData(++(extGraph.connections.lastId), kExternalGraphGroupMidiIn, portId, kExternalGraphGroupCarla, kExternalGraphCarlaPortMidiIn);
  410. std::snprintf(strBuf, STR_MAX-1, "%i:%i:%i:%i", connectionToId.groupA, connectionToId.portA, connectionToId.groupB, connectionToId.portB);
  411. strBuf[STR_MAX-1] = '\0';
  412. callback(sendHost, sendOSC,
  413. ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED,
  414. connectionToId.id,
  415. 0, 0, 0, 0.0f,
  416. strBuf);
  417. extGraph.connections.list.append(connectionToId);
  418. }
  419. fMidiOutMutex.lock();
  420. for (LinkedList<MidiOutPort>::Itenerator it=fMidiOuts.begin2(); it.valid(); it.next())
  421. {
  422. const MidiOutPort& outPort(it.getValue(kMidiOutPortFallback));
  423. CARLA_SAFE_ASSERT_CONTINUE(outPort.port != nullptr);
  424. bool ok;
  425. const uint portId = extGraph.midiPorts.getPortIdFromIdentifier(false, outPort.identifier, &ok);
  426. CARLA_SAFE_ASSERT_UINT_CONTINUE(ok, portId);
  427. ConnectionToId connectionToId;
  428. connectionToId.setData(++(extGraph.connections.lastId), kExternalGraphGroupCarla, kExternalGraphCarlaPortMidiOut, kExternalGraphGroupMidiOut, portId);
  429. std::snprintf(strBuf, STR_MAX-1, "%i:%i:%i:%i", connectionToId.groupA, connectionToId.portA, connectionToId.groupB, connectionToId.portB);
  430. strBuf[STR_MAX-1] = '\0';
  431. callback(sendHost, sendOSC,
  432. ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED,
  433. connectionToId.id,
  434. 0, 0, 0, 0.0f,
  435. strBuf);
  436. extGraph.connections.list.append(connectionToId);
  437. }
  438. fMidiOutMutex.unlock();
  439. return true;
  440. }
  441. bool patchbayRefresh(const bool sendHost, const bool sendOSC, const bool external) override
  442. {
  443. CARLA_SAFE_ASSERT_RETURN(pData->graph.isReady(), false);
  444. if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
  445. return refreshExternalGraphPorts<RackGraph>(pData->graph.getRackGraph(), sendHost, sendOSC);
  446. if (sendHost)
  447. pData->graph.setUsingExternalHost(external);
  448. if (sendOSC)
  449. pData->graph.setUsingExternalOSC(external);
  450. if (external)
  451. return refreshExternalGraphPorts<PatchbayGraph>(pData->graph.getPatchbayGraph(), sendHost, sendOSC);
  452. return CarlaEngine::patchbayRefresh(sendHost, sendOSC, false);
  453. }
  454. // -------------------------------------------------------------------
  455. protected:
  456. void audioDeviceIOCallback(const float** inputChannelData, int numInputChannels, float** outputChannelData,
  457. int numOutputChannels, int numSamples) override
  458. {
  459. CARLA_SAFE_ASSERT_RETURN(numSamples >= 0,);
  460. const uint32_t nframes(static_cast<uint32_t>(numSamples));
  461. const PendingRtEventsRunner prt(this, nframes, true); // FIXME remove dspCalc after updating juce
  462. // assert juce buffers
  463. CARLA_SAFE_ASSERT_RETURN(numInputChannels >= 0,);
  464. CARLA_SAFE_ASSERT_RETURN(numOutputChannels > 0,);
  465. CARLA_SAFE_ASSERT_RETURN(outputChannelData != nullptr,);
  466. CARLA_SAFE_ASSERT_RETURN(numSamples == static_cast<int>(pData->bufferSize),);
  467. // initialize juce output
  468. for (int i=0; i < numOutputChannels; ++i)
  469. carla_zeroFloats(outputChannelData[i], nframes);
  470. // initialize events
  471. carla_zeroStructs(pData->events.in, kMaxEngineEventInternalCount);
  472. carla_zeroStructs(pData->events.out, kMaxEngineEventInternalCount);
  473. if (fMidiInEvents.mutex.tryLock())
  474. {
  475. uint32_t engineEventIndex = 0;
  476. fMidiInEvents.splice();
  477. for (LinkedList<RtMidiEvent>::Itenerator it = fMidiInEvents.data.begin2(); it.valid(); it.next())
  478. {
  479. const RtMidiEvent& midiEvent(it.getValue(kRtMidiEventFallback));
  480. CARLA_SAFE_ASSERT_CONTINUE(midiEvent.size > 0);
  481. EngineEvent& engineEvent(pData->events.in[engineEventIndex++]);
  482. if (midiEvent.time < pData->timeInfo.frame)
  483. {
  484. engineEvent.time = 0;
  485. }
  486. else if (midiEvent.time >= pData->timeInfo.frame + nframes)
  487. {
  488. carla_stderr("MIDI Event in the future!, %i vs %i", engineEvent.time, pData->timeInfo.frame);
  489. engineEvent.time = static_cast<uint32_t>(pData->timeInfo.frame) + nframes - 1;
  490. }
  491. else
  492. engineEvent.time = static_cast<uint32_t>(midiEvent.time - pData->timeInfo.frame);
  493. engineEvent.fillFromMidiData(midiEvent.size, midiEvent.data, 0);
  494. if (engineEventIndex >= kMaxEngineEventInternalCount)
  495. break;
  496. }
  497. fMidiInEvents.data.clear();
  498. fMidiInEvents.mutex.unlock();
  499. }
  500. pData->graph.process(pData, inputChannelData, outputChannelData, nframes);
  501. fMidiOutMutex.lock();
  502. if (fMidiOuts.count() > 0)
  503. {
  504. uint8_t size = 0;
  505. uint8_t data[3] = { 0, 0, 0 };
  506. const uint8_t* dataPtr = data;
  507. for (ushort i=0; i < kMaxEngineEventInternalCount; ++i)
  508. {
  509. const EngineEvent& engineEvent(pData->events.out[i]);
  510. if (engineEvent.type == kEngineEventTypeNull)
  511. break;
  512. else if (engineEvent.type == kEngineEventTypeControl)
  513. {
  514. const EngineControlEvent& ctrlEvent(engineEvent.ctrl);
  515. ctrlEvent.convertToMidiData(engineEvent.channel, data);
  516. dataPtr = data;
  517. }
  518. else if (engineEvent.type == kEngineEventTypeMidi)
  519. {
  520. const EngineMidiEvent& midiEvent(engineEvent.midi);
  521. size = midiEvent.size;
  522. if (size > EngineMidiEvent::kDataSize && midiEvent.dataExt != nullptr)
  523. dataPtr = midiEvent.dataExt;
  524. else
  525. dataPtr = midiEvent.data;
  526. }
  527. else
  528. {
  529. continue;
  530. }
  531. if (size > 0)
  532. {
  533. juce::MidiMessage message(static_cast<const void*>(dataPtr), static_cast<int>(size), static_cast<double>(engineEvent.time)/nframes);
  534. for (LinkedList<MidiOutPort>::Itenerator it=fMidiOuts.begin2(); it.valid(); it.next())
  535. {
  536. MidiOutPort& outPort(it.getValue(kMidiOutPortFallbackNC));
  537. CARLA_SAFE_ASSERT_CONTINUE(outPort.port != nullptr);
  538. outPort.port->sendMessageNow(message);
  539. }
  540. }
  541. }
  542. }
  543. fMidiOutMutex.unlock();
  544. }
  545. void audioDeviceAboutToStart(juce::AudioIODevice* /*device*/) override
  546. {
  547. }
  548. void audioDeviceStopped() override
  549. {
  550. }
  551. void audioDeviceError(const juce::String& errorMessage) override
  552. {
  553. callback(true, true, ENGINE_CALLBACK_ERROR, 0, 0, 0, 0, 0.0f, errorMessage.toRawUTF8());
  554. }
  555. // -------------------------------------------------------------------
  556. void handleIncomingMidiMessage(juce::MidiInput* /*source*/, const juce::MidiMessage& message) override
  557. {
  558. const int messageSize(message.getRawDataSize());
  559. if (messageSize <= 0 || messageSize > EngineMidiEvent::kDataSize)
  560. return;
  561. const uint8_t* const messageData(message.getRawData());
  562. RtMidiEvent midiEvent;
  563. midiEvent.time = 0; // TODO
  564. midiEvent.size = static_cast<uint8_t>(messageSize);
  565. int i=0;
  566. for (; i < messageSize; ++i)
  567. midiEvent.data[i] = messageData[i];
  568. for (; i < EngineMidiEvent::kDataSize; ++i)
  569. midiEvent.data[i] = 0;
  570. fMidiInEvents.append(midiEvent);
  571. }
  572. // -------------------------------------------------------------------
  573. bool connectExternalGraphPort(const uint connectionType, const uint portId, const char* const portName) override
  574. {
  575. CARLA_SAFE_ASSERT_RETURN(connectionType != 0 || (portName != nullptr && portName[0] != '\0'), false);
  576. carla_stdout("CarlaEngineJuce::connectExternalGraphPort(%u, %u, \"%s\")", connectionType, portId, portName);
  577. switch (connectionType)
  578. {
  579. case kExternalGraphConnectionAudioIn1:
  580. case kExternalGraphConnectionAudioIn2:
  581. case kExternalGraphConnectionAudioOut1:
  582. case kExternalGraphConnectionAudioOut2:
  583. return CarlaEngine::connectExternalGraphPort(connectionType, portId, portName);
  584. case kExternalGraphConnectionMidiInput: {
  585. juce::Array<juce::MidiDeviceInfo> midiIns(juce::MidiInput::getAvailableDevices());
  586. for (int i=0, count=midiIns.size(); i<count; ++i)
  587. {
  588. const juce::MidiDeviceInfo devInfo(midiIns[i]);
  589. if (devInfo.name != portName)
  590. continue;
  591. std::unique_ptr<juce::MidiInput> juceMidiIn(juce::MidiInput::openDevice(devInfo.identifier, this));
  592. juceMidiIn->start();
  593. MidiInPort midiPort;
  594. midiPort.port = juceMidiIn.release();
  595. std::strncpy(midiPort.name, portName, STR_MAX-1);
  596. midiPort.name[STR_MAX-1] = '\0';
  597. std::strncpy(midiPort.identifier, devInfo.identifier.toRawUTF8(), STR_MAX-1);
  598. midiPort.identifier[STR_MAX-1] = '\0';
  599. carla_stdout("MIDI CON '%s' '%s'", midiPort.name, midiPort.identifier);
  600. fMidiIns.append(midiPort);
  601. return true;
  602. }
  603. return false;
  604. }
  605. case kExternalGraphConnectionMidiOutput: {
  606. juce::Array<juce::MidiDeviceInfo> midiOuts(juce::MidiOutput::getAvailableDevices());
  607. for (int i=0, count=midiOuts.size(); i<count; ++i)
  608. {
  609. const juce::MidiDeviceInfo devInfo(midiOuts[i]);
  610. if (devInfo.name != portName)
  611. continue;
  612. std::unique_ptr<juce::MidiOutput> juceMidiOut(juce::MidiOutput::openDevice(devInfo.identifier));
  613. juceMidiOut->startBackgroundThread();
  614. MidiOutPort midiPort;
  615. midiPort.port = juceMidiOut.release();
  616. std::strncpy(midiPort.name, portName, STR_MAX-1);
  617. midiPort.name[STR_MAX-1] = '\0';
  618. std::strncpy(midiPort.identifier, devInfo.identifier.toRawUTF8(), STR_MAX-1);
  619. midiPort.identifier[STR_MAX-1] = '\0';
  620. const CarlaMutexLocker cml(fMidiOutMutex);
  621. fMidiOuts.append(midiPort);
  622. return true;
  623. }
  624. return false;
  625. }
  626. }
  627. return false;
  628. }
  629. bool disconnectExternalGraphPort(const uint connectionType, const uint portId, const char* const portName) override
  630. {
  631. CARLA_SAFE_ASSERT_RETURN(connectionType != 0 || (portName != nullptr && portName[0] != '\0'), false);
  632. carla_debug("CarlaEngineJuce::disconnectExternalGraphPort(%u, %u, \"%s\")", connectionType, portId, portName);
  633. switch (connectionType)
  634. {
  635. case kExternalGraphConnectionAudioIn1:
  636. case kExternalGraphConnectionAudioIn2:
  637. case kExternalGraphConnectionAudioOut1:
  638. case kExternalGraphConnectionAudioOut2:
  639. return CarlaEngine::disconnectExternalGraphPort(connectionType, portId, portName);
  640. case kExternalGraphConnectionMidiInput:
  641. for (LinkedList<MidiInPort>::Itenerator it=fMidiIns.begin2(); it.valid(); it.next())
  642. {
  643. MidiInPort& inPort(it.getValue(kMidiInPortFallbackNC));
  644. CARLA_SAFE_ASSERT_CONTINUE(inPort.port != nullptr);
  645. if (std::strcmp(inPort.name, portName) != 0)
  646. continue;
  647. inPort.port->stop();
  648. delete inPort.port;
  649. fMidiIns.remove(it);
  650. return true;
  651. }
  652. break;
  653. case kExternalGraphConnectionMidiOutput: {
  654. const CarlaMutexLocker cml(fMidiOutMutex);
  655. for (LinkedList<MidiOutPort>::Itenerator it=fMidiOuts.begin2(); it.valid(); it.next())
  656. {
  657. MidiOutPort& outPort(it.getValue(kMidiOutPortFallbackNC));
  658. CARLA_SAFE_ASSERT_CONTINUE(outPort.port != nullptr);
  659. if (std::strcmp(outPort.name, portName) != 0)
  660. continue;
  661. outPort.port->stopBackgroundThread();
  662. delete outPort.port;
  663. fMidiOuts.remove(it);
  664. return true;
  665. }
  666. } break;
  667. }
  668. return false;
  669. }
  670. // -------------------------------------
  671. private:
  672. CarlaScopedPointer<juce::AudioIODevice> fDevice;
  673. juce::AudioIODeviceType* const fDeviceType;
  674. struct RtMidiEvents {
  675. CarlaMutex mutex;
  676. RtLinkedList<RtMidiEvent>::Pool dataPool;
  677. RtLinkedList<RtMidiEvent> data;
  678. RtLinkedList<RtMidiEvent> dataPending;
  679. RtMidiEvents()
  680. : mutex(),
  681. dataPool("RtMidiEvents", 512, 512),
  682. data(dataPool),
  683. dataPending(dataPool) {}
  684. ~RtMidiEvents()
  685. {
  686. clear();
  687. }
  688. void append(const RtMidiEvent& event)
  689. {
  690. mutex.lock();
  691. dataPending.append(event);
  692. mutex.unlock();
  693. }
  694. void clear()
  695. {
  696. mutex.lock();
  697. data.clear();
  698. dataPending.clear();
  699. mutex.unlock();
  700. }
  701. void splice()
  702. {
  703. if (dataPending.count() > 0)
  704. dataPending.moveTo(data, true /* append */);
  705. }
  706. };
  707. LinkedList<MidiInPort> fMidiIns;
  708. RtMidiEvents fMidiInEvents;
  709. LinkedList<MidiOutPort> fMidiOuts;
  710. CarlaMutex fMidiOutMutex;
  711. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJuce)
  712. };
  713. // -----------------------------------------
  714. namespace EngineInit {
  715. CarlaEngine* newJuce(const AudioApi api)
  716. {
  717. initJuceDevicesIfNeeded();
  718. juce::String juceApi;
  719. switch (api)
  720. {
  721. case AUDIO_API_NULL:
  722. case AUDIO_API_OSS:
  723. case AUDIO_API_PULSEAUDIO:
  724. break;
  725. case AUDIO_API_JACK:
  726. juceApi = "JACK";
  727. break;
  728. case AUDIO_API_ALSA:
  729. juceApi = "ALSA";
  730. break;
  731. case AUDIO_API_COREAUDIO:
  732. juceApi = "CoreAudio";
  733. break;
  734. case AUDIO_API_ASIO:
  735. juceApi = "ASIO";
  736. break;
  737. case AUDIO_API_DIRECTSOUND:
  738. juceApi = "DirectSound";
  739. break;
  740. case AUDIO_API_WASAPI:
  741. juceApi = "Windows Audio";
  742. break;
  743. }
  744. if (juceApi.isEmpty())
  745. return nullptr;
  746. juce::AudioIODeviceType* deviceType = nullptr;
  747. for (int i=0, count=gDeviceTypes.size(); i < count; ++i)
  748. {
  749. deviceType = gDeviceTypes[i];
  750. if (deviceType == nullptr || deviceType->getTypeName() == juceApi)
  751. break;
  752. }
  753. if (deviceType == nullptr)
  754. return nullptr;
  755. deviceType->scanForDevices();
  756. return new CarlaEngineJuce(deviceType);
  757. }
  758. uint getJuceApiCount()
  759. {
  760. initJuceDevicesIfNeeded();
  761. return static_cast<uint>(gDeviceTypes.size());
  762. }
  763. const char* getJuceApiName(const uint uindex)
  764. {
  765. initJuceDevicesIfNeeded();
  766. const int index = static_cast<int>(uindex);
  767. CARLA_SAFE_ASSERT_RETURN(index < gDeviceTypes.size(), nullptr);
  768. juce::AudioIODeviceType* const deviceType(gDeviceTypes[index]);
  769. CARLA_SAFE_ASSERT_RETURN(deviceType != nullptr, nullptr);
  770. return deviceType->getTypeName().toRawUTF8();
  771. }
  772. const char* const* getJuceApiDeviceNames(const uint uindex)
  773. {
  774. initJuceDevicesIfNeeded();
  775. const int index = static_cast<int>(uindex);
  776. CARLA_SAFE_ASSERT_RETURN(index < gDeviceTypes.size(), nullptr);
  777. juce::AudioIODeviceType* const deviceType(gDeviceTypes[index]);
  778. CARLA_SAFE_ASSERT_RETURN(deviceType != nullptr, nullptr);
  779. deviceType->scanForDevices();
  780. juce::StringArray juceDeviceNames(deviceType->getDeviceNames());
  781. const int juceDeviceNameCount(juceDeviceNames.size());
  782. if (juceDeviceNameCount <= 0)
  783. return nullptr;
  784. CarlaStringList devNames;
  785. for (int i=0; i < juceDeviceNameCount; ++i)
  786. devNames.append(juceDeviceNames[i].toRawUTF8());
  787. gDeviceNames = devNames.toCharStringListPtr();
  788. return gDeviceNames;
  789. }
  790. const EngineDriverDeviceInfo* getJuceDeviceInfo(const uint uindex, const char* const deviceName)
  791. {
  792. initJuceDevicesIfNeeded();
  793. const int index = static_cast<int>(uindex);
  794. CARLA_SAFE_ASSERT_RETURN(index < gDeviceTypes.size(), nullptr);
  795. juce::AudioIODeviceType* const deviceType(gDeviceTypes[index]);
  796. CARLA_SAFE_ASSERT_RETURN(deviceType != nullptr, nullptr);
  797. deviceType->scanForDevices();
  798. CarlaScopedPointer<juce::AudioIODevice> device(deviceType->createDevice(deviceName, deviceName));
  799. if (device == nullptr)
  800. return nullptr;
  801. static EngineDriverDeviceInfo devInfo = { 0x0, nullptr, nullptr };
  802. static uint32_t dummyBufferSizes[11] = { 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 0 };
  803. static double dummySampleRates[14] = { 22050.0, 32000.0, 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0, 0.0 };
  804. // reset
  805. devInfo.hints = ENGINE_DRIVER_DEVICE_VARIABLE_BUFFER_SIZE | ENGINE_DRIVER_DEVICE_VARIABLE_SAMPLE_RATE;
  806. // cleanup
  807. if (devInfo.bufferSizes != nullptr && devInfo.bufferSizes != dummyBufferSizes)
  808. {
  809. delete[] devInfo.bufferSizes;
  810. devInfo.bufferSizes = nullptr;
  811. }
  812. if (devInfo.sampleRates != nullptr && devInfo.sampleRates != dummySampleRates)
  813. {
  814. delete[] devInfo.sampleRates;
  815. devInfo.sampleRates = nullptr;
  816. }
  817. if (device->hasControlPanel())
  818. devInfo.hints |= ENGINE_DRIVER_DEVICE_HAS_CONTROL_PANEL;
  819. juce::Array<int> juceBufferSizes = device->getAvailableBufferSizes();
  820. if (const int bufferSizesCount = juceBufferSizes.size())
  821. {
  822. uint32_t* const bufferSizes(new uint32_t[bufferSizesCount+1]);
  823. for (int i=0; i < bufferSizesCount; ++i)
  824. bufferSizes[i] = static_cast<uint32_t>(juceBufferSizes[i]);
  825. bufferSizes[bufferSizesCount] = 0;
  826. devInfo.bufferSizes = bufferSizes;
  827. }
  828. else
  829. {
  830. devInfo.bufferSizes = dummyBufferSizes;
  831. }
  832. juce::Array<double> juceSampleRates = device->getAvailableSampleRates();
  833. if (const int sampleRatesCount = juceSampleRates.size())
  834. {
  835. double* const sampleRates(new double[sampleRatesCount+1]);
  836. for (int i=0; i < sampleRatesCount; ++i)
  837. sampleRates[i] = juceSampleRates[i];
  838. sampleRates[sampleRatesCount] = 0.0;
  839. devInfo.sampleRates = sampleRates;
  840. }
  841. else
  842. {
  843. devInfo.sampleRates = dummySampleRates;
  844. }
  845. return &devInfo;
  846. }
  847. bool showJuceDeviceControlPanel(const uint uindex, const char* const deviceName)
  848. {
  849. const int index = static_cast<int>(uindex);
  850. CARLA_SAFE_ASSERT_RETURN(index < gDeviceTypes.size(), false);
  851. juce::AudioIODeviceType* const deviceType(gDeviceTypes[index]);
  852. CARLA_SAFE_ASSERT_RETURN(deviceType != nullptr, false);
  853. deviceType->scanForDevices();
  854. CarlaScopedPointer<juce::AudioIODevice> device(deviceType->createDevice(deviceName, deviceName));
  855. CARLA_SAFE_ASSERT_RETURN(device != nullptr, false);
  856. return device->showControlPanel();
  857. }
  858. }
  859. // -----------------------------------------
  860. CARLA_BACKEND_END_NAMESPACE