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.

968 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. #ifdef DEBUG
  302. if (opcode != kPluginBridgeNonRtPing) {
  303. carla_debug("CarlaEngineBridge::handleNonRtData() - got opcode: %s", PluginBridgeNonRtOpcode2str(opcode));
  304. }
  305. #endif
  306. switch (opcode)
  307. {
  308. case kPluginBridgeNonRtNull:
  309. break;
  310. case kPluginBridgeNonRtPing:
  311. oscSend_bridge_pong();
  312. break;
  313. case kPluginBridgeNonRtActivate:
  314. if (plugin != nullptr && plugin->isEnabled())
  315. plugin->setActive(true, false, false);
  316. break;
  317. case kPluginBridgeNonRtDeactivate:
  318. if (plugin != nullptr && plugin->isEnabled())
  319. plugin->setActive(false, false, false);
  320. break;
  321. case kPluginBridgeNonRtSetBufferSize: {
  322. const uint32_t bufferSize(fShmNonRtControl.readUInt());
  323. pData->bufferSize = bufferSize;
  324. bufferSizeChanged(bufferSize);
  325. break;
  326. }
  327. case kPluginBridgeNonRtSetSampleRate: {
  328. const double sampleRate(fShmNonRtControl.readDouble());
  329. pData->sampleRate = sampleRate;
  330. sampleRateChanged(sampleRate);
  331. break;
  332. }
  333. case kPluginBridgeNonRtSetOffline:
  334. fIsOffline = true;
  335. offlineModeChanged(true);
  336. break;
  337. case kPluginBridgeNonRtSetOnline:
  338. fIsOffline = false;
  339. offlineModeChanged(false);
  340. break;
  341. case kPluginBridgeNonRtSetParameterValue: {
  342. const uint32_t index(fShmNonRtControl.readUInt());
  343. const float value(fShmNonRtControl.readFloat());
  344. if (plugin != nullptr && plugin->isEnabled())
  345. plugin->setParameterValue(index, value, false, false, false);
  346. break;
  347. }
  348. case kPluginBridgeNonRtSetParameterMidiChannel: {
  349. const uint32_t index(fShmNonRtControl.readUInt());
  350. const uint8_t channel(fShmNonRtControl.readByte());
  351. if (plugin != nullptr && plugin->isEnabled())
  352. plugin->setParameterMidiChannel(index, channel, false, false);
  353. break;
  354. }
  355. case kPluginBridgeNonRtSetParameterMidiCC: {
  356. const uint32_t index(fShmNonRtControl.readUInt());
  357. const int16_t cc(fShmNonRtControl.readShort());
  358. if (plugin != nullptr && plugin->isEnabled())
  359. plugin->setParameterMidiCC(index, cc, false, false);
  360. break;
  361. }
  362. case kPluginBridgeNonRtSetProgram: {
  363. const int32_t index(fShmNonRtControl.readInt());
  364. if (plugin != nullptr && plugin->isEnabled())
  365. plugin->setProgram(index, false, false, false);
  366. break;
  367. }
  368. case kPluginBridgeNonRtSetMidiProgram: {
  369. const int32_t index(fShmNonRtControl.readInt());
  370. if (plugin != nullptr && plugin->isEnabled())
  371. plugin->setMidiProgram(index, false, false, false);
  372. break;
  373. }
  374. case kPluginBridgeNonRtSetCustomData: {
  375. // type
  376. const uint32_t typeSize(fShmNonRtControl.readUInt());
  377. char typeStr[typeSize+1];
  378. carla_zeroChar(typeStr, typeSize+1);
  379. fShmNonRtControl.readCustomData(typeStr, typeSize);
  380. // key
  381. const uint32_t keySize(fShmNonRtControl.readUInt());
  382. char keyStr[keySize+1];
  383. carla_zeroChar(keyStr, keySize+1);
  384. fShmNonRtControl.readCustomData(keyStr, keySize);
  385. // value
  386. const uint32_t valueSize(fShmNonRtControl.readUInt());
  387. char valueStr[valueSize+1];
  388. carla_zeroChar(valueStr, valueSize+1);
  389. fShmNonRtControl.readCustomData(valueStr, valueSize);
  390. if (plugin != nullptr && plugin->isEnabled())
  391. plugin->setCustomData(typeStr, keyStr, valueStr, true);
  392. break;
  393. }
  394. case kPluginBridgeNonRtSetChunkDataFile: {
  395. const uint32_t size(fShmNonRtControl.readUInt());
  396. CARLA_SAFE_ASSERT_BREAK(size > 0);
  397. char chunkFilePathTry[size+1];
  398. carla_zeroChar(chunkFilePathTry, size+1);
  399. fShmNonRtControl.readCustomData(chunkFilePathTry, size);
  400. CARLA_SAFE_ASSERT_BREAK(chunkFilePathTry[0] != '\0');
  401. if (plugin == nullptr || ! plugin->isEnabled()) break;
  402. String chunkFilePath(chunkFilePathTry);
  403. #ifdef CARLA_OS_WIN
  404. // check if running under Wine
  405. if (chunkFilePath.startsWith("/"))
  406. chunkFilePath = chunkFilePath.replaceSection(0, 1, "Z:\\").replace("/", "\\");
  407. #endif
  408. File chunkFile(chunkFilePath);
  409. CARLA_SAFE_ASSERT_BREAK(chunkFile.existsAsFile());
  410. String chunkDataBase64(chunkFile.loadFileAsString());
  411. chunkFile.deleteFile();
  412. CARLA_SAFE_ASSERT_BREAK(chunkDataBase64.isNotEmpty());
  413. std::vector<uint8_t> chunk(carla_getChunkFromBase64String(chunkDataBase64.toRawUTF8()));
  414. plugin->setChunkData(chunk.data(), chunk.size());
  415. break;
  416. }
  417. case kPluginBridgeNonRtSetCtrlChannel: {
  418. const int16_t channel(fShmNonRtControl.readShort());
  419. CARLA_SAFE_ASSERT_BREAK(channel >= -1 && channel < MAX_MIDI_CHANNELS);
  420. if (plugin != nullptr && plugin->isEnabled())
  421. plugin->setCtrlChannel(static_cast<int8_t>(channel), false, false);
  422. break;
  423. }
  424. case kPluginBridgeNonRtSetOscURL: {
  425. const uint32_t size(fShmNonRtControl.readUInt());
  426. char url[size+1];
  427. carla_zeroChar(url, size+1);
  428. fShmNonRtControl.readCustomData(url, size);
  429. CARLA_SAFE_ASSERT_BREAK(url[0] != '\0');
  430. if (plugin == nullptr || ! plugin->isEnabled()) break;
  431. pData->oscData->setNewURL(url);
  432. break;
  433. }
  434. case kPluginBridgeNonRtSetOption: {
  435. const uint32_t option(fShmNonRtControl.readUInt());
  436. const bool yesNo(fShmNonRtControl.readBool());
  437. if (plugin != nullptr && plugin->isEnabled())
  438. plugin->setOption(option, yesNo, false);
  439. break;
  440. }
  441. case kPluginBridgeNonRtPrepareForSave: {
  442. if (plugin == nullptr || ! plugin->isEnabled()) break;
  443. plugin->prepareForSave();
  444. for (uint32_t i=0, count=plugin->getCustomDataCount(); i<count; ++i)
  445. {
  446. const CustomData& cdata(plugin->getCustomData(i));
  447. oscSend_bridge_set_custom_data(cdata.type, cdata.key, cdata.value);
  448. }
  449. if (plugin->getOptionsEnabled() & PLUGIN_OPTION_USE_CHUNKS)
  450. {
  451. void* data = nullptr;
  452. if (const std::size_t dataSize = plugin->getChunkData(&data))
  453. {
  454. CARLA_SAFE_ASSERT_BREAK(data != nullptr);
  455. CarlaString dataBase64 = CarlaString::asBase64(data, dataSize);
  456. CARLA_SAFE_ASSERT_BREAK(dataBase64.length() > 0);
  457. String filePath(File::getSpecialLocation(File::tempDirectory).getFullPathName());
  458. filePath += CARLA_OS_SEP_STR;
  459. filePath += ".CarlaChunk_";
  460. filePath += fShmNonRtControl.filename.buffer() + 24;
  461. if (File(filePath).replaceWithText(dataBase64.buffer()))
  462. oscSend_bridge_set_chunk_data_file(filePath.toRawUTF8());
  463. }
  464. }
  465. oscSend_bridge_configure(CARLA_BRIDGE_MSG_SAVED, "");
  466. break;
  467. }
  468. case kPluginBridgeNonRtShowUI:
  469. if (plugin != nullptr && plugin->isEnabled())
  470. plugin->showCustomUI(true);
  471. break;
  472. case kPluginBridgeNonRtHideUI:
  473. if (plugin != nullptr && plugin->isEnabled())
  474. plugin->showCustomUI(false);
  475. break;
  476. case kPluginBridgeNonRtUiParameterChange: {
  477. const uint32_t index(fShmNonRtControl.readUInt());
  478. const float value(fShmNonRtControl.readFloat());
  479. if (plugin != nullptr && plugin->isEnabled())
  480. plugin->uiParameterChange(index, value);
  481. break;
  482. }
  483. case kPluginBridgeNonRtUiProgramChange: {
  484. const uint32_t index(fShmNonRtControl.readUInt());
  485. if (plugin != nullptr && plugin->isEnabled())
  486. plugin->uiProgramChange(index);
  487. break;
  488. }
  489. case kPluginBridgeNonRtUiMidiProgramChange: {
  490. const uint32_t index(fShmNonRtControl.readUInt());
  491. if (plugin != nullptr && plugin->isEnabled())
  492. plugin->uiMidiProgramChange(index);
  493. break;
  494. }
  495. case kPluginBridgeNonRtUiNoteOn: {
  496. const uint8_t chnl(fShmNonRtControl.readByte());
  497. const uint8_t note(fShmNonRtControl.readByte());
  498. const uint8_t velo(fShmNonRtControl.readByte());
  499. if (plugin != nullptr && plugin->isEnabled())
  500. plugin->uiNoteOn(chnl, note, velo);
  501. break;
  502. }
  503. case kPluginBridgeNonRtUiNoteOff: {
  504. const uint8_t chnl(fShmNonRtControl.readByte());
  505. const uint8_t note(fShmNonRtControl.readByte());
  506. if (plugin != nullptr && plugin->isEnabled())
  507. plugin->uiNoteOff(chnl, note);
  508. break;
  509. }
  510. case kPluginBridgeNonRtQuit:
  511. signalThreadShouldExit();
  512. callback(ENGINE_CALLBACK_QUIT, 0, 0, 0, 0.0f, nullptr);
  513. break;
  514. }
  515. }
  516. }
  517. // -------------------------------------------------------------------
  518. protected:
  519. void run() override
  520. {
  521. for (; ! shouldThreadExit();)
  522. {
  523. if (! jackbridge_sem_timedwait(&fShmRtControl.data->sem.server, 5))
  524. {
  525. if (errno == ETIMEDOUT)
  526. {
  527. signalThreadShouldExit();
  528. break;
  529. }
  530. }
  531. for (; fShmRtControl.isDataAvailableForReading();)
  532. {
  533. const PluginBridgeRtOpcode opcode(fShmRtControl.readOpcode());
  534. CarlaPlugin* const plugin(pData->plugins[0].plugin);
  535. #ifdef DEBUG
  536. if (opcode != kPluginBridgeRtProcess && opcode != kPluginBridgeRtMidiEvent) {
  537. carla_debug("CarlaEngineBridgeRtThread::run() - got opcode: %s", PluginBridgeRtOpcode2str(opcode));
  538. }
  539. #endif
  540. switch (opcode)
  541. {
  542. case kPluginBridgeRtNull:
  543. break;
  544. case kPluginBridgeRtSetAudioPool: {
  545. const uint64_t poolSize(fShmRtControl.readULong());
  546. CARLA_SAFE_ASSERT_BREAK(poolSize > 0);
  547. fShmAudioPool.data = (float*)jackbridge_shm_map(fShmAudioPool.shm, static_cast<size_t>(poolSize));
  548. break;
  549. }
  550. case kPluginBridgeRtSetCVPool: {
  551. const uint64_t poolSize(fShmRtControl.readULong());
  552. CARLA_SAFE_ASSERT_BREAK(poolSize > 0);
  553. //fShmCVPool.data = (float*)jackbridge_shm_map(fShmCVPool.shm, static_cast<size_t>(poolSize));
  554. break;
  555. }
  556. case kPluginBridgeRtControlEventParameter: {
  557. const uint32_t time(fShmRtControl.readUInt());
  558. const uint8_t channel(fShmRtControl.readByte());
  559. const uint16_t param(fShmRtControl.readUShort());
  560. const float value(fShmRtControl.readFloat());
  561. if (EngineEvent* const event = getNextFreeInputEvent())
  562. {
  563. event->type = kEngineEventTypeControl;
  564. event->time = time;
  565. event->channel = channel;
  566. event->ctrl.type = kEngineControlEventTypeParameter;
  567. event->ctrl.param = param;
  568. event->ctrl.value = value;
  569. }
  570. break;
  571. }
  572. case kPluginBridgeRtControlEventMidiBank: {
  573. const uint32_t time(fShmRtControl.readUInt());
  574. const uint8_t channel(fShmRtControl.readByte());
  575. const uint16_t index(fShmRtControl.readUShort());
  576. if (EngineEvent* const event = getNextFreeInputEvent())
  577. {
  578. event->type = kEngineEventTypeControl;
  579. event->time = time;
  580. event->channel = channel;
  581. event->ctrl.type = kEngineControlEventTypeMidiBank;
  582. event->ctrl.param = index;
  583. event->ctrl.value = 0.0f;
  584. }
  585. break;
  586. }
  587. case kPluginBridgeRtControlEventMidiProgram: {
  588. const uint32_t time(fShmRtControl.readUInt());
  589. const uint8_t channel(fShmRtControl.readByte());
  590. const uint16_t index(fShmRtControl.readUShort());
  591. if (EngineEvent* const event = getNextFreeInputEvent())
  592. {
  593. event->type = kEngineEventTypeControl;
  594. event->time = time;
  595. event->channel = channel;
  596. event->ctrl.type = kEngineControlEventTypeMidiProgram;
  597. event->ctrl.param = index;
  598. event->ctrl.value = 0.0f;
  599. }
  600. break;
  601. }
  602. case kPluginBridgeRtControlEventAllSoundOff: {
  603. const uint32_t time(fShmRtControl.readUInt());
  604. const uint8_t channel(fShmRtControl.readByte());
  605. if (EngineEvent* const event = getNextFreeInputEvent())
  606. {
  607. event->type = kEngineEventTypeControl;
  608. event->time = time;
  609. event->channel = channel;
  610. event->ctrl.type = kEngineControlEventTypeAllSoundOff;
  611. event->ctrl.param = 0;
  612. event->ctrl.value = 0.0f;
  613. }
  614. }
  615. case kPluginBridgeRtControlEventAllNotesOff: {
  616. const uint32_t time(fShmRtControl.readUInt());
  617. const uint8_t channel(fShmRtControl.readByte());
  618. if (EngineEvent* const event = getNextFreeInputEvent())
  619. {
  620. event->type = kEngineEventTypeControl;
  621. event->time = time;
  622. event->channel = channel;
  623. event->ctrl.type = kEngineControlEventTypeAllNotesOff;
  624. event->ctrl.param = 0;
  625. event->ctrl.value = 0.0f;
  626. }
  627. }
  628. case kPluginBridgeRtMidiEvent: {
  629. const uint32_t time(fShmRtControl.readUInt());
  630. const uint8_t port(fShmRtControl.readByte());
  631. const uint8_t size(fShmRtControl.readByte());
  632. CARLA_SAFE_ASSERT_BREAK(size > 0);
  633. uint8_t data[size];
  634. for (uint8_t i=0; i<size; ++i)
  635. data[i] = fShmRtControl.readByte();
  636. if (EngineEvent* const event = getNextFreeInputEvent())
  637. {
  638. event->type = kEngineEventTypeMidi;
  639. event->time = time;
  640. event->channel = MIDI_GET_CHANNEL_FROM_DATA(data);
  641. event->midi.port = port;
  642. event->midi.size = size;
  643. if (size > EngineMidiEvent::kDataSize)
  644. {
  645. event->midi.dataExt = data;
  646. std::memset(event->midi.data, 0, sizeof(uint8_t)*EngineMidiEvent::kDataSize);
  647. }
  648. else
  649. {
  650. event->midi.data[0] = MIDI_GET_STATUS_FROM_DATA(data);
  651. uint8_t i=1;
  652. for (; i < size; ++i)
  653. event->midi.data[i] = data[i];
  654. for (; i < EngineMidiEvent::kDataSize; ++i)
  655. event->midi.data[i] = 0;
  656. event->midi.dataExt = nullptr;
  657. }
  658. }
  659. break;
  660. }
  661. case kPluginBridgeRtProcess: {
  662. CARLA_SAFE_ASSERT_BREAK(fShmAudioPool.data != nullptr);
  663. if (plugin != nullptr && plugin->isEnabled() && plugin->tryLock(false))
  664. {
  665. const BridgeTimeInfo& bridgeTimeInfo(fShmRtControl.data->timeInfo);
  666. const uint32_t audioInCount(plugin->getAudioInCount());
  667. const uint32_t audioOutCount(plugin->getAudioOutCount());
  668. const uint32_t cvInCount(plugin->getCVInCount());
  669. const uint32_t cvOutCount(plugin->getCVOutCount());
  670. const float* audioIn[audioInCount];
  671. /* */ float* audioOut[audioOutCount];
  672. const float* cvIn[cvInCount];
  673. /* */ float* cvOut[cvOutCount];
  674. for (uint32_t i=0; i < audioInCount; ++i)
  675. audioIn[i] = fShmAudioPool.data + i*pData->bufferSize;
  676. for (uint32_t i=0; i < audioOutCount; ++i)
  677. audioOut[i] = fShmAudioPool.data + (i+audioInCount)*pData->bufferSize;
  678. for (uint32_t i=0; i < cvInCount; ++i)
  679. cvIn[i] = fShmAudioPool.data + i*pData->bufferSize;
  680. for (uint32_t i=0; i < cvOutCount; ++i)
  681. cvOut[i] = fShmAudioPool.data + (i+cvInCount)*pData->bufferSize;
  682. EngineTimeInfo& timeInfo(pData->timeInfo);
  683. timeInfo.playing = bridgeTimeInfo.playing;
  684. timeInfo.frame = bridgeTimeInfo.frame;
  685. timeInfo.usecs = bridgeTimeInfo.usecs;
  686. timeInfo.valid = bridgeTimeInfo.valid;
  687. if (timeInfo.valid & EngineTimeInfo::kValidBBT)
  688. {
  689. timeInfo.bbt.bar = bridgeTimeInfo.bar;
  690. timeInfo.bbt.beat = bridgeTimeInfo.beat;
  691. timeInfo.bbt.tick = bridgeTimeInfo.tick;
  692. timeInfo.bbt.beatsPerBar = bridgeTimeInfo.beatsPerBar;
  693. timeInfo.bbt.beatType = bridgeTimeInfo.beatType;
  694. timeInfo.bbt.ticksPerBeat = bridgeTimeInfo.ticksPerBeat;
  695. timeInfo.bbt.beatsPerMinute = bridgeTimeInfo.beatsPerMinute;
  696. timeInfo.bbt.barStartTick = bridgeTimeInfo.barStartTick;
  697. }
  698. plugin->initBuffers();
  699. plugin->process(audioIn, audioOut, cvIn, cvOut, pData->bufferSize);
  700. plugin->unlock();
  701. }
  702. // clear buffer
  703. CARLA_SAFE_ASSERT_BREAK(pData->events.in != nullptr);
  704. if (pData->events.in[0].type != kEngineEventTypeNull)
  705. carla_zeroStruct<EngineEvent>(pData->events.in, kMaxEngineEventInternalCount);
  706. break;
  707. }
  708. case kPluginBridgeRtQuit:
  709. signalThreadShouldExit();
  710. break;
  711. }
  712. }
  713. if (! jackbridge_sem_post(&fShmRtControl.data->sem.client))
  714. carla_stderr2("Could not post to rt semaphore");
  715. }
  716. fIsRunning = false;
  717. callback(ENGINE_CALLBACK_ENGINE_STOPPED, 0, 0, 0, 0.0f, nullptr);
  718. }
  719. // called from process thread above
  720. EngineEvent* getNextFreeInputEvent() const noexcept
  721. {
  722. for (ushort i=0; i < kMaxEngineEventInternalCount; ++i)
  723. {
  724. EngineEvent& event(pData->events.in[i]);
  725. if (event.type == kEngineEventTypeNull)
  726. return &event;
  727. }
  728. return nullptr;
  729. }
  730. // -------------------------------------------------------------------
  731. private:
  732. BridgeAudioPool fShmAudioPool;
  733. BridgeAudioPool fShmCVPool;
  734. BridgeRtControl fShmRtControl;
  735. BridgeNonRtControl fShmNonRtControl;
  736. bool fIsRunning;
  737. bool fIsOffline;
  738. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineBridge)
  739. };
  740. // -----------------------------------------------------------------------
  741. CarlaEngine* CarlaEngine::newBridge(const char* const audioPoolBaseName, const char* const rtBaseName, const char* const nonRtBaseName)
  742. {
  743. return new CarlaEngineBridge(audioPoolBaseName, rtBaseName, nonRtBaseName);
  744. }
  745. // -----------------------------------------------------------------------
  746. #ifdef BRIDGE_PLUGIN
  747. CarlaPlugin* CarlaPlugin::newNative(const CarlaPlugin::Initializer&) { return nullptr; }
  748. CarlaPlugin* CarlaPlugin::newFileGIG(const CarlaPlugin::Initializer&, const bool) { return nullptr; }
  749. CarlaPlugin* CarlaPlugin::newFileSF2(const CarlaPlugin::Initializer&, const bool) { return nullptr; }
  750. CarlaPlugin* CarlaPlugin::newFileSFZ(const CarlaPlugin::Initializer&) { return nullptr; }
  751. #endif
  752. CARLA_BACKEND_END_NAMESPACE
  753. // -----------------------------------------------------------------------
  754. #if defined(CARLA_OS_WIN) && ! defined(__WINE__)
  755. extern "C" __declspec (dllexport)
  756. #else
  757. extern "C" __attribute__ ((visibility("default")))
  758. #endif
  759. void carla_register_native_plugin_carla();
  760. void carla_register_native_plugin_carla(){}
  761. // -----------------------------------------------------------------------