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.

887 lines
29KB

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