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.

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