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.

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