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.

913 lines
30KB

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