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.

963 lines
32KB

  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. #include <cerrno>
  28. #include <ctime>
  29. using juce::File;
  30. using juce::MemoryBlock;
  31. using juce::String;
  32. // -------------------------------------------------------------------
  33. template<typename T>
  34. bool jackbridge_shm_map2(char* shm, T*& value) noexcept
  35. {
  36. value = (T*)jackbridge_shm_map(shm, sizeof(T));
  37. return (value != nullptr);
  38. }
  39. // -------------------------------------------------------------------
  40. CARLA_BACKEND_START_NAMESPACE
  41. // -------------------------------------------------------------------
  42. struct BridgeAudioPool {
  43. CarlaString filename;
  44. float* data;
  45. char shm[64];
  46. BridgeAudioPool() noexcept
  47. : filename(),
  48. data(nullptr)
  49. {
  50. carla_zeroChar(shm, 64);
  51. jackbridge_shm_init(shm);
  52. }
  53. ~BridgeAudioPool() noexcept
  54. {
  55. // should be cleared by now
  56. CARLA_SAFE_ASSERT(data == nullptr);
  57. clear();
  58. }
  59. bool attach() noexcept
  60. {
  61. jackbridge_shm_attach(shm, filename);
  62. return jackbridge_shm_is_valid(shm);
  63. }
  64. void clear() noexcept
  65. {
  66. filename.clear();
  67. data = nullptr;
  68. if (jackbridge_shm_is_valid(shm))
  69. jackbridge_shm_close(shm);
  70. }
  71. CARLA_DECLARE_NON_COPY_STRUCT(BridgeAudioPool)
  72. };
  73. // -------------------------------------------------------------------
  74. struct BridgeRtControl : public CarlaRingBuffer<StackBuffer> {
  75. CarlaString filename;
  76. BridgeRtData* data;
  77. char shm[64];
  78. BridgeRtControl() noexcept
  79. : filename(),
  80. data(nullptr)
  81. {
  82. carla_zeroChar(shm, 64);
  83. jackbridge_shm_init(shm);
  84. }
  85. ~BridgeRtControl() noexcept override
  86. {
  87. // should be cleared by now
  88. CARLA_SAFE_ASSERT(data == nullptr);
  89. clear();
  90. }
  91. bool attach() noexcept
  92. {
  93. jackbridge_shm_attach(shm, filename);
  94. return jackbridge_shm_is_valid(shm);
  95. }
  96. void clear() noexcept
  97. {
  98. filename.clear();
  99. data = nullptr;
  100. if (jackbridge_shm_is_valid(shm))
  101. jackbridge_shm_close(shm);
  102. }
  103. bool mapData() noexcept
  104. {
  105. CARLA_SAFE_ASSERT(data == nullptr);
  106. if (jackbridge_shm_map2<BridgeRtData>(shm, data))
  107. {
  108. setRingBuffer(&data->ringBuffer, false);
  109. return true;
  110. }
  111. return false;
  112. }
  113. PluginBridgeRtOpcode readOpcode() noexcept
  114. {
  115. return static_cast<PluginBridgeRtOpcode>(readInt());
  116. }
  117. CARLA_DECLARE_NON_COPY_STRUCT(BridgeRtControl)
  118. };
  119. // -------------------------------------------------------------------
  120. struct BridgeNonRtControl : public CarlaRingBuffer<BigStackBuffer> {
  121. CarlaString filename;
  122. BridgeNonRtData* data;
  123. char shm[64];
  124. BridgeNonRtControl() noexcept
  125. : filename(),
  126. data(nullptr)
  127. {
  128. carla_zeroChar(shm, 64);
  129. jackbridge_shm_init(shm);
  130. }
  131. ~BridgeNonRtControl() noexcept override
  132. {
  133. // should be cleared by now
  134. CARLA_SAFE_ASSERT(data == nullptr);
  135. clear();
  136. }
  137. bool attach() noexcept
  138. {
  139. jackbridge_shm_attach(shm, filename);
  140. return jackbridge_shm_is_valid(shm);
  141. }
  142. void clear() noexcept
  143. {
  144. filename.clear();
  145. data = nullptr;
  146. if (jackbridge_shm_is_valid(shm))
  147. jackbridge_shm_close(shm);
  148. }
  149. bool mapData() noexcept
  150. {
  151. CARLA_SAFE_ASSERT(data == nullptr);
  152. if (jackbridge_shm_map2<BridgeNonRtData>(shm, data))
  153. {
  154. setRingBuffer(&data->ringBuffer, false);
  155. return true;
  156. }
  157. return false;
  158. }
  159. PluginBridgeNonRtOpcode readOpcode() noexcept
  160. {
  161. return static_cast<PluginBridgeNonRtOpcode>(readInt());
  162. }
  163. CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtControl)
  164. };
  165. // -------------------------------------------------------------------
  166. class CarlaEngineBridge : public CarlaEngine,
  167. public CarlaThread
  168. {
  169. public:
  170. CarlaEngineBridge(const char* const audioPoolBaseName, const char* const rtBaseName, const char* const nonRtBaseName)
  171. : CarlaEngine(),
  172. CarlaThread("CarlaEngineBridge"),
  173. fShmAudioPool(),
  174. fShmCVPool(),
  175. fShmRtControl(),
  176. fShmNonRtControl(),
  177. fIsRunning(false),
  178. fIsOffline(false),
  179. leakDetector_CarlaEngineBridge()
  180. {
  181. carla_stdout("CarlaEngineBridge::CarlaEngineBridge(\"%s\", \"%s\", \"%s\")", audioPoolBaseName, rtBaseName, nonRtBaseName);
  182. fShmAudioPool.filename = "/carla-bridge_shm_ap_";
  183. fShmAudioPool.filename += audioPoolBaseName;
  184. //fShmCVPool.filename = "/carla-bridge_shm_cvp_";
  185. //fShmCVPool.filename += cvPoolBaseName;
  186. fShmRtControl.filename = "/carla-bridge_shm_rt_";
  187. fShmRtControl.filename += rtBaseName;
  188. fShmNonRtControl.filename = "/carla-bridge_shm_nonrt_";
  189. fShmNonRtControl.filename += nonRtBaseName;
  190. }
  191. ~CarlaEngineBridge() noexcept override
  192. {
  193. carla_debug("CarlaEngineBridge::~CarlaEngineBridge()");
  194. }
  195. // -------------------------------------
  196. // CarlaEngine virtual calls
  197. bool init(const char* const clientName) override
  198. {
  199. carla_debug("CarlaEngineBridge::init(\"%s\")", clientName);
  200. if (! pData->init(clientName))
  201. {
  202. setLastError("Failed to init internal data");
  203. return false;
  204. }
  205. if (! fShmAudioPool.attach())
  206. {
  207. carla_stdout("Failed to attach to audio pool shared memory");
  208. return false;
  209. }
  210. if (! fShmRtControl.attach())
  211. {
  212. clear();
  213. carla_stdout("Failed to attach to rt control shared memory");
  214. return false;
  215. }
  216. if (! fShmRtControl.mapData())
  217. {
  218. clear();
  219. carla_stdout("Failed to map rt control shared memory");
  220. return false;
  221. }
  222. if (! fShmNonRtControl.attach())
  223. {
  224. clear();
  225. carla_stdout("Failed to attach to non-rt control shared memory");
  226. return false;
  227. }
  228. if (! fShmNonRtControl.mapData())
  229. {
  230. clear();
  231. carla_stdout("Failed to map non-rt control shared memory");
  232. return false;
  233. }
  234. PluginBridgeNonRtOpcode opcode;
  235. opcode = fShmNonRtControl.readOpcode();
  236. CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtNull, opcode);
  237. const uint32_t shmRtDataSize = fShmNonRtControl.readUInt();
  238. CARLA_SAFE_ASSERT_INT2(shmRtDataSize == sizeof(BridgeRtData), shmRtDataSize, sizeof(BridgeRtData));
  239. const uint32_t shmNonRtDataSize = fShmNonRtControl.readUInt();
  240. CARLA_SAFE_ASSERT_INT2(shmNonRtDataSize == sizeof(BridgeNonRtData), shmNonRtDataSize, sizeof(BridgeNonRtData));
  241. opcode = fShmNonRtControl.readOpcode();
  242. CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtSetBufferSize, opcode);
  243. pData->bufferSize = fShmNonRtControl.readUInt();
  244. opcode = fShmNonRtControl.readOpcode();
  245. CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtSetSampleRate, opcode);
  246. pData->sampleRate = fShmNonRtControl.readDouble();
  247. carla_stdout("Carla Client Info:");
  248. carla_stdout(" BufferSize: %i", pData->bufferSize);
  249. carla_stdout(" SampleRate: %g", pData->sampleRate);
  250. carla_stdout(" sizeof(BridgeRtData): %i/" P_SIZE, shmRtDataSize, sizeof(BridgeRtData));
  251. carla_stdout(" sizeof(BridgeNonRtData): %i/" P_SIZE, shmNonRtDataSize, sizeof(BridgeNonRtData));
  252. if (shmRtDataSize != sizeof(BridgeRtData) || shmNonRtDataSize != sizeof(BridgeNonRtData))
  253. return false;
  254. startThread();
  255. return true;
  256. }
  257. bool close() override
  258. {
  259. carla_debug("CarlaEnginePlugin::close()");
  260. CarlaEngine::close();
  261. stopThread(5000);
  262. clear();
  263. return true;
  264. }
  265. bool isRunning() const noexcept override
  266. {
  267. return isThreadRunning();
  268. }
  269. bool isOffline() const noexcept override
  270. {
  271. return fIsOffline;
  272. }
  273. EngineType getType() const noexcept override
  274. {
  275. return kEngineTypeBridge;
  276. }
  277. const char* getCurrentDriverName() const noexcept
  278. {
  279. return "Bridge";
  280. }
  281. void idle() noexcept override
  282. {
  283. CarlaEngine::idle();
  284. try {
  285. handleNonRtData();
  286. } CARLA_SAFE_EXCEPTION("handleNonRtData");
  287. }
  288. // -------------------------------------------------------------------
  289. void clear() noexcept
  290. {
  291. fShmAudioPool.clear();
  292. fShmRtControl.clear();
  293. fShmNonRtControl.clear();
  294. }
  295. void handleNonRtData()
  296. {
  297. for (; fShmNonRtControl.isDataAvailableForReading();)
  298. {
  299. const PluginBridgeNonRtOpcode opcode(fShmNonRtControl.readOpcode());
  300. CarlaPlugin* const plugin(pData->plugins[0].plugin);
  301. if (opcode != kPluginBridgeNonRtPing)
  302. carla_stdout("CarlaEngineBridge::handleNonRtData() - got opcode: %s", PluginBridgeNonRtOpcode2str(opcode));
  303. switch (opcode)
  304. {
  305. case kPluginBridgeNonRtNull:
  306. break;
  307. case kPluginBridgeNonRtPing:
  308. oscSend_bridge_pong();
  309. break;
  310. case kPluginBridgeNonRtActivate:
  311. if (plugin != nullptr && plugin->isEnabled())
  312. plugin->setActive(true, false, false);
  313. break;
  314. case kPluginBridgeNonRtDeactivate:
  315. if (plugin != nullptr && plugin->isEnabled())
  316. plugin->setActive(false, false, false);
  317. break;
  318. case kPluginBridgeNonRtSetBufferSize: {
  319. const uint32_t bufferSize(fShmNonRtControl.readUInt());
  320. pData->bufferSize = bufferSize;
  321. bufferSizeChanged(bufferSize);
  322. break;
  323. }
  324. case kPluginBridgeNonRtSetSampleRate: {
  325. const double sampleRate(fShmNonRtControl.readDouble());
  326. pData->sampleRate = sampleRate;
  327. sampleRateChanged(sampleRate);
  328. break;
  329. }
  330. case kPluginBridgeNonRtSetOffline:
  331. fIsOffline = true;
  332. offlineModeChanged(true);
  333. break;
  334. case kPluginBridgeNonRtSetOnline:
  335. fIsOffline = false;
  336. offlineModeChanged(false);
  337. break;
  338. case kPluginBridgeNonRtSetParameterValue: {
  339. const uint32_t index(fShmNonRtControl.readUInt());
  340. const float value(fShmNonRtControl.readFloat());
  341. if (plugin != nullptr && plugin->isEnabled())
  342. plugin->setParameterValue(index, value, false, false, false);
  343. break;
  344. }
  345. case kPluginBridgeNonRtSetParameterMidiChannel: {
  346. const uint32_t index(fShmNonRtControl.readUInt());
  347. const uint8_t channel(fShmNonRtControl.readByte());
  348. if (plugin != nullptr && plugin->isEnabled())
  349. plugin->setParameterMidiChannel(index, channel, false, false);
  350. break;
  351. }
  352. case kPluginBridgeNonRtSetParameterMidiCC: {
  353. const uint32_t index(fShmNonRtControl.readUInt());
  354. const int16_t cc(fShmNonRtControl.readShort());
  355. if (plugin != nullptr && plugin->isEnabled())
  356. plugin->setParameterMidiCC(index, cc, false, false);
  357. break;
  358. }
  359. case kPluginBridgeNonRtSetProgram: {
  360. const int32_t index(fShmNonRtControl.readInt());
  361. if (plugin != nullptr && plugin->isEnabled())
  362. plugin->setProgram(index, false, false, false);
  363. break;
  364. }
  365. case kPluginBridgeNonRtSetMidiProgram: {
  366. const int32_t index(fShmNonRtControl.readInt());
  367. if (plugin != nullptr && plugin->isEnabled())
  368. plugin->setMidiProgram(index, false, false, false);
  369. break;
  370. }
  371. case kPluginBridgeNonRtSetCustomData: {
  372. // type
  373. const uint32_t typeSize(fShmNonRtControl.readUInt());
  374. char typeStr[typeSize+1];
  375. carla_zeroChar(typeStr, typeSize+1);
  376. fShmNonRtControl.readCustomData(typeStr, typeSize);
  377. // key
  378. const uint32_t keySize(fShmNonRtControl.readUInt());
  379. char keyStr[keySize+1];
  380. carla_zeroChar(keyStr, keySize+1);
  381. fShmNonRtControl.readCustomData(keyStr, keySize);
  382. // value
  383. const uint32_t valueSize(fShmNonRtControl.readUInt());
  384. char valueStr[valueSize+1];
  385. carla_zeroChar(valueStr, valueSize+1);
  386. fShmNonRtControl.readCustomData(valueStr, valueSize);
  387. if (plugin != nullptr && plugin->isEnabled())
  388. plugin->setCustomData(typeStr, keyStr, valueStr, true);
  389. break;
  390. }
  391. case kPluginBridgeNonRtSetChunkDataFile: {
  392. const uint32_t size(fShmNonRtControl.readUInt());
  393. CARLA_SAFE_ASSERT_BREAK(size > 0);
  394. char chunkFilePathTry[size+1];
  395. carla_zeroChar(chunkFilePathTry, size+1);
  396. fShmNonRtControl.readCustomData(chunkFilePathTry, size);
  397. CARLA_SAFE_ASSERT_BREAK(chunkFilePathTry[0] != '\0');
  398. if (plugin == nullptr || ! plugin->isEnabled()) break;
  399. String chunkFilePath(chunkFilePathTry);
  400. #ifdef CARLA_OS_WIN
  401. // check if running under Wine
  402. if (chunkFilePath.startsWith("/"))
  403. chunkFilePath = chunkFilePath.replaceSection(0, 1, "Z:\\").replace("/", "\\");
  404. #endif
  405. File chunkFile(chunkFilePath);
  406. CARLA_SAFE_ASSERT_BREAK(chunkFile.existsAsFile());
  407. String chunkDataBase64(chunkFile.loadFileAsString());
  408. chunkFile.deleteFile();
  409. CARLA_SAFE_ASSERT_BREAK(chunkDataBase64.isNotEmpty());
  410. std::vector<uint8_t> chunk(carla_getChunkFromBase64String(chunkDataBase64.toRawUTF8()));
  411. plugin->setChunkData(chunk.data(), chunk.size());
  412. break;
  413. }
  414. case kPluginBridgeNonRtSetCtrlChannel: {
  415. const int16_t channel(fShmNonRtControl.readShort());
  416. CARLA_SAFE_ASSERT_BREAK(channel >= -1 && channel < MAX_MIDI_CHANNELS);
  417. if (plugin != nullptr && plugin->isEnabled())
  418. plugin->setCtrlChannel(static_cast<int8_t>(channel), false, false);
  419. break;
  420. }
  421. case kPluginBridgeNonRtSetOscURL: {
  422. const uint32_t size(fShmNonRtControl.readUInt());
  423. char url[size+1];
  424. carla_zeroChar(url, size+1);
  425. fShmNonRtControl.readCustomData(url, size);
  426. CARLA_SAFE_ASSERT_BREAK(url[0] != '\0');
  427. if (plugin == nullptr || ! plugin->isEnabled()) break;
  428. pData->oscData->setNewURL(url);
  429. break;
  430. }
  431. case kPluginBridgeNonRtSetOption: {
  432. const uint32_t option(fShmNonRtControl.readUInt());
  433. const bool yesNo(fShmNonRtControl.readBool());
  434. if (plugin != nullptr && plugin->isEnabled())
  435. plugin->setOption(option, yesNo, false);
  436. break;
  437. }
  438. case kPluginBridgeNonRtPrepareForSave: {
  439. if (plugin == nullptr || ! plugin->isEnabled()) break;
  440. plugin->prepareForSave();
  441. for (uint32_t i=0, count=plugin->getCustomDataCount(); i<count; ++i)
  442. {
  443. const CustomData& cdata(plugin->getCustomData(i));
  444. oscSend_bridge_set_custom_data(cdata.type, cdata.key, cdata.value);
  445. }
  446. if (plugin->getOptionsEnabled() & PLUGIN_OPTION_USE_CHUNKS)
  447. {
  448. void* data = nullptr;
  449. if (const std::size_t dataSize = plugin->getChunkData(&data))
  450. {
  451. CARLA_SAFE_ASSERT_BREAK(data != nullptr);
  452. CarlaString dataBase64 = CarlaString::asBase64(data, dataSize);
  453. CARLA_SAFE_ASSERT_BREAK(dataBase64.length() > 0);
  454. String filePath(File::getSpecialLocation(File::tempDirectory).getFullPathName());
  455. filePath += CARLA_OS_SEP_STR;
  456. filePath += ".CarlaChunk_";
  457. filePath += fShmNonRtControl.filename.buffer() + 24;
  458. if (File(filePath).replaceWithText(dataBase64.buffer()))
  459. oscSend_bridge_set_chunk_data_file(filePath.toRawUTF8());
  460. }
  461. }
  462. oscSend_bridge_configure(CARLA_BRIDGE_MSG_SAVED, "");
  463. break;
  464. }
  465. case kPluginBridgeNonRtShowUI:
  466. if (plugin != nullptr && plugin->isEnabled())
  467. plugin->showCustomUI(true);
  468. break;
  469. case kPluginBridgeNonRtHideUI:
  470. if (plugin != nullptr && plugin->isEnabled())
  471. plugin->showCustomUI(false);
  472. break;
  473. case kPluginBridgeNonRtUiParameterChange: {
  474. const uint32_t index(fShmNonRtControl.readUInt());
  475. const float value(fShmNonRtControl.readFloat());
  476. if (plugin != nullptr && plugin->isEnabled())
  477. plugin->uiParameterChange(index, value);
  478. break;
  479. }
  480. case kPluginBridgeNonRtUiProgramChange: {
  481. const uint32_t index(fShmNonRtControl.readUInt());
  482. if (plugin != nullptr && plugin->isEnabled())
  483. plugin->uiProgramChange(index);
  484. break;
  485. }
  486. case kPluginBridgeNonRtUiMidiProgramChange: {
  487. const uint32_t index(fShmNonRtControl.readUInt());
  488. if (plugin != nullptr && plugin->isEnabled())
  489. plugin->uiMidiProgramChange(index);
  490. break;
  491. }
  492. case kPluginBridgeNonRtUiNoteOn: {
  493. const uint8_t chnl(fShmNonRtControl.readByte());
  494. const uint8_t note(fShmNonRtControl.readByte());
  495. const uint8_t velo(fShmNonRtControl.readByte());
  496. if (plugin != nullptr && plugin->isEnabled())
  497. plugin->uiNoteOn(chnl, note, velo);
  498. break;
  499. }
  500. case kPluginBridgeNonRtUiNoteOff: {
  501. const uint8_t chnl(fShmNonRtControl.readByte());
  502. const uint8_t note(fShmNonRtControl.readByte());
  503. if (plugin != nullptr && plugin->isEnabled())
  504. plugin->uiNoteOff(chnl, note);
  505. break;
  506. }
  507. case kPluginBridgeNonRtQuit:
  508. signalThreadShouldExit();
  509. callback(ENGINE_CALLBACK_QUIT, 0, 0, 0, 0.0f, nullptr);
  510. break;
  511. }
  512. }
  513. }
  514. // -------------------------------------------------------------------
  515. protected:
  516. void run() override
  517. {
  518. for (; ! shouldThreadExit();)
  519. {
  520. if (! jackbridge_sem_timedwait(&fShmRtControl.data->sem.server, 5))
  521. {
  522. if (errno == ETIMEDOUT)
  523. {
  524. signalThreadShouldExit();
  525. break;
  526. }
  527. }
  528. for (; fShmRtControl.isDataAvailableForReading();)
  529. {
  530. const PluginBridgeRtOpcode opcode(fShmRtControl.readOpcode());
  531. CarlaPlugin* const plugin(pData->plugins[0].plugin);
  532. if (opcode != kPluginBridgeRtProcess && opcode != kPluginBridgeRtMidiEvent) {
  533. carla_stdout("CarlaEngineBridgeRtThread::run() - got opcode: %s", PluginBridgeRtOpcode2str(opcode));
  534. }
  535. switch (opcode)
  536. {
  537. case kPluginBridgeRtNull:
  538. break;
  539. case kPluginBridgeRtSetAudioPool: {
  540. const uint64_t poolSize(fShmRtControl.readULong());
  541. CARLA_SAFE_ASSERT_BREAK(poolSize > 0);
  542. fShmAudioPool.data = (float*)jackbridge_shm_map(fShmAudioPool.shm, static_cast<size_t>(poolSize));
  543. break;
  544. }
  545. case kPluginBridgeRtSetCVPool: {
  546. const uint64_t poolSize(fShmRtControl.readULong());
  547. CARLA_SAFE_ASSERT_BREAK(poolSize > 0);
  548. fShmCVPool.data = (float*)jackbridge_shm_map(fShmCVPool.shm, static_cast<size_t>(poolSize));
  549. break;
  550. }
  551. case kPluginBridgeRtControlEventParameter: {
  552. const uint32_t time(fShmRtControl.readUInt());
  553. const uint8_t channel(fShmRtControl.readByte());
  554. const uint16_t param(fShmRtControl.readUShort());
  555. const float value(fShmRtControl.readFloat());
  556. if (EngineEvent* const event = getNextFreeInputEvent())
  557. {
  558. event->type = kEngineEventTypeControl;
  559. event->time = time;
  560. event->channel = channel;
  561. event->ctrl.type = kEngineControlEventTypeParameter;
  562. event->ctrl.param = param;
  563. event->ctrl.value = value;
  564. }
  565. break;
  566. }
  567. case kPluginBridgeRtControlEventMidiBank: {
  568. const uint32_t time(fShmRtControl.readUInt());
  569. const uint8_t channel(fShmRtControl.readByte());
  570. const uint16_t index(fShmRtControl.readUShort());
  571. if (EngineEvent* const event = getNextFreeInputEvent())
  572. {
  573. event->type = kEngineEventTypeControl;
  574. event->time = time;
  575. event->channel = channel;
  576. event->ctrl.type = kEngineControlEventTypeMidiBank;
  577. event->ctrl.param = index;
  578. event->ctrl.value = 0.0f;
  579. }
  580. break;
  581. }
  582. case kPluginBridgeRtControlEventMidiProgram: {
  583. const uint32_t time(fShmRtControl.readUInt());
  584. const uint8_t channel(fShmRtControl.readByte());
  585. const uint16_t index(fShmRtControl.readUShort());
  586. if (EngineEvent* const event = getNextFreeInputEvent())
  587. {
  588. event->type = kEngineEventTypeControl;
  589. event->time = time;
  590. event->channel = channel;
  591. event->ctrl.type = kEngineControlEventTypeMidiProgram;
  592. event->ctrl.param = index;
  593. event->ctrl.value = 0.0f;
  594. }
  595. break;
  596. }
  597. case kPluginBridgeRtControlEventAllSoundOff: {
  598. const uint32_t time(fShmRtControl.readUInt());
  599. const uint8_t channel(fShmRtControl.readByte());
  600. if (EngineEvent* const event = getNextFreeInputEvent())
  601. {
  602. event->type = kEngineEventTypeControl;
  603. event->time = time;
  604. event->channel = channel;
  605. event->ctrl.type = kEngineControlEventTypeAllSoundOff;
  606. event->ctrl.param = 0;
  607. event->ctrl.value = 0.0f;
  608. }
  609. }
  610. case kPluginBridgeRtControlEventAllNotesOff: {
  611. const uint32_t time(fShmRtControl.readUInt());
  612. const uint8_t channel(fShmRtControl.readByte());
  613. if (EngineEvent* const event = getNextFreeInputEvent())
  614. {
  615. event->type = kEngineEventTypeControl;
  616. event->time = time;
  617. event->channel = channel;
  618. event->ctrl.type = kEngineControlEventTypeAllNotesOff;
  619. event->ctrl.param = 0;
  620. event->ctrl.value = 0.0f;
  621. }
  622. }
  623. case kPluginBridgeRtMidiEvent: {
  624. const uint32_t time(fShmRtControl.readUInt());
  625. const uint8_t port(fShmRtControl.readByte());
  626. const uint8_t size(fShmRtControl.readByte());
  627. CARLA_SAFE_ASSERT_BREAK(size > 0);
  628. uint8_t data[size];
  629. for (uint8_t i=0; i<size; ++i)
  630. data[i] = fShmRtControl.readByte();
  631. if (EngineEvent* const event = getNextFreeInputEvent())
  632. {
  633. event->type = kEngineEventTypeMidi;
  634. event->time = time;
  635. event->channel = MIDI_GET_CHANNEL_FROM_DATA(data);
  636. event->midi.port = port;
  637. event->midi.size = size;
  638. if (size > EngineMidiEvent::kDataSize)
  639. {
  640. event->midi.dataExt = data;
  641. std::memset(event->midi.data, 0, sizeof(uint8_t)*EngineMidiEvent::kDataSize);
  642. }
  643. else
  644. {
  645. event->midi.data[0] = MIDI_GET_STATUS_FROM_DATA(data);
  646. uint8_t i=1;
  647. for (; i < size; ++i)
  648. event->midi.data[i] = data[i];
  649. for (; i < EngineMidiEvent::kDataSize; ++i)
  650. event->midi.data[i] = 0;
  651. event->midi.dataExt = nullptr;
  652. }
  653. }
  654. break;
  655. }
  656. case kPluginBridgeRtProcess: {
  657. CARLA_SAFE_ASSERT_BREAK(fShmAudioPool.data != nullptr);
  658. if (plugin != nullptr && plugin->isEnabled() && plugin->tryLock(false))
  659. {
  660. const BridgeTimeInfo& bridgeTimeInfo(fShmRtControl.data->timeInfo);
  661. const uint32_t audioInCount(plugin->getAudioInCount());
  662. const uint32_t audioOutCount(plugin->getAudioOutCount());
  663. const uint32_t cvInCount(plugin->getCVInCount());
  664. const uint32_t cvOutCount(plugin->getCVOutCount());
  665. const float* audioIn[audioInCount];
  666. /* */ float* audioOut[audioOutCount];
  667. const float* cvIn[cvInCount];
  668. /* */ float* cvOut[cvOutCount];
  669. for (uint32_t i=0; i < audioInCount; ++i)
  670. audioIn[i] = fShmAudioPool.data + i*pData->bufferSize;
  671. for (uint32_t i=0; i < audioOutCount; ++i)
  672. audioOut[i] = fShmAudioPool.data + (i+audioInCount)*pData->bufferSize;
  673. for (uint32_t i=0; i < cvInCount; ++i)
  674. cvIn[i] = fShmAudioPool.data + i*pData->bufferSize;
  675. for (uint32_t i=0; i < cvOutCount; ++i)
  676. cvOut[i] = fShmAudioPool.data + (i+cvInCount)*pData->bufferSize;
  677. EngineTimeInfo& timeInfo(pData->timeInfo);
  678. timeInfo.playing = bridgeTimeInfo.playing;
  679. timeInfo.frame = bridgeTimeInfo.frame;
  680. timeInfo.usecs = bridgeTimeInfo.usecs;
  681. timeInfo.valid = bridgeTimeInfo.valid;
  682. if (timeInfo.valid & EngineTimeInfo::kValidBBT)
  683. {
  684. timeInfo.bbt.bar = bridgeTimeInfo.bar;
  685. timeInfo.bbt.beat = bridgeTimeInfo.beat;
  686. timeInfo.bbt.tick = bridgeTimeInfo.tick;
  687. timeInfo.bbt.beatsPerBar = bridgeTimeInfo.beatsPerBar;
  688. timeInfo.bbt.beatType = bridgeTimeInfo.beatType;
  689. timeInfo.bbt.ticksPerBeat = bridgeTimeInfo.ticksPerBeat;
  690. timeInfo.bbt.beatsPerMinute = bridgeTimeInfo.beatsPerMinute;
  691. timeInfo.bbt.barStartTick = bridgeTimeInfo.barStartTick;
  692. }
  693. plugin->initBuffers();
  694. plugin->process(audioIn, audioOut, cvIn, cvOut, pData->bufferSize);
  695. plugin->unlock();
  696. }
  697. // clear buffer
  698. CARLA_SAFE_ASSERT_BREAK(pData->events.in != nullptr);
  699. if (pData->events.in[0].type != kEngineEventTypeNull)
  700. carla_zeroStruct<EngineEvent>(pData->events.in, kMaxEngineEventInternalCount);
  701. break;
  702. }
  703. case kPluginBridgeRtQuit:
  704. signalThreadShouldExit();
  705. break;
  706. }
  707. }
  708. if (! jackbridge_sem_post(&fShmRtControl.data->sem.client))
  709. carla_stderr2("Could not post to rt semaphore");
  710. }
  711. fIsRunning = false;
  712. callback(ENGINE_CALLBACK_ENGINE_STOPPED, 0, 0, 0, 0.0f, nullptr);
  713. }
  714. // called from process thread above
  715. EngineEvent* getNextFreeInputEvent() const noexcept
  716. {
  717. for (ushort i=0; i < kMaxEngineEventInternalCount; ++i)
  718. {
  719. EngineEvent& event(pData->events.in[i]);
  720. if (event.type == kEngineEventTypeNull)
  721. return &event;
  722. }
  723. return nullptr;
  724. }
  725. // -------------------------------------------------------------------
  726. private:
  727. BridgeAudioPool fShmAudioPool;
  728. BridgeAudioPool fShmCVPool;
  729. BridgeRtControl fShmRtControl;
  730. BridgeNonRtControl fShmNonRtControl;
  731. bool fIsRunning;
  732. bool fIsOffline;
  733. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineBridge)
  734. };
  735. // -----------------------------------------------------------------------
  736. CarlaEngine* CarlaEngine::newBridge(const char* const audioPoolBaseName, const char* const rtBaseName, const char* const nonRtBaseName)
  737. {
  738. return new CarlaEngineBridge(audioPoolBaseName, rtBaseName, nonRtBaseName);
  739. }
  740. // -----------------------------------------------------------------------
  741. #ifdef BRIDGE_PLUGIN
  742. CarlaPlugin* CarlaPlugin::newNative(const CarlaPlugin::Initializer&) { return nullptr; }
  743. CarlaPlugin* CarlaPlugin::newFileGIG(const CarlaPlugin::Initializer&, const bool) { return nullptr; }
  744. CarlaPlugin* CarlaPlugin::newFileSF2(const CarlaPlugin::Initializer&, const bool) { return nullptr; }
  745. CarlaPlugin* CarlaPlugin::newFileSFZ(const CarlaPlugin::Initializer&) { return nullptr; }
  746. #endif
  747. CARLA_BACKEND_END_NAMESPACE
  748. // -----------------------------------------------------------------------
  749. #if defined(CARLA_OS_WIN) && ! defined(__WINE__)
  750. extern "C" __declspec (dllexport)
  751. #else
  752. extern "C" __attribute__ ((visibility("default")))
  753. #endif
  754. void carla_register_native_plugin_carla();
  755. void carla_register_native_plugin_carla(){}
  756. // -----------------------------------------------------------------------