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.

1169 lines
40KB

  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. template<typename T>
  31. bool jackbridge_shm_map2(char* shm, T*& value) noexcept
  32. {
  33. value = (T*)jackbridge_shm_map(shm, sizeof(T));
  34. return (value != nullptr);
  35. }
  36. CARLA_BACKEND_START_NAMESPACE
  37. // -------------------------------------------------------------------
  38. struct BridgeAudioPool {
  39. CarlaString filename;
  40. float* data;
  41. char shm[64];
  42. BridgeAudioPool() noexcept
  43. : filename(),
  44. data(nullptr)
  45. {
  46. carla_zeroChar(shm, 64);
  47. jackbridge_shm_init(shm);
  48. }
  49. ~BridgeAudioPool() noexcept
  50. {
  51. // should be cleared by now
  52. CARLA_SAFE_ASSERT(data == nullptr);
  53. clear();
  54. }
  55. void clear() noexcept
  56. {
  57. filename.clear();
  58. if (! jackbridge_shm_is_valid(shm))
  59. {
  60. CARLA_SAFE_ASSERT(data == nullptr);
  61. return;
  62. }
  63. data = nullptr;
  64. jackbridge_shm_close(shm);
  65. jackbridge_shm_init(shm);
  66. }
  67. bool attach() noexcept
  68. {
  69. // must be invalid right now
  70. CARLA_SAFE_ASSERT_RETURN(! jackbridge_shm_is_valid(shm), false);
  71. jackbridge_shm_attach(shm, filename);
  72. return jackbridge_shm_is_valid(shm);
  73. }
  74. CARLA_DECLARE_NON_COPY_STRUCT(BridgeAudioPool)
  75. };
  76. // -------------------------------------------------------------------
  77. struct BridgeRtClientControl : public CarlaRingBufferControl<SmallStackBuffer> {
  78. CarlaString filename;
  79. BridgeRtClientData* data;
  80. char shm[64];
  81. BridgeRtClientControl() noexcept
  82. : filename(),
  83. data(nullptr)
  84. {
  85. carla_zeroChar(shm, 64);
  86. jackbridge_shm_init(shm);
  87. }
  88. ~BridgeRtClientControl() noexcept override
  89. {
  90. // should be cleared by now
  91. CARLA_SAFE_ASSERT(data == nullptr);
  92. clear();
  93. }
  94. void clear() noexcept
  95. {
  96. filename.clear();
  97. if (data != nullptr)
  98. unmapData();
  99. if (! jackbridge_shm_is_valid(shm))
  100. return;
  101. jackbridge_shm_close(shm);
  102. jackbridge_shm_init(shm);
  103. }
  104. bool attach() noexcept
  105. {
  106. // must be invalid right now
  107. CARLA_SAFE_ASSERT_RETURN(! jackbridge_shm_is_valid(shm), false);
  108. jackbridge_shm_attach(shm, filename);
  109. return jackbridge_shm_is_valid(shm);
  110. }
  111. bool mapData() noexcept
  112. {
  113. CARLA_SAFE_ASSERT(data == nullptr);
  114. if (jackbridge_shm_map2<BridgeRtClientData>(shm, data))
  115. {
  116. CARLA_SAFE_ASSERT(data->midiOut[0] == 0);
  117. setRingBuffer(&data->ringBuffer, false);
  118. return true;
  119. }
  120. return false;
  121. }
  122. void unmapData() noexcept
  123. {
  124. data = nullptr;
  125. setRingBuffer(nullptr, false);
  126. }
  127. bool postClient() noexcept
  128. {
  129. CARLA_SAFE_ASSERT_RETURN(data != nullptr, false);
  130. return jackbridge_sem_post(&data->sem.client);
  131. }
  132. bool waitForServer(const uint secs) noexcept
  133. {
  134. CARLA_SAFE_ASSERT_RETURN(data != nullptr, false);
  135. return jackbridge_sem_timedwait(&data->sem.server, secs);
  136. }
  137. PluginBridgeRtClientOpcode readOpcode() noexcept
  138. {
  139. return static_cast<PluginBridgeRtClientOpcode>(readUInt());
  140. }
  141. CARLA_DECLARE_NON_COPY_STRUCT(BridgeRtClientControl)
  142. };
  143. // -------------------------------------------------------------------
  144. struct BridgeNonRtClientControl : public CarlaRingBufferControl<BigStackBuffer> {
  145. CarlaString filename;
  146. BridgeNonRtClientData* data;
  147. char shm[64];
  148. BridgeNonRtClientControl() noexcept
  149. : filename(),
  150. data(nullptr)
  151. {
  152. carla_zeroChar(shm, 64);
  153. jackbridge_shm_init(shm);
  154. }
  155. ~BridgeNonRtClientControl() noexcept override
  156. {
  157. // should be cleared by now
  158. CARLA_SAFE_ASSERT(data == nullptr);
  159. clear();
  160. }
  161. void clear() noexcept
  162. {
  163. filename.clear();
  164. if (data != nullptr)
  165. unmapData();
  166. if (! jackbridge_shm_is_valid(shm))
  167. {
  168. CARLA_SAFE_ASSERT(data == nullptr);
  169. return;
  170. }
  171. jackbridge_shm_close(shm);
  172. jackbridge_shm_init(shm);
  173. }
  174. bool attach() noexcept
  175. {
  176. // must be invalid right now
  177. CARLA_SAFE_ASSERT_RETURN(! jackbridge_shm_is_valid(shm), false);
  178. jackbridge_shm_attach(shm, filename);
  179. return jackbridge_shm_is_valid(shm);
  180. }
  181. bool mapData() noexcept
  182. {
  183. CARLA_SAFE_ASSERT(data == nullptr);
  184. if (jackbridge_shm_map2<BridgeNonRtClientData>(shm, data))
  185. {
  186. setRingBuffer(&data->ringBuffer, false);
  187. return true;
  188. }
  189. return false;
  190. }
  191. void unmapData() noexcept
  192. {
  193. data = nullptr;
  194. setRingBuffer(nullptr, false);
  195. }
  196. PluginBridgeNonRtClientOpcode readOpcode() noexcept
  197. {
  198. return static_cast<PluginBridgeNonRtClientOpcode>(readUInt());
  199. }
  200. CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtClientControl)
  201. };
  202. // -------------------------------------------------------------------
  203. struct BridgeNonRtServerControl : public CarlaRingBufferControl<HugeStackBuffer> {
  204. CarlaMutex mutex;
  205. CarlaString filename;
  206. BridgeNonRtServerData* data;
  207. char shm[64];
  208. BridgeNonRtServerControl() noexcept
  209. : mutex(),
  210. filename(),
  211. data(nullptr)
  212. {
  213. carla_zeroChar(shm, 64);
  214. jackbridge_shm_init(shm);
  215. }
  216. ~BridgeNonRtServerControl() noexcept override
  217. {
  218. // should be cleared by now
  219. CARLA_SAFE_ASSERT(data == nullptr);
  220. clear();
  221. }
  222. void clear() noexcept
  223. {
  224. filename.clear();
  225. if (data != nullptr)
  226. unmapData();
  227. if (! jackbridge_shm_is_valid(shm))
  228. {
  229. CARLA_SAFE_ASSERT(data == nullptr);
  230. return;
  231. }
  232. jackbridge_shm_close(shm);
  233. jackbridge_shm_init(shm);
  234. }
  235. bool attach() noexcept
  236. {
  237. // must be invalid right now
  238. CARLA_SAFE_ASSERT_RETURN(! jackbridge_shm_is_valid(shm), false);
  239. jackbridge_shm_attach(shm, filename);
  240. return jackbridge_shm_is_valid(shm);
  241. }
  242. bool mapData() noexcept
  243. {
  244. CARLA_SAFE_ASSERT(data == nullptr);
  245. if (jackbridge_shm_map2<BridgeNonRtServerData>(shm, data))
  246. {
  247. setRingBuffer(&data->ringBuffer, false);
  248. return true;
  249. }
  250. return false;
  251. }
  252. void unmapData() noexcept
  253. {
  254. data = nullptr;
  255. setRingBuffer(nullptr, false);
  256. }
  257. void writeOpcode(const PluginBridgeNonRtServerOpcode opcode) noexcept
  258. {
  259. writeUInt(static_cast<uint32_t>(opcode));
  260. }
  261. CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtServerControl)
  262. };
  263. // -------------------------------------------------------------------
  264. class CarlaEngineBridge : public CarlaEngine,
  265. public CarlaThread
  266. {
  267. public:
  268. CarlaEngineBridge(const char* const audioPoolBaseName, const char* const rtClientBaseName, const char* const nonRtClientBaseName, const char* const nonRtServerBaseName)
  269. : CarlaEngine(),
  270. CarlaThread("CarlaEngineBridge"),
  271. fShmAudioPool(),
  272. fShmRtClientControl(),
  273. fShmNonRtClientControl(),
  274. fShmNonRtServerControl(),
  275. fIsRunning(false),
  276. fIsOffline(false),
  277. fFirstIdle(true),
  278. fLastPingCounter(-1),
  279. leakDetector_CarlaEngineBridge()
  280. {
  281. carla_stdout("CarlaEngineBridge::CarlaEngineBridge(\"%s\", \"%s\", \"%s\", \"%s\")", audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName);
  282. fShmAudioPool.filename = PLUGIN_BRIDGE_NAMEPREFIX_AUDIO_POOL;
  283. fShmAudioPool.filename += audioPoolBaseName;
  284. fShmRtClientControl.filename = PLUGIN_BRIDGE_NAMEPREFIX_RT_CLIENT;
  285. fShmRtClientControl.filename += rtClientBaseName;
  286. fShmNonRtClientControl.filename = PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_CLIENT;
  287. fShmNonRtClientControl.filename += nonRtClientBaseName;
  288. fShmNonRtServerControl.filename = PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_SERVER;
  289. fShmNonRtServerControl.filename += nonRtServerBaseName;
  290. }
  291. ~CarlaEngineBridge() noexcept override
  292. {
  293. carla_debug("CarlaEngineBridge::~CarlaEngineBridge()");
  294. }
  295. // -------------------------------------
  296. // CarlaEngine virtual calls
  297. bool init(const char* const clientName) override
  298. {
  299. carla_debug("CarlaEngineBridge::init(\"%s\")", clientName);
  300. if (! pData->init(clientName))
  301. {
  302. setLastError("Failed to init internal data");
  303. return false;
  304. }
  305. if (! fShmAudioPool.attach())
  306. {
  307. carla_stdout("Failed to attach to audio pool shared memory");
  308. return false;
  309. }
  310. if (! fShmRtClientControl.attach())
  311. {
  312. clear();
  313. carla_stdout("Failed to attach to rt client control shared memory");
  314. return false;
  315. }
  316. if (! fShmRtClientControl.mapData())
  317. {
  318. clear();
  319. carla_stdout("Failed to map rt client control shared memory");
  320. return false;
  321. }
  322. if (! fShmNonRtClientControl.attach())
  323. {
  324. clear();
  325. carla_stdout("Failed to attach to non-rt client control shared memory");
  326. return false;
  327. }
  328. if (! fShmNonRtClientControl.mapData())
  329. {
  330. clear();
  331. carla_stdout("Failed to map non-rt control client shared memory");
  332. return false;
  333. }
  334. if (! fShmNonRtServerControl.attach())
  335. {
  336. clear();
  337. carla_stdout("Failed to attach to non-rt server control shared memory");
  338. return false;
  339. }
  340. if (! fShmNonRtServerControl.mapData())
  341. {
  342. clear();
  343. carla_stdout("Failed to map non-rt control server shared memory");
  344. return false;
  345. }
  346. PluginBridgeNonRtClientOpcode opcode;
  347. opcode = fShmNonRtClientControl.readOpcode();
  348. CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtClientNull, opcode);
  349. const uint32_t shmRtClientDataSize = fShmNonRtClientControl.readUInt();
  350. CARLA_SAFE_ASSERT_INT2(shmRtClientDataSize == sizeof(BridgeRtClientData), shmRtClientDataSize, sizeof(BridgeRtClientData));
  351. const uint32_t shmNonRtClientDataSize = fShmNonRtClientControl.readUInt();
  352. CARLA_SAFE_ASSERT_INT2(shmNonRtClientDataSize == sizeof(BridgeNonRtClientData), shmNonRtClientDataSize, sizeof(BridgeNonRtClientData));
  353. const uint32_t shmNonRtServerDataSize = fShmNonRtClientControl.readUInt();
  354. CARLA_SAFE_ASSERT_INT2(shmNonRtServerDataSize == sizeof(BridgeNonRtServerData), shmNonRtServerDataSize, sizeof(BridgeNonRtServerData));
  355. opcode = fShmNonRtClientControl.readOpcode();
  356. CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtClientSetBufferSize, opcode);
  357. pData->bufferSize = fShmNonRtClientControl.readUInt();
  358. opcode = fShmNonRtClientControl.readOpcode();
  359. CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtClientSetSampleRate, opcode);
  360. pData->sampleRate = fShmNonRtClientControl.readDouble();
  361. carla_stdout("Carla Client Info:");
  362. carla_stdout(" BufferSize: %i", pData->bufferSize);
  363. carla_stdout(" SampleRate: %g", pData->sampleRate);
  364. carla_stdout(" sizeof(BridgeRtClientData): %i/" P_SIZE, shmRtClientDataSize, sizeof(BridgeRtClientData));
  365. carla_stdout(" sizeof(BridgeNonRtClientData): %i/" P_SIZE, shmNonRtClientDataSize, sizeof(BridgeNonRtClientData));
  366. carla_stdout(" sizeof(BridgeNonRtServerData): %i/" P_SIZE, shmNonRtServerDataSize, sizeof(BridgeNonRtServerData));
  367. if (shmRtClientDataSize != sizeof(BridgeRtClientData) || shmNonRtClientDataSize != sizeof(BridgeNonRtClientData) || shmNonRtServerDataSize != sizeof(BridgeNonRtServerData))
  368. return false;
  369. startThread();
  370. return true;
  371. }
  372. bool close() override
  373. {
  374. carla_debug("CarlaEnginePlugin::close()");
  375. fLastPingCounter = -1;
  376. CarlaEngine::close();
  377. stopThread(5000);
  378. clear();
  379. return true;
  380. }
  381. bool isRunning() const noexcept override
  382. {
  383. return isThreadRunning();
  384. }
  385. bool isOffline() const noexcept override
  386. {
  387. return fIsOffline;
  388. }
  389. EngineType getType() const noexcept override
  390. {
  391. return kEngineTypeBridge;
  392. }
  393. const char* getCurrentDriverName() const noexcept
  394. {
  395. return "Bridge";
  396. }
  397. void idle() noexcept override
  398. {
  399. if (fFirstIdle)
  400. {
  401. fFirstIdle = false;
  402. fLastPingCounter = 0;
  403. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  404. // TODO - send plugin data
  405. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerReady);
  406. fShmNonRtServerControl.commitWrite();
  407. carla_stdout("Carla Client Ready!");
  408. }
  409. // TODO - send output parameters to server
  410. CarlaEngine::idle();
  411. try {
  412. handleNonRtData();
  413. } CARLA_SAFE_EXCEPTION("handleNonRtData");
  414. if (fLastPingCounter >= 0 && ++fLastPingCounter == 500)
  415. {
  416. carla_stderr("Did not receive ping message from server for a long time, closing...");
  417. callback(ENGINE_CALLBACK_QUIT, 0, 0, 0, 0.0f, nullptr);
  418. }
  419. }
  420. // -------------------------------------------------------------------
  421. void clear() noexcept
  422. {
  423. fShmAudioPool.clear();
  424. fShmRtClientControl.clear();
  425. fShmNonRtClientControl.clear();
  426. fShmNonRtServerControl.clear();
  427. }
  428. void handleNonRtData()
  429. {
  430. for (; fShmNonRtClientControl.isDataAvailableForReading();)
  431. {
  432. const PluginBridgeNonRtClientOpcode opcode(fShmNonRtClientControl.readOpcode());
  433. CarlaPlugin* const plugin(pData->plugins[0].plugin);
  434. #ifdef DEBUG
  435. if (opcode != kPluginBridgeNonRtClientPing) {
  436. carla_debug("CarlaEngineBridge::handleNonRtData() - got opcode: %s", PluginBridgeNonRtClientOpcode2str(opcode));
  437. }
  438. #endif
  439. switch (opcode)
  440. {
  441. case kPluginBridgeNonRtClientNull:
  442. break;
  443. case kPluginBridgeNonRtClientPing: {
  444. if (fLastPingCounter > 0)
  445. fLastPingCounter = 0;
  446. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  447. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPong);
  448. fShmNonRtServerControl.commitWrite();
  449. } break;
  450. case kPluginBridgeNonRtClientActivate:
  451. if (plugin != nullptr && plugin->isEnabled())
  452. plugin->setActive(true, false, false);
  453. break;
  454. case kPluginBridgeNonRtClientDeactivate:
  455. if (plugin != nullptr && plugin->isEnabled())
  456. plugin->setActive(false, false, false);
  457. break;
  458. case kPluginBridgeNonRtClientSetBufferSize: {
  459. const uint32_t bufferSize(fShmNonRtClientControl.readUInt());
  460. pData->bufferSize = bufferSize;
  461. bufferSizeChanged(bufferSize);
  462. break;
  463. }
  464. case kPluginBridgeNonRtClientSetSampleRate: {
  465. const double sampleRate(fShmNonRtClientControl.readDouble());
  466. pData->sampleRate = sampleRate;
  467. sampleRateChanged(sampleRate);
  468. break;
  469. }
  470. case kPluginBridgeNonRtClientSetOffline:
  471. fIsOffline = true;
  472. offlineModeChanged(true);
  473. break;
  474. case kPluginBridgeNonRtClientSetOnline:
  475. fIsOffline = false;
  476. offlineModeChanged(false);
  477. break;
  478. case kPluginBridgeNonRtClientSetParameterValue: {
  479. const uint32_t index(fShmNonRtClientControl.readUInt());
  480. const float value(fShmNonRtClientControl.readFloat());
  481. if (plugin != nullptr && plugin->isEnabled())
  482. plugin->setParameterValue(index, value, false, false, false);
  483. break;
  484. }
  485. case kPluginBridgeNonRtClientSetParameterMidiChannel: {
  486. const uint32_t index(fShmNonRtClientControl.readUInt());
  487. const uint8_t channel(fShmNonRtClientControl.readByte());
  488. if (plugin != nullptr && plugin->isEnabled())
  489. plugin->setParameterMidiChannel(index, channel, false, false);
  490. break;
  491. }
  492. case kPluginBridgeNonRtClientSetParameterMidiCC: {
  493. const uint32_t index(fShmNonRtClientControl.readUInt());
  494. const int16_t cc(fShmNonRtClientControl.readShort());
  495. if (plugin != nullptr && plugin->isEnabled())
  496. plugin->setParameterMidiCC(index, cc, false, false);
  497. break;
  498. }
  499. case kPluginBridgeNonRtClientSetProgram: {
  500. const int32_t index(fShmNonRtClientControl.readInt());
  501. if (plugin != nullptr && plugin->isEnabled())
  502. plugin->setProgram(index, false, false, false);
  503. break;
  504. }
  505. case kPluginBridgeNonRtClientSetMidiProgram: {
  506. const int32_t index(fShmNonRtClientControl.readInt());
  507. if (plugin != nullptr && plugin->isEnabled())
  508. plugin->setMidiProgram(index, false, false, false);
  509. break;
  510. }
  511. case kPluginBridgeNonRtClientSetCustomData: {
  512. // type
  513. const uint32_t typeSize(fShmNonRtClientControl.readUInt());
  514. char typeStr[typeSize+1];
  515. carla_zeroChar(typeStr, typeSize+1);
  516. fShmNonRtClientControl.readCustomData(typeStr, typeSize);
  517. // key
  518. const uint32_t keySize(fShmNonRtClientControl.readUInt());
  519. char keyStr[keySize+1];
  520. carla_zeroChar(keyStr, keySize+1);
  521. fShmNonRtClientControl.readCustomData(keyStr, keySize);
  522. // value
  523. const uint32_t valueSize(fShmNonRtClientControl.readUInt());
  524. char valueStr[valueSize+1];
  525. carla_zeroChar(valueStr, valueSize+1);
  526. fShmNonRtClientControl.readCustomData(valueStr, valueSize);
  527. if (plugin != nullptr && plugin->isEnabled())
  528. plugin->setCustomData(typeStr, keyStr, valueStr, true);
  529. break;
  530. }
  531. case kPluginBridgeNonRtClientSetChunkDataFile: {
  532. const uint32_t size(fShmNonRtClientControl.readUInt());
  533. CARLA_SAFE_ASSERT_BREAK(size > 0);
  534. char chunkFilePathTry[size+1];
  535. carla_zeroChar(chunkFilePathTry, size+1);
  536. fShmNonRtClientControl.readCustomData(chunkFilePathTry, size);
  537. CARLA_SAFE_ASSERT_BREAK(chunkFilePathTry[0] != '\0');
  538. if (plugin == nullptr || ! plugin->isEnabled()) break;
  539. String chunkFilePath(chunkFilePathTry);
  540. #ifdef CARLA_OS_WIN
  541. // check if running under Wine
  542. if (chunkFilePath.startsWith("/"))
  543. chunkFilePath = chunkFilePath.replaceSection(0, 1, "Z:\\").replace("/", "\\");
  544. #endif
  545. File chunkFile(chunkFilePath);
  546. CARLA_SAFE_ASSERT_BREAK(chunkFile.existsAsFile());
  547. String chunkDataBase64(chunkFile.loadFileAsString());
  548. chunkFile.deleteFile();
  549. CARLA_SAFE_ASSERT_BREAK(chunkDataBase64.isNotEmpty());
  550. std::vector<uint8_t> chunk(carla_getChunkFromBase64String(chunkDataBase64.toRawUTF8()));
  551. plugin->setChunkData(chunk.data(), chunk.size());
  552. break;
  553. }
  554. case kPluginBridgeNonRtClientSetCtrlChannel: {
  555. const int16_t channel(fShmNonRtClientControl.readShort());
  556. CARLA_SAFE_ASSERT_BREAK(channel >= -1 && channel < MAX_MIDI_CHANNELS);
  557. if (plugin != nullptr && plugin->isEnabled())
  558. plugin->setCtrlChannel(static_cast<int8_t>(channel), false, false);
  559. break;
  560. }
  561. case kPluginBridgeNonRtClientSetOption: {
  562. const uint32_t option(fShmNonRtClientControl.readUInt());
  563. const bool yesNo(fShmNonRtClientControl.readBool());
  564. if (plugin != nullptr && plugin->isEnabled())
  565. plugin->setOption(option, yesNo, false);
  566. break;
  567. }
  568. case kPluginBridgeNonRtClientPrepareForSave: {
  569. if (plugin == nullptr || ! plugin->isEnabled()) break;
  570. plugin->prepareForSave();
  571. for (uint32_t i=0, count=plugin->getCustomDataCount(); i<count; ++i)
  572. {
  573. using namespace juce;
  574. const CustomData& cdata(plugin->getCustomData(i));
  575. const uint32_t typeLen(static_cast<uint32_t>(std::strlen(cdata.type)));
  576. const uint32_t keyLen(static_cast<uint32_t>(std::strlen(cdata.key)));
  577. MemoryOutputStream valueMemStream;
  578. GZIPCompressorOutputStream compressedValueStream(&valueMemStream, 9, false);
  579. compressedValueStream.write(cdata.value, std::strlen(cdata.value));
  580. const CarlaString valueBase64(CarlaString::asBase64(valueMemStream.getData(), valueMemStream.getDataSize()));
  581. const uint32_t valueBase64Len(static_cast<uint32_t>(valueBase64.length()));
  582. CARLA_SAFE_ASSERT_CONTINUE(valueBase64.length() > 0);
  583. {
  584. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  585. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSetCustomData);
  586. fShmNonRtServerControl.writeUInt(typeLen);
  587. fShmNonRtServerControl.writeCustomData(cdata.type, typeLen);
  588. fShmNonRtServerControl.writeUInt(keyLen);
  589. fShmNonRtServerControl.writeCustomData(cdata.key, keyLen);
  590. fShmNonRtServerControl.writeUInt(valueBase64Len);
  591. fShmNonRtServerControl.writeCustomData(valueBase64.buffer(), valueBase64Len);
  592. fShmNonRtServerControl.commitWrite();
  593. }
  594. }
  595. if (plugin->getOptionsEnabled() & PLUGIN_OPTION_USE_CHUNKS)
  596. {
  597. void* data = nullptr;
  598. if (const std::size_t dataSize = plugin->getChunkData(&data))
  599. {
  600. CARLA_SAFE_ASSERT_BREAK(data != nullptr);
  601. CarlaString dataBase64 = CarlaString::asBase64(data, dataSize);
  602. CARLA_SAFE_ASSERT_BREAK(dataBase64.length() > 0);
  603. String filePath(File::getSpecialLocation(File::tempDirectory).getFullPathName());
  604. filePath += CARLA_OS_SEP_STR;
  605. filePath += ".CarlaChunk_";
  606. filePath += fShmNonRtClientControl.filename.buffer() + 24;
  607. if (File(filePath).replaceWithText(dataBase64.buffer()))
  608. {
  609. const uint32_t ulength(static_cast<uint32_t>(filePath.length()));
  610. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  611. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSetChunkDataFile);
  612. fShmNonRtServerControl.writeUInt(ulength);
  613. fShmNonRtServerControl.writeCustomData(filePath.toRawUTF8(), ulength);
  614. fShmNonRtServerControl.commitWrite();
  615. }
  616. }
  617. }
  618. {
  619. const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex);
  620. fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerSaved);
  621. fShmNonRtServerControl.commitWrite();
  622. }
  623. break;
  624. }
  625. case kPluginBridgeNonRtClientShowUI:
  626. if (plugin != nullptr && plugin->isEnabled())
  627. plugin->showCustomUI(true);
  628. break;
  629. case kPluginBridgeNonRtClientHideUI:
  630. if (plugin != nullptr && plugin->isEnabled())
  631. plugin->showCustomUI(false);
  632. break;
  633. case kPluginBridgeNonRtClientUiParameterChange: {
  634. const uint32_t index(fShmNonRtClientControl.readUInt());
  635. const float value(fShmNonRtClientControl.readFloat());
  636. if (plugin != nullptr && plugin->isEnabled())
  637. plugin->uiParameterChange(index, value);
  638. break;
  639. }
  640. case kPluginBridgeNonRtClientUiProgramChange: {
  641. const uint32_t index(fShmNonRtClientControl.readUInt());
  642. if (plugin != nullptr && plugin->isEnabled())
  643. plugin->uiProgramChange(index);
  644. break;
  645. }
  646. case kPluginBridgeNonRtClientUiMidiProgramChange: {
  647. const uint32_t index(fShmNonRtClientControl.readUInt());
  648. if (plugin != nullptr && plugin->isEnabled())
  649. plugin->uiMidiProgramChange(index);
  650. break;
  651. }
  652. case kPluginBridgeNonRtClientUiNoteOn: {
  653. const uint8_t chnl(fShmNonRtClientControl.readByte());
  654. const uint8_t note(fShmNonRtClientControl.readByte());
  655. const uint8_t velo(fShmNonRtClientControl.readByte());
  656. if (plugin != nullptr && plugin->isEnabled())
  657. plugin->uiNoteOn(chnl, note, velo);
  658. break;
  659. }
  660. case kPluginBridgeNonRtClientUiNoteOff: {
  661. const uint8_t chnl(fShmNonRtClientControl.readByte());
  662. const uint8_t note(fShmNonRtClientControl.readByte());
  663. if (plugin != nullptr && plugin->isEnabled())
  664. plugin->uiNoteOff(chnl, note);
  665. break;
  666. }
  667. case kPluginBridgeNonRtClientQuit:
  668. signalThreadShouldExit();
  669. callback(ENGINE_CALLBACK_QUIT, 0, 0, 0, 0.0f, nullptr);
  670. break;
  671. }
  672. }
  673. }
  674. // -------------------------------------------------------------------
  675. protected:
  676. void run() override
  677. {
  678. for (; ! shouldThreadExit();)
  679. {
  680. if (! fShmRtClientControl.waitForServer(5))
  681. {
  682. carla_stderr2("Bridge timed-out, final post...");
  683. fShmRtClientControl.postClient();
  684. carla_stderr2("Bridge timed-out, done.");
  685. signalThreadShouldExit();
  686. break;
  687. }
  688. for (; fShmRtClientControl.isDataAvailableForReading();)
  689. {
  690. const PluginBridgeRtClientOpcode opcode(fShmRtClientControl.readOpcode());
  691. CarlaPlugin* const plugin(pData->plugins[0].plugin);
  692. #ifdef DEBUG
  693. if (opcode != kPluginBridgeRtClientProcess && opcode != kPluginBridgeRtClientMidiEvent) {
  694. carla_debug("CarlaEngineBridgeRtThread::run() - got opcode: %s", PluginBridgeRtClientOpcode2str(opcode));
  695. }
  696. #endif
  697. switch (opcode)
  698. {
  699. case kPluginBridgeRtClientNull:
  700. break;
  701. case kPluginBridgeRtClientSetAudioPool: {
  702. const uint64_t poolSize(fShmRtClientControl.readULong());
  703. CARLA_SAFE_ASSERT_BREAK(poolSize > 0);
  704. fShmAudioPool.data = (float*)jackbridge_shm_map(fShmAudioPool.shm, static_cast<size_t>(poolSize));
  705. break;
  706. }
  707. case kPluginBridgeRtClientControlEventParameter: {
  708. const uint32_t time(fShmRtClientControl.readUInt());
  709. const uint8_t channel(fShmRtClientControl.readByte());
  710. const uint16_t param(fShmRtClientControl.readUShort());
  711. const float value(fShmRtClientControl.readFloat());
  712. if (EngineEvent* const event = getNextFreeInputEvent())
  713. {
  714. event->type = kEngineEventTypeControl;
  715. event->time = time;
  716. event->channel = channel;
  717. event->ctrl.type = kEngineControlEventTypeParameter;
  718. event->ctrl.param = param;
  719. event->ctrl.value = value;
  720. }
  721. break;
  722. }
  723. case kPluginBridgeRtClientControlEventMidiBank: {
  724. const uint32_t time(fShmRtClientControl.readUInt());
  725. const uint8_t channel(fShmRtClientControl.readByte());
  726. const uint16_t index(fShmRtClientControl.readUShort());
  727. if (EngineEvent* const event = getNextFreeInputEvent())
  728. {
  729. event->type = kEngineEventTypeControl;
  730. event->time = time;
  731. event->channel = channel;
  732. event->ctrl.type = kEngineControlEventTypeMidiBank;
  733. event->ctrl.param = index;
  734. event->ctrl.value = 0.0f;
  735. }
  736. break;
  737. }
  738. case kPluginBridgeRtClientControlEventMidiProgram: {
  739. const uint32_t time(fShmRtClientControl.readUInt());
  740. const uint8_t channel(fShmRtClientControl.readByte());
  741. const uint16_t index(fShmRtClientControl.readUShort());
  742. if (EngineEvent* const event = getNextFreeInputEvent())
  743. {
  744. event->type = kEngineEventTypeControl;
  745. event->time = time;
  746. event->channel = channel;
  747. event->ctrl.type = kEngineControlEventTypeMidiProgram;
  748. event->ctrl.param = index;
  749. event->ctrl.value = 0.0f;
  750. }
  751. break;
  752. }
  753. case kPluginBridgeRtClientControlEventAllSoundOff: {
  754. const uint32_t time(fShmRtClientControl.readUInt());
  755. const uint8_t channel(fShmRtClientControl.readByte());
  756. if (EngineEvent* const event = getNextFreeInputEvent())
  757. {
  758. event->type = kEngineEventTypeControl;
  759. event->time = time;
  760. event->channel = channel;
  761. event->ctrl.type = kEngineControlEventTypeAllSoundOff;
  762. event->ctrl.param = 0;
  763. event->ctrl.value = 0.0f;
  764. }
  765. }
  766. case kPluginBridgeRtClientControlEventAllNotesOff: {
  767. const uint32_t time(fShmRtClientControl.readUInt());
  768. const uint8_t channel(fShmRtClientControl.readByte());
  769. if (EngineEvent* const event = getNextFreeInputEvent())
  770. {
  771. event->type = kEngineEventTypeControl;
  772. event->time = time;
  773. event->channel = channel;
  774. event->ctrl.type = kEngineControlEventTypeAllNotesOff;
  775. event->ctrl.param = 0;
  776. event->ctrl.value = 0.0f;
  777. }
  778. }
  779. case kPluginBridgeRtClientMidiEvent: {
  780. const uint32_t time(fShmRtClientControl.readUInt());
  781. const uint8_t port(fShmRtClientControl.readByte());
  782. const uint8_t size(fShmRtClientControl.readByte());
  783. CARLA_SAFE_ASSERT_BREAK(size > 0);
  784. uint8_t data[size];
  785. for (uint8_t i=0; i<size; ++i)
  786. data[i] = fShmRtClientControl.readByte();
  787. if (EngineEvent* const event = getNextFreeInputEvent())
  788. {
  789. event->type = kEngineEventTypeMidi;
  790. event->time = time;
  791. event->channel = MIDI_GET_CHANNEL_FROM_DATA(data);
  792. event->midi.port = port;
  793. event->midi.size = size;
  794. if (size > EngineMidiEvent::kDataSize)
  795. {
  796. event->midi.dataExt = data;
  797. std::memset(event->midi.data, 0, sizeof(uint8_t)*EngineMidiEvent::kDataSize);
  798. }
  799. else
  800. {
  801. event->midi.data[0] = MIDI_GET_STATUS_FROM_DATA(data);
  802. uint8_t i=1;
  803. for (; i < size; ++i)
  804. event->midi.data[i] = data[i];
  805. for (; i < EngineMidiEvent::kDataSize; ++i)
  806. event->midi.data[i] = 0;
  807. event->midi.dataExt = nullptr;
  808. }
  809. }
  810. break;
  811. }
  812. case kPluginBridgeRtClientProcess: {
  813. CARLA_SAFE_ASSERT_BREAK(fShmAudioPool.data != nullptr);
  814. if (plugin != nullptr && plugin->isEnabled() && plugin->tryLock(false))
  815. {
  816. const BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo);
  817. const uint32_t audioInCount(plugin->getAudioInCount());
  818. const uint32_t audioOutCount(plugin->getAudioOutCount());
  819. const uint32_t cvInCount(plugin->getCVInCount());
  820. const uint32_t cvOutCount(plugin->getCVOutCount());
  821. const float* audioIn[audioInCount];
  822. /* */ float* audioOut[audioOutCount];
  823. const float* cvIn[cvInCount];
  824. /* */ float* cvOut[cvOutCount];
  825. for (uint32_t i=0; i < audioInCount; ++i)
  826. audioIn[i] = fShmAudioPool.data + i*pData->bufferSize;
  827. for (uint32_t i=0; i < audioOutCount; ++i)
  828. audioOut[i] = fShmAudioPool.data + (i+audioInCount)*pData->bufferSize;
  829. for (uint32_t i=0; i < cvInCount; ++i)
  830. cvIn[i] = fShmAudioPool.data + i*pData->bufferSize;
  831. for (uint32_t i=0; i < cvOutCount; ++i)
  832. cvOut[i] = fShmAudioPool.data + (i+cvInCount)*pData->bufferSize;
  833. EngineTimeInfo& timeInfo(pData->timeInfo);
  834. timeInfo.playing = bridgeTimeInfo.playing;
  835. timeInfo.frame = bridgeTimeInfo.frame;
  836. timeInfo.usecs = bridgeTimeInfo.usecs;
  837. timeInfo.valid = bridgeTimeInfo.valid;
  838. if (timeInfo.valid & EngineTimeInfo::kValidBBT)
  839. {
  840. timeInfo.bbt.bar = bridgeTimeInfo.bar;
  841. timeInfo.bbt.beat = bridgeTimeInfo.beat;
  842. timeInfo.bbt.tick = bridgeTimeInfo.tick;
  843. timeInfo.bbt.beatsPerBar = bridgeTimeInfo.beatsPerBar;
  844. timeInfo.bbt.beatType = bridgeTimeInfo.beatType;
  845. timeInfo.bbt.ticksPerBeat = bridgeTimeInfo.ticksPerBeat;
  846. timeInfo.bbt.beatsPerMinute = bridgeTimeInfo.beatsPerMinute;
  847. timeInfo.bbt.barStartTick = bridgeTimeInfo.barStartTick;
  848. }
  849. plugin->initBuffers();
  850. plugin->process(audioIn, audioOut, cvIn, cvOut, pData->bufferSize);
  851. plugin->unlock();
  852. }
  853. // clear buffer
  854. CARLA_SAFE_ASSERT_BREAK(pData->events.in != nullptr);
  855. if (pData->events.in[0].type != kEngineEventTypeNull)
  856. carla_zeroStruct<EngineEvent>(pData->events.in, kMaxEngineEventInternalCount);
  857. break;
  858. }
  859. case kPluginBridgeRtClientQuit:
  860. signalThreadShouldExit();
  861. break;
  862. }
  863. }
  864. if (! fShmRtClientControl.postClient())
  865. carla_stderr2("Could not post to client rt semaphore");
  866. }
  867. fIsRunning = false;
  868. callback(ENGINE_CALLBACK_ENGINE_STOPPED, 0, 0, 0, 0.0f, nullptr);
  869. }
  870. // called from process thread above
  871. EngineEvent* getNextFreeInputEvent() const noexcept
  872. {
  873. for (ushort i=0; i < kMaxEngineEventInternalCount; ++i)
  874. {
  875. EngineEvent& event(pData->events.in[i]);
  876. if (event.type == kEngineEventTypeNull)
  877. return &event;
  878. }
  879. return nullptr;
  880. }
  881. // -------------------------------------------------------------------
  882. private:
  883. BridgeAudioPool fShmAudioPool;
  884. BridgeRtClientControl fShmRtClientControl;
  885. BridgeNonRtClientControl fShmNonRtClientControl;
  886. BridgeNonRtServerControl fShmNonRtServerControl;
  887. bool fIsRunning;
  888. bool fIsOffline;
  889. bool fFirstIdle;
  890. int32_t fLastPingCounter;
  891. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineBridge)
  892. };
  893. // -----------------------------------------------------------------------
  894. CarlaEngine* CarlaEngine::newBridge(const char* const audioPoolBaseName, const char* const rtClientBaseName, const char* const nonRtClientBaseName, const char* const nonRtServerBaseName)
  895. {
  896. return new CarlaEngineBridge(audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName);
  897. }
  898. // -----------------------------------------------------------------------
  899. #ifdef BRIDGE_PLUGIN
  900. CarlaPlugin* CarlaPlugin::newNative(const CarlaPlugin::Initializer&) { return nullptr; }
  901. CarlaPlugin* CarlaPlugin::newFileGIG(const CarlaPlugin::Initializer&, const bool) { return nullptr; }
  902. CarlaPlugin* CarlaPlugin::newFileSF2(const CarlaPlugin::Initializer&, const bool) { return nullptr; }
  903. CarlaPlugin* CarlaPlugin::newFileSFZ(const CarlaPlugin::Initializer&) { return nullptr; }
  904. #endif
  905. CARLA_BACKEND_END_NAMESPACE
  906. // -----------------------------------------------------------------------
  907. #if defined(CARLA_OS_WIN) && ! defined(__WINE__)
  908. extern "C" __declspec (dllexport)
  909. #else
  910. extern "C" __attribute__ ((visibility("default")))
  911. #endif
  912. void carla_register_native_plugin_carla();
  913. void carla_register_native_plugin_carla(){}
  914. // -----------------------------------------------------------------------