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.

726 lines
19KB

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