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.

932 lines
31KB

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