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.

1053 lines
35KB

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