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.

1505 lines
47KB

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