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.

CarlaEngineInternal.cpp 22KB

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
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
6 years ago
10 years ago
6 years ago
6 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835
  1. /*
  2. * Carla Plugin Host
  3. * Copyright (C) 2011-2018 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. #include "CarlaEngineInternal.hpp"
  18. #include "CarlaPlugin.hpp"
  19. #include "CarlaSemUtils.hpp"
  20. #include "jackbridge/JackBridge.hpp"
  21. CARLA_BACKEND_START_NAMESPACE
  22. // -----------------------------------------------------------------------
  23. // Engine Internal helper macro, sets lastError and returns false/NULL
  24. #define CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(cond, err) if (! (cond)) { carla_safe_assert(#cond, __FILE__, __LINE__); lastError = err; return false; }
  25. #define CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERRN(cond, err) if (! (cond)) { carla_safe_assert(#cond, __FILE__, __LINE__); lastError = err; return nullptr; }
  26. // -----------------------------------------------------------------------
  27. // InternalEvents
  28. EngineInternalEvents::EngineInternalEvents() noexcept
  29. : in(nullptr),
  30. out(nullptr) {}
  31. EngineInternalEvents::~EngineInternalEvents() noexcept
  32. {
  33. CARLA_SAFE_ASSERT(in == nullptr);
  34. CARLA_SAFE_ASSERT(out == nullptr);
  35. }
  36. void EngineInternalEvents::clear() noexcept
  37. {
  38. if (in != nullptr)
  39. {
  40. delete[] in;
  41. in = nullptr;
  42. }
  43. if (out != nullptr)
  44. {
  45. delete[] out;
  46. out = nullptr;
  47. }
  48. }
  49. // -----------------------------------------------------------------------
  50. // InternalTime
  51. static const double kTicksPerBeat = 1920.0;
  52. #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
  53. static uint32_t calculate_link_latency(const double bufferSize, const double sampleRate) noexcept
  54. {
  55. CARLA_SAFE_ASSERT_RETURN(carla_isNotZero(sampleRate), 0);
  56. const long long int latency = llround(1.0e6 * bufferSize / sampleRate);
  57. CARLA_SAFE_ASSERT_RETURN(latency >= 0 && latency < UINT32_MAX, 0);
  58. return static_cast<uint32_t>(latency);
  59. }
  60. #endif
  61. EngineInternalTime::EngineInternalTime(EngineTimeInfo& ti, const EngineTransportMode& tm) noexcept
  62. : beatsPerBar(4.0),
  63. beatsPerMinute(120.0),
  64. bufferSize(0.0),
  65. sampleRate(0.0),
  66. tick(0.0),
  67. needsReset(false),
  68. nextFrame(0),
  69. #ifndef BUILD_BRIDGE
  70. hylia(),
  71. #endif
  72. timeInfo(ti),
  73. transportMode(tm) {}
  74. void EngineInternalTime::init(const uint32_t bsize, const double srate)
  75. {
  76. bufferSize = bsize;
  77. sampleRate = srate;
  78. #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
  79. if (hylia.instance != nullptr)
  80. {
  81. hylia_set_beats_per_bar(hylia.instance, beatsPerBar);
  82. hylia_set_beats_per_minute(hylia.instance, beatsPerMinute);
  83. hylia_set_output_latency(hylia.instance, calculate_link_latency(bsize, srate));
  84. if (hylia.enabled)
  85. hylia_enable(hylia.instance, true);
  86. }
  87. #endif
  88. needsReset = true;
  89. }
  90. void EngineInternalTime::updateAudioValues(const uint32_t bsize, const double srate)
  91. {
  92. bufferSize = bsize;
  93. sampleRate = srate;
  94. #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
  95. if (hylia.instance != nullptr)
  96. hylia_set_output_latency(hylia.instance, calculate_link_latency(bsize, srate));
  97. #endif
  98. needsReset = true;
  99. }
  100. void EngineInternalTime::enableLink(const bool enable)
  101. {
  102. #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
  103. if (hylia.enabled == enable)
  104. return;
  105. if (hylia.instance != nullptr)
  106. {
  107. hylia.enabled = enable;
  108. hylia_enable(hylia.instance, enable);
  109. }
  110. #else
  111. // unused
  112. (void)enable;
  113. #endif
  114. needsReset = true;
  115. }
  116. void EngineInternalTime::setBPM(const double bpm)
  117. {
  118. beatsPerMinute = bpm;
  119. #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
  120. if (hylia.instance != nullptr)
  121. hylia_set_beats_per_minute(hylia.instance, bpm);
  122. #endif
  123. }
  124. void EngineInternalTime::setNeedsReset() noexcept
  125. {
  126. needsReset = true;
  127. }
  128. void EngineInternalTime::pause() noexcept
  129. {
  130. timeInfo.playing = false;
  131. nextFrame = timeInfo.frame;
  132. needsReset = true;
  133. }
  134. void EngineInternalTime::relocate(const uint64_t frame) noexcept
  135. {
  136. timeInfo.frame = frame;
  137. nextFrame = frame;
  138. needsReset = true;
  139. }
  140. void EngineInternalTime::fillEngineTimeInfo(const uint32_t newFrames) noexcept
  141. {
  142. CARLA_SAFE_ASSERT_RETURN(carla_isNotZero(sampleRate),);
  143. CARLA_SAFE_ASSERT_RETURN(newFrames > 0,);
  144. double ticktmp;
  145. timeInfo.usecs = 0;
  146. if (transportMode == ENGINE_TRANSPORT_MODE_INTERNAL)
  147. timeInfo.frame = nextFrame;
  148. if (needsReset)
  149. {
  150. timeInfo.bbt.valid = true;
  151. timeInfo.bbt.beatType = 4.0f;
  152. timeInfo.bbt.ticksPerBeat = kTicksPerBeat;
  153. double abs_beat, abs_tick;
  154. #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
  155. if (hylia.enabled)
  156. {
  157. if (hylia.timeInfo.beat >= 0.0)
  158. {
  159. abs_beat = hylia.timeInfo.beat;
  160. abs_tick = abs_beat * kTicksPerBeat;
  161. }
  162. else
  163. {
  164. abs_beat = 0.0;
  165. abs_tick = 0.0;
  166. timeInfo.playing = false;
  167. }
  168. }
  169. else
  170. #endif
  171. {
  172. const double min = static_cast<double>(timeInfo.frame) / (sampleRate * 60.0);
  173. abs_beat = min * beatsPerMinute;
  174. abs_tick = abs_beat * kTicksPerBeat;
  175. needsReset = false;
  176. }
  177. const double bar = std::floor(abs_beat / beatsPerBar);
  178. const double beat = std::floor(std::fmod(abs_beat, beatsPerBar));
  179. timeInfo.bbt.bar = static_cast<int32_t>(bar) + 1;
  180. timeInfo.bbt.beat = static_cast<int32_t>(beat) + 1;
  181. timeInfo.bbt.barStartTick = ((bar * beatsPerBar) + beat) * kTicksPerBeat;
  182. ticktmp = abs_tick - timeInfo.bbt.barStartTick;
  183. }
  184. else if (timeInfo.playing)
  185. {
  186. ticktmp = tick + (newFrames * kTicksPerBeat * beatsPerMinute / (sampleRate * 60));
  187. while (ticktmp >= kTicksPerBeat)
  188. {
  189. ticktmp -= kTicksPerBeat;
  190. if (++timeInfo.bbt.beat > beatsPerBar)
  191. {
  192. ++timeInfo.bbt.bar;
  193. timeInfo.bbt.beat = 1;
  194. timeInfo.bbt.barStartTick += beatsPerBar * kTicksPerBeat;
  195. }
  196. }
  197. }
  198. else
  199. {
  200. ticktmp = tick;
  201. }
  202. timeInfo.bbt.beatsPerBar = static_cast<float>(beatsPerBar);
  203. timeInfo.bbt.beatsPerMinute = beatsPerMinute;
  204. timeInfo.bbt.tick = ticktmp;
  205. tick = ticktmp;
  206. if (transportMode == ENGINE_TRANSPORT_MODE_INTERNAL && timeInfo.playing)
  207. nextFrame += newFrames;
  208. }
  209. void EngineInternalTime::fillJackTimeInfo(jack_position_t* const pos, const uint32_t newFrames) noexcept
  210. {
  211. CARLA_SAFE_ASSERT_RETURN(carla_isNotZero(sampleRate),);
  212. CARLA_SAFE_ASSERT_RETURN(newFrames > 0,);
  213. double ticktmp;
  214. if (needsReset)
  215. {
  216. pos->valid = JackPositionBBT;
  217. pos->beat_type = 4.0f;
  218. pos->ticks_per_beat = kTicksPerBeat;
  219. double abs_beat, abs_tick;
  220. #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
  221. if (hylia.enabled)
  222. {
  223. if (hylia.timeInfo.beat >= 0.0)
  224. {
  225. abs_beat = hylia.timeInfo.beat;
  226. abs_tick = abs_beat * kTicksPerBeat;
  227. }
  228. else
  229. {
  230. abs_beat = 0.0;
  231. abs_tick = 0.0;
  232. timeInfo.playing = false;
  233. }
  234. }
  235. else
  236. #endif
  237. {
  238. const double min = static_cast<double>(pos->frame) / (sampleRate * 60.0);
  239. abs_beat = min * beatsPerMinute;
  240. abs_tick = abs_beat * kTicksPerBeat;
  241. }
  242. const double bar = std::floor(abs_beat / beatsPerBar);
  243. const double beat = std::floor(std::fmod(abs_beat, beatsPerBar));
  244. pos->bar = static_cast<int32_t>(bar) + 1;
  245. pos->beat = static_cast<int32_t>(beat) + 1;
  246. pos->bar_start_tick = ((bar * beatsPerBar) + beat) * kTicksPerBeat;
  247. ticktmp = abs_tick - pos->bar_start_tick;
  248. }
  249. else if (timeInfo.playing)
  250. {
  251. ticktmp = tick + (newFrames * kTicksPerBeat * beatsPerMinute / (sampleRate * 60.0));
  252. while (ticktmp >= kTicksPerBeat)
  253. {
  254. ticktmp -= kTicksPerBeat;
  255. if (++pos->beat > beatsPerBar)
  256. {
  257. ++pos->bar;
  258. pos->beat = 1;
  259. pos->bar_start_tick += beatsPerBar * kTicksPerBeat;
  260. }
  261. }
  262. }
  263. else
  264. {
  265. ticktmp = tick;
  266. }
  267. pos->beats_per_bar = static_cast<float>(beatsPerBar);
  268. pos->beats_per_minute = beatsPerMinute;
  269. pos->tick = ticktmp;
  270. tick = ticktmp;
  271. }
  272. void EngineInternalTime::preProcess(const uint32_t numFrames)
  273. {
  274. #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
  275. if (hylia.enabled)
  276. {
  277. hylia_process(hylia.instance, numFrames, &hylia.timeInfo);
  278. const double new_bpb = hylia.timeInfo.beatsPerBar;
  279. const double new_bpm = hylia.timeInfo.beatsPerMinute;
  280. if (new_bpb >= 1.0 && carla_isNotEqual(beatsPerBar, new_bpb))
  281. {
  282. beatsPerBar = new_bpb;
  283. needsReset = true;
  284. }
  285. if (new_bpm > 0.0 && carla_isNotEqual(beatsPerMinute, new_bpm))
  286. {
  287. beatsPerMinute = new_bpm;
  288. needsReset = true;
  289. }
  290. }
  291. #endif
  292. if (transportMode == ENGINE_TRANSPORT_MODE_INTERNAL)
  293. fillEngineTimeInfo(numFrames);
  294. }
  295. // -----------------------------------------------------------------------
  296. // EngineInternalTime::Hylia
  297. #ifndef BUILD_BRIDGE
  298. EngineInternalTime::Hylia::Hylia()
  299. : enabled(false),
  300. instance(nullptr),
  301. timeInfo()
  302. {
  303. carla_zeroStruct(timeInfo);
  304. # ifdef HAVE_HYLIA
  305. instance = hylia_create();
  306. # endif
  307. }
  308. EngineInternalTime::Hylia::~Hylia()
  309. {
  310. # ifdef HAVE_HYLIA
  311. hylia_cleanup(instance);
  312. # endif
  313. }
  314. #endif
  315. // -----------------------------------------------------------------------
  316. // NextAction
  317. EngineNextAction::EngineNextAction() noexcept
  318. : opcode(kEnginePostActionNull),
  319. pluginId(0),
  320. value(0),
  321. mutex(),
  322. needsPost(false),
  323. postDone(false),
  324. sem(carla_sem_create()) {}
  325. EngineNextAction::~EngineNextAction() noexcept
  326. {
  327. CARLA_SAFE_ASSERT(opcode == kEnginePostActionNull);
  328. if (sem != nullptr)
  329. {
  330. carla_sem_destroy(sem);
  331. sem = nullptr;
  332. }
  333. }
  334. void EngineNextAction::clearAndReset() noexcept
  335. {
  336. mutex.lock();
  337. CARLA_SAFE_ASSERT(opcode == kEnginePostActionNull);
  338. opcode = kEnginePostActionNull;
  339. pluginId = 0;
  340. value = 0;
  341. needsPost = false;
  342. postDone = false;
  343. mutex.unlock();
  344. }
  345. // -----------------------------------------------------------------------
  346. // CarlaEngine::ProtectedData
  347. CarlaEngine::ProtectedData::ProtectedData(CarlaEngine* const engine) noexcept
  348. : thread(engine),
  349. #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
  350. osc(engine),
  351. oscData(nullptr),
  352. #endif
  353. callback(nullptr),
  354. callbackPtr(nullptr),
  355. fileCallback(nullptr),
  356. fileCallbackPtr(nullptr),
  357. #ifndef BUILD_BRIDGE
  358. loadingProject(false),
  359. #endif
  360. hints(0x0),
  361. bufferSize(0),
  362. sampleRate(0.0),
  363. aboutToClose(false),
  364. isIdling(0),
  365. curPluginCount(0),
  366. maxPluginNumber(0),
  367. nextPluginId(0),
  368. envMutex(),
  369. lastError(),
  370. name(),
  371. options(),
  372. timeInfo(),
  373. #ifndef BUILD_BRIDGE
  374. plugins(nullptr),
  375. #endif
  376. events(),
  377. #ifndef BUILD_BRIDGE
  378. graph(engine),
  379. #endif
  380. time(timeInfo, options.transportMode),
  381. nextAction()
  382. {
  383. #ifdef BUILD_BRIDGE
  384. carla_zeroStructs(plugins, 1);
  385. #endif
  386. }
  387. CarlaEngine::ProtectedData::~ProtectedData() noexcept
  388. {
  389. CARLA_SAFE_ASSERT(curPluginCount == 0);
  390. CARLA_SAFE_ASSERT(maxPluginNumber == 0);
  391. CARLA_SAFE_ASSERT(nextPluginId == 0);
  392. CARLA_SAFE_ASSERT(isIdling == 0);
  393. #ifndef BUILD_BRIDGE
  394. CARLA_SAFE_ASSERT(plugins == nullptr);
  395. #endif
  396. }
  397. // -----------------------------------------------------------------------
  398. bool CarlaEngine::ProtectedData::init(const char* const clientName)
  399. {
  400. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(name.isEmpty(), "Invalid engine internal data (err #1)");
  401. #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
  402. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(oscData == nullptr, "Invalid engine internal data (err #2)");
  403. #endif
  404. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(events.in == nullptr, "Invalid engine internal data (err #4)");
  405. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(events.out == nullptr, "Invalid engine internal data (err #5)");
  406. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(clientName != nullptr && clientName[0] != '\0', "Invalid client name");
  407. #ifndef BUILD_BRIDGE
  408. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(plugins == nullptr, "Invalid engine internal data (err #3)");
  409. #endif
  410. aboutToClose = false;
  411. curPluginCount = 0;
  412. nextPluginId = 0;
  413. switch (options.processMode)
  414. {
  415. case ENGINE_PROCESS_MODE_CONTINUOUS_RACK:
  416. maxPluginNumber = MAX_RACK_PLUGINS;
  417. options.forceStereo = true;
  418. break;
  419. case ENGINE_PROCESS_MODE_PATCHBAY:
  420. maxPluginNumber = MAX_PATCHBAY_PLUGINS;
  421. break;
  422. case ENGINE_PROCESS_MODE_BRIDGE:
  423. maxPluginNumber = 1;
  424. break;
  425. default:
  426. maxPluginNumber = MAX_DEFAULT_PLUGINS;
  427. break;
  428. }
  429. switch (options.processMode)
  430. {
  431. case ENGINE_PROCESS_MODE_CONTINUOUS_RACK:
  432. case ENGINE_PROCESS_MODE_PATCHBAY:
  433. case ENGINE_PROCESS_MODE_BRIDGE:
  434. events.in = new EngineEvent[kMaxEngineEventInternalCount];
  435. events.out = new EngineEvent[kMaxEngineEventInternalCount];
  436. break;
  437. default:
  438. break;
  439. }
  440. nextPluginId = maxPluginNumber;
  441. name = clientName;
  442. name.toBasic();
  443. timeInfo.clear();
  444. #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
  445. osc.init(clientName);
  446. # ifndef BUILD_BRIDGE
  447. oscData = osc.getControlData();
  448. # endif
  449. #endif
  450. #ifndef BUILD_BRIDGE
  451. plugins = new EnginePluginData[maxPluginNumber];
  452. carla_zeroStructs(plugins, maxPluginNumber);
  453. #endif
  454. nextAction.clearAndReset();
  455. thread.startThread();
  456. return true;
  457. }
  458. void CarlaEngine::ProtectedData::close()
  459. {
  460. CARLA_SAFE_ASSERT(name.isNotEmpty());
  461. #ifndef BUILD_BRIDGE
  462. CARLA_SAFE_ASSERT(plugins != nullptr);
  463. CARLA_SAFE_ASSERT(nextPluginId == maxPluginNumber);
  464. #endif
  465. aboutToClose = true;
  466. thread.stopThread(500);
  467. nextAction.clearAndReset();
  468. #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
  469. osc.close();
  470. oscData = nullptr;
  471. #endif
  472. aboutToClose = false;
  473. curPluginCount = 0;
  474. maxPluginNumber = 0;
  475. nextPluginId = 0;
  476. #ifndef BUILD_BRIDGE
  477. if (plugins != nullptr)
  478. {
  479. delete[] plugins;
  480. plugins = nullptr;
  481. }
  482. #endif
  483. events.clear();
  484. name.clear();
  485. }
  486. void CarlaEngine::ProtectedData::initTime(const char* const features)
  487. {
  488. time.init(bufferSize, sampleRate);
  489. #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
  490. const bool linkEnabled = features != nullptr && std::strstr(features, ":link:") != nullptr;
  491. time.enableLink(linkEnabled);
  492. #else
  493. return;
  494. // unused
  495. (void)features;
  496. #endif
  497. }
  498. // -----------------------------------------------------------------------
  499. #ifndef BUILD_BRIDGE
  500. void CarlaEngine::ProtectedData::doPluginRemove(const uint pluginId) noexcept
  501. {
  502. CARLA_SAFE_ASSERT_RETURN(curPluginCount > 0,);
  503. CARLA_SAFE_ASSERT_RETURN(pluginId < curPluginCount,);
  504. --curPluginCount;
  505. // move all plugins 1 spot backwards
  506. for (uint i=pluginId; i < curPluginCount; ++i)
  507. {
  508. CarlaPlugin* const plugin(plugins[i+1].plugin);
  509. CARLA_SAFE_ASSERT_BREAK(plugin != nullptr);
  510. plugin->setId(i);
  511. plugins[i].plugin = plugin;
  512. plugins[i].insPeak[0] = 0.0f;
  513. plugins[i].insPeak[1] = 0.0f;
  514. plugins[i].outsPeak[0] = 0.0f;
  515. plugins[i].outsPeak[1] = 0.0f;
  516. }
  517. const uint id(curPluginCount);
  518. // reset last plugin (now removed)
  519. plugins[id].plugin = nullptr;
  520. plugins[id].insPeak[0] = 0.0f;
  521. plugins[id].insPeak[1] = 0.0f;
  522. plugins[id].outsPeak[0] = 0.0f;
  523. plugins[id].outsPeak[1] = 0.0f;
  524. }
  525. void CarlaEngine::ProtectedData::doPluginsSwitch(const uint idA, const uint idB) noexcept
  526. {
  527. CARLA_SAFE_ASSERT_RETURN(curPluginCount >= 2,);
  528. CARLA_SAFE_ASSERT_RETURN(idA < curPluginCount,);
  529. CARLA_SAFE_ASSERT_RETURN(idB < curPluginCount,);
  530. CarlaPlugin* const pluginA(plugins[idA].plugin);
  531. CARLA_SAFE_ASSERT_RETURN(pluginA != nullptr,);
  532. CarlaPlugin* const pluginB(plugins[idB].plugin);
  533. CARLA_SAFE_ASSERT_RETURN(pluginB != nullptr,);
  534. pluginA->setId(idB);
  535. plugins[idA].plugin = pluginB;
  536. pluginB->setId(idA);
  537. plugins[idB].plugin = pluginA;
  538. }
  539. #endif
  540. void CarlaEngine::ProtectedData::doNextPluginAction() noexcept
  541. {
  542. if (! nextAction.mutex.tryLock())
  543. return;
  544. const EnginePostAction opcode = nextAction.opcode;
  545. const bool needsPost = nextAction.needsPost;
  546. #ifndef BUILD_BRIDGE
  547. const uint pluginId = nextAction.pluginId;
  548. const uint value = nextAction.value;
  549. #endif
  550. nextAction.opcode = kEnginePostActionNull;
  551. nextAction.pluginId = 0;
  552. nextAction.value = 0;
  553. nextAction.needsPost = false;
  554. nextAction.mutex.unlock();
  555. switch (opcode)
  556. {
  557. case kEnginePostActionNull:
  558. break;
  559. case kEnginePostActionZeroCount:
  560. curPluginCount = 0;
  561. break;
  562. #ifndef BUILD_BRIDGE
  563. case kEnginePostActionRemovePlugin:
  564. doPluginRemove(pluginId);
  565. break;
  566. case kEnginePostActionSwitchPlugins:
  567. doPluginsSwitch(pluginId, value);
  568. break;
  569. #endif
  570. }
  571. if (needsPost)
  572. {
  573. if (nextAction.sem != nullptr)
  574. carla_sem_post(*nextAction.sem);
  575. nextAction.postDone = true;
  576. }
  577. }
  578. // -----------------------------------------------------------------------
  579. // PendingRtEventsRunner
  580. PendingRtEventsRunner::PendingRtEventsRunner(CarlaEngine* const engine, const uint32_t frames) noexcept
  581. : pData(engine->pData)
  582. {
  583. pData->time.preProcess(frames);
  584. }
  585. PendingRtEventsRunner::~PendingRtEventsRunner() noexcept
  586. {
  587. pData->doNextPluginAction();
  588. }
  589. // -----------------------------------------------------------------------
  590. // ScopedActionLock
  591. ScopedActionLock::ScopedActionLock(CarlaEngine* const engine,
  592. const EnginePostAction action,
  593. const uint pluginId,
  594. const uint value) noexcept
  595. : pData(engine->pData)
  596. {
  597. CARLA_SAFE_ASSERT_RETURN(action != kEnginePostActionNull,);
  598. {
  599. const CarlaMutexLocker cml(pData->nextAction.mutex);
  600. CARLA_SAFE_ASSERT_RETURN(pData->nextAction.opcode == kEnginePostActionNull,);
  601. pData->nextAction.opcode = action;
  602. pData->nextAction.pluginId = pluginId;
  603. pData->nextAction.value = value;
  604. pData->nextAction.needsPost = engine->isRunning();
  605. pData->nextAction.postDone = false;
  606. }
  607. #ifdef BUILD_BRIDGE
  608. #define ACTION_MSG_PREFIX "Bridge: "
  609. #else
  610. #define ACTION_MSG_PREFIX ""
  611. #endif
  612. if (pData->nextAction.needsPost)
  613. {
  614. // block wait for unlock on processing side
  615. carla_stdout(ACTION_MSG_PREFIX "ScopedPluginAction(%i) - blocking START", pluginId);
  616. bool engineStoppedWhileWaiting = false;
  617. if (! pData->nextAction.postDone)
  618. {
  619. for (int i = 10; --i >= 0;)
  620. {
  621. if (pData->nextAction.sem != nullptr)
  622. {
  623. if (carla_sem_timedwait(*pData->nextAction.sem, 200))
  624. break;
  625. }
  626. else
  627. {
  628. carla_msleep(200);
  629. }
  630. if (! engine->isRunning())
  631. {
  632. engineStoppedWhileWaiting = true;
  633. break;
  634. }
  635. }
  636. }
  637. carla_stdout(ACTION_MSG_PREFIX "ScopedPluginAction(%i) - blocking DONE", pluginId);
  638. // check if anything went wrong...
  639. if (! pData->nextAction.postDone)
  640. {
  641. bool needsCorrection = false;
  642. {
  643. const CarlaMutexLocker cml(pData->nextAction.mutex);
  644. if (pData->nextAction.opcode != kEnginePostActionNull)
  645. {
  646. needsCorrection = true;
  647. pData->nextAction.needsPost = false;
  648. }
  649. }
  650. if (needsCorrection)
  651. {
  652. pData->doNextPluginAction();
  653. if (! engineStoppedWhileWaiting)
  654. carla_stderr2(ACTION_MSG_PREFIX "Failed to wait for engine, is audio not running?");
  655. }
  656. }
  657. }
  658. else
  659. {
  660. pData->doNextPluginAction();
  661. }
  662. }
  663. ScopedActionLock::~ScopedActionLock() noexcept
  664. {
  665. CARLA_SAFE_ASSERT(pData->nextAction.opcode == kEnginePostActionNull);
  666. }
  667. // -----------------------------------------------------------------------
  668. // ScopedThreadStopper
  669. ScopedThreadStopper::ScopedThreadStopper(CarlaEngine* const e) noexcept
  670. : engine(e),
  671. pData(e->pData)
  672. {
  673. pData->thread.stopThread(500);
  674. }
  675. ScopedThreadStopper::~ScopedThreadStopper() noexcept
  676. {
  677. if (engine->isRunning() && ! pData->aboutToClose)
  678. pData->thread.startThread();
  679. }
  680. // -----------------------------------------------------------------------
  681. // ScopedEngineEnvironmentLocker
  682. ScopedEngineEnvironmentLocker::ScopedEngineEnvironmentLocker(CarlaEngine* const engine) noexcept
  683. : pData(engine->pData)
  684. {
  685. pData->envMutex.lock();
  686. }
  687. ScopedEngineEnvironmentLocker::~ScopedEngineEnvironmentLocker() noexcept
  688. {
  689. pData->envMutex.unlock();
  690. }
  691. // -----------------------------------------------------------------------
  692. CARLA_BACKEND_END_NAMESPACE