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.

1581 lines
59KB

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