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.

1579 lines
58KB

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