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.

1709 lines
67KB

  1. /*
  2. * Carla Plugin Host
  3. * Copyright (C) 2011-2022 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. #ifndef BUILD_BRIDGE
  18. # error This file should not be compiled if not building bridge
  19. #endif
  20. // must be first so we can undef CARLA_SAFE_*_RETURN_ERR* macros
  21. #include "CarlaPluginInternal.hpp"
  22. #undef CARLA_SAFE_ASSERT_RETURN_ERR
  23. #undef CARLA_SAFE_ASSERT_RETURN_ERRN
  24. #undef CARLA_SAFE_EXCEPTION_RETURN_ERR
  25. #undef CARLA_SAFE_EXCEPTION_RETURN_ERRN
  26. #include "CarlaEngineClient.hpp"
  27. #include "CarlaEngineInit.hpp"
  28. #include "CarlaBackendUtils.hpp"
  29. #include "CarlaBase64Utils.hpp"
  30. #include "CarlaBridgeUtils.hpp"
  31. #include "CarlaMIDI.h"
  32. #ifdef __SSE2_MATH__
  33. # include <xmmintrin.h>
  34. #endif
  35. #include "water/files/File.h"
  36. #include "water/misc/Time.h"
  37. // must be last
  38. #include "jackbridge/JackBridge.hpp"
  39. using water::File;
  40. using water::MemoryBlock;
  41. using water::String;
  42. using water::Time;
  43. CARLA_BACKEND_START_NAMESPACE
  44. // -----------------------------------------------------------------------
  45. // Bridge Engine client
  46. struct LatencyChangedCallback {
  47. virtual ~LatencyChangedCallback() noexcept {}
  48. virtual void latencyChanged(const uint32_t samples) noexcept = 0;
  49. };
  50. class CarlaEngineBridgeClient : public CarlaEngineClientForSubclassing
  51. {
  52. public:
  53. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  54. CarlaEngineBridgeClient(const CarlaEngine& engine,
  55. EngineInternalGraph& egraph,
  56. const CarlaPluginPtr plugin,
  57. LatencyChangedCallback* const cb)
  58. : CarlaEngineClientForSubclassing(engine, egraph, plugin),
  59. fLatencyCallback(cb) {}
  60. #else
  61. CarlaEngineBridgeClient(const CarlaEngine& engine, LatencyChangedCallback* const cb)
  62. : CarlaEngineClientForSubclassing(engine),
  63. fLatencyCallback(cb) {}
  64. #endif
  65. protected:
  66. void setLatency(const uint32_t samples) noexcept override
  67. {
  68. if (getLatency() == samples)
  69. return;
  70. fLatencyCallback->latencyChanged(samples);
  71. CarlaEngineClient::setLatency(samples);
  72. }
  73. private:
  74. LatencyChangedCallback* const fLatencyCallback;
  75. CARLA_DECLARE_NON_COPYABLE(CarlaEngineBridgeClient)
  76. };
  77. // -------------------------------------------------------------------
  78. struct BridgeTextReader {
  79. char* text;
  80. BridgeTextReader(BridgeNonRtClientControl& nonRtClientCtrl)
  81. : text(nullptr)
  82. {
  83. const uint32_t size = nonRtClientCtrl.readUInt();
  84. CARLA_SAFE_ASSERT_RETURN(size != 0,);
  85. text = new char[size + 1];
  86. nonRtClientCtrl.readCustomData(text, size);
  87. text[size] = '\0';
  88. }
  89. BridgeTextReader(BridgeNonRtClientControl& nonRtClientCtrl, const uint32_t size)
  90. : text(nullptr)
  91. {
  92. text = new char[size + 1];
  93. if (size != 0)
  94. nonRtClientCtrl.readCustomData(text, size);
  95. text[size] = '\0';
  96. }
  97. ~BridgeTextReader() noexcept
  98. {
  99. delete[] text;
  100. }
  101. CARLA_DECLARE_NON_COPYABLE(BridgeTextReader)
  102. };
  103. // -------------------------------------------------------------------
  104. class CarlaEngineBridge : public CarlaEngine,
  105. private CarlaThread,
  106. private LatencyChangedCallback
  107. {
  108. public:
  109. CarlaEngineBridge(const char* const audioPoolBaseName, const char* const rtClientBaseName, const char* const nonRtClientBaseName, const char* const nonRtServerBaseName)
  110. : CarlaEngine(),
  111. CarlaThread("CarlaEngineBridge"),
  112. fShmAudioPool(),
  113. fShmRtClientControl(),
  114. fShmNonRtClientControl(),
  115. fShmNonRtServerControl(),
  116. fBaseNameAudioPool(audioPoolBaseName),
  117. fBaseNameRtClientControl(rtClientBaseName),
  118. fBaseNameNonRtClientControl(nonRtClientBaseName),
  119. fBaseNameNonRtServerControl(nonRtServerBaseName),
  120. fClosingDown(false),
  121. fIsOffline(false),
  122. fFirstIdle(true),
  123. fLastPingTime(-1)
  124. {
  125. carla_debug("CarlaEngineBridge::CarlaEngineBridge(\"%s\", \"%s\", \"%s\", \"%s\")", audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName);
  126. }
  127. ~CarlaEngineBridge() noexcept override
  128. {
  129. carla_debug("CarlaEngineBridge::~CarlaEngineBridge()");
  130. clear();
  131. }
  132. // -------------------------------------
  133. // CarlaEngine virtual calls
  134. bool init(const char* const clientName) override
  135. {
  136. carla_debug("CarlaEngineBridge::init(\"%s\")", clientName);
  137. if (! pData->init(clientName))
  138. {
  139. setLastError("Failed to init internal data");
  140. return false;
  141. }
  142. if (! fShmAudioPool.attachClient(fBaseNameAudioPool))
  143. {
  144. pData->close();
  145. setLastError("Failed to attach to audio pool shared memory");
  146. return false;
  147. }
  148. if (! fShmRtClientControl.attachClient(fBaseNameRtClientControl))
  149. {
  150. pData->close();
  151. clear();
  152. setLastError("Failed to attach to rt client control shared memory");
  153. return false;
  154. }
  155. if (! fShmRtClientControl.mapData())
  156. {
  157. pData->close();
  158. clear();
  159. setLastError("Failed to map rt client control shared memory");
  160. return false;
  161. }
  162. if (! fShmNonRtClientControl.attachClient(fBaseNameNonRtClientControl))
  163. {
  164. pData->close();
  165. clear();
  166. setLastError("Failed to attach to non-rt client control shared memory");
  167. return false;
  168. }
  169. if (! fShmNonRtClientControl.mapData())
  170. {
  171. pData->close();
  172. clear();
  173. setLastError("Failed to map non-rt control client shared memory");
  174. return false;
  175. }
  176. if (! fShmNonRtServerControl.attachClient(fBaseNameNonRtServerControl))
  177. {
  178. pData->close();
  179. clear();
  180. setLastError("Failed to attach to non-rt server control shared memory");
  181. return false;
  182. }
  183. if (! fShmNonRtServerControl.mapData())
  184. {
  185. pData->close();
  186. clear();
  187. setLastError("Failed to map non-rt control server shared memory");
  188. return false;
  189. }
  190. PluginBridgeNonRtClientOpcode opcode;
  191. opcode = fShmNonRtClientControl.readOpcode();
  192. CARLA_SAFE_ASSERT_RETURN(opcode == kPluginBridgeNonRtClientVersion, false);
  193. const uint32_t apiVersion = fShmNonRtClientControl.readUInt();
  194. CARLA_SAFE_ASSERT_RETURN(apiVersion >= CARLA_PLUGIN_BRIDGE_API_VERSION_MINIMUM, false);
  195. const uint32_t shmRtClientDataSize = fShmNonRtClientControl.readUInt();
  196. CARLA_SAFE_ASSERT_INT2(shmRtClientDataSize == sizeof(BridgeRtClientData), shmRtClientDataSize, sizeof(BridgeRtClientData));
  197. const uint32_t shmNonRtClientDataSize = fShmNonRtClientControl.readUInt();
  198. CARLA_SAFE_ASSERT_INT2(shmNonRtClientDataSize == sizeof(BridgeNonRtClientData), shmNonRtClientDataSize, sizeof(BridgeNonRtClientData));
  199. const uint32_t shmNonRtServerDataSize = fShmNonRtClientControl.readUInt();
  200. CARLA_SAFE_ASSERT_INT2(shmNonRtServerDataSize == sizeof(BridgeNonRtServerData), shmNonRtServerDataSize, sizeof(BridgeNonRtServerData));
  201. if (shmRtClientDataSize != sizeof(BridgeRtClientData) ||
  202. shmNonRtClientDataSize != sizeof(BridgeNonRtClientData) ||
  203. shmNonRtServerDataSize != sizeof(BridgeNonRtServerData))
  204. {
  205. pData->close();
  206. clear();
  207. setLastError("Shared memory data size mismatch");
  208. return false;
  209. }
  210. opcode = fShmNonRtClientControl.readOpcode();
  211. CARLA_SAFE_ASSERT_RETURN(opcode == kPluginBridgeNonRtClientInitialSetup, false);
  212. pData->bufferSize = fShmNonRtClientControl.readUInt();
  213. pData->sampleRate = fShmNonRtClientControl.readDouble();
  214. if (pData->bufferSize == 0 || carla_isZero(pData->sampleRate))
  215. {
  216. pData->close();
  217. clear();
  218. setLastError("Shared memory has invalid data");
  219. return false;
  220. }
  221. pData->initTime(nullptr);
  222. // tell backend we're live
  223. {
  224. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  225. // kPluginBridgeNonRtServerVersion was added in API 7
  226. if (apiVersion >= 7)
  227. {
  228. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerVersion);
  229. fShmNonRtServerControl.writeUInt(CARLA_PLUGIN_BRIDGE_API_VERSION_CURRENT);
  230. }
  231. else
  232. {
  233. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPong);
  234. }
  235. fShmNonRtServerControl.commitWrite();
  236. }
  237. startThread(true);
  238. return true;
  239. }
  240. bool close() override
  241. {
  242. carla_debug("CarlaEngineBridge::close()");
  243. fLastPingTime = -1;
  244. CarlaEngine::close();
  245. stopThread(5000);
  246. clear();
  247. return true;
  248. }
  249. bool hasIdleOnMainThread() const noexcept override
  250. {
  251. return true;
  252. }
  253. bool isRunning() const noexcept override
  254. {
  255. if (fClosingDown)
  256. return false;
  257. return isThreadRunning() || ! fFirstIdle;
  258. }
  259. bool isOffline() const noexcept override
  260. {
  261. return fIsOffline;
  262. }
  263. EngineType getType() const noexcept override
  264. {
  265. return kEngineTypeBridge;
  266. }
  267. const char* getCurrentDriverName() const noexcept override
  268. {
  269. return "Bridge";
  270. }
  271. void touchPluginParameter(const uint id, const uint32_t parameterId, const bool touch) noexcept override
  272. {
  273. CARLA_SAFE_ASSERT_RETURN(id == 0,);
  274. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  275. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterTouch);
  276. fShmNonRtServerControl.writeUInt(parameterId);
  277. fShmNonRtServerControl.writeBool(touch);
  278. fShmNonRtServerControl.commitWrite();
  279. }
  280. CarlaEngineClient* addClient(const CarlaPluginPtr plugin) override
  281. {
  282. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  283. return new CarlaEngineBridgeClient(*this, pData->graph, plugin, this);
  284. #else
  285. return new CarlaEngineBridgeClient(*this, this);
  286. // unused
  287. (void)plugin;
  288. #endif
  289. }
  290. void idle() noexcept override
  291. {
  292. const CarlaPluginPtr plugin = pData->plugins[0].plugin;
  293. if (plugin.get() == nullptr)
  294. {
  295. if (const uint32_t length = static_cast<uint32_t>(pData->lastError.length()))
  296. {
  297. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  298. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerError);
  299. fShmNonRtServerControl.writeUInt(length);
  300. fShmNonRtServerControl.writeCustomData(pData->lastError.buffer(), length);
  301. fShmNonRtServerControl.commitWrite();
  302. }
  303. signalThreadShouldExit();
  304. callback(true, true, ENGINE_CALLBACK_QUIT, 0, 0, 0, 0, 0.0f, nullptr);
  305. return;
  306. }
  307. const bool wasFirstIdle(fFirstIdle);
  308. if (wasFirstIdle)
  309. {
  310. fFirstIdle = false;
  311. fLastPingTime = Time::currentTimeMillis();
  312. CARLA_SAFE_ASSERT(fLastPingTime > 0);
  313. char bufStr[STR_MAX+1];
  314. carla_zeroChars(bufStr, STR_MAX+1);
  315. uint32_t bufStrSize;
  316. const CarlaEngineClient* const client(plugin->getEngineClient());
  317. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  318. // kPluginBridgeNonRtServerPluginInfo1
  319. {
  320. // uint/category, uint/hints, uint/optionsAvailable, uint/optionsEnabled, long/uniqueId
  321. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPluginInfo1);
  322. fShmNonRtServerControl.writeUInt(plugin->getCategory());
  323. fShmNonRtServerControl.writeUInt(plugin->getHints());
  324. fShmNonRtServerControl.writeUInt(plugin->getOptionsAvailable());
  325. fShmNonRtServerControl.writeUInt(plugin->getOptionsEnabled());
  326. fShmNonRtServerControl.writeLong(plugin->getUniqueId());
  327. fShmNonRtServerControl.commitWrite();
  328. }
  329. // kPluginBridgeNonRtServerPluginInfo2
  330. {
  331. // uint/size, str[] (realName), uint/size, str[] (label), uint/size, str[] (maker), uint/size, str[] (copyright)
  332. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPluginInfo2);
  333. if (! plugin->getRealName(bufStr))
  334. bufStr[0] = '\0';
  335. bufStrSize = carla_fixedValue(1U, 64U, static_cast<uint32_t>(std::strlen(bufStr)));
  336. fShmNonRtServerControl.writeUInt(bufStrSize);
  337. fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);
  338. if (! plugin->getLabel(bufStr))
  339. bufStr[0] = '\0';
  340. bufStrSize = carla_fixedValue(1U, 256U, static_cast<uint32_t>(std::strlen(bufStr)));
  341. fShmNonRtServerControl.writeUInt(bufStrSize);
  342. fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);
  343. if (! plugin->getMaker(bufStr))
  344. bufStr[0] = '\0';
  345. bufStrSize = carla_fixedValue(1U, 64U, static_cast<uint32_t>(std::strlen(bufStr)));
  346. fShmNonRtServerControl.writeUInt(bufStrSize);
  347. fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);
  348. if (! plugin->getCopyright(bufStr))
  349. bufStr[0] = '\0';
  350. bufStrSize = carla_fixedValue(1U, 64U, static_cast<uint32_t>(std::strlen(bufStr)));
  351. fShmNonRtServerControl.writeUInt(bufStrSize);
  352. fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);
  353. fShmNonRtServerControl.commitWrite();
  354. }
  355. // kPluginBridgeNonRtServerAudioCount
  356. {
  357. const uint32_t aIns = plugin->getAudioInCount();
  358. const uint32_t aOuts = plugin->getAudioOutCount();
  359. // uint/ins, uint/outs
  360. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerAudioCount);
  361. fShmNonRtServerControl.writeUInt(aIns);
  362. fShmNonRtServerControl.writeUInt(aOuts);
  363. fShmNonRtServerControl.commitWrite();
  364. // kPluginBridgeNonRtServerPortName
  365. for (uint32_t i=0; i<aIns; ++i)
  366. {
  367. const char* const portName(client->getAudioPortName(true, i));
  368. CARLA_SAFE_ASSERT_CONTINUE(portName != nullptr && portName[0] != '\0');
  369. // byte/type, uint/index, uint/size, str[] (name)
  370. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPortName);
  371. fShmNonRtServerControl.writeByte(kPluginBridgePortAudioInput);
  372. fShmNonRtServerControl.writeUInt(i);
  373. bufStrSize = static_cast<uint32_t>(std::strlen(portName));
  374. fShmNonRtServerControl.writeUInt(bufStrSize);
  375. fShmNonRtServerControl.writeCustomData(portName, bufStrSize);
  376. }
  377. // kPluginBridgeNonRtServerPortName
  378. for (uint32_t i=0; i<aOuts; ++i)
  379. {
  380. const char* const portName(client->getAudioPortName(false, i));
  381. CARLA_SAFE_ASSERT_CONTINUE(portName != nullptr && portName[0] != '\0');
  382. // byte/type, uint/index, uint/size, str[] (name)
  383. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPortName);
  384. fShmNonRtServerControl.writeByte(kPluginBridgePortAudioOutput);
  385. fShmNonRtServerControl.writeUInt(i);
  386. bufStrSize = static_cast<uint32_t>(std::strlen(portName));
  387. fShmNonRtServerControl.writeUInt(bufStrSize);
  388. fShmNonRtServerControl.writeCustomData(portName, bufStrSize);
  389. }
  390. }
  391. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  392. // kPluginBridgeNonRtServerMidiCount
  393. {
  394. // uint/ins, uint/outs
  395. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerMidiCount);
  396. fShmNonRtServerControl.writeUInt(plugin->getMidiInCount());
  397. fShmNonRtServerControl.writeUInt(plugin->getMidiOutCount());
  398. fShmNonRtServerControl.commitWrite();
  399. }
  400. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  401. // kPluginBridgeNonRtServerCvCount
  402. {
  403. // uint/ins, uint/outs
  404. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerCvCount);
  405. fShmNonRtServerControl.writeUInt(plugin->getCVInCount());
  406. fShmNonRtServerControl.writeUInt(plugin->getCVOutCount());
  407. fShmNonRtServerControl.commitWrite();
  408. }
  409. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  410. // kPluginBridgeNonRtServerParameter*
  411. if (const uint32_t count = plugin->getParameterCount())
  412. {
  413. // uint/count
  414. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterCount);
  415. fShmNonRtServerControl.writeUInt(count);
  416. fShmNonRtServerControl.commitWrite();
  417. for (uint32_t i=0; i<count; ++i)
  418. {
  419. const ParameterData& paramData(plugin->getParameterData(i));
  420. if (paramData.type != PARAMETER_INPUT && paramData.type != PARAMETER_OUTPUT)
  421. continue;
  422. if ((paramData.hints & PARAMETER_IS_ENABLED) == 0)
  423. continue;
  424. // kPluginBridgeNonRtServerParameterData1
  425. {
  426. // uint/index, int/rindex, uint/type, uint/hints, short/cc
  427. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterData1);
  428. fShmNonRtServerControl.writeUInt(i);
  429. fShmNonRtServerControl.writeInt(paramData.rindex);
  430. fShmNonRtServerControl.writeUInt(paramData.type);
  431. fShmNonRtServerControl.writeUInt(paramData.hints);
  432. fShmNonRtServerControl.writeShort(paramData.mappedControlIndex);
  433. fShmNonRtServerControl.commitWrite();
  434. }
  435. // kPluginBridgeNonRtServerParameterData2
  436. {
  437. // uint/index, uint/size, str[] (name), uint/size, str[] (symbol), uint/size, str[] (unit)
  438. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterData2);
  439. fShmNonRtServerControl.writeUInt(i);
  440. if (! plugin->getParameterName(i, bufStr))
  441. std::snprintf(bufStr, STR_MAX, "Param %u", i+1);
  442. bufStrSize = carla_fixedValue(1U, 32U, static_cast<uint32_t>(std::strlen(bufStr)));
  443. fShmNonRtServerControl.writeUInt(bufStrSize);
  444. fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);
  445. if (! plugin->getParameterSymbol(i, bufStr))
  446. bufStr[0] = '\0';
  447. bufStrSize = carla_fixedValue(1U, 64U, static_cast<uint32_t>(std::strlen(bufStr)));
  448. fShmNonRtServerControl.writeUInt(bufStrSize);
  449. fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);
  450. if (! plugin->getParameterUnit(i, bufStr))
  451. bufStr[0] = '\0';
  452. bufStrSize = carla_fixedValue(1U, 32U, static_cast<uint32_t>(std::strlen(bufStr)));
  453. fShmNonRtServerControl.writeUInt(bufStrSize);
  454. fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);
  455. fShmNonRtServerControl.commitWrite();
  456. }
  457. // kPluginBridgeNonRtServerParameterRanges
  458. {
  459. const ParameterRanges& paramRanges(plugin->getParameterRanges(i));
  460. // uint/index, float/def, float/min, float/max, float/step, float/stepSmall, float/stepLarge
  461. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterRanges);
  462. fShmNonRtServerControl.writeUInt(i);
  463. fShmNonRtServerControl.writeFloat(paramRanges.def);
  464. fShmNonRtServerControl.writeFloat(paramRanges.min);
  465. fShmNonRtServerControl.writeFloat(paramRanges.max);
  466. fShmNonRtServerControl.writeFloat(paramRanges.step);
  467. fShmNonRtServerControl.writeFloat(paramRanges.stepSmall);
  468. fShmNonRtServerControl.writeFloat(paramRanges.stepLarge);
  469. fShmNonRtServerControl.commitWrite();
  470. }
  471. // kPluginBridgeNonRtServerParameterValue2
  472. {
  473. // uint/index float/value (used for init/output parameters only, don't resend values)
  474. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterValue2);
  475. fShmNonRtServerControl.writeUInt(i);
  476. fShmNonRtServerControl.writeFloat(plugin->getParameterValue(i));
  477. fShmNonRtServerControl.commitWrite();
  478. }
  479. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  480. }
  481. }
  482. // kPluginBridgeNonRtServerProgram*
  483. if (const uint32_t count = plugin->getProgramCount())
  484. {
  485. // uint/count
  486. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerProgramCount);
  487. fShmNonRtServerControl.writeUInt(count);
  488. fShmNonRtServerControl.commitWrite();
  489. for (uint32_t i=0; i < count; ++i)
  490. {
  491. // uint/index, uint/size, str[] (name)
  492. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerProgramName);
  493. fShmNonRtServerControl.writeUInt(i);
  494. if (! plugin->getProgramName(i, bufStr))
  495. bufStr[0] = '\0';
  496. bufStrSize = carla_fixedValue(1U, 32U, static_cast<uint32_t>(std::strlen(bufStr)));
  497. fShmNonRtServerControl.writeUInt(bufStrSize);
  498. fShmNonRtServerControl.writeCustomData(bufStr, bufStrSize);
  499. fShmNonRtServerControl.commitWrite();
  500. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  501. }
  502. }
  503. // kPluginBridgeNonRtServerMidiProgram*
  504. if (const uint32_t count = plugin->getMidiProgramCount())
  505. {
  506. // uint/count
  507. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerMidiProgramCount);
  508. fShmNonRtServerControl.writeUInt(count);
  509. fShmNonRtServerControl.commitWrite();
  510. for (uint32_t i=0; i < count; ++i)
  511. {
  512. const MidiProgramData& mpData(plugin->getMidiProgramData(i));
  513. CARLA_SAFE_ASSERT_CONTINUE(mpData.name != nullptr);
  514. // uint/index, uint/bank, uint/program, uint/size, str[] (name)
  515. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerMidiProgramData);
  516. fShmNonRtServerControl.writeUInt(i);
  517. fShmNonRtServerControl.writeUInt(mpData.bank);
  518. fShmNonRtServerControl.writeUInt(mpData.program);
  519. bufStrSize = carla_fixedValue(1U, 32U, static_cast<uint32_t>(std::strlen(mpData.name)));
  520. fShmNonRtServerControl.writeUInt(bufStrSize);
  521. fShmNonRtServerControl.writeCustomData(mpData.name, bufStrSize);
  522. fShmNonRtServerControl.commitWrite();
  523. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  524. }
  525. }
  526. if (const uint32_t latency = plugin->getLatencyInFrames())
  527. {
  528. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSetLatency);
  529. fShmNonRtServerControl.writeUInt(latency);
  530. fShmNonRtServerControl.commitWrite();
  531. }
  532. // ready!
  533. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerReady);
  534. fShmNonRtServerControl.commitWrite();
  535. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  536. carla_stdout("Carla Bridge Ready!");
  537. fLastPingTime = Time::currentTimeMillis();
  538. }
  539. // send parameter outputs
  540. if (const uint32_t count = plugin->getParameterCount())
  541. {
  542. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  543. for (uint32_t i=0; i < count; ++i)
  544. {
  545. if (! plugin->isParameterOutput(i))
  546. continue;
  547. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterValue2);
  548. fShmNonRtServerControl.writeUInt(i);
  549. fShmNonRtServerControl.writeFloat(plugin->getParameterValue(i));
  550. // parameter outputs are not that important, we can skip some
  551. if (! fShmNonRtServerControl.commitWrite())
  552. break;
  553. }
  554. }
  555. CarlaEngine::idle();
  556. try {
  557. handleNonRtData();
  558. } CARLA_SAFE_EXCEPTION("handleNonRtData");
  559. if (fLastPingTime > 0 && Time::currentTimeMillis() > fLastPingTime + 30000 && ! wasFirstIdle)
  560. {
  561. carla_stderr("Did not receive ping message from server for 30 secs, closing...");
  562. signalThreadShouldExit();
  563. callback(true, true, ENGINE_CALLBACK_QUIT, 0, 0, 0, 0, 0.0f, nullptr);
  564. }
  565. }
  566. void callback(const bool sendHost, const bool sendOsc,
  567. const EngineCallbackOpcode action, const uint pluginId,
  568. const int value1, const int value2, const int value3,
  569. const float valuef, const char* const valueStr) noexcept override
  570. {
  571. CarlaEngine::callback(sendHost, sendOsc, action, pluginId, value1, value2, value3, valuef, valueStr);
  572. if (fClosingDown || ! sendHost)
  573. return;
  574. switch (action)
  575. {
  576. // uint/index float/value
  577. case ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED: {
  578. CARLA_SAFE_ASSERT_BREAK(value1 >= 0);
  579. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  580. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterValue);
  581. fShmNonRtServerControl.writeUInt(static_cast<uint>(value1));
  582. fShmNonRtServerControl.writeFloat(valuef);
  583. fShmNonRtServerControl.commitWrite();
  584. } break;
  585. // uint/index float/value
  586. case ENGINE_CALLBACK_PARAMETER_DEFAULT_CHANGED: {
  587. CARLA_SAFE_ASSERT_BREAK(value1 >= 0);
  588. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  589. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerDefaultValue);
  590. fShmNonRtServerControl.writeUInt(static_cast<uint>(value1));
  591. fShmNonRtServerControl.writeFloat(valuef);
  592. fShmNonRtServerControl.commitWrite();
  593. } break;
  594. // int/index
  595. case ENGINE_CALLBACK_PROGRAM_CHANGED: {
  596. CARLA_SAFE_ASSERT_BREAK(value1 >= -1);
  597. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  598. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerCurrentProgram);
  599. fShmNonRtServerControl.writeInt(value1);
  600. fShmNonRtServerControl.commitWrite();
  601. } break;
  602. // int/index
  603. case ENGINE_CALLBACK_MIDI_PROGRAM_CHANGED: {
  604. CARLA_SAFE_ASSERT_BREAK(value1 >= -1);
  605. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  606. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerCurrentMidiProgram);
  607. fShmNonRtServerControl.writeInt(value1);
  608. fShmNonRtServerControl.commitWrite();
  609. } break;
  610. case ENGINE_CALLBACK_UI_STATE_CHANGED:
  611. if (value1 != 1)
  612. {
  613. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  614. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerUiClosed);
  615. fShmNonRtServerControl.commitWrite();
  616. }
  617. break;
  618. case ENGINE_CALLBACK_EMBED_UI_RESIZED: {
  619. CARLA_SAFE_ASSERT_BREAK(value1 > 1);
  620. CARLA_SAFE_ASSERT_BREAK(value2 > 1);
  621. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  622. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerResizeEmbedUI);
  623. fShmNonRtServerControl.writeUInt(static_cast<uint>(value1));
  624. fShmNonRtServerControl.writeUInt(static_cast<uint>(value2));
  625. fShmNonRtServerControl.commitWrite();
  626. } break;
  627. case ENGINE_CALLBACK_RELOAD_PARAMETERS:
  628. if (const CarlaPluginPtr plugin = pData->plugins[0].plugin)
  629. {
  630. if (const uint32_t count = plugin->getParameterCount())
  631. {
  632. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  633. for (uint32_t i=0; i<count; ++i)
  634. {
  635. const ParameterData& paramData(plugin->getParameterData(i));
  636. if (paramData.type != PARAMETER_INPUT && paramData.type != PARAMETER_OUTPUT)
  637. continue;
  638. if ((paramData.hints & PARAMETER_IS_ENABLED) == 0)
  639. continue;
  640. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerParameterValue);
  641. fShmNonRtServerControl.writeUInt(i);
  642. fShmNonRtServerControl.writeFloat(plugin->getParameterValue(i));
  643. fShmNonRtServerControl.commitWrite();
  644. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  645. }
  646. }
  647. }
  648. break;
  649. default:
  650. break;
  651. }
  652. }
  653. // -------------------------------------------------------------------
  654. void clear() noexcept
  655. {
  656. fShmAudioPool.clear();
  657. fShmRtClientControl.clear();
  658. fShmNonRtClientControl.clear();
  659. fShmNonRtServerControl.clear();
  660. }
  661. void handleNonRtData()
  662. {
  663. const CarlaPluginPtr plugin = pData->plugins[0].plugin;
  664. CARLA_SAFE_ASSERT_RETURN(plugin.get() != nullptr,);
  665. for (; fShmNonRtClientControl.isDataAvailableForReading();)
  666. {
  667. const PluginBridgeNonRtClientOpcode opcode = fShmNonRtClientControl.readOpcode();
  668. #ifdef DEBUG
  669. if (opcode != kPluginBridgeNonRtClientPing) {
  670. carla_debug("CarlaEngineBridge::handleNonRtData() - got opcode: %i:%s",
  671. opcode, PluginBridgeNonRtClientOpcode2str(opcode));
  672. }
  673. #endif
  674. if (opcode != kPluginBridgeNonRtClientNull && opcode != kPluginBridgeNonRtClientPingOnOff && fLastPingTime > 0)
  675. fLastPingTime = Time::currentTimeMillis();
  676. switch (opcode)
  677. {
  678. case kPluginBridgeNonRtClientNull:
  679. break;
  680. case kPluginBridgeNonRtClientVersion: {
  681. const uint apiVersion = fShmNonRtServerControl.readUInt();
  682. CARLA_SAFE_ASSERT_UINT2(apiVersion >= CARLA_PLUGIN_BRIDGE_API_VERSION_MINIMUM,
  683. apiVersion, CARLA_PLUGIN_BRIDGE_API_VERSION_MINIMUM);
  684. } break;
  685. case kPluginBridgeNonRtClientPing: {
  686. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  687. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPong);
  688. fShmNonRtServerControl.commitWrite();
  689. } break;
  690. case kPluginBridgeNonRtClientPingOnOff: {
  691. const uint32_t onOff(fShmNonRtClientControl.readBool());
  692. fLastPingTime = onOff ? Time::currentTimeMillis() : -1;
  693. } break;
  694. case kPluginBridgeNonRtClientActivate:
  695. if (plugin->isEnabled())
  696. plugin->setActive(true, false, false);
  697. break;
  698. case kPluginBridgeNonRtClientDeactivate:
  699. if (plugin->isEnabled())
  700. plugin->setActive(false, false, false);
  701. break;
  702. case kPluginBridgeNonRtClientInitialSetup:
  703. // should never happen!!
  704. fShmNonRtServerControl.readUInt();
  705. fShmNonRtServerControl.readDouble();
  706. break;
  707. case kPluginBridgeNonRtClientSetParameterValue: {
  708. const uint32_t index(fShmNonRtClientControl.readUInt());
  709. const float value(fShmNonRtClientControl.readFloat());
  710. if (plugin->isEnabled())
  711. plugin->setParameterValue(index, value, false, false, false);
  712. break;
  713. }
  714. case kPluginBridgeNonRtClientSetParameterMidiChannel: {
  715. const uint32_t index(fShmNonRtClientControl.readUInt());
  716. const uint8_t channel(fShmNonRtClientControl.readByte());
  717. if (plugin->isEnabled())
  718. plugin->setParameterMidiChannel(index, channel, false, false);
  719. break;
  720. }
  721. case kPluginBridgeNonRtClientSetParameterMappedControlIndex: {
  722. const uint32_t index(fShmNonRtClientControl.readUInt());
  723. const int16_t ctrl(fShmNonRtClientControl.readShort());
  724. if (plugin->isEnabled())
  725. plugin->setParameterMappedControlIndex(index, ctrl, false, false, true);
  726. break;
  727. }
  728. case kPluginBridgeNonRtClientSetParameterMappedRange: {
  729. const uint32_t index = fShmNonRtClientControl.readUInt();
  730. const float minimum = fShmNonRtClientControl.readFloat();
  731. const float maximum = fShmNonRtClientControl.readFloat();
  732. if (plugin->isEnabled())
  733. plugin->setParameterMappedRange(index, minimum, maximum, false, false);
  734. break;
  735. }
  736. case kPluginBridgeNonRtClientSetProgram: {
  737. const int32_t index(fShmNonRtClientControl.readInt());
  738. if (plugin->isEnabled())
  739. plugin->setProgram(index, true, false, false);
  740. break;
  741. }
  742. case kPluginBridgeNonRtClientSetMidiProgram: {
  743. const int32_t index(fShmNonRtClientControl.readInt());
  744. if (plugin->isEnabled())
  745. plugin->setMidiProgram(index, true, false, false);
  746. break;
  747. }
  748. case kPluginBridgeNonRtClientSetCustomData: {
  749. // type
  750. const BridgeTextReader type(fShmNonRtClientControl);
  751. // key
  752. const BridgeTextReader key(fShmNonRtClientControl);
  753. // value
  754. const uint32_t valueSize = fShmNonRtClientControl.readUInt();
  755. if (valueSize > 0)
  756. {
  757. if (valueSize > 16384)
  758. {
  759. const BridgeTextReader bigValueFilePathTry(fShmNonRtClientControl, valueSize);
  760. CARLA_SAFE_ASSERT_BREAK(bigValueFilePathTry.text[0] != '\0');
  761. if (! plugin->isEnabled()) break;
  762. String bigValueFilePath(bigValueFilePathTry.text);
  763. #ifdef CARLA_OS_WIN
  764. // check if running under Wine
  765. if (bigValueFilePath.startsWith("/"))
  766. bigValueFilePath = bigValueFilePath.replaceSection(0, 1, "Z:\\").replace("/", "\\");
  767. #endif
  768. File bigValueFile(bigValueFilePath);
  769. CARLA_SAFE_ASSERT_BREAK(bigValueFile.existsAsFile());
  770. plugin->setCustomData(type.text, key.text, bigValueFile.loadFileAsString().toRawUTF8(), true);
  771. bigValueFile.deleteFile();
  772. }
  773. else
  774. {
  775. const BridgeTextReader value(fShmNonRtClientControl, valueSize);
  776. if (plugin->isEnabled())
  777. plugin->setCustomData(type.text, key.text, value.text, true);
  778. }
  779. }
  780. else
  781. {
  782. if (plugin->isEnabled())
  783. plugin->setCustomData(type.text, key.text, "", true);
  784. }
  785. break;
  786. }
  787. case kPluginBridgeNonRtClientSetChunkDataFile: {
  788. const uint32_t size = fShmNonRtClientControl.readUInt();
  789. CARLA_SAFE_ASSERT_BREAK(size > 0);
  790. const BridgeTextReader chunkFilePathTry(fShmNonRtClientControl, size);
  791. CARLA_SAFE_ASSERT_BREAK(chunkFilePathTry.text[0] != '\0');
  792. if (! plugin->isEnabled()) break;
  793. String chunkFilePath(chunkFilePathTry.text);
  794. #ifdef CARLA_OS_WIN
  795. // check if running under Wine
  796. if (chunkFilePath.startsWith("/"))
  797. chunkFilePath = chunkFilePath.replaceSection(0, 1, "Z:\\").replace("/", "\\");
  798. #endif
  799. File chunkFile(chunkFilePath);
  800. CARLA_SAFE_ASSERT_BREAK(chunkFile.existsAsFile());
  801. String chunkDataBase64(chunkFile.loadFileAsString());
  802. chunkFile.deleteFile();
  803. CARLA_SAFE_ASSERT_BREAK(chunkDataBase64.isNotEmpty());
  804. std::vector<uint8_t> chunk(carla_getChunkFromBase64String(chunkDataBase64.toRawUTF8()));
  805. #ifdef CARLA_PROPER_CPP11_SUPPORT
  806. plugin->setChunkData(chunk.data(), chunk.size());
  807. #else
  808. plugin->setChunkData(&chunk.front(), chunk.size());
  809. #endif
  810. break;
  811. }
  812. case kPluginBridgeNonRtClientSetCtrlChannel: {
  813. const int16_t channel(fShmNonRtClientControl.readShort());
  814. CARLA_SAFE_ASSERT_BREAK(channel >= -1 && channel < MAX_MIDI_CHANNELS);
  815. if (plugin->isEnabled())
  816. plugin->setCtrlChannel(static_cast<int8_t>(channel), false, false);
  817. break;
  818. }
  819. case kPluginBridgeNonRtClientSetOption: {
  820. const uint32_t option(fShmNonRtClientControl.readUInt());
  821. const bool yesNo(fShmNonRtClientControl.readBool());
  822. if (plugin->isEnabled())
  823. plugin->setOption(option, yesNo, false);
  824. break;
  825. }
  826. case kPluginBridgeNonRtClientSetOptions: {
  827. const uint32_t options(fShmNonRtClientControl.readUInt());
  828. plugin->pData->options = options;
  829. break;
  830. }
  831. case kPluginBridgeNonRtClientSetWindowTitle: {
  832. const BridgeTextReader title(fShmNonRtClientControl);
  833. plugin->setCustomUITitle(title.text);
  834. break;
  835. }
  836. case kPluginBridgeNonRtClientGetParameterText: {
  837. const int32_t index = fShmNonRtClientControl.readInt();
  838. if (index >= 0 && plugin->isEnabled())
  839. {
  840. char bufStr[STR_MAX+1];
  841. carla_zeroChars(bufStr, STR_MAX+1);
  842. if (! plugin->getParameterText(static_cast<uint32_t>(index), bufStr))
  843. bufStr[0] = '\0';
  844. const uint32_t bufStrLen = static_cast<uint32_t>(std::strlen(bufStr));
  845. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  846. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSetParameterText);
  847. fShmNonRtServerControl.writeInt(index);
  848. fShmNonRtServerControl.writeUInt(bufStrLen);
  849. fShmNonRtServerControl.writeCustomData(bufStr, bufStrLen);
  850. fShmNonRtServerControl.commitWrite();
  851. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  852. }
  853. else
  854. {
  855. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  856. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSetParameterText);
  857. fShmNonRtServerControl.writeInt(index);
  858. fShmNonRtServerControl.writeUInt(0);
  859. fShmNonRtServerControl.commitWrite();
  860. }
  861. break;
  862. }
  863. case kPluginBridgeNonRtClientPrepareForSave: {
  864. if (! plugin->isEnabled())
  865. {
  866. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  867. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSaved);
  868. fShmNonRtServerControl.commitWrite();
  869. return;
  870. }
  871. plugin->prepareForSave(false);
  872. for (uint32_t i=0, count=plugin->getCustomDataCount(); i<count; ++i)
  873. {
  874. const CustomData& cdata(plugin->getCustomData(i));
  875. if (std::strcmp(cdata.type, CUSTOM_DATA_TYPE_PROPERTY) == 0)
  876. continue;
  877. const uint32_t typeLen = static_cast<uint32_t>(std::strlen(cdata.type));
  878. const uint32_t keyLen = static_cast<uint32_t>(std::strlen(cdata.key));
  879. const uint32_t valueLen = static_cast<uint32_t>(std::strlen(cdata.value));
  880. if (valueLen > 16384)
  881. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  882. {
  883. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  884. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSetCustomData);
  885. fShmNonRtServerControl.writeUInt(typeLen);
  886. fShmNonRtServerControl.writeCustomData(cdata.type, typeLen);
  887. fShmNonRtServerControl.writeUInt(keyLen);
  888. fShmNonRtServerControl.writeCustomData(cdata.key, keyLen);
  889. fShmNonRtServerControl.writeUInt(valueLen);
  890. if (valueLen > 0)
  891. {
  892. if (valueLen > 16384)
  893. {
  894. String filePath(File::getSpecialLocation(File::tempDirectory).getFullPathName());
  895. filePath += CARLA_OS_SEP_STR ".CarlaCustomData_";
  896. filePath += fShmAudioPool.getFilenameSuffix();
  897. if (File(filePath).replaceWithText(cdata.value))
  898. {
  899. const uint32_t ulength(static_cast<uint32_t>(filePath.length()));
  900. fShmNonRtServerControl.writeUInt(ulength);
  901. fShmNonRtServerControl.writeCustomData(filePath.toRawUTF8(), ulength);
  902. }
  903. else
  904. {
  905. fShmNonRtServerControl.writeUInt(0);
  906. }
  907. }
  908. else
  909. {
  910. fShmNonRtServerControl.writeCustomData(cdata.value, valueLen);
  911. }
  912. }
  913. fShmNonRtServerControl.commitWrite();
  914. }
  915. fShmNonRtServerControl.waitIfDataIsReachingLimit();
  916. }
  917. if (plugin->getOptionsEnabled() & PLUGIN_OPTION_USE_CHUNKS)
  918. {
  919. void* data = nullptr;
  920. if (const std::size_t dataSize = plugin->getChunkData(&data))
  921. {
  922. CARLA_SAFE_ASSERT_BREAK(data != nullptr);
  923. CarlaString dataBase64 = CarlaString::asBase64(data, dataSize);
  924. CARLA_SAFE_ASSERT_BREAK(dataBase64.length() > 0);
  925. String filePath(File::getSpecialLocation(File::tempDirectory).getFullPathName());
  926. filePath += CARLA_OS_SEP_STR ".CarlaChunk_";
  927. filePath += fShmAudioPool.getFilenameSuffix();
  928. if (File(filePath).replaceWithText(dataBase64.buffer()))
  929. {
  930. const uint32_t ulength(static_cast<uint32_t>(filePath.length()));
  931. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  932. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSetChunkDataFile);
  933. fShmNonRtServerControl.writeUInt(ulength);
  934. fShmNonRtServerControl.writeCustomData(filePath.toRawUTF8(), ulength);
  935. fShmNonRtServerControl.commitWrite();
  936. }
  937. }
  938. }
  939. {
  940. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  941. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSaved);
  942. fShmNonRtServerControl.commitWrite();
  943. }
  944. break;
  945. }
  946. case kPluginBridgeNonRtClientRestoreLV2State:
  947. if (plugin->isEnabled())
  948. plugin->restoreLV2State(false);
  949. break;
  950. case kPluginBridgeNonRtClientShowUI:
  951. if (plugin->isEnabled())
  952. plugin->showCustomUI(true);
  953. break;
  954. case kPluginBridgeNonRtClientHideUI:
  955. if (plugin->isEnabled())
  956. plugin->showCustomUI(false);
  957. break;
  958. case kPluginBridgeNonRtClientEmbedUI: {
  959. const uint64_t winId = fShmNonRtClientControl.readULong();
  960. uint64_t resp = 0;
  961. if (plugin->isEnabled())
  962. resp = reinterpret_cast<uint64_t>(plugin->embedCustomUI(reinterpret_cast<void*>(winId)));
  963. if (resp == 0)
  964. resp = 1;
  965. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  966. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerRespEmbedUI);
  967. fShmNonRtServerControl.writeULong(resp);
  968. fShmNonRtServerControl.commitWrite();
  969. break;
  970. }
  971. case kPluginBridgeNonRtClientUiParameterChange: {
  972. const uint32_t index = fShmNonRtClientControl.readUInt();
  973. const float value = fShmNonRtClientControl.readFloat();
  974. if (plugin->isEnabled())
  975. plugin->uiParameterChange(index, value);
  976. break;
  977. }
  978. case kPluginBridgeNonRtClientUiProgramChange: {
  979. const uint32_t index(fShmNonRtClientControl.readUInt());
  980. if (plugin->isEnabled())
  981. plugin->uiProgramChange(index);
  982. break;
  983. }
  984. case kPluginBridgeNonRtClientUiMidiProgramChange: {
  985. const uint32_t index(fShmNonRtClientControl.readUInt());
  986. if (plugin->isEnabled())
  987. plugin->uiMidiProgramChange(index);
  988. break;
  989. }
  990. case kPluginBridgeNonRtClientUiNoteOn: {
  991. const uint8_t chnl(fShmNonRtClientControl.readByte());
  992. const uint8_t note(fShmNonRtClientControl.readByte());
  993. const uint8_t velo(fShmNonRtClientControl.readByte());
  994. if (plugin->isEnabled())
  995. plugin->uiNoteOn(chnl, note, velo);
  996. break;
  997. }
  998. case kPluginBridgeNonRtClientUiNoteOff: {
  999. const uint8_t chnl(fShmNonRtClientControl.readByte());
  1000. const uint8_t note(fShmNonRtClientControl.readByte());
  1001. if (plugin->isEnabled())
  1002. plugin->uiNoteOff(chnl, note);
  1003. break;
  1004. }
  1005. case kPluginBridgeNonRtClientQuit:
  1006. fClosingDown = true;
  1007. signalThreadShouldExit();
  1008. callback(true, true, ENGINE_CALLBACK_QUIT, 0, 0, 0, 0, 0.0f, nullptr);
  1009. break;
  1010. }
  1011. }
  1012. }
  1013. // -------------------------------------------------------------------
  1014. protected:
  1015. void run() override
  1016. {
  1017. #ifdef __SSE2_MATH__
  1018. // Set FTZ and DAZ flags
  1019. _mm_setcsr(_mm_getcsr() | 0x8040);
  1020. #endif
  1021. bool quitReceived = false;
  1022. for (; ! shouldThreadExit();)
  1023. {
  1024. const BridgeRtClientControl::WaitHelper helper(fShmRtClientControl);
  1025. if (! helper.ok)
  1026. continue;
  1027. for (; fShmRtClientControl.isDataAvailableForReading();)
  1028. {
  1029. const PluginBridgeRtClientOpcode opcode(fShmRtClientControl.readOpcode());
  1030. const CarlaPluginPtr plugin = pData->plugins[0].plugin;
  1031. #ifdef DEBUG
  1032. if (opcode != kPluginBridgeRtClientProcess && opcode != kPluginBridgeRtClientMidiEvent) {
  1033. carla_debug("CarlaEngineBridgeRtThread::run() - got opcode: %s", PluginBridgeRtClientOpcode2str(opcode));
  1034. }
  1035. #endif
  1036. switch (opcode)
  1037. {
  1038. case kPluginBridgeRtClientNull:
  1039. break;
  1040. case kPluginBridgeRtClientSetAudioPool: {
  1041. if (fShmAudioPool.data != nullptr)
  1042. {
  1043. jackbridge_shm_unmap(fShmAudioPool.shm, fShmAudioPool.data);
  1044. fShmAudioPool.data = nullptr;
  1045. }
  1046. const uint64_t poolSize(fShmRtClientControl.readULong());
  1047. CARLA_SAFE_ASSERT_BREAK(poolSize > 0);
  1048. fShmAudioPool.data = (float*)jackbridge_shm_map(fShmAudioPool.shm, static_cast<size_t>(poolSize));
  1049. break;
  1050. }
  1051. case kPluginBridgeRtClientSetBufferSize: {
  1052. const uint32_t bufferSize(fShmRtClientControl.readUInt());
  1053. pData->bufferSize = bufferSize;
  1054. bufferSizeChanged(bufferSize);
  1055. break;
  1056. }
  1057. case kPluginBridgeRtClientSetSampleRate: {
  1058. const double sampleRate(fShmRtClientControl.readDouble());
  1059. pData->sampleRate = sampleRate;
  1060. sampleRateChanged(sampleRate);
  1061. break;
  1062. }
  1063. case kPluginBridgeRtClientSetOnline:
  1064. fIsOffline = fShmRtClientControl.readBool();
  1065. offlineModeChanged(fIsOffline);
  1066. break;
  1067. // NOTE this is never used
  1068. case kPluginBridgeRtClientControlEventParameter: {
  1069. const uint32_t time(fShmRtClientControl.readUInt());
  1070. const uint8_t channel(fShmRtClientControl.readByte());
  1071. const uint16_t param(fShmRtClientControl.readUShort());
  1072. const float value(fShmRtClientControl.readFloat());
  1073. if (EngineEvent* const event = getNextFreeInputEvent())
  1074. {
  1075. event->type = kEngineEventTypeControl;
  1076. event->time = time;
  1077. event->channel = channel;
  1078. event->ctrl.type = kEngineControlEventTypeParameter;
  1079. event->ctrl.param = param;
  1080. event->ctrl.midiValue = -1;
  1081. event->ctrl.normalizedValue = value;
  1082. event->ctrl.handled = true;
  1083. }
  1084. break;
  1085. }
  1086. case kPluginBridgeRtClientControlEventMidiBank: {
  1087. const uint32_t time(fShmRtClientControl.readUInt());
  1088. const uint8_t channel(fShmRtClientControl.readByte());
  1089. const uint16_t index(fShmRtClientControl.readUShort());
  1090. if (EngineEvent* const event = getNextFreeInputEvent())
  1091. {
  1092. event->type = kEngineEventTypeControl;
  1093. event->time = time;
  1094. event->channel = channel;
  1095. event->ctrl.type = kEngineControlEventTypeMidiBank;
  1096. event->ctrl.param = index;
  1097. event->ctrl.midiValue = -1;
  1098. event->ctrl.normalizedValue = 0.0f;
  1099. event->ctrl.handled = true;
  1100. }
  1101. break;
  1102. }
  1103. case kPluginBridgeRtClientControlEventMidiProgram: {
  1104. const uint32_t time(fShmRtClientControl.readUInt());
  1105. const uint8_t channel(fShmRtClientControl.readByte());
  1106. const uint16_t index(fShmRtClientControl.readUShort());
  1107. if (EngineEvent* const event = getNextFreeInputEvent())
  1108. {
  1109. event->type = kEngineEventTypeControl;
  1110. event->time = time;
  1111. event->channel = channel;
  1112. event->ctrl.type = kEngineControlEventTypeMidiProgram;
  1113. event->ctrl.param = index;
  1114. event->ctrl.midiValue = -1;
  1115. event->ctrl.normalizedValue = 0.0f;
  1116. event->ctrl.handled = true;
  1117. }
  1118. break;
  1119. }
  1120. case kPluginBridgeRtClientControlEventAllSoundOff: {
  1121. const uint32_t time(fShmRtClientControl.readUInt());
  1122. const uint8_t channel(fShmRtClientControl.readByte());
  1123. if (EngineEvent* const event = getNextFreeInputEvent())
  1124. {
  1125. event->type = kEngineEventTypeControl;
  1126. event->time = time;
  1127. event->channel = channel;
  1128. event->ctrl.type = kEngineControlEventTypeAllSoundOff;
  1129. event->ctrl.param = 0;
  1130. event->ctrl.midiValue = -1;
  1131. event->ctrl.normalizedValue = 0.0f;
  1132. event->ctrl.handled = true;
  1133. }
  1134. } break;
  1135. case kPluginBridgeRtClientControlEventAllNotesOff: {
  1136. const uint32_t time(fShmRtClientControl.readUInt());
  1137. const uint8_t channel(fShmRtClientControl.readByte());
  1138. if (EngineEvent* const event = getNextFreeInputEvent())
  1139. {
  1140. event->type = kEngineEventTypeControl;
  1141. event->time = time;
  1142. event->channel = channel;
  1143. event->ctrl.type = kEngineControlEventTypeAllNotesOff;
  1144. event->ctrl.param = 0;
  1145. event->ctrl.midiValue = -1;
  1146. event->ctrl.normalizedValue = 0.0f;
  1147. event->ctrl.handled = true;
  1148. }
  1149. } break;
  1150. case kPluginBridgeRtClientMidiEvent: {
  1151. const uint32_t time(fShmRtClientControl.readUInt());
  1152. const uint8_t port(fShmRtClientControl.readByte());
  1153. const uint8_t size(fShmRtClientControl.readByte());
  1154. CARLA_SAFE_ASSERT_BREAK(size > 0);
  1155. // FIXME variable-size stack
  1156. uint8_t data[4];
  1157. {
  1158. uint8_t i=0;
  1159. for (; i<size && i<4; ++i)
  1160. data[i] = fShmRtClientControl.readByte();
  1161. for (; i<size; ++i)
  1162. fShmRtClientControl.readByte();
  1163. }
  1164. if (size > 4)
  1165. continue;
  1166. if (EngineEvent* const event = getNextFreeInputEvent())
  1167. {
  1168. event->type = kEngineEventTypeMidi;
  1169. event->time = time;
  1170. event->channel = MIDI_GET_CHANNEL_FROM_DATA(data);
  1171. event->midi.port = port;
  1172. event->midi.size = size;
  1173. if (size > EngineMidiEvent::kDataSize)
  1174. {
  1175. event->midi.dataExt = data;
  1176. std::memset(event->midi.data, 0, sizeof(uint8_t)*EngineMidiEvent::kDataSize);
  1177. }
  1178. else
  1179. {
  1180. event->midi.data[0] = MIDI_GET_STATUS_FROM_DATA(data);
  1181. uint8_t i=1;
  1182. for (; i < size; ++i)
  1183. event->midi.data[i] = data[i];
  1184. for (; i < EngineMidiEvent::kDataSize; ++i)
  1185. event->midi.data[i] = 0;
  1186. event->midi.dataExt = nullptr;
  1187. }
  1188. }
  1189. break;
  1190. }
  1191. case kPluginBridgeRtClientProcess: {
  1192. const uint32_t frames(fShmRtClientControl.readUInt());
  1193. CARLA_SAFE_ASSERT_BREAK(fShmAudioPool.data != nullptr);
  1194. if (plugin.get() != nullptr && plugin->isEnabled() && plugin->tryLock(fIsOffline))
  1195. {
  1196. const BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo);
  1197. const uint32_t audioInCount = plugin->getAudioInCount();
  1198. const uint32_t audioOutCount = plugin->getAudioOutCount();
  1199. const uint32_t cvInCount = plugin->getCVInCount();
  1200. const uint32_t cvOutCount = plugin->getCVOutCount();
  1201. const float* audioIn[64];
  1202. /* */ float* audioOut[64];
  1203. const float* cvIn[32];
  1204. /* */ float* cvOut[32];
  1205. float* fdata = fShmAudioPool.data;
  1206. for (uint32_t i=0; i < audioInCount; ++i, fdata += pData->bufferSize)
  1207. audioIn[i] = fdata;
  1208. for (uint32_t i=0; i < audioOutCount; ++i, fdata += pData->bufferSize)
  1209. audioOut[i] = fdata;
  1210. for (uint32_t i=0; i < cvInCount; ++i, fdata += pData->bufferSize)
  1211. cvIn[i] = fdata;
  1212. for (uint32_t i=0; i < cvOutCount; ++i, fdata += pData->bufferSize)
  1213. cvOut[i] = fdata;
  1214. EngineTimeInfo& timeInfo(pData->timeInfo);
  1215. timeInfo.playing = bridgeTimeInfo.playing;
  1216. timeInfo.frame = bridgeTimeInfo.frame;
  1217. timeInfo.usecs = bridgeTimeInfo.usecs;
  1218. timeInfo.bbt.valid = (bridgeTimeInfo.validFlags & kPluginBridgeTimeInfoValidBBT) != 0;
  1219. if (timeInfo.bbt.valid)
  1220. {
  1221. timeInfo.bbt.bar = bridgeTimeInfo.bar;
  1222. timeInfo.bbt.beat = bridgeTimeInfo.beat;
  1223. timeInfo.bbt.tick = bridgeTimeInfo.tick;
  1224. timeInfo.bbt.beatsPerBar = bridgeTimeInfo.beatsPerBar;
  1225. timeInfo.bbt.beatType = bridgeTimeInfo.beatType;
  1226. timeInfo.bbt.ticksPerBeat = bridgeTimeInfo.ticksPerBeat;
  1227. timeInfo.bbt.beatsPerMinute = bridgeTimeInfo.beatsPerMinute;
  1228. timeInfo.bbt.barStartTick = bridgeTimeInfo.barStartTick;
  1229. }
  1230. plugin->initBuffers();
  1231. plugin->process(audioIn, audioOut, cvIn, cvOut, frames);
  1232. plugin->unlock();
  1233. }
  1234. uint8_t* midiData(fShmRtClientControl.data->midiOut);
  1235. carla_zeroBytes(midiData, kBridgeBaseMidiOutHeaderSize);
  1236. std::size_t curMidiDataPos = 0;
  1237. if (pData->events.in[0].type != kEngineEventTypeNull)
  1238. carla_zeroStructs(pData->events.in, kMaxEngineEventInternalCount);
  1239. if (pData->events.out[0].type != kEngineEventTypeNull)
  1240. {
  1241. for (ushort i=0; i < kMaxEngineEventInternalCount; ++i)
  1242. {
  1243. const EngineEvent& event(pData->events.out[i]);
  1244. if (event.type == kEngineEventTypeNull)
  1245. break;
  1246. if (event.type == kEngineEventTypeControl)
  1247. {
  1248. uint8_t data[3];
  1249. const uint8_t size = event.ctrl.convertToMidiData(event.channel, data);
  1250. CARLA_SAFE_ASSERT_CONTINUE(size > 0 && size <= 3);
  1251. if (curMidiDataPos + kBridgeBaseMidiOutHeaderSize + size >= kBridgeRtClientDataMidiOutSize)
  1252. break;
  1253. // set time
  1254. *(uint32_t*)midiData = event.time;
  1255. midiData = midiData + 4;
  1256. curMidiDataPos += 4;
  1257. // set port
  1258. *midiData++ = 0;
  1259. ++curMidiDataPos;
  1260. // set size
  1261. *midiData++ = size;
  1262. ++curMidiDataPos;
  1263. // set data
  1264. for (uint8_t j=0; j<size; ++j)
  1265. *midiData++ = data[j];
  1266. curMidiDataPos += size;
  1267. }
  1268. else if (event.type == kEngineEventTypeMidi)
  1269. {
  1270. const EngineMidiEvent& _midiEvent(event.midi);
  1271. if (curMidiDataPos + kBridgeBaseMidiOutHeaderSize + _midiEvent.size >= kBridgeRtClientDataMidiOutSize)
  1272. break;
  1273. const uint8_t* const _midiData(_midiEvent.dataExt != nullptr ? _midiEvent.dataExt : _midiEvent.data);
  1274. // set time
  1275. *(uint32_t*)midiData = event.time;
  1276. midiData += 4;
  1277. curMidiDataPos += 4;
  1278. // set port
  1279. *midiData++ = _midiEvent.port;
  1280. ++curMidiDataPos;
  1281. // set size
  1282. *midiData++ = _midiEvent.size;
  1283. ++curMidiDataPos;
  1284. // set data
  1285. *midiData++ = uint8_t(_midiData[0] | (event.channel & MIDI_CHANNEL_BIT));
  1286. for (uint8_t j=1; j<_midiEvent.size; ++j)
  1287. *midiData++ = _midiData[j];
  1288. curMidiDataPos += _midiEvent.size;
  1289. }
  1290. }
  1291. if (curMidiDataPos != 0 &&
  1292. curMidiDataPos + kBridgeBaseMidiOutHeaderSize < kBridgeRtClientDataMidiOutSize)
  1293. carla_zeroBytes(midiData, kBridgeBaseMidiOutHeaderSize);
  1294. carla_zeroStructs(pData->events.out, kMaxEngineEventInternalCount);
  1295. }
  1296. } break;
  1297. case kPluginBridgeRtClientQuit: {
  1298. quitReceived = true;
  1299. fClosingDown = true;
  1300. signalThreadShouldExit();
  1301. } break;
  1302. }
  1303. }
  1304. }
  1305. callback(true, true, ENGINE_CALLBACK_ENGINE_STOPPED, 0, 0, 0, 0, 0.0f, nullptr);
  1306. if (! quitReceived)
  1307. {
  1308. const char* const message("Plugin bridge error, process thread has stopped");
  1309. const std::size_t messageSize(std::strlen(message));
  1310. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  1311. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerError);
  1312. fShmNonRtServerControl.writeUInt(messageSize);
  1313. fShmNonRtServerControl.writeCustomData(message, messageSize);
  1314. fShmNonRtServerControl.commitWrite();
  1315. }
  1316. }
  1317. // called from process thread above
  1318. EngineEvent* getNextFreeInputEvent() const noexcept
  1319. {
  1320. for (ushort i=0; i < kMaxEngineEventInternalCount; ++i)
  1321. {
  1322. EngineEvent* const event(&pData->events.in[i]);
  1323. if (event->type == kEngineEventTypeNull)
  1324. return event;
  1325. }
  1326. return nullptr;
  1327. }
  1328. void latencyChanged(const uint32_t samples) noexcept override
  1329. {
  1330. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  1331. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSetLatency);
  1332. fShmNonRtServerControl.writeUInt(samples);
  1333. fShmNonRtServerControl.commitWrite();
  1334. }
  1335. // -------------------------------------------------------------------
  1336. private:
  1337. BridgeAudioPool fShmAudioPool;
  1338. BridgeRtClientControl fShmRtClientControl;
  1339. BridgeNonRtClientControl fShmNonRtClientControl;
  1340. BridgeNonRtServerControl fShmNonRtServerControl;
  1341. CarlaString fBaseNameAudioPool;
  1342. CarlaString fBaseNameRtClientControl;
  1343. CarlaString fBaseNameNonRtClientControl;
  1344. CarlaString fBaseNameNonRtServerControl;
  1345. bool fClosingDown;
  1346. bool fIsOffline;
  1347. bool fFirstIdle;
  1348. int64_t fLastPingTime;
  1349. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineBridge)
  1350. };
  1351. // -----------------------------------------------------------------------
  1352. namespace EngineInit {
  1353. CarlaEngine* newBridge(const char* const audioPoolBaseName,
  1354. const char* const rtClientBaseName,
  1355. const char* const nonRtClientBaseName,
  1356. const char* const nonRtServerBaseName)
  1357. {
  1358. return new CarlaEngineBridge(audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName);
  1359. }
  1360. }
  1361. // -----------------------------------------------------------------------
  1362. CARLA_BACKEND_END_NAMESPACE
  1363. // -----------------------------------------------------------------------
  1364. #include "CarlaBridgeUtils.cpp"
  1365. // -----------------------------------------------------------------------