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.

CarlaEngineBridge.cpp 31KB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  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. // -----------------------------------------------------------------------