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 19KB

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