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.

782 lines
21KB

  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.bbt.valid = true;
  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. condition(),
  310. mutex(),
  311. triggered(false)
  312. {
  313. pthread_condattr_t cattr;
  314. pthread_condattr_init(&cattr);
  315. pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_PRIVATE);
  316. pthread_cond_init(&condition, &cattr);
  317. pthread_condattr_destroy(&cattr);
  318. pthread_mutexattr_t mattr;
  319. pthread_mutexattr_init(&mattr);
  320. pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT);
  321. pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_NORMAL);
  322. pthread_mutex_init(&mutex, &mattr);
  323. pthread_mutexattr_destroy(&mattr);
  324. }
  325. EngineNextAction::~EngineNextAction() noexcept
  326. {
  327. CARLA_SAFE_ASSERT(opcode == kEnginePostActionNull);
  328. pthread_cond_destroy(&condition);
  329. pthread_mutex_destroy(&mutex);
  330. }
  331. // void EngineNextAction::ready() const noexcept
  332. // {
  333. // mutex.lock();
  334. // mutex.unlock();
  335. // }
  336. void EngineNextAction::clearAndReset() noexcept
  337. {
  338. pthread_mutex_lock(&mutex);
  339. opcode = kEnginePostActionNull;
  340. pluginId = 0;
  341. value = 0;
  342. pthread_mutex_unlock(&mutex);
  343. }
  344. // -----------------------------------------------------------------------
  345. // CarlaEngine::ProtectedData
  346. CarlaEngine::ProtectedData::ProtectedData(CarlaEngine* const engine) noexcept
  347. : thread(engine),
  348. #ifdef HAVE_LIBLO
  349. osc(engine),
  350. oscData(nullptr),
  351. #endif
  352. callback(nullptr),
  353. callbackPtr(nullptr),
  354. fileCallback(nullptr),
  355. fileCallbackPtr(nullptr),
  356. #ifndef BUILD_BRIDGE
  357. firstLinuxSamplerInstance(true),
  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. #ifdef HAVE_LIBLO
  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. #ifdef HAVE_LIBLO
  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. CARLA_SAFE_ASSERT(nextAction.opcode == kEnginePostActionNull);
  466. aboutToClose = true;
  467. thread.stopThread(500);
  468. nextAction.clearAndReset();
  469. #ifdef HAVE_LIBLO
  470. osc.close();
  471. oscData = nullptr;
  472. #endif
  473. aboutToClose = false;
  474. curPluginCount = 0;
  475. maxPluginNumber = 0;
  476. nextPluginId = 0;
  477. #ifndef BUILD_BRIDGE
  478. if (plugins != nullptr)
  479. {
  480. delete[] plugins;
  481. plugins = nullptr;
  482. }
  483. #endif
  484. events.clear();
  485. name.clear();
  486. }
  487. void CarlaEngine::ProtectedData::initTime(const char* const features)
  488. {
  489. time.init(bufferSize, sampleRate);
  490. #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
  491. const bool linkEnabled = features != nullptr && std::strstr(features, ":link:") != nullptr;
  492. time.enableLink(linkEnabled);
  493. #else
  494. return;
  495. // unused
  496. (void)features;
  497. #endif
  498. }
  499. // -----------------------------------------------------------------------
  500. #ifndef BUILD_BRIDGE
  501. void CarlaEngine::ProtectedData::doPluginRemove() noexcept
  502. {
  503. CARLA_SAFE_ASSERT_RETURN(curPluginCount > 0,);
  504. CARLA_SAFE_ASSERT_RETURN(nextAction.pluginId < curPluginCount,);
  505. --curPluginCount;
  506. // move all plugins 1 spot backwards
  507. for (uint i=nextAction.pluginId; i < curPluginCount; ++i)
  508. {
  509. CarlaPlugin* const plugin(plugins[i+1].plugin);
  510. CARLA_SAFE_ASSERT_BREAK(plugin != nullptr);
  511. plugin->setId(i);
  512. plugins[i].plugin = plugin;
  513. plugins[i].insPeak[0] = 0.0f;
  514. plugins[i].insPeak[1] = 0.0f;
  515. plugins[i].outsPeak[0] = 0.0f;
  516. plugins[i].outsPeak[1] = 0.0f;
  517. }
  518. const uint id(curPluginCount);
  519. // reset last plugin (now removed)
  520. plugins[id].plugin = nullptr;
  521. plugins[id].insPeak[0] = 0.0f;
  522. plugins[id].insPeak[1] = 0.0f;
  523. plugins[id].outsPeak[0] = 0.0f;
  524. plugins[id].outsPeak[1] = 0.0f;
  525. }
  526. void CarlaEngine::ProtectedData::doPluginsSwitch() noexcept
  527. {
  528. CARLA_SAFE_ASSERT_RETURN(curPluginCount >= 2,);
  529. const uint idA(nextAction.pluginId);
  530. const uint idB(nextAction.value);
  531. CARLA_SAFE_ASSERT_RETURN(idA < curPluginCount,);
  532. CARLA_SAFE_ASSERT_RETURN(idB < curPluginCount,);
  533. CARLA_SAFE_ASSERT_RETURN(plugins[idA].plugin != nullptr,);
  534. CARLA_SAFE_ASSERT_RETURN(plugins[idB].plugin != nullptr,);
  535. #if 0
  536. std::swap(plugins[idA].plugin, plugins[idB].plugin);
  537. #else
  538. CarlaPlugin* const tmp(plugins[idA].plugin);
  539. plugins[idA].plugin = plugins[idB].plugin;
  540. plugins[idB].plugin = tmp;
  541. #endif
  542. }
  543. #endif
  544. void CarlaEngine::ProtectedData::doNextPluginAction(const bool unlock) noexcept
  545. {
  546. switch (nextAction.opcode)
  547. {
  548. case kEnginePostActionNull:
  549. break;
  550. case kEnginePostActionZeroCount:
  551. curPluginCount = 0;
  552. break;
  553. #ifndef BUILD_BRIDGE
  554. case kEnginePostActionRemovePlugin:
  555. doPluginRemove();
  556. break;
  557. case kEnginePostActionSwitchPlugins:
  558. doPluginsSwitch();
  559. break;
  560. #endif
  561. }
  562. nextAction.opcode = kEnginePostActionNull;
  563. nextAction.pluginId = 0;
  564. nextAction.value = 0;
  565. if (unlock)
  566. {
  567. pthread_mutex_lock(&nextAction.mutex);
  568. if (! nextAction.triggered)
  569. {
  570. nextAction.triggered = true;
  571. pthread_cond_broadcast(&nextAction.condition);
  572. }
  573. pthread_mutex_unlock(&nextAction.mutex);
  574. }
  575. }
  576. // -----------------------------------------------------------------------
  577. // PendingRtEventsRunner
  578. PendingRtEventsRunner::PendingRtEventsRunner(CarlaEngine* const engine, const uint32_t frames) noexcept
  579. : pData(engine->pData)
  580. {
  581. pData->time.preProcess(frames);
  582. }
  583. PendingRtEventsRunner::~PendingRtEventsRunner() noexcept
  584. {
  585. pData->doNextPluginAction(true);
  586. }
  587. // -----------------------------------------------------------------------
  588. // ScopedActionLock
  589. ScopedActionLock::ScopedActionLock(CarlaEngine* const engine, const EnginePostAction action, const uint pluginId, const uint value, const bool lockWait) noexcept
  590. : pData(engine->pData)
  591. {
  592. CARLA_SAFE_ASSERT_RETURN(action != kEnginePostActionNull,);
  593. pthread_mutex_lock(&pData->nextAction.mutex);
  594. CARLA_SAFE_ASSERT_RETURN(pData->nextAction.opcode == kEnginePostActionNull,);
  595. pData->nextAction.opcode = action;
  596. pData->nextAction.pluginId = pluginId;
  597. pData->nextAction.value = value;
  598. if (lockWait)
  599. {
  600. // block wait for unlock on processing side
  601. carla_stdout("ScopedPluginAction(%i) - blocking START", pluginId);
  602. while (! pData->nextAction.triggered)
  603. {
  604. try {
  605. pthread_cond_wait(&pData->nextAction.condition, &pData->nextAction.mutex);
  606. } CARLA_SAFE_EXCEPTION("pthread_cond_wait");
  607. }
  608. pData->nextAction.triggered = false;
  609. carla_stdout("ScopedPluginAction(%i) - blocking DONE", pluginId);
  610. }
  611. else
  612. {
  613. pData->doNextPluginAction(false);
  614. }
  615. pthread_mutex_unlock(&pData->nextAction.mutex);
  616. }
  617. ScopedActionLock::~ScopedActionLock() noexcept
  618. {
  619. pthread_mutex_lock(&pData->nextAction.mutex);
  620. CARLA_SAFE_ASSERT(pData->nextAction.opcode == kEnginePostActionNull);
  621. pthread_mutex_unlock(&pData->nextAction.mutex);
  622. }
  623. // -----------------------------------------------------------------------
  624. // ScopedThreadStopper
  625. ScopedThreadStopper::ScopedThreadStopper(CarlaEngine* const e) noexcept
  626. : engine(e),
  627. pData(e->pData)
  628. {
  629. pData->thread.stopThread(500);
  630. }
  631. ScopedThreadStopper::~ScopedThreadStopper() noexcept
  632. {
  633. if (engine->isRunning() && ! pData->aboutToClose)
  634. pData->thread.startThread();
  635. }
  636. // -----------------------------------------------------------------------
  637. // ScopedEngineEnvironmentLocker
  638. ScopedEngineEnvironmentLocker::ScopedEngineEnvironmentLocker(CarlaEngine* const engine) noexcept
  639. : pData(engine->pData)
  640. {
  641. pData->envMutex.lock();
  642. }
  643. ScopedEngineEnvironmentLocker::~ScopedEngineEnvironmentLocker() noexcept
  644. {
  645. pData->envMutex.unlock();
  646. }
  647. // -----------------------------------------------------------------------
  648. CARLA_BACKEND_END_NAMESPACE