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.

1162 lines
36KB

  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 "RtLinkedList.hpp"
  20. #include "rtaudio/RtAudio.h"
  21. #include "rtmidi/RtMidi.h"
  22. CARLA_BACKEND_START_NAMESPACE
  23. #if 0
  24. } // Fix editor indentation
  25. #endif
  26. // -------------------------------------------------------------------------------------------------------------------
  27. static const char** gRetNames = nullptr;
  28. static std::vector<RtAudio::Api> gRtAudioApis;
  29. static void initRtApis()
  30. {
  31. if (gRtAudioApis.size() == 0)
  32. {
  33. RtAudio::getCompiledApi(gRtAudioApis);
  34. #ifdef HAVE_JUCE
  35. // prefer juce to handle some APIs
  36. std::vector<RtAudio::Api>::iterator it = std::find(gRtAudioApis.begin(), gRtAudioApis.end(), RtAudio::LINUX_ALSA);
  37. if (it != gRtAudioApis.end()) gRtAudioApis.erase(it);
  38. it = std::find(gRtAudioApis.begin(), gRtAudioApis.end(), RtAudio::MACOSX_CORE);
  39. if (it != gRtAudioApis.end()) gRtAudioApis.erase(it);
  40. it = std::find(gRtAudioApis.begin(), gRtAudioApis.end(), RtAudio::WINDOWS_ASIO);
  41. if (it != gRtAudioApis.end()) gRtAudioApis.erase(it);
  42. it = std::find(gRtAudioApis.begin(), gRtAudioApis.end(), RtAudio::WINDOWS_DS);
  43. if (it != gRtAudioApis.end()) gRtAudioApis.erase(it);
  44. #endif
  45. // in case rtaudio has no apis, add dummy one so that size() != 0
  46. if (gRtAudioApis.size() == 0)
  47. gRtAudioApis.push_back(RtAudio::RTAUDIO_DUMMY);
  48. }
  49. }
  50. const char* getRtAudioApiName(const RtAudio::Api api)
  51. {
  52. switch (api)
  53. {
  54. case RtAudio::UNSPECIFIED:
  55. return "Unspecified";
  56. case RtAudio::LINUX_ALSA:
  57. return "ALSA";
  58. case RtAudio::LINUX_PULSE:
  59. return "PulseAudio";
  60. case RtAudio::LINUX_OSS:
  61. return "OSS";
  62. case RtAudio::UNIX_JACK:
  63. #if defined(CARLA_OS_WIN)
  64. return "JACK with WinMM";
  65. #elif defined(CARLA_OS_MAC)
  66. return "JACK with CoreMidi";
  67. #elif defined(CARLA_OS_LINUX)
  68. return "JACK with ALSA-MIDI";
  69. #else
  70. return "JACK (RtAudio)";
  71. #endif
  72. case RtAudio::MACOSX_CORE:
  73. return "CoreAudio";
  74. case RtAudio::WINDOWS_ASIO:
  75. return "ASIO";
  76. case RtAudio::WINDOWS_DS:
  77. return "DirectSound";
  78. case RtAudio::RTAUDIO_DUMMY:
  79. return "Dummy";
  80. }
  81. carla_stderr("CarlaBackend::getRtAudioApiName(%i) - invalid API", api);
  82. return nullptr;
  83. }
  84. RtMidi::Api getMatchedAudioMidiAPi(const RtAudio::Api rtApi)
  85. {
  86. switch (rtApi)
  87. {
  88. case RtAudio::UNSPECIFIED:
  89. return RtMidi::UNSPECIFIED;
  90. case RtAudio::LINUX_ALSA:
  91. case RtAudio::LINUX_OSS:
  92. case RtAudio::LINUX_PULSE:
  93. return RtMidi::LINUX_ALSA;
  94. case RtAudio::UNIX_JACK:
  95. #if defined(CARLA_OS_WIN)
  96. return RtMidi::WINDOWS_MM;
  97. #elif defined(CARLA_OS_MAC)
  98. return RtMidi::MACOSX_CORE;
  99. #elif defined(CARLA_OS_LINUX)
  100. return RtMidi::LINUX_ALSA;
  101. #else
  102. return RtMidi::UNIX_JACK;
  103. #endif
  104. case RtAudio::MACOSX_CORE:
  105. return RtMidi::MACOSX_CORE;
  106. case RtAudio::WINDOWS_ASIO:
  107. case RtAudio::WINDOWS_DS:
  108. return RtMidi::WINDOWS_MM;
  109. case RtAudio::RTAUDIO_DUMMY:
  110. return RtMidi::RTMIDI_DUMMY;
  111. }
  112. return RtMidi::UNSPECIFIED;
  113. }
  114. // -------------------------------------------------------------------------------------------------------------------
  115. // RtAudio Engine
  116. class CarlaEngineRtAudio : public CarlaEngine
  117. {
  118. public:
  119. CarlaEngineRtAudio(const RtAudio::Api api)
  120. : CarlaEngine(),
  121. fAudio(api),
  122. fAudioBufIn(nullptr),
  123. fAudioBufOut(nullptr),
  124. fIsAudioInterleaved(false),
  125. fLastEventTime(0),
  126. fDummyMidiIn(getMatchedAudioMidiAPi(api), "Carla"),
  127. fDummyMidiOut(getMatchedAudioMidiAPi(api), "Carla")
  128. {
  129. carla_debug("CarlaEngineRtAudio::CarlaEngineRtAudio(%i)", api);
  130. // just to make sure
  131. pData->options.transportMode = ENGINE_TRANSPORT_MODE_INTERNAL;
  132. }
  133. ~CarlaEngineRtAudio() override
  134. {
  135. CARLA_ASSERT(fAudioBufIn == nullptr);
  136. CARLA_ASSERT(fAudioBufOut == nullptr);
  137. carla_debug("CarlaEngineRtAudio::~CarlaEngineRtAudio()");
  138. fUsedMidiIns.clear();
  139. fUsedMidiOuts.clear();
  140. if (gRetNames != nullptr)
  141. {
  142. delete[] gRetNames;
  143. gRetNames = nullptr;
  144. }
  145. gRtAudioApis.clear();
  146. }
  147. // -------------------------------------
  148. bool init(const char* const clientName) override
  149. {
  150. CARLA_SAFE_ASSERT_RETURN(fAudioBufIn == nullptr, false);
  151. CARLA_SAFE_ASSERT_RETURN(fAudioBufOut == nullptr, false);
  152. CARLA_SAFE_ASSERT_RETURN(clientName != nullptr && clientName[0] != '\0', false);
  153. carla_debug("CarlaEngineRtAudio::init(\"%s\")", clientName);
  154. if (pData->options.processMode != ENGINE_PROCESS_MODE_CONTINUOUS_RACK && pData->options.processMode != ENGINE_PROCESS_MODE_PATCHBAY)
  155. {
  156. setLastError("Invalid process mode");
  157. return false;
  158. }
  159. pData->bufAudio.usePatchbay = (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY);
  160. RtAudio::StreamParameters iParams, oParams;
  161. bool deviceSet = false;
  162. const unsigned int devCount(fAudio.getDeviceCount());
  163. if (devCount == 0)
  164. {
  165. setLastError("No audio devices available for this driver");
  166. return false;
  167. }
  168. if (pData->options.audioDevice != nullptr && pData->options.audioDevice[0] != '\0')
  169. {
  170. for (unsigned int i=0; i < devCount; ++i)
  171. {
  172. RtAudio::DeviceInfo devInfo(fAudio.getDeviceInfo(i));
  173. if (devInfo.probed && devInfo.outputChannels > 0 && devInfo.name == pData->options.audioDevice)
  174. {
  175. deviceSet = true;
  176. fDeviceName = devInfo.name.c_str();
  177. iParams.deviceId = i;
  178. oParams.deviceId = i;
  179. iParams.nChannels = devInfo.inputChannels;
  180. oParams.nChannels = devInfo.outputChannels;
  181. break;
  182. }
  183. }
  184. }
  185. if (! deviceSet)
  186. {
  187. iParams.deviceId = fAudio.getDefaultInputDevice();
  188. oParams.deviceId = fAudio.getDefaultOutputDevice();
  189. iParams.nChannels = fAudio.getDeviceInfo(iParams.deviceId).inputChannels;
  190. oParams.nChannels = fAudio.getDeviceInfo(oParams.deviceId).outputChannels;
  191. }
  192. RtAudio::StreamOptions rtOptions;
  193. rtOptions.flags = RTAUDIO_MINIMIZE_LATENCY | RTAUDIO_HOG_DEVICE | RTAUDIO_SCHEDULE_REALTIME;
  194. rtOptions.streamName = clientName;
  195. rtOptions.priority = 85;
  196. if (fAudio.getCurrentApi() != RtAudio::LINUX_PULSE)
  197. {
  198. rtOptions.flags |= RTAUDIO_NONINTERLEAVED;
  199. fIsAudioInterleaved = false;
  200. if (fAudio.getCurrentApi() == RtAudio::LINUX_ALSA && ! deviceSet)
  201. rtOptions.flags |= RTAUDIO_ALSA_USE_DEFAULT;
  202. }
  203. else
  204. fIsAudioInterleaved = true;
  205. fLastEventTime = 0;
  206. unsigned int bufferFrames = pData->options.audioBufferSize;
  207. try {
  208. fAudio.openStream(&oParams, &iParams, RTAUDIO_FLOAT32, pData->options.audioSampleRate, &bufferFrames, carla_rtaudio_process_callback, this, &rtOptions);
  209. }
  210. catch (const RtError& e)
  211. {
  212. setLastError(e.what());
  213. return false;
  214. }
  215. pData->bufferSize = bufferFrames;
  216. pData->sampleRate = fAudio.getStreamSampleRate();
  217. pData->bufAudio.inCount = iParams.nChannels;
  218. pData->bufAudio.outCount = oParams.nChannels;
  219. CARLA_ASSERT(pData->bufAudio.outCount > 0);
  220. if (pData->bufAudio.inCount > 0)
  221. {
  222. fAudioBufIn = new float*[pData->bufAudio.inCount];
  223. for (uint i=0; i < pData->bufAudio.inCount; ++i)
  224. fAudioBufIn[i] = new float[pData->bufferSize];
  225. }
  226. if (pData->bufAudio.outCount > 0)
  227. {
  228. fAudioBufOut = new float*[pData->bufAudio.outCount];
  229. for (uint i=0; i < pData->bufAudio.outCount; ++i)
  230. fAudioBufOut[i] = new float[pData->bufferSize];
  231. }
  232. pData->bufAudio.create(pData->bufferSize);
  233. try {
  234. fAudio.startStream();
  235. }
  236. catch (const RtError& e)
  237. {
  238. setLastError(e.what());
  239. fAudio.closeStream();
  240. return false;
  241. }
  242. CarlaEngine::init(clientName);
  243. patchbayRefresh();
  244. return true;
  245. }
  246. bool close() override
  247. {
  248. CARLA_ASSERT(fAudioBufOut != nullptr);
  249. carla_debug("CarlaEngineRtAudio::close()");
  250. pData->bufAudio.isReady = false;
  251. bool hasError = !CarlaEngine::close();
  252. if (fAudio.isStreamOpen())
  253. {
  254. if (fAudio.isStreamRunning())
  255. {
  256. try {
  257. fAudio.stopStream();
  258. }
  259. catch (const RtError& e)
  260. {
  261. if (! hasError)
  262. {
  263. setLastError(e.what());
  264. hasError = true;
  265. }
  266. }
  267. }
  268. fAudio.closeStream();
  269. }
  270. if (fAudioBufIn != nullptr)
  271. {
  272. for (uint i=0; i < pData->bufAudio.inCount; ++i)
  273. delete[] fAudioBufIn[i];
  274. delete[] fAudioBufIn;
  275. fAudioBufIn = nullptr;
  276. }
  277. if (fAudioBufOut != nullptr)
  278. {
  279. for (uint i=0; i < pData->bufAudio.outCount; ++i)
  280. delete[] fAudioBufOut[i];
  281. delete[] fAudioBufOut;
  282. fAudioBufOut = nullptr;
  283. }
  284. pData->bufAudio.clear();
  285. fDeviceName.clear();
  286. for (LinkedList<MidiPort>::Itenerator it = fMidiIns.begin(); it.valid(); it.next())
  287. {
  288. MidiPort& port(it.getValue());
  289. RtMidiIn* const midiInPort((RtMidiIn*)port.rtmidi);
  290. midiInPort->cancelCallback();
  291. delete midiInPort;
  292. }
  293. for (LinkedList<MidiPort>::Itenerator it = fMidiOuts.begin(); it.valid(); it.next())
  294. {
  295. MidiPort& port(it.getValue());
  296. RtMidiOut* const midiOutPort((RtMidiOut*)port.rtmidi);
  297. delete midiOutPort;
  298. }
  299. fMidiIns.clear();
  300. fMidiOuts.clear();
  301. fMidiInEvents.clear();
  302. //fMidiOutEvents.clear();
  303. return !hasError;
  304. }
  305. bool isRunning() const noexcept override
  306. {
  307. return fAudio.isStreamRunning();
  308. }
  309. bool isOffline() const noexcept override
  310. {
  311. return false;
  312. }
  313. EngineType getType() const noexcept override
  314. {
  315. return kEngineTypeRtAudio;
  316. }
  317. const char* getCurrentDriverName() const noexcept override
  318. {
  319. return CarlaBackend::getRtAudioApiName(fAudio.getCurrentApi());
  320. }
  321. // -------------------------------------------------------------------
  322. // Patchbay
  323. bool patchbayRefresh() override
  324. {
  325. CARLA_SAFE_ASSERT_RETURN(pData->bufAudio.isReady, false);
  326. fUsedMidiIns.clear();
  327. fUsedMidiOuts.clear();
  328. pData->bufAudio.initPatchbay();
  329. if (pData->bufAudio.usePatchbay)
  330. {
  331. // not implemented yet
  332. return false;
  333. }
  334. char strBuf[STR_MAX+1];
  335. strBuf[STR_MAX] = '\0';
  336. EngineRackBuffers* const rack(pData->bufAudio.rack);
  337. // Main
  338. {
  339. callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, RACK_PATCHBAY_GROUP_CARLA, 0, 0, 0.0f, getName());
  340. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_PORT_AUDIO_IN1, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0.0f, "audio-in1");
  341. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_PORT_AUDIO_IN2, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0.0f, "audio-in2");
  342. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_PORT_AUDIO_OUT1, PATCHBAY_PORT_TYPE_AUDIO, 0.0f, "audio-out1");
  343. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_PORT_AUDIO_OUT2, PATCHBAY_PORT_TYPE_AUDIO, 0.0f, "audio-out2");
  344. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_PORT_MIDI_IN, PATCHBAY_PORT_TYPE_MIDI|PATCHBAY_PORT_IS_INPUT, 0.0f, "midi-in");
  345. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_CARLA, RACK_PATCHBAY_PORT_MIDI_OUT, PATCHBAY_PORT_TYPE_MIDI, 0.0f, "midi-out");
  346. }
  347. // Audio In
  348. {
  349. if (fDeviceName.isNotEmpty())
  350. std::snprintf(strBuf, STR_MAX, "Capture (%s)", (const char*)fDeviceName);
  351. else
  352. std::strncpy(strBuf, "Capture", STR_MAX);
  353. callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, RACK_PATCHBAY_GROUP_AUDIO_IN, 0, 0, 0.0f, strBuf);
  354. for (uint i=0; i < pData->bufAudio.inCount; ++i)
  355. {
  356. std::snprintf(strBuf, STR_MAX, "capture_%i", i+1);
  357. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_AUDIO_IN, RACK_PATCHBAY_GROUP_AUDIO_IN*1000 + i, PATCHBAY_PORT_TYPE_AUDIO, 0.0f, strBuf);
  358. }
  359. }
  360. // Audio Out
  361. {
  362. if (fDeviceName.isNotEmpty())
  363. std::snprintf(strBuf, STR_MAX, "Playback (%s)", (const char*)fDeviceName);
  364. else
  365. std::strncpy(strBuf, "Playback", STR_MAX);
  366. callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, RACK_PATCHBAY_GROUP_AUDIO_OUT, 0, 0, 0.0f, strBuf);
  367. for (uint i=0; i < pData->bufAudio.outCount; ++i)
  368. {
  369. std::snprintf(strBuf, STR_MAX, "playback_%i", i+1);
  370. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_AUDIO_OUT, RACK_PATCHBAY_GROUP_AUDIO_OUT*1000 + i, PATCHBAY_PORT_TYPE_AUDIO|PATCHBAY_PORT_IS_INPUT, 0.0f, strBuf);
  371. }
  372. }
  373. // MIDI In
  374. {
  375. callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, RACK_PATCHBAY_GROUP_MIDI_IN, 0, 0, 0.0f, "Readable MIDI ports");
  376. for (unsigned int i=0, count=fDummyMidiIn.getPortCount(); i < count; ++i)
  377. {
  378. PortNameToId portNameToId;
  379. portNameToId.portId = RACK_PATCHBAY_GROUP_MIDI_IN*1000 + i;
  380. std::strncpy(portNameToId.name, fDummyMidiIn.getPortName(i).c_str(), STR_MAX);
  381. fUsedMidiIns.append(portNameToId);
  382. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, RACK_PATCHBAY_GROUP_MIDI_IN, portNameToId.portId, PATCHBAY_PORT_TYPE_MIDI, 0.0f, portNameToId.name);
  383. }
  384. }
  385. #if 0 // midi-out not implemented yet
  386. // MIDI Out
  387. {
  388. callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, 0, RACK_PATCHBAY_GROUP_MIDI_OUT, 0, 0.0f, "Writable MIDI ports");
  389. for (unsigned int i=0, count=fDummyMidiOut.getPortCount(); i < count; ++i)
  390. {
  391. PortNameToId portNameToId;
  392. portNameToId.portId = RACK_PATCHBAY_GROUP_MIDI_OUT*1000 + i;
  393. std::strncpy(portNameToId.name, fDummyMidiOut.getPortName(i).c_str(), STR_MAX);
  394. fUsedMidiOuts.append(portNameToId);
  395. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, 0, RACK_PATCHBAY_GROUP_MIDI_OUT, portNameToId.portId, PATCHBAY_PORT_TYPE_MIDI|PATCHBAY_PORT_IS_INPUT, portNameToId.name);
  396. }
  397. }
  398. #endif
  399. // Connections
  400. rack->connectLock.lock();
  401. for (LinkedList<uint>::Itenerator it = rack->connectedIns[0].begin(); it.valid(); it.next())
  402. {
  403. const uint& port(it.getValue());
  404. CARLA_SAFE_ASSERT_CONTINUE(port < pData->bufAudio.inCount);
  405. ConnectionToId connectionToId;
  406. connectionToId.id = rack->lastConnectionId;
  407. connectionToId.portOut = RACK_PATCHBAY_GROUP_AUDIO_IN*1000 + port;
  408. connectionToId.portIn = RACK_PATCHBAY_PORT_AUDIO_IN1;
  409. callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, connectionToId.portOut, connectionToId.portIn, 0.0f, nullptr);
  410. rack->usedConnections.append(connectionToId);
  411. rack->lastConnectionId++;
  412. }
  413. for (LinkedList<uint>::Itenerator it = rack->connectedIns[1].begin(); it.valid(); it.next())
  414. {
  415. const uint& port(it.getValue());
  416. CARLA_SAFE_ASSERT_CONTINUE(port < pData->bufAudio.inCount);
  417. ConnectionToId connectionToId;
  418. connectionToId.id = rack->lastConnectionId;
  419. connectionToId.portOut = RACK_PATCHBAY_GROUP_AUDIO_IN*1000 + port;
  420. connectionToId.portIn = RACK_PATCHBAY_PORT_AUDIO_IN2;
  421. callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, connectionToId.portOut, connectionToId.portIn, 0.0f, nullptr);
  422. rack->usedConnections.append(connectionToId);
  423. rack->lastConnectionId++;
  424. }
  425. for (LinkedList<uint>::Itenerator it = rack->connectedOuts[0].begin(); it.valid(); it.next())
  426. {
  427. const uint& port(it.getValue());
  428. CARLA_SAFE_ASSERT_CONTINUE(port < pData->bufAudio.outCount);
  429. ConnectionToId connectionToId;
  430. connectionToId.id = rack->lastConnectionId;
  431. connectionToId.portOut = RACK_PATCHBAY_PORT_AUDIO_OUT1;
  432. connectionToId.portIn = RACK_PATCHBAY_GROUP_AUDIO_OUT*1000 + port;
  433. callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, connectionToId.portOut, connectionToId.portIn, 0.0f, nullptr);
  434. rack->usedConnections.append(connectionToId);
  435. rack->lastConnectionId++;
  436. }
  437. for (LinkedList<uint>::Itenerator it = rack->connectedOuts[1].begin(); it.valid(); it.next())
  438. {
  439. const uint& port(it.getValue());
  440. CARLA_SAFE_ASSERT_CONTINUE(port < pData->bufAudio.outCount);
  441. ConnectionToId connectionToId;
  442. connectionToId.id = rack->lastConnectionId;
  443. connectionToId.portOut = RACK_PATCHBAY_PORT_AUDIO_OUT2;
  444. connectionToId.portIn = RACK_PATCHBAY_GROUP_AUDIO_OUT*1000 + port;
  445. callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, connectionToId.portOut, connectionToId.portIn, 0.0f, nullptr);
  446. rack->usedConnections.append(connectionToId);
  447. rack->lastConnectionId++;
  448. }
  449. pData->bufAudio.rack->connectLock.unlock();
  450. for (LinkedList<MidiPort>::Itenerator it=fMidiIns.begin(); it.valid(); it.next())
  451. {
  452. const MidiPort& midiPort(it.getValue());
  453. ConnectionToId connectionToId;
  454. connectionToId.id = rack->lastConnectionId;
  455. connectionToId.portOut = RACK_PATCHBAY_GROUP_MIDI_IN*1000 + midiPort.portId;
  456. connectionToId.portIn = RACK_PATCHBAY_PORT_MIDI_IN;
  457. callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, connectionToId.portOut, connectionToId.portIn, 0.0f, nullptr);
  458. rack->usedConnections.append(connectionToId);
  459. rack->lastConnectionId++;
  460. }
  461. for (LinkedList<MidiPort>::Itenerator it=fMidiOuts.begin(); it.valid(); it.next())
  462. {
  463. const MidiPort& midiPort(it.getValue());
  464. ConnectionToId connectionToId;
  465. connectionToId.id = rack->lastConnectionId;
  466. connectionToId.portOut = RACK_PATCHBAY_PORT_MIDI_OUT;
  467. connectionToId.portIn = RACK_PATCHBAY_GROUP_MIDI_OUT*1000 + midiPort.portId;
  468. callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, rack->lastConnectionId, connectionToId.portOut, connectionToId.portIn, 0.0f, nullptr);
  469. rack->usedConnections.append(connectionToId);
  470. rack->lastConnectionId++;
  471. }
  472. return true;
  473. }
  474. // -------------------------------------------------------------------
  475. protected:
  476. void handleAudioProcessCallback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status)
  477. {
  478. // get buffers from RtAudio
  479. float* const insPtr = (float*)inputBuffer;
  480. float* const outsPtr = (float*)outputBuffer;
  481. // assert rtaudio buffers
  482. CARLA_SAFE_ASSERT_RETURN(outputBuffer != nullptr,);
  483. CARLA_SAFE_ASSERT_RETURN(nframes == pData->bufferSize,);
  484. if (pData->bufAudio.outCount == 0 || ! pData->bufAudio.isReady)
  485. return runPendingRtEvents();
  486. // initialize rtaudio input
  487. if (fIsAudioInterleaved)
  488. {
  489. for (unsigned int i=0, j=0, count=nframes*pData->bufAudio.inCount; i < count; ++i)
  490. {
  491. fAudioBufIn[i/pData->bufAudio.inCount][j] = insPtr[i];
  492. if ((i+1) % pData->bufAudio.inCount == 0)
  493. j += 1;
  494. }
  495. }
  496. else
  497. {
  498. for (unsigned int i=0; i < pData->bufAudio.inCount; ++i)
  499. FLOAT_COPY(fAudioBufIn[i], insPtr+(nframes*i), nframes);
  500. }
  501. // initialize rtaudio output
  502. for (unsigned int i=0; i < pData->bufAudio.outCount; ++i)
  503. FLOAT_CLEAR(fAudioBufOut[i], nframes);
  504. // initialize input events
  505. carla_zeroStruct<EngineEvent>(pData->bufEvents.in, kEngineMaxInternalEventCount);
  506. if (fMidiInEvents.mutex.tryLock())
  507. {
  508. uint32_t engineEventIndex = 0;
  509. fMidiInEvents.splice();
  510. while (! fMidiInEvents.data.isEmpty())
  511. {
  512. const RtMidiEvent& midiEvent(fMidiInEvents.data.getFirst(true));
  513. EngineEvent& engineEvent(pData->bufEvents.in[engineEventIndex++]);
  514. if (midiEvent.time < pData->timeInfo.frame)
  515. {
  516. engineEvent.time = 0;
  517. }
  518. else if (midiEvent.time >= pData->timeInfo.frame + nframes)
  519. {
  520. carla_stderr("MIDI Event in the future!, %i vs %i", engineEvent.time, pData->timeInfo.frame);
  521. engineEvent.time = static_cast<uint32_t>(pData->timeInfo.frame) + nframes - 1;
  522. }
  523. else
  524. engineEvent.time = static_cast<uint32_t>(midiEvent.time - pData->timeInfo.frame);
  525. engineEvent.fillFromMidiData(midiEvent.size, midiEvent.data);
  526. if (engineEventIndex >= kEngineMaxInternalEventCount)
  527. break;
  528. }
  529. fMidiInEvents.mutex.unlock();
  530. }
  531. if (pData->bufAudio.usePatchbay)
  532. {
  533. }
  534. else
  535. {
  536. pData->processRackFull(fAudioBufIn, pData->bufAudio.inCount, fAudioBufOut, pData->bufAudio.outCount, nframes, false);
  537. }
  538. // output audio
  539. if (fIsAudioInterleaved)
  540. {
  541. for (unsigned int i=0, j=0; i < nframes*pData->bufAudio.outCount; ++i)
  542. {
  543. outsPtr[i] = fAudioBufOut[i/pData->bufAudio.outCount][j];
  544. if ((i+1) % pData->bufAudio.outCount == 0)
  545. j += 1;
  546. }
  547. }
  548. else
  549. {
  550. for (unsigned int i=0; i < pData->bufAudio.outCount; ++i)
  551. FLOAT_COPY(outsPtr+(nframes*i), fAudioBufOut[i], nframes);
  552. }
  553. // output events
  554. {
  555. // TODO
  556. //fMidiOutEvents...
  557. }
  558. runPendingRtEvents();
  559. return;
  560. // unused
  561. (void)streamTime;
  562. (void)status;
  563. }
  564. void handleMidiCallback(double timeStamp, std::vector<unsigned char>* const message)
  565. {
  566. if (! pData->bufAudio.isReady)
  567. return;
  568. const size_t messageSize(message->size());
  569. if (messageSize == 0 || messageSize > EngineMidiEvent::kDataSize)
  570. return;
  571. timeStamp /= 2;
  572. if (timeStamp > 0.95)
  573. timeStamp = 0.95;
  574. else if (timeStamp < 0.0)
  575. timeStamp = 0.0;
  576. RtMidiEvent midiEvent;
  577. midiEvent.time = pData->timeInfo.frame + uint64_t(timeStamp * (double)pData->bufferSize);
  578. if (midiEvent.time < fLastEventTime)
  579. midiEvent.time = fLastEventTime;
  580. else
  581. fLastEventTime = midiEvent.time;
  582. midiEvent.size = static_cast<uint8_t>(messageSize);
  583. size_t i=0;
  584. for (; i < messageSize; ++i)
  585. midiEvent.data[i] = message->at(i);
  586. for (; i < EngineMidiEvent::kDataSize; ++i)
  587. midiEvent.data[i] = 0;
  588. fMidiInEvents.append(midiEvent);
  589. }
  590. // -------------------------------------------------------------------
  591. bool connectRackMidiInPort(const int portId) override
  592. {
  593. CARLA_SAFE_ASSERT_RETURN(fUsedMidiIns.count() > 0, false);
  594. CARLA_SAFE_ASSERT_RETURN(portId >= 0, false);
  595. CARLA_SAFE_ASSERT_RETURN(static_cast<size_t>(portId) < fUsedMidiIns.count(), false);
  596. carla_debug("CarlaEngineRtAudio::connectRackMidiInPort(%i)", portId);
  597. const char* const portName(fUsedMidiIns.getAt(portId).name);
  598. char newPortName[STR_MAX+1];
  599. std::snprintf(newPortName, STR_MAX, "%s:in-%i", (const char*)getName(), portId+1);
  600. int rtMidiPortIndex = -1;
  601. RtMidiIn* const rtMidiIn(new RtMidiIn(getMatchedAudioMidiAPi(fAudio.getCurrentApi()), newPortName, 512));
  602. rtMidiIn->ignoreTypes();
  603. rtMidiIn->setCallback(carla_rtmidi_callback, this);
  604. for (unsigned int i=0, count=rtMidiIn->getPortCount(); i < count; ++i)
  605. {
  606. if (rtMidiIn->getPortName(i) == portName)
  607. {
  608. rtMidiPortIndex = i;
  609. break;
  610. }
  611. }
  612. if (rtMidiPortIndex == -1)
  613. {
  614. delete rtMidiIn;
  615. return false;
  616. }
  617. rtMidiIn->openPort(rtMidiPortIndex, newPortName+(std::strlen(getName())+1));
  618. MidiPort midiPort;
  619. midiPort.portId = portId;
  620. midiPort.rtmidi = rtMidiIn;
  621. fMidiIns.append(midiPort);
  622. return true;
  623. }
  624. bool connectRackMidiOutPort(const int portId) override
  625. {
  626. CARLA_SAFE_ASSERT_RETURN(fUsedMidiOuts.count() > 0, false);
  627. CARLA_SAFE_ASSERT_RETURN(portId >= 0, false);
  628. CARLA_SAFE_ASSERT_RETURN(static_cast<size_t>(portId) < fUsedMidiOuts.count(), false);
  629. carla_debug("CarlaEngineRtAudio::connectRackMidiOutPort(%i)", portId);
  630. const char* const portName(fUsedMidiOuts.getAt(portId).name);
  631. char newPortName[STR_MAX+1];
  632. std::snprintf(newPortName, STR_MAX, "%s:out-%i", (const char*)getName(), portId+1);
  633. int rtMidiPortIndex = -1;
  634. RtMidiOut* const rtMidiOut(new RtMidiOut(getMatchedAudioMidiAPi(fAudio.getCurrentApi()), newPortName));
  635. for (unsigned int i=0, count=rtMidiOut->getPortCount(); i < count; ++i)
  636. {
  637. if (rtMidiOut->getPortName(i) == portName)
  638. {
  639. rtMidiPortIndex = i;
  640. break;
  641. }
  642. }
  643. if (rtMidiPortIndex == -1)
  644. {
  645. delete rtMidiOut;
  646. return false;
  647. }
  648. rtMidiOut->openPort(rtMidiPortIndex, newPortName+(std::strlen(getName())+1));
  649. MidiPort midiPort;
  650. midiPort.portId = portId;
  651. midiPort.rtmidi = rtMidiOut;
  652. fMidiOuts.append(midiPort);
  653. return true;
  654. }
  655. bool disconnectRackMidiInPort(const int portId) override
  656. {
  657. CARLA_SAFE_ASSERT_RETURN(fUsedMidiIns.count() > 0, false);
  658. CARLA_SAFE_ASSERT_RETURN(portId >= 0, false);
  659. CARLA_SAFE_ASSERT_RETURN(static_cast<size_t>(portId) < fUsedMidiIns.count(), false);
  660. carla_debug("CarlaEngineRtAudio::connectRackMidiInPort(%i)", portId);
  661. for (LinkedList<MidiPort>::Itenerator it=fMidiOuts.begin(); it.valid(); it.next())
  662. {
  663. MidiPort& midiPort(it.getValue());
  664. if (midiPort.portId == portId)
  665. {
  666. RtMidiOut* const midiOutPort((RtMidiOut*)midiPort.rtmidi);
  667. delete midiOutPort;
  668. fMidiOuts.remove(it);
  669. return true;
  670. }
  671. }
  672. return false;
  673. }
  674. bool disconnectRackMidiOutPort(const int portId) override
  675. {
  676. CARLA_SAFE_ASSERT_RETURN(fUsedMidiOuts.count() > 0, false);
  677. CARLA_SAFE_ASSERT_RETURN(portId >= 0, false);
  678. CARLA_SAFE_ASSERT_RETURN(static_cast<size_t>(portId) < fUsedMidiOuts.count(), false);
  679. carla_debug("CarlaEngineRtAudio::disconnectRackMidiOutPort(%i)", portId);
  680. for (LinkedList<MidiPort>::Itenerator it=fMidiIns.begin(); it.valid(); it.next())
  681. {
  682. MidiPort& midiPort(it.getValue());
  683. if (midiPort.portId == portId)
  684. {
  685. RtMidiIn* const midiInPort((RtMidiIn*)midiPort.rtmidi);
  686. midiInPort->cancelCallback();
  687. delete midiInPort;
  688. fMidiIns.remove(it);
  689. return true;
  690. }
  691. }
  692. return false;
  693. }
  694. // -------------------------------------
  695. private:
  696. RtAudio fAudio;
  697. // audio copy to split and de-interleave rtaudio buffers
  698. float** fAudioBufIn;
  699. float** fAudioBufOut;
  700. // useful info
  701. bool fIsAudioInterleaved;
  702. uint64_t fLastEventTime;
  703. // current device name
  704. CarlaString fDeviceName;
  705. // dummy rtmidi to scan available ports
  706. RtMidiIn fDummyMidiIn;
  707. RtMidiOut fDummyMidiOut;
  708. LinkedList<PortNameToId> fUsedMidiIns;
  709. LinkedList<PortNameToId> fUsedMidiOuts;
  710. struct MidiPort {
  711. RtMidi* rtmidi;
  712. int portId;
  713. };
  714. LinkedList<MidiPort> fMidiIns;
  715. LinkedList<MidiPort> fMidiOuts;
  716. struct RtMidiEvent {
  717. uint64_t time; // needs to compare to internal time
  718. uint8_t size;
  719. uint8_t data[EngineMidiEvent::kDataSize];
  720. };
  721. struct RtMidiEvents {
  722. CarlaMutex mutex;
  723. RtLinkedList<RtMidiEvent>::Pool dataPool;
  724. RtLinkedList<RtMidiEvent> data;
  725. RtLinkedList<RtMidiEvent> dataPending;
  726. RtMidiEvents()
  727. : dataPool(512, 512),
  728. data(dataPool),
  729. dataPending(dataPool) {}
  730. ~RtMidiEvents()
  731. {
  732. clear();
  733. }
  734. void append(const RtMidiEvent& event)
  735. {
  736. mutex.lock();
  737. dataPending.append(event);
  738. mutex.unlock();
  739. }
  740. void clear()
  741. {
  742. mutex.lock();
  743. data.clear();
  744. dataPending.clear();
  745. mutex.unlock();
  746. }
  747. void splice()
  748. {
  749. dataPending.spliceAppend(data);
  750. }
  751. };
  752. RtMidiEvents fMidiInEvents;
  753. //RtMidiEvents fMidiOutEvents;
  754. #define handlePtr ((CarlaEngineRtAudio*)userData)
  755. static int carla_rtaudio_process_callback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status, void* userData)
  756. {
  757. handlePtr->handleAudioProcessCallback(outputBuffer, inputBuffer, nframes, streamTime, status);
  758. return 0;
  759. }
  760. static void carla_rtmidi_callback(double timeStamp, std::vector<unsigned char>* message, void* userData)
  761. {
  762. handlePtr->handleMidiCallback(timeStamp, message);
  763. }
  764. #undef handlePtr
  765. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineRtAudio)
  766. };
  767. // -----------------------------------------
  768. CarlaEngine* CarlaEngine::newRtAudio(AudioApi api)
  769. {
  770. initRtApis();
  771. RtAudio::Api rtApi(RtAudio::UNSPECIFIED);
  772. switch (api)
  773. {
  774. case AUDIO_API_NULL:
  775. rtApi = RtAudio::RTAUDIO_DUMMY;
  776. break;
  777. case AUDIO_API_JACK:
  778. rtApi = RtAudio::UNIX_JACK;
  779. break;
  780. case AUDIO_API_ALSA:
  781. rtApi = RtAudio::LINUX_ALSA;
  782. break;
  783. case AUDIO_API_OSS:
  784. rtApi = RtAudio::LINUX_OSS;
  785. break;
  786. case AUDIO_API_PULSE:
  787. rtApi = RtAudio::LINUX_PULSE;
  788. break;
  789. case AUDIO_API_CORE:
  790. rtApi = RtAudio::MACOSX_CORE;
  791. break;
  792. case AUDIO_API_ASIO:
  793. rtApi = RtAudio::WINDOWS_ASIO;
  794. break;
  795. case AUDIO_API_DS:
  796. rtApi = RtAudio::WINDOWS_DS;
  797. break;
  798. }
  799. return new CarlaEngineRtAudio(rtApi);
  800. }
  801. unsigned int CarlaEngine::getRtAudioApiCount()
  802. {
  803. initRtApis();
  804. return static_cast<unsigned int>(gRtAudioApis.size());
  805. }
  806. const char* CarlaEngine::getRtAudioApiName(const unsigned int index)
  807. {
  808. initRtApis();
  809. if (index >= gRtAudioApis.size())
  810. return nullptr;
  811. return CarlaBackend::getRtAudioApiName(gRtAudioApis[index]);
  812. }
  813. const char* const* CarlaEngine::getRtAudioApiDeviceNames(const unsigned int index)
  814. {
  815. initRtApis();
  816. if (index >= gRtAudioApis.size())
  817. return nullptr;
  818. const RtAudio::Api& api(gRtAudioApis[index]);
  819. RtAudio rtAudio(api);
  820. const unsigned int devCount(rtAudio.getDeviceCount());
  821. if (devCount == 0)
  822. return nullptr;
  823. LinkedList<const char*> devNames;
  824. for (unsigned int i=0; i < devCount; ++i)
  825. {
  826. RtAudio::DeviceInfo devInfo(rtAudio.getDeviceInfo(i));
  827. if (devInfo.probed && devInfo.outputChannels > 0 /*&& (devInfo.nativeFormats & RTAUDIO_FLOAT32) != 0*/)
  828. devNames.append(carla_strdup(devInfo.name.c_str()));
  829. }
  830. const size_t realDevCount(devNames.count());
  831. if (gRetNames != nullptr)
  832. {
  833. for (int i=0; gRetNames[i] != nullptr; ++i)
  834. delete[] gRetNames[i];
  835. delete[] gRetNames;
  836. }
  837. gRetNames = new const char*[realDevCount+1];
  838. for (size_t i=0; i < realDevCount; ++i)
  839. gRetNames[i] = devNames.getAt(i);
  840. gRetNames[realDevCount] = nullptr;
  841. devNames.clear();
  842. return gRetNames;
  843. }
  844. const EngineDriverDeviceInfo* CarlaEngine::getRtAudioDeviceInfo(const unsigned int index, const char* const deviceName)
  845. {
  846. initRtApis();
  847. carla_stderr("here 000");
  848. if (index >= gRtAudioApis.size())
  849. {
  850. carla_stderr("here 001");
  851. return nullptr;
  852. }
  853. const RtAudio::Api& api(gRtAudioApis[index]);
  854. RtAudio rtAudio(api);
  855. const unsigned int devCount(rtAudio.getDeviceCount());
  856. if (devCount == 0)
  857. {
  858. carla_stderr("here 002");
  859. return nullptr;
  860. }
  861. unsigned int i;
  862. RtAudio::DeviceInfo rtAudioDevInfo;
  863. for (i=0; i < devCount; ++i)
  864. {
  865. rtAudioDevInfo = rtAudio.getDeviceInfo(i);
  866. if (rtAudioDevInfo.name == deviceName)
  867. break;
  868. }
  869. if (i == devCount)
  870. {
  871. carla_stderr("here 003");
  872. return nullptr;
  873. }
  874. static EngineDriverDeviceInfo devInfo = { 0x0, nullptr, nullptr };
  875. static uint32_t dummyBufferSizes[11] = { 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 0 };
  876. static double dummySampleRates[14] = { 22050.0, 32000.0, 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0, 0.0 };
  877. // reset
  878. devInfo.hints = 0x0;
  879. devInfo.bufferSizes = dummyBufferSizes;
  880. // cleanup
  881. if (devInfo.sampleRates != nullptr && devInfo.sampleRates != dummySampleRates)
  882. {
  883. delete[] devInfo.sampleRates;
  884. devInfo.sampleRates = nullptr;
  885. }
  886. if (size_t sampleRatesCount = rtAudioDevInfo.sampleRates.size())
  887. {
  888. double* const sampleRates(new double[sampleRatesCount+1]);
  889. for (size_t i=0; i < sampleRatesCount; ++i)
  890. sampleRates[i] = rtAudioDevInfo.sampleRates[i];
  891. sampleRates[sampleRatesCount] = 0.0;
  892. devInfo.sampleRates = sampleRates;
  893. }
  894. else
  895. {
  896. devInfo.sampleRates = dummySampleRates;
  897. }
  898. carla_stderr("here 004");
  899. return &devInfo;
  900. }
  901. // -----------------------------------------
  902. CARLA_BACKEND_END_NAMESPACE