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.

1610 lines
49KB

  1. /*
  2. * Carla RtAudio Engine
  3. * Copyright (C) 2012-2013 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 doc/GPL.txt file.
  16. */
  17. #include "CarlaEngineInternal.hpp"
  18. #include "CarlaBackendUtils.hpp"
  19. #include "CarlaMIDI.h"
  20. #include "RtList.hpp"
  21. #include "rtaudio/RtAudio.h"
  22. #include "rtmidi/RtMidi.h"
  23. #ifdef USE_JUCE
  24. #include "juce_audio_basics.h"
  25. using juce::FloatVectorOperations;
  26. #endif
  27. CARLA_BACKEND_START_NAMESPACE
  28. #if 0
  29. } // Fix editor indentation
  30. #endif
  31. // -------------------------------------------------------------------------------------------------------------------
  32. static const char** gRetNames = nullptr;
  33. static std::vector<RtAudio::Api> gRtAudioApis;
  34. static void initRtApis()
  35. {
  36. if (gRtAudioApis.size() == 0)
  37. RtAudio::getCompiledApi(gRtAudioApis);
  38. }
  39. RtMidi::Api getMatchedAudioMidiAPi(const RtAudio::Api rtApi)
  40. {
  41. switch (rtApi)
  42. {
  43. case RtAudio::UNSPECIFIED:
  44. return RtMidi::UNSPECIFIED;
  45. case RtAudio::LINUX_ALSA:
  46. case RtAudio::LINUX_OSS:
  47. case RtAudio::LINUX_PULSE:
  48. return RtMidi::LINUX_ALSA;
  49. case RtAudio::UNIX_JACK:
  50. #if defined(CARLA_OS_WIN)
  51. return RtMidi::WINDOWS_MM;
  52. #elif defined(CARLA_OS_MAC)
  53. return RtMidi::MACOSX_CORE;
  54. #elif defined(CARLA_OS_LINUX)
  55. return RtMidi::LINUX_ALSA;
  56. #else
  57. return RtMidi::UNIX_JACK;
  58. #endif
  59. case RtAudio::MACOSX_CORE:
  60. return RtMidi::MACOSX_CORE;
  61. case RtAudio::WINDOWS_ASIO:
  62. case RtAudio::WINDOWS_DS:
  63. return RtMidi::WINDOWS_MM;
  64. case RtAudio::RTAUDIO_DUMMY:
  65. return RtMidi::RTMIDI_DUMMY;
  66. }
  67. return RtMidi::UNSPECIFIED;
  68. }
  69. // -------------------------------------------------------------------------------------------------------------------
  70. // RtAudio Engine
  71. class CarlaEngineRtAudio : public CarlaEngine
  72. {
  73. public:
  74. CarlaEngineRtAudio(const RtAudio::Api api)
  75. : CarlaEngine(),
  76. fAudio(api),
  77. fAudioBufIn(nullptr),
  78. fAudioBufOut(nullptr),
  79. #ifdef CARLA_PROPER_CPP11_SUPPORT
  80. fAudioBufRackIn{nullptr},
  81. fAudioBufRackOut{nullptr},
  82. #endif
  83. fAudioCountIn(0),
  84. fAudioCountOut(0),
  85. fAudioIsInterleaved(false),
  86. fAudioIsReady(false),
  87. fDummyMidiIn(getMatchedAudioMidiAPi(api), "Carla"),
  88. fDummyMidiOut(getMatchedAudioMidiAPi(api), "Carla"),
  89. fLastConnectionId(0)
  90. {
  91. carla_debug("CarlaEngineRtAudio::CarlaEngineRtAudio(%i)", api);
  92. #ifndef CARLA_PROPER_CPP11_SUPPORT
  93. fAudioBufRackIn[0] = fAudioBufRackIn[1] = nullptr;
  94. fAudioBufRackOut[0] = fAudioBufRackOut[1] = nullptr;
  95. #endif
  96. // just to make sure
  97. fOptions.forceStereo = true;
  98. fOptions.processMode = ENGINE_PROCESS_MODE_CONTINUOUS_RACK;
  99. fOptions.transportMode = ENGINE_TRANSPORT_MODE_INTERNAL;
  100. }
  101. ~CarlaEngineRtAudio() override
  102. {
  103. CARLA_ASSERT(fAudioBufIn == nullptr);
  104. CARLA_ASSERT(fAudioBufOut == nullptr);
  105. CARLA_ASSERT(fAudioCountIn == 0);
  106. CARLA_ASSERT(fAudioCountOut == 0);
  107. CARLA_ASSERT(! fAudioIsReady);
  108. carla_debug("CarlaEngineRtAudio::~CarlaEngineRtAudio()");
  109. fUsedMidiIns.clear();
  110. fUsedMidiOuts.clear();
  111. fUsedConnections.clear();
  112. if (gRetNames != nullptr)
  113. {
  114. delete[] gRetNames;
  115. gRetNames = nullptr;
  116. }
  117. }
  118. // -------------------------------------
  119. bool init(const char* const clientName) override
  120. {
  121. CARLA_ASSERT(fAudioBufIn == nullptr);
  122. CARLA_ASSERT(fAudioBufOut == nullptr);
  123. CARLA_ASSERT(fAudioCountIn == 0);
  124. CARLA_ASSERT(fAudioCountOut == 0);
  125. CARLA_ASSERT(! fAudioIsReady);
  126. CARLA_ASSERT(clientName != nullptr);
  127. carla_debug("CarlaEngineRtAudio::init(\"%s\")", clientName);
  128. RtAudio::StreamParameters iParams, oParams;
  129. bool deviceSet = false;
  130. const unsigned int devCount(fAudio.getDeviceCount());
  131. if (devCount == 0)
  132. {
  133. setLastError("No audio devices available for this driver");
  134. return false;
  135. }
  136. if (fOptions.audioDevice.isNotEmpty())
  137. {
  138. for (unsigned int i=0; i < devCount; ++i)
  139. {
  140. RtAudio::DeviceInfo devInfo(fAudio.getDeviceInfo(i));
  141. if (devInfo.probed && devInfo.outputChannels > 0 && devInfo.name == (const char*)fOptions.audioDevice)
  142. {
  143. deviceSet = true;
  144. fConnectName = devInfo.name.c_str();
  145. iParams.deviceId = i;
  146. oParams.deviceId = i;
  147. iParams.nChannels = devInfo.inputChannels;
  148. oParams.nChannels = devInfo.outputChannels;
  149. break;
  150. }
  151. }
  152. }
  153. if (! deviceSet)
  154. {
  155. iParams.deviceId = fAudio.getDefaultInputDevice();
  156. oParams.deviceId = fAudio.getDefaultOutputDevice();
  157. iParams.nChannels = 2;
  158. oParams.nChannels = 2;
  159. }
  160. RtAudio::StreamOptions rtOptions;
  161. rtOptions.flags = RTAUDIO_MINIMIZE_LATENCY | RTAUDIO_HOG_DEVICE | RTAUDIO_SCHEDULE_REALTIME;
  162. rtOptions.streamName = clientName;
  163. rtOptions.priority = 85;
  164. if (fAudio.getCurrentApi() != RtAudio::LINUX_PULSE)
  165. {
  166. rtOptions.flags |= RTAUDIO_NONINTERLEAVED;
  167. fAudioIsInterleaved = false;
  168. if (fAudio.getCurrentApi() == RtAudio::LINUX_ALSA && ! deviceSet)
  169. rtOptions.flags |= RTAUDIO_ALSA_USE_DEFAULT;
  170. }
  171. else
  172. fAudioIsInterleaved = true;
  173. fBufferSize = fOptions.audioBufferSize;
  174. try {
  175. fAudio.openStream(&oParams, &iParams, RTAUDIO_FLOAT32, fOptions.audioSampleRate, &fBufferSize, carla_rtaudio_process_callback, this, &rtOptions);
  176. }
  177. catch (RtError& e)
  178. {
  179. setLastError(e.what());
  180. return false;
  181. }
  182. try {
  183. fAudio.startStream();
  184. }
  185. catch (RtError& e)
  186. {
  187. setLastError(e.what());
  188. fAudio.closeStream();
  189. return false;
  190. }
  191. fAudioCountIn = iParams.nChannels;
  192. fAudioCountOut = oParams.nChannels;
  193. fSampleRate = fAudio.getStreamSampleRate();
  194. CARLA_ASSERT(fAudioCountOut > 0);
  195. if (fAudioCountIn > 0)
  196. {
  197. fAudioBufIn = new float*[fAudioCountIn];
  198. for (uint i=0; i < fAudioCountIn; ++i)
  199. fAudioBufIn[i] = new float[fBufferSize];
  200. }
  201. if (fAudioCountOut > 0)
  202. {
  203. fAudioBufOut = new float*[fAudioCountOut];
  204. for (uint i=0; i < fAudioCountOut; ++i)
  205. fAudioBufOut[i] = new float[fBufferSize];
  206. }
  207. fAudioBufRackIn[0] = new float[fBufferSize];
  208. fAudioBufRackIn[1] = new float[fBufferSize];
  209. fAudioBufRackOut[0] = new float[fBufferSize];
  210. fAudioBufRackOut[1] = new float[fBufferSize];
  211. fAudioIsReady = true;
  212. CarlaEngine::init(clientName);
  213. patchbayRefresh();
  214. return true;
  215. }
  216. bool close() override
  217. {
  218. carla_debug("CarlaEngineRtAudio::close()");
  219. CARLA_ASSERT(fAudioBufOut != nullptr);
  220. CARLA_ASSERT(fAudioCountOut > 0);
  221. CARLA_ASSERT(fAudioIsReady);
  222. fAudioIsReady = false;
  223. bool hasError = !CarlaEngine::close();
  224. if (fAudio.isStreamRunning())
  225. {
  226. try {
  227. fAudio.stopStream();
  228. }
  229. catch (RtError& e)
  230. {
  231. if (! hasError)
  232. {
  233. setLastError(e.what());
  234. hasError = true;
  235. }
  236. }
  237. }
  238. if (fAudio.isStreamOpen())
  239. {
  240. try {
  241. fAudio.closeStream();
  242. }
  243. catch (RtError& e)
  244. {
  245. if (! hasError)
  246. {
  247. setLastError(e.what());
  248. hasError = true;
  249. }
  250. }
  251. }
  252. if (fAudioBufIn != nullptr)
  253. {
  254. CARLA_ASSERT(fAudioCountIn > 0);
  255. for (uint i=0; i < fAudioCountIn; ++i)
  256. delete[] fAudioBufIn[i];
  257. delete[] fAudioBufIn;
  258. fAudioBufIn = nullptr;
  259. }
  260. if (fAudioBufOut != nullptr)
  261. {
  262. CARLA_ASSERT(fAudioCountOut > 0);
  263. for (uint i=0; i < fAudioCountOut; ++i)
  264. delete[] fAudioBufOut[i];
  265. delete[] fAudioBufOut;
  266. fAudioBufOut = nullptr;
  267. }
  268. delete[] fAudioBufRackIn[0];
  269. delete[] fAudioBufRackIn[1];
  270. delete[] fAudioBufRackOut[0];
  271. delete[] fAudioBufRackOut[1];
  272. fAudioCountIn = 0;
  273. fAudioCountOut = 0;
  274. fConnectedAudioIns[0].clear();
  275. fConnectedAudioIns[1].clear();
  276. fConnectedAudioOuts[0].clear();
  277. fConnectedAudioOuts[1].clear();
  278. fConnectName.clear();
  279. for (List<MidiPort>::Itenerator it = fMidiIns.begin(); it.valid(); it.next())
  280. {
  281. MidiPort& port(*it);
  282. RtMidiIn* const midiInPort((RtMidiIn*)port.rtmidi);
  283. midiInPort->cancelCallback();
  284. delete midiInPort;
  285. }
  286. for (List<MidiPort>::Itenerator it = fMidiOuts.begin(); it.valid(); it.next())
  287. {
  288. MidiPort& port(*it);
  289. RtMidiOut* const midiOutPort((RtMidiOut*)port.rtmidi);
  290. delete midiOutPort;
  291. }
  292. fMidiIns.clear();
  293. fMidiOuts.clear();
  294. fMidiInEvents.clear();
  295. //fMidiOutEvents.clear();
  296. return (! hasError);
  297. }
  298. bool isRunning() const noexcept override
  299. {
  300. return fAudio.isStreamRunning();
  301. }
  302. bool isOffline() const noexcept override
  303. {
  304. return false;
  305. }
  306. EngineType getType() const noexcept override
  307. {
  308. return kEngineTypeRtAudio;
  309. }
  310. const char* getCurrentDriverName() const noexcept override
  311. {
  312. const RtAudio::Api api(fAudio.getCurrentApi());
  313. switch (api)
  314. {
  315. case RtAudio::UNSPECIFIED:
  316. return "Unspecified";
  317. case RtAudio::LINUX_ALSA:
  318. return "ALSA";
  319. case RtAudio::LINUX_PULSE:
  320. return "PulseAudio";
  321. case RtAudio::LINUX_OSS:
  322. return "OSS";
  323. case RtAudio::UNIX_JACK:
  324. #if defined(CARLA_OS_WIN)
  325. return "JACK with WinMM";
  326. #elif defined(CARLA_OS_MAC)
  327. return "JACK with CoreMidi";
  328. #elif defined(CARLA_OS_LINUX)
  329. return "JACK with ALSA-MIDI";
  330. #else
  331. return "JACK (RtAudio)";
  332. #endif
  333. case RtAudio::MACOSX_CORE:
  334. return "CoreAudio";
  335. case RtAudio::WINDOWS_ASIO:
  336. return "ASIO";
  337. case RtAudio::WINDOWS_DS:
  338. return "DirectSound";
  339. case RtAudio::RTAUDIO_DUMMY:
  340. return "Dummy";
  341. }
  342. return nullptr;
  343. }
  344. // -------------------------------------------------------------------
  345. // Patchbay
  346. bool patchbayConnect(int portA, int portB) override
  347. {
  348. CARLA_ASSERT(fAudioIsReady);
  349. CARLA_ASSERT(portA > PATCHBAY_PORT_MAX);
  350. CARLA_ASSERT(portB > PATCHBAY_PORT_MAX);
  351. carla_debug("CarlaEngineRtAudio::patchbayConnect(%i, %i)", portA, portB);
  352. if (! fAudioIsReady)
  353. {
  354. setLastError("Engine not ready");
  355. return false;
  356. }
  357. if (portA < PATCHBAY_PORT_MAX)
  358. {
  359. setLastError("Invalid output port");
  360. return false;
  361. }
  362. if (portB < PATCHBAY_PORT_MAX)
  363. {
  364. setLastError("Invalid input port");
  365. return false;
  366. }
  367. // only allow connections between Carla and other ports
  368. if (portA < 0 && portB < 0)
  369. {
  370. setLastError("Invalid connection (1)");
  371. return false;
  372. }
  373. if (portA >= 0 && portB >= 0)
  374. {
  375. setLastError("Invalid connection (2)");
  376. return false;
  377. }
  378. const int carlaPort = (portA < 0) ? portA : portB;
  379. const int targetPort = (carlaPort == portA) ? portB : portA;
  380. bool makeConnection = false;
  381. switch (carlaPort)
  382. {
  383. case PATCHBAY_PORT_AUDIO_IN1:
  384. CARLA_ASSERT(targetPort >= PATCHBAY_GROUP_AUDIO_IN*1000);
  385. CARLA_ASSERT(targetPort <= PATCHBAY_GROUP_AUDIO_IN*1000+999);
  386. fConnectAudioLock.lock();
  387. fConnectedAudioIns[0].append(targetPort - PATCHBAY_GROUP_AUDIO_IN*1000);
  388. fConnectAudioLock.unlock();
  389. makeConnection = true;
  390. break;
  391. case PATCHBAY_PORT_AUDIO_IN2:
  392. CARLA_ASSERT(targetPort >= PATCHBAY_GROUP_AUDIO_IN*1000);
  393. CARLA_ASSERT(targetPort <= PATCHBAY_GROUP_AUDIO_IN*1000+999);
  394. fConnectAudioLock.lock();
  395. fConnectedAudioIns[1].append(targetPort - PATCHBAY_GROUP_AUDIO_IN*1000);
  396. fConnectAudioLock.unlock();
  397. makeConnection = true;
  398. break;
  399. case PATCHBAY_PORT_AUDIO_OUT1:
  400. CARLA_ASSERT(targetPort >= PATCHBAY_GROUP_AUDIO_OUT*1000);
  401. CARLA_ASSERT(targetPort <= PATCHBAY_GROUP_AUDIO_OUT*1000+999);
  402. fConnectAudioLock.lock();
  403. fConnectedAudioOuts[0].append(targetPort - PATCHBAY_GROUP_AUDIO_OUT*1000);
  404. fConnectAudioLock.unlock();
  405. makeConnection = true;
  406. break;
  407. case PATCHBAY_PORT_AUDIO_OUT2:
  408. CARLA_ASSERT(targetPort >= PATCHBAY_GROUP_AUDIO_OUT*1000);
  409. CARLA_ASSERT(targetPort <= PATCHBAY_GROUP_AUDIO_OUT*1000+999);
  410. fConnectAudioLock.lock();
  411. fConnectedAudioOuts[1].append(targetPort - PATCHBAY_GROUP_AUDIO_OUT*1000);
  412. fConnectAudioLock.unlock();
  413. makeConnection = true;
  414. break;
  415. case PATCHBAY_PORT_MIDI_IN:
  416. CARLA_ASSERT(targetPort >= PATCHBAY_GROUP_MIDI_IN*1000);
  417. CARLA_ASSERT(targetPort <= PATCHBAY_GROUP_MIDI_IN*1000+999);
  418. makeConnection = connectMidiInPort(targetPort - PATCHBAY_GROUP_MIDI_IN*1000);
  419. break;
  420. case PATCHBAY_PORT_MIDI_OUT:
  421. CARLA_ASSERT(targetPort >= PATCHBAY_GROUP_MIDI_OUT*1000);
  422. CARLA_ASSERT(targetPort <= PATCHBAY_GROUP_MIDI_OUT*1000+999);
  423. makeConnection = connectMidiOutPort(targetPort - PATCHBAY_GROUP_MIDI_OUT*1000);
  424. break;
  425. }
  426. if (! makeConnection)
  427. {
  428. setLastError("Invalid connection (3)");
  429. return false;
  430. }
  431. ConnectionToId connectionToId;
  432. connectionToId.id = fLastConnectionId;
  433. connectionToId.portOut = portA;
  434. connectionToId.portIn = portB;
  435. callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, 0, fLastConnectionId, portA, portB, nullptr);
  436. fUsedConnections.append(connectionToId);
  437. fLastConnectionId++;
  438. return true;
  439. }
  440. bool patchbayDisconnect(int connectionId) override
  441. {
  442. CARLA_ASSERT(fAudioIsReady);
  443. CARLA_ASSERT(fUsedConnections.count() > 0);
  444. carla_debug("CarlaEngineRtAudio::patchbayDisconnect(%i)", connectionId);
  445. if (! fAudioIsReady)
  446. {
  447. setLastError("Engine not ready");
  448. return false;
  449. }
  450. if (fUsedConnections.count() == 0)
  451. {
  452. setLastError("No connections available");
  453. return false;
  454. }
  455. for (List<ConnectionToId>::Itenerator it=fUsedConnections.begin(); it.valid(); it.next())
  456. {
  457. const ConnectionToId& connection(*it);
  458. if (connection.id == connectionId)
  459. {
  460. const int targetPort((connection.portOut >= 0) ? connection.portOut : connection.portIn);
  461. const int carlaPort((targetPort == connection.portOut) ? connection.portIn : connection.portOut);
  462. if (targetPort >= PATCHBAY_GROUP_MIDI_OUT*1000)
  463. {
  464. const int portId(targetPort-PATCHBAY_GROUP_MIDI_OUT*1000);
  465. for (List<MidiPort>::Itenerator it=fMidiOuts.begin(); it.valid(); it.next())
  466. {
  467. MidiPort& midiPort(*it);
  468. if (midiPort.portId == portId)
  469. {
  470. RtMidiOut* const midiOutPort((RtMidiOut*)midiPort.rtmidi);
  471. delete midiOutPort;
  472. fMidiOuts.remove(it);
  473. break;
  474. }
  475. }
  476. }
  477. else if (targetPort >= PATCHBAY_GROUP_MIDI_IN*1000)
  478. {
  479. const int portId(targetPort-PATCHBAY_GROUP_MIDI_IN*1000);
  480. for (List<MidiPort>::Itenerator it=fMidiIns.begin(); it.valid(); it.next())
  481. {
  482. MidiPort& midiPort(*it);
  483. if (midiPort.portId == portId)
  484. {
  485. RtMidiIn* const midiInPort((RtMidiIn*)midiPort.rtmidi);
  486. midiInPort->cancelCallback();
  487. delete midiInPort;
  488. fMidiIns.remove(it);
  489. break;
  490. }
  491. }
  492. }
  493. else if (targetPort >= PATCHBAY_GROUP_AUDIO_OUT*1000)
  494. {
  495. CARLA_ASSERT(carlaPort == PATCHBAY_PORT_AUDIO_OUT1 || carlaPort == PATCHBAY_PORT_AUDIO_OUT2);
  496. const int portId(targetPort-PATCHBAY_GROUP_AUDIO_OUT*1000);
  497. fConnectAudioLock.lock();
  498. if (carlaPort == PATCHBAY_PORT_AUDIO_OUT1)
  499. fConnectedAudioOuts[0].removeAll(portId);
  500. else
  501. fConnectedAudioOuts[1].removeAll(portId);
  502. fConnectAudioLock.unlock();
  503. }
  504. else if (targetPort >= PATCHBAY_GROUP_AUDIO_IN*1000)
  505. {
  506. CARLA_ASSERT(carlaPort == PATCHBAY_PORT_AUDIO_IN1 || carlaPort == PATCHBAY_PORT_AUDIO_IN2);
  507. const int portId(targetPort-PATCHBAY_GROUP_AUDIO_IN*1000);
  508. fConnectAudioLock.lock();
  509. if (carlaPort == PATCHBAY_PORT_AUDIO_IN1)
  510. fConnectedAudioIns[0].removeAll(portId);
  511. else
  512. fConnectedAudioIns[1].removeAll(portId);
  513. fConnectAudioLock.unlock();
  514. }
  515. else
  516. {
  517. CARLA_ASSERT(false);
  518. }
  519. callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED, 0, connection.id, 0, 0.0f, nullptr);
  520. fUsedConnections.remove(it);
  521. break;
  522. }
  523. }
  524. return true;
  525. }
  526. void patchbayRefresh() override
  527. {
  528. CARLA_ASSERT(fAudioIsReady);
  529. if (! fAudioIsReady)
  530. return;
  531. char strBuf[STR_MAX+1];
  532. fLastConnectionId = 0;
  533. fUsedMidiIns.clear();
  534. fUsedMidiOuts.clear();
  535. fUsedConnections.clear();
  536. // Main
  537. {
  538. callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, 0, PATCHBAY_GROUP_CARLA, 0, 0.0f, getName());
  539. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, 0, PATCHBAY_GROUP_CARLA, PATCHBAY_PORT_AUDIO_IN1, PATCHBAY_PORT_IS_AUDIO|PATCHBAY_PORT_IS_INPUT, "audio-in1");
  540. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, 0, PATCHBAY_GROUP_CARLA, PATCHBAY_PORT_AUDIO_IN2, PATCHBAY_PORT_IS_AUDIO|PATCHBAY_PORT_IS_INPUT, "audio-in2");
  541. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, 0, PATCHBAY_GROUP_CARLA, PATCHBAY_PORT_AUDIO_OUT1, PATCHBAY_PORT_IS_AUDIO|PATCHBAY_PORT_IS_OUTPUT, "audio-out1");
  542. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, 0, PATCHBAY_GROUP_CARLA, PATCHBAY_PORT_AUDIO_OUT2, PATCHBAY_PORT_IS_AUDIO|PATCHBAY_PORT_IS_OUTPUT, "audio-out2");
  543. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, 0, PATCHBAY_GROUP_CARLA, PATCHBAY_PORT_MIDI_IN, PATCHBAY_PORT_IS_MIDI|PATCHBAY_PORT_IS_INPUT, "midi-in");
  544. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, 0, PATCHBAY_GROUP_CARLA, PATCHBAY_PORT_MIDI_OUT, PATCHBAY_PORT_IS_MIDI|PATCHBAY_PORT_IS_OUTPUT, "midi-out");
  545. }
  546. // Audio In
  547. {
  548. if (fConnectName.isNotEmpty())
  549. std::snprintf(strBuf, STR_MAX, "Capture (%s)", (const char*)fConnectName);
  550. else
  551. std::strncpy(strBuf, "Capture", STR_MAX);
  552. callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, 0, PATCHBAY_GROUP_AUDIO_IN, 0, 0.0f, strBuf);
  553. for (unsigned int i=0; i < fAudioCountIn; ++i)
  554. {
  555. std::snprintf(strBuf, STR_MAX, "capture_%i", i+1);
  556. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, 0, PATCHBAY_GROUP_AUDIO_IN, PATCHBAY_GROUP_AUDIO_IN*1000 + i, PATCHBAY_PORT_IS_AUDIO|PATCHBAY_PORT_IS_OUTPUT, strBuf);
  557. }
  558. }
  559. // Audio Out
  560. {
  561. if (fConnectName.isNotEmpty())
  562. std::snprintf(strBuf, STR_MAX, "Playback (%s)", (const char*)fConnectName);
  563. else
  564. std::strncpy(strBuf, "Playback", STR_MAX);
  565. callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, 0, PATCHBAY_GROUP_AUDIO_OUT, 0, 0.0f, strBuf);
  566. for (unsigned int i=0; i < fAudioCountOut; ++i)
  567. {
  568. std::snprintf(strBuf, STR_MAX, "playback_%i", i+1);
  569. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, 0, PATCHBAY_GROUP_AUDIO_OUT, PATCHBAY_GROUP_AUDIO_OUT*1000 + i, PATCHBAY_PORT_IS_AUDIO|PATCHBAY_PORT_IS_INPUT, strBuf);
  570. }
  571. }
  572. // MIDI In
  573. {
  574. callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, 0, PATCHBAY_GROUP_MIDI_IN, 0, 0.0f, "Readable MIDI ports");
  575. for (unsigned int i=0, count=fDummyMidiIn.getPortCount(); i < count; ++i)
  576. {
  577. PortNameToId portNameToId;
  578. portNameToId.portId = PATCHBAY_GROUP_MIDI_IN*1000 + i;
  579. std::strncpy(portNameToId.name, fDummyMidiIn.getPortName(i).c_str(), STR_MAX);
  580. fUsedMidiIns.append(portNameToId);
  581. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, 0, PATCHBAY_GROUP_MIDI_IN, portNameToId.portId, PATCHBAY_PORT_IS_MIDI|PATCHBAY_PORT_IS_OUTPUT, portNameToId.name);
  582. }
  583. }
  584. #if 0 // midi-out not implemented yet
  585. // MIDI Out
  586. {
  587. callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, 0, PATCHBAY_GROUP_MIDI_OUT, 0, 0.0f, "Writable MIDI ports");
  588. for (unsigned int i=0, count=fDummyMidiOut.getPortCount(); i < count; ++i)
  589. {
  590. PortNameToId portNameToId;
  591. portNameToId.portId = PATCHBAY_GROUP_MIDI_OUT*1000 + i;
  592. std::strncpy(portNameToId.name, fDummyMidiOut.getPortName(i).c_str(), STR_MAX);
  593. fUsedMidiOuts.append(portNameToId);
  594. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, 0, PATCHBAY_GROUP_MIDI_OUT, portNameToId.portId, PATCHBAY_PORT_IS_MIDI|PATCHBAY_PORT_IS_INPUT, portNameToId.name);
  595. }
  596. }
  597. #endif
  598. // Connections
  599. fConnectAudioLock.lock();
  600. for (List<uint>::Itenerator it = fConnectedAudioIns[0].begin(); it.valid(); it.next())
  601. {
  602. const uint& port(*it);
  603. CARLA_ASSERT(port < fAudioCountIn);
  604. ConnectionToId connectionToId;
  605. connectionToId.id = fLastConnectionId;
  606. connectionToId.portOut = PATCHBAY_GROUP_AUDIO_IN*1000 + port;
  607. connectionToId.portIn = PATCHBAY_PORT_AUDIO_IN1;
  608. callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, 0, fLastConnectionId, connectionToId.portOut, connectionToId.portIn, nullptr);
  609. fUsedConnections.append(connectionToId);
  610. fLastConnectionId++;
  611. }
  612. for (List<uint>::Itenerator it = fConnectedAudioIns[1].begin(); it.valid(); it.next())
  613. {
  614. const uint& port(*it);
  615. CARLA_ASSERT(port < fAudioCountIn);
  616. ConnectionToId connectionToId;
  617. connectionToId.id = fLastConnectionId;
  618. connectionToId.portOut = PATCHBAY_GROUP_AUDIO_IN*1000 + port;
  619. connectionToId.portIn = PATCHBAY_PORT_AUDIO_IN2;
  620. callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, 0, fLastConnectionId, connectionToId.portOut, connectionToId.portIn, nullptr);
  621. fUsedConnections.append(connectionToId);
  622. fLastConnectionId++;
  623. }
  624. for (List<uint>::Itenerator it = fConnectedAudioOuts[0].begin(); it.valid(); it.next())
  625. {
  626. const uint& port(*it);
  627. CARLA_ASSERT(port < fAudioCountOut);
  628. ConnectionToId connectionToId;
  629. connectionToId.id = fLastConnectionId;
  630. connectionToId.portOut = PATCHBAY_PORT_AUDIO_OUT1;
  631. connectionToId.portIn = PATCHBAY_GROUP_AUDIO_OUT*1000 + port;
  632. callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, 0, fLastConnectionId, connectionToId.portOut, connectionToId.portIn, nullptr);
  633. fUsedConnections.append(connectionToId);
  634. fLastConnectionId++;
  635. }
  636. for (List<uint>::Itenerator it = fConnectedAudioOuts[1].begin(); it.valid(); it.next())
  637. {
  638. const uint& port(*it);
  639. CARLA_ASSERT(port < fAudioCountOut);
  640. ConnectionToId connectionToId;
  641. connectionToId.id = fLastConnectionId;
  642. connectionToId.portOut = PATCHBAY_PORT_AUDIO_OUT2;
  643. connectionToId.portIn = PATCHBAY_GROUP_AUDIO_OUT*1000 + port;
  644. callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, 0, fLastConnectionId, connectionToId.portOut, connectionToId.portIn, nullptr);
  645. fUsedConnections.append(connectionToId);
  646. fLastConnectionId++;
  647. }
  648. fConnectAudioLock.unlock();
  649. for (List<MidiPort>::Itenerator it=fMidiIns.begin(); it.valid(); it.next())
  650. {
  651. const MidiPort& midiPort(*it);
  652. ConnectionToId connectionToId;
  653. connectionToId.id = fLastConnectionId;
  654. connectionToId.portOut = PATCHBAY_GROUP_MIDI_IN*1000 + midiPort.portId;
  655. connectionToId.portIn = PATCHBAY_PORT_MIDI_IN;
  656. callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, 0, fLastConnectionId, connectionToId.portOut, connectionToId.portIn, nullptr);
  657. fUsedConnections.append(connectionToId);
  658. fLastConnectionId++;
  659. }
  660. for (List<MidiPort>::Itenerator it=fMidiOuts.begin(); it.valid(); it.next())
  661. {
  662. const MidiPort& midiPort(*it);
  663. ConnectionToId connectionToId;
  664. connectionToId.id = fLastConnectionId;
  665. connectionToId.portOut = PATCHBAY_PORT_MIDI_OUT;
  666. connectionToId.portIn = PATCHBAY_GROUP_MIDI_OUT*1000 + midiPort.portId;
  667. callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, 0, fLastConnectionId, connectionToId.portOut, connectionToId.portIn, nullptr);
  668. fUsedConnections.append(connectionToId);
  669. fLastConnectionId++;
  670. }
  671. }
  672. // -------------------------------------------------------------------
  673. protected:
  674. void handleAudioProcessCallback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status)
  675. {
  676. // get buffers from RtAudio
  677. float* insPtr = (float*)inputBuffer;
  678. float* outsPtr = (float*)outputBuffer;
  679. // assert buffers
  680. CARLA_ASSERT(nframes != 0);
  681. CARLA_ASSERT_INT2(nframes == fBufferSize, nframes, fBufferSize);
  682. CARLA_ASSERT(outsPtr != nullptr);
  683. if (pData->curPluginCount == 0 || fAudioCountOut == 0 || ! fAudioIsReady)
  684. {
  685. if (fAudioCountOut > 0 && fAudioIsReady)
  686. {
  687. #ifdef USE_JUCE
  688. FloatVectorOperations::clear(outsPtr, nframes*fAudioCountOut);
  689. #endif
  690. }
  691. return runPendingRtEvents();
  692. }
  693. // initialize audio input
  694. if (fAudioIsInterleaved)
  695. {
  696. for (unsigned int i=0, j=0; i < nframes*fAudioCountIn; ++i)
  697. {
  698. fAudioBufIn[i/fAudioCountIn][j] = insPtr[i];
  699. if ((i+1) % fAudioCountIn == 0)
  700. j += 1;
  701. }
  702. }
  703. else
  704. {
  705. for (unsigned int i=0; i < fAudioCountIn; ++i)
  706. {
  707. #ifdef USE_JUCE
  708. FloatVectorOperations::copy(fAudioBufIn[i], insPtr+(nframes*i), nframes);
  709. #endif
  710. }
  711. }
  712. #ifdef USE_JUCE
  713. // initialize audio output
  714. for (unsigned int i=0; i < fAudioCountOut; ++i)
  715. FloatVectorOperations::clear(fAudioBufOut[i], nframes);
  716. FloatVectorOperations::clear(fAudioBufRackOut[0], nframes);
  717. FloatVectorOperations::clear(fAudioBufRackOut[1], nframes);
  718. #endif
  719. // initialize input events
  720. carla_zeroMem(pData->bufEvents.in, sizeof(EngineEvent)*kEngineMaxInternalEventCount);
  721. if (fMidiInEvents.mutex.tryLock())
  722. {
  723. uint32_t engineEventIndex = 0;
  724. fMidiInEvents.splice();
  725. while (! fMidiInEvents.data.isEmpty())
  726. {
  727. const RtMidiEvent& midiEvent(fMidiInEvents.data.getFirst(true));
  728. EngineEvent& engineEvent(pData->bufEvents.in[engineEventIndex++]);
  729. engineEvent.clear();
  730. const uint8_t midiStatus = MIDI_GET_STATUS_FROM_DATA(midiEvent.data);
  731. const uint8_t midiChannel = MIDI_GET_CHANNEL_FROM_DATA(midiEvent.data);
  732. engineEvent.channel = midiChannel;
  733. if (midiEvent.time < fTimeInfo.frame)
  734. {
  735. engineEvent.time = 0;
  736. }
  737. else if (midiEvent.time >= fTimeInfo.frame + nframes)
  738. {
  739. engineEvent.time = fTimeInfo.frame + nframes-1;
  740. carla_stderr("MIDI Event in the future!, %i vs %i", engineEvent.time, fTimeInfo.frame);
  741. }
  742. else
  743. engineEvent.time = midiEvent.time - fTimeInfo.frame;
  744. if (MIDI_IS_STATUS_CONTROL_CHANGE(midiStatus))
  745. {
  746. const uint8_t midiControl = midiEvent.data[1];
  747. engineEvent.type = kEngineEventTypeControl;
  748. if (MIDI_IS_CONTROL_BANK_SELECT(midiControl))
  749. {
  750. const uint8_t midiBank = midiEvent.data[2];
  751. engineEvent.ctrl.type = kEngineControlEventTypeMidiBank;
  752. engineEvent.ctrl.param = midiBank;
  753. engineEvent.ctrl.value = 0.0f;
  754. }
  755. else if (midiControl == MIDI_CONTROL_ALL_SOUND_OFF)
  756. {
  757. engineEvent.ctrl.type = kEngineControlEventTypeAllSoundOff;
  758. engineEvent.ctrl.param = 0;
  759. engineEvent.ctrl.value = 0.0f;
  760. }
  761. else if (midiControl == MIDI_CONTROL_ALL_NOTES_OFF)
  762. {
  763. engineEvent.ctrl.type = kEngineControlEventTypeAllNotesOff;
  764. engineEvent.ctrl.param = 0;
  765. engineEvent.ctrl.value = 0.0f;
  766. }
  767. else
  768. {
  769. const uint8_t midiValue = midiEvent.data[2];
  770. engineEvent.ctrl.type = kEngineControlEventTypeParameter;
  771. engineEvent.ctrl.param = midiControl;
  772. engineEvent.ctrl.value = float(midiValue)/127.0f;
  773. }
  774. }
  775. else if (MIDI_IS_STATUS_PROGRAM_CHANGE(midiStatus))
  776. {
  777. const uint8_t midiProgram = midiEvent.data[1];
  778. engineEvent.type = kEngineEventTypeControl;
  779. engineEvent.ctrl.type = kEngineControlEventTypeMidiProgram;
  780. engineEvent.ctrl.param = midiProgram;
  781. engineEvent.ctrl.value = 0.0f;
  782. }
  783. else
  784. {
  785. engineEvent.type = kEngineEventTypeMidi;
  786. engineEvent.midi.data[0] = midiStatus;
  787. engineEvent.midi.data[1] = midiEvent.data[1];
  788. engineEvent.midi.data[2] = midiEvent.data[2];
  789. engineEvent.midi.data[3] = midiEvent.data[3];
  790. engineEvent.midi.size = midiEvent.size;
  791. }
  792. if (engineEventIndex >= kEngineMaxInternalEventCount)
  793. break;
  794. }
  795. fMidiInEvents.mutex.unlock();
  796. }
  797. fConnectAudioLock.lock();
  798. // connect input buffers
  799. if (fConnectedAudioIns[0].count() == 0)
  800. {
  801. #ifdef USE_JUCE
  802. FloatVectorOperations::clear(fAudioBufRackIn[0], nframes);
  803. #endif
  804. }
  805. else
  806. {
  807. bool first = true;
  808. for (List<uint>::Itenerator it = fConnectedAudioIns[0].begin(); it.valid(); it.next())
  809. {
  810. const uint& port(*it);
  811. CARLA_ASSERT(port < fAudioCountIn);
  812. if (first)
  813. {
  814. #ifdef USE_JUCE
  815. FloatVectorOperations::copy(fAudioBufRackIn[0], fAudioBufIn[port], nframes);
  816. #endif
  817. first = false;
  818. }
  819. else
  820. {
  821. #ifdef USE_JUCE
  822. FloatVectorOperations::add(fAudioBufRackIn[0], fAudioBufIn[port], nframes);
  823. #endif
  824. }
  825. }
  826. if (first)
  827. {
  828. #ifdef USE_JUCE
  829. FloatVectorOperations::clear(fAudioBufRackIn[0], nframes);
  830. #endif
  831. }
  832. }
  833. if (fConnectedAudioIns[1].count() == 0)
  834. {
  835. #ifdef USE_JUCE
  836. FloatVectorOperations::clear(fAudioBufRackIn[1], nframes);
  837. #endif
  838. }
  839. else
  840. {
  841. bool first = true;
  842. for (List<uint>::Itenerator it = fConnectedAudioIns[1].begin(); it.valid(); it.next())
  843. {
  844. const uint& port(*it);
  845. CARLA_ASSERT(port < fAudioCountIn);
  846. if (first)
  847. {
  848. #ifdef USE_JUCE
  849. FloatVectorOperations::copy(fAudioBufRackIn[1], fAudioBufIn[port], nframes);
  850. #endif
  851. first = false;
  852. }
  853. else
  854. {
  855. #ifdef USE_JUCE
  856. FloatVectorOperations::add(fAudioBufRackIn[1], fAudioBufIn[port], nframes);
  857. #endif
  858. }
  859. }
  860. if (first)
  861. {
  862. #ifdef USE_JUCE
  863. FloatVectorOperations::clear(fAudioBufRackIn[1], nframes);
  864. #endif
  865. }
  866. }
  867. // process
  868. processRack(fAudioBufRackIn, fAudioBufRackOut, nframes);
  869. // connect output buffers
  870. if (fConnectedAudioOuts[0].count() != 0)
  871. {
  872. for (List<uint>::Itenerator it = fConnectedAudioOuts[0].begin(); it.valid(); it.next())
  873. {
  874. const uint& port(*it);
  875. CARLA_ASSERT(port < fAudioCountOut);
  876. #ifdef USE_JUCE
  877. FloatVectorOperations::add(fAudioBufOut[port], fAudioBufRackOut[0], nframes);
  878. #endif
  879. }
  880. }
  881. if (fConnectedAudioOuts[1].count() != 0)
  882. {
  883. for (List<uint>::Itenerator it = fConnectedAudioOuts[1].begin(); it.valid(); it.next())
  884. {
  885. const uint& port(*it);
  886. CARLA_ASSERT(port < fAudioCountOut);
  887. #ifdef USE_JUCE
  888. FloatVectorOperations::add(fAudioBufOut[port], fAudioBufRackOut[1], nframes);
  889. #endif
  890. }
  891. }
  892. fConnectAudioLock.unlock();
  893. // output audio
  894. if (fAudioIsInterleaved)
  895. {
  896. for (unsigned int i=0, j=0; i < nframes*fAudioCountOut; ++i)
  897. {
  898. outsPtr[i] = fAudioBufOut[i/fAudioCountOut][j];
  899. if ((i+1) % fAudioCountOut == 0)
  900. j += 1;
  901. }
  902. }
  903. else
  904. {
  905. for (unsigned int i=0; i < fAudioCountOut; ++i)
  906. {
  907. #ifdef USE_JUCE
  908. FloatVectorOperations::copy(outsPtr+(nframes*i), fAudioBufOut[i], nframes);
  909. #endif
  910. }
  911. }
  912. // output events
  913. {
  914. // TODO
  915. //fMidiOutEvents...
  916. }
  917. runPendingRtEvents();
  918. return;
  919. // unused
  920. (void)streamTime;
  921. (void)status;
  922. }
  923. void handleMidiCallback(double timeStamp, std::vector<unsigned char>* const message)
  924. {
  925. if (! fAudioIsReady)
  926. return;
  927. const size_t messageSize = message->size();
  928. static uint32_t lastTime = 0;
  929. if (messageSize == 0 || messageSize > 4)
  930. return;
  931. timeStamp /= 2;
  932. if (timeStamp > 0.95)
  933. timeStamp = 0.95;
  934. else if (timeStamp < 0.0)
  935. timeStamp = 0.0;
  936. RtMidiEvent midiEvent;
  937. midiEvent.time = fTimeInfo.frame + (timeStamp*(double)fBufferSize);
  938. if (midiEvent.time < lastTime)
  939. midiEvent.time = lastTime;
  940. else
  941. lastTime = midiEvent.time;
  942. if (messageSize == 1)
  943. {
  944. midiEvent.data[0] = message->at(0);
  945. midiEvent.data[1] = 0;
  946. midiEvent.data[2] = 0;
  947. midiEvent.data[3] = 0;
  948. midiEvent.size = 1;
  949. }
  950. else if (messageSize == 2)
  951. {
  952. midiEvent.data[0] = message->at(0);
  953. midiEvent.data[1] = message->at(1);
  954. midiEvent.data[2] = 0;
  955. midiEvent.data[3] = 0;
  956. midiEvent.size = 2;
  957. }
  958. else if (messageSize == 3)
  959. {
  960. midiEvent.data[0] = message->at(0);
  961. midiEvent.data[1] = message->at(1);
  962. midiEvent.data[2] = message->at(2);
  963. midiEvent.data[3] = 0;
  964. midiEvent.size = 3;
  965. }
  966. else
  967. {
  968. midiEvent.data[0] = message->at(0);
  969. midiEvent.data[1] = message->at(1);
  970. midiEvent.data[2] = message->at(2);
  971. midiEvent.data[3] = message->at(3);
  972. midiEvent.size = 4;
  973. }
  974. fMidiInEvents.append(midiEvent);
  975. }
  976. bool connectMidiInPort(const int portId)
  977. {
  978. CARLA_ASSERT(fUsedMidiIns.count() > 0);
  979. CARLA_ASSERT(portId >= 0);
  980. CARLA_ASSERT(static_cast<size_t>(portId) < fUsedMidiIns.count());
  981. carla_debug("CarlaEngineRtAudio::connectMidiInPort(%i)", portId);
  982. if (portId < 0 || static_cast<size_t>(portId) >= fUsedMidiIns.count())
  983. return false;
  984. const char* const portName(fUsedMidiIns.getAt(portId).name);
  985. char newPortName[STR_MAX+1];
  986. std::snprintf(newPortName, STR_MAX, "%s:in-%i", (const char*)getName(), portId+1);
  987. int rtMidiPortIndex = -1;
  988. RtMidiIn* const rtMidiIn(new RtMidiIn(getMatchedAudioMidiAPi(fAudio.getCurrentApi()), newPortName, 512));
  989. rtMidiIn->ignoreTypes();
  990. rtMidiIn->setCallback(carla_rtmidi_callback, this);
  991. for (unsigned int i=0, count=rtMidiIn->getPortCount(); i < count; ++i)
  992. {
  993. if (rtMidiIn->getPortName(i) == portName)
  994. {
  995. rtMidiPortIndex = i;
  996. break;
  997. }
  998. }
  999. if (rtMidiPortIndex == -1)
  1000. {
  1001. delete rtMidiIn;
  1002. return false;
  1003. }
  1004. rtMidiIn->openPort(rtMidiPortIndex, newPortName+(std::strlen(getName())+1));
  1005. MidiPort midiPort;
  1006. midiPort.portId = portId;
  1007. midiPort.rtmidi = rtMidiIn;
  1008. fMidiIns.append(midiPort);
  1009. return true;
  1010. }
  1011. bool connectMidiOutPort(const int portId)
  1012. {
  1013. CARLA_ASSERT(fUsedMidiOuts.count() > 0);
  1014. CARLA_ASSERT(portId >= 0);
  1015. CARLA_ASSERT(static_cast<size_t>(portId) < fUsedMidiOuts.count());
  1016. carla_debug("CarlaEngineRtAudio::connectMidiOutPort(%i)", portId);
  1017. if (portId < 0 || static_cast<size_t>(portId) >= fUsedMidiOuts.count())
  1018. return false;
  1019. const char* const portName(fUsedMidiOuts.getAt(portId).name);
  1020. char newPortName[STR_MAX+1];
  1021. std::snprintf(newPortName, STR_MAX, "%s:out-%i", (const char*)getName(), portId+1);
  1022. int rtMidiPortIndex = -1;
  1023. RtMidiOut* const rtMidiOut(new RtMidiOut(getMatchedAudioMidiAPi(fAudio.getCurrentApi()), newPortName));
  1024. for (unsigned int i=0, count=rtMidiOut->getPortCount(); i < count; ++i)
  1025. {
  1026. if (rtMidiOut->getPortName(i) == portName)
  1027. {
  1028. rtMidiPortIndex = i;
  1029. break;
  1030. }
  1031. }
  1032. if (rtMidiPortIndex == -1)
  1033. {
  1034. delete rtMidiOut;
  1035. return false;
  1036. }
  1037. rtMidiOut->openPort(rtMidiPortIndex, newPortName+(std::strlen(getName())+1));
  1038. MidiPort midiPort;
  1039. midiPort.portId = portId;
  1040. midiPort.rtmidi = rtMidiOut;
  1041. fMidiOuts.append(midiPort);
  1042. return true;
  1043. }
  1044. // -------------------------------------
  1045. private:
  1046. RtAudio fAudio;
  1047. float** fAudioBufIn;
  1048. float** fAudioBufOut;
  1049. float* fAudioBufRackIn[2];
  1050. float* fAudioBufRackOut[2];
  1051. uint fAudioCountIn;
  1052. uint fAudioCountOut;
  1053. bool fAudioIsInterleaved;
  1054. bool fAudioIsReady;
  1055. List<uint> fConnectedAudioIns[2];
  1056. List<uint> fConnectedAudioOuts[2];
  1057. CarlaMutex fConnectAudioLock;
  1058. CarlaString fConnectName;
  1059. RtMidiIn fDummyMidiIn;
  1060. RtMidiOut fDummyMidiOut;
  1061. enum PatchbayGroupIds {
  1062. PATCHBAY_GROUP_CARLA = -1,
  1063. PATCHBAY_GROUP_AUDIO_IN = 0,
  1064. PATCHBAY_GROUP_AUDIO_OUT = 1,
  1065. PATCHBAY_GROUP_MIDI_IN = 2,
  1066. PATCHBAY_GROUP_MIDI_OUT = 3,
  1067. PATCHBAY_GROUP_MAX = 4
  1068. };
  1069. enum PatchbayPortIds {
  1070. PATCHBAY_PORT_AUDIO_IN1 = -1,
  1071. PATCHBAY_PORT_AUDIO_IN2 = -2,
  1072. PATCHBAY_PORT_AUDIO_OUT1 = -3,
  1073. PATCHBAY_PORT_AUDIO_OUT2 = -4,
  1074. PATCHBAY_PORT_MIDI_IN = -5,
  1075. PATCHBAY_PORT_MIDI_OUT = -6,
  1076. PATCHBAY_PORT_MAX = -7
  1077. };
  1078. struct ConnectionToId {
  1079. int id;
  1080. int portOut;
  1081. int portIn;
  1082. };
  1083. struct PortNameToId {
  1084. int portId;
  1085. char name[STR_MAX+1];
  1086. };
  1087. int fLastConnectionId;
  1088. List<PortNameToId> fUsedMidiIns;
  1089. List<PortNameToId> fUsedMidiOuts;
  1090. List<ConnectionToId> fUsedConnections;
  1091. struct MidiPort {
  1092. RtMidi* rtmidi;
  1093. int portId;
  1094. };
  1095. List<MidiPort> fMidiIns;
  1096. List<MidiPort> fMidiOuts;
  1097. struct RtMidiEvent {
  1098. uint32_t time;
  1099. unsigned char data[4];
  1100. unsigned char size;
  1101. };
  1102. struct RtMidiEvents {
  1103. CarlaMutex mutex;
  1104. RtList<RtMidiEvent>::Pool dataPool;
  1105. RtList<RtMidiEvent> data;
  1106. RtList<RtMidiEvent> dataPending;
  1107. RtMidiEvents()
  1108. : dataPool(512, 512),
  1109. data(dataPool),
  1110. dataPending(dataPool) {}
  1111. ~RtMidiEvents()
  1112. {
  1113. clear();
  1114. }
  1115. void append(const RtMidiEvent& event)
  1116. {
  1117. mutex.lock();
  1118. dataPending.append(event);
  1119. mutex.unlock();
  1120. }
  1121. void clear()
  1122. {
  1123. mutex.lock();
  1124. data.clear();
  1125. dataPending.clear();
  1126. mutex.unlock();
  1127. }
  1128. void splice()
  1129. {
  1130. dataPending.spliceAppend(data);
  1131. }
  1132. };
  1133. RtMidiEvents fMidiInEvents;
  1134. //RtMidiEvents fMidiOutEvents;
  1135. #define handlePtr ((CarlaEngineRtAudio*)userData)
  1136. static int carla_rtaudio_process_callback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status, void* userData)
  1137. {
  1138. handlePtr->handleAudioProcessCallback(outputBuffer, inputBuffer, nframes, streamTime, status);
  1139. return 0;
  1140. }
  1141. static void carla_rtmidi_callback(double timeStamp, std::vector<unsigned char>* message, void* userData)
  1142. {
  1143. handlePtr->handleMidiCallback(timeStamp, message);
  1144. }
  1145. #undef handlePtr
  1146. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineRtAudio)
  1147. };
  1148. // -----------------------------------------
  1149. CarlaEngine* CarlaEngine::newRtAudio(AudioApi api)
  1150. {
  1151. RtAudio::Api rtApi(RtAudio::UNSPECIFIED);
  1152. switch (api)
  1153. {
  1154. case AUDIO_API_NULL:
  1155. rtApi = RtAudio::RTAUDIO_DUMMY;
  1156. break;
  1157. case AUDIO_API_JACK:
  1158. rtApi = RtAudio::UNIX_JACK;
  1159. break;
  1160. case AUDIO_API_ALSA:
  1161. rtApi = RtAudio::LINUX_ALSA;
  1162. break;
  1163. case AUDIO_API_OSS:
  1164. rtApi = RtAudio::LINUX_OSS;
  1165. break;
  1166. case AUDIO_API_PULSE:
  1167. rtApi = RtAudio::LINUX_PULSE;
  1168. break;
  1169. case AUDIO_API_CORE:
  1170. rtApi = RtAudio::MACOSX_CORE;
  1171. break;
  1172. case AUDIO_API_ASIO:
  1173. rtApi = RtAudio::WINDOWS_ASIO;
  1174. break;
  1175. case AUDIO_API_DS:
  1176. rtApi = RtAudio::WINDOWS_DS;
  1177. break;
  1178. }
  1179. return new CarlaEngineRtAudio(rtApi);
  1180. }
  1181. size_t CarlaEngine::getRtAudioApiCount()
  1182. {
  1183. initRtApis();
  1184. return gRtAudioApis.size();
  1185. }
  1186. const char* CarlaEngine::getRtAudioApiName(const unsigned int index)
  1187. {
  1188. initRtApis();
  1189. if (index >= gRtAudioApis.size())
  1190. return nullptr;
  1191. const RtAudio::Api& api(gRtAudioApis[index]);
  1192. switch (api)
  1193. {
  1194. case RtAudio::UNSPECIFIED:
  1195. return "Unspecified";
  1196. case RtAudio::LINUX_ALSA:
  1197. return "ALSA";
  1198. case RtAudio::LINUX_PULSE:
  1199. return "PulseAudio";
  1200. case RtAudio::LINUX_OSS:
  1201. return "OSS";
  1202. case RtAudio::UNIX_JACK:
  1203. #if defined(CARLA_OS_WIN)
  1204. return "JACK with WinMM";
  1205. #elif defined(CARLA_OS_MAC)
  1206. return "JACK with CoreMidi";
  1207. #elif defined(CARLA_OS_LINUX)
  1208. return "JACK with ALSA-MIDI";
  1209. #else
  1210. return "JACK (RtAudio)";
  1211. #endif
  1212. case RtAudio::MACOSX_CORE:
  1213. return "CoreAudio";
  1214. case RtAudio::WINDOWS_ASIO:
  1215. return "ASIO";
  1216. case RtAudio::WINDOWS_DS:
  1217. return "DirectSound";
  1218. case RtAudio::RTAUDIO_DUMMY:
  1219. return "Dummy";
  1220. }
  1221. return nullptr;
  1222. }
  1223. const char* const* CarlaEngine::getRtAudioApiDeviceNames(const unsigned int index)
  1224. {
  1225. initRtApis();
  1226. if (index >= gRtAudioApis.size())
  1227. return nullptr;
  1228. const RtAudio::Api& api(gRtAudioApis[index]);
  1229. RtAudio rtAudio(api);
  1230. if (gRetNames != nullptr)
  1231. {
  1232. int i=0;
  1233. while (gRetNames[i] != nullptr)
  1234. delete[] gRetNames[i++];
  1235. delete[] gRetNames;
  1236. gRetNames = nullptr;
  1237. }
  1238. const unsigned int devCount(rtAudio.getDeviceCount());
  1239. if (devCount == 0)
  1240. return nullptr;
  1241. List<const char*> devNames;
  1242. for (unsigned int i=0; i < devCount; ++i)
  1243. {
  1244. RtAudio::DeviceInfo devInfo(rtAudio.getDeviceInfo(i));
  1245. if (devInfo.probed && devInfo.outputChannels > 0 /*&& (devInfo.nativeFormats & RTAUDIO_FLOAT32) != 0*/)
  1246. devNames.append(carla_strdup(devInfo.name.c_str()));
  1247. }
  1248. const unsigned int realDevCount(devNames.count());
  1249. gRetNames = new const char*[realDevCount+1];
  1250. for (unsigned int i=0; i < realDevCount; ++i)
  1251. gRetNames[i] = devNames.getAt(i);
  1252. gRetNames[realDevCount] = nullptr;
  1253. devNames.clear();
  1254. return gRetNames;
  1255. }
  1256. const EngineDriverDeviceInfo* CarlaEngine::getRtAudioDeviceInfo(const unsigned int index, const char* const deviceName)
  1257. {
  1258. initRtApis();
  1259. if (index >= gRtAudioApis.size())
  1260. return nullptr;
  1261. const RtAudio::Api& api(gRtAudioApis[index]);
  1262. RtAudio rtAudio(api);
  1263. const unsigned int devCount(rtAudio.getDeviceCount());
  1264. if (devCount == 0)
  1265. return nullptr;
  1266. unsigned int i;
  1267. RtAudio::DeviceInfo rtAudioDevInfo;
  1268. for (i=0; i < devCount; ++i)
  1269. {
  1270. rtAudioDevInfo = rtAudio.getDeviceInfo(i);
  1271. if (rtAudioDevInfo.name == deviceName)
  1272. break;
  1273. }
  1274. if (i == devCount)
  1275. return nullptr;
  1276. static EngineDriverDeviceInfo devInfo;
  1277. static uint32_t dummyBufferSizes[11] = { 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 0 };
  1278. static double dummySampleRates[14] = { 22050.0, 32000.0, 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0, 0.0 };
  1279. // reset
  1280. devInfo.hints = 0x0;
  1281. devInfo.bufferSizes = dummyBufferSizes;
  1282. // cleanup
  1283. if (devInfo.sampleRates != nullptr && devInfo.sampleRates != dummySampleRates)
  1284. {
  1285. delete[] devInfo.sampleRates;
  1286. devInfo.sampleRates = nullptr;
  1287. }
  1288. if (size_t sampleRatesCount = rtAudioDevInfo.sampleRates.size())
  1289. {
  1290. double* sampleRates(new double[sampleRatesCount+1]);
  1291. for (size_t i=0; i < sampleRatesCount; ++i)
  1292. sampleRates[i] = rtAudioDevInfo.sampleRates[i];
  1293. sampleRates[sampleRatesCount] = 0.0;
  1294. devInfo.sampleRates = sampleRates;
  1295. }
  1296. else
  1297. {
  1298. devInfo.sampleRates = dummySampleRates;
  1299. }
  1300. return &devInfo;
  1301. }
  1302. // -----------------------------------------
  1303. CARLA_BACKEND_END_NAMESPACE