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.

1157 lines
36KB

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