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.

837 lines
22KB

  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 = static_cast<int32_t>(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 = static_cast<int32_t>(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. #ifdef HAVE_LIBLO
  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. firstLinuxSamplerInstance(true),
  359. loadingProject(false),
  360. #endif
  361. hints(0x0),
  362. bufferSize(0),
  363. sampleRate(0.0),
  364. aboutToClose(false),
  365. isIdling(0),
  366. curPluginCount(0),
  367. maxPluginNumber(0),
  368. nextPluginId(0),
  369. envMutex(),
  370. lastError(),
  371. name(),
  372. options(),
  373. timeInfo(),
  374. #ifndef BUILD_BRIDGE
  375. plugins(nullptr),
  376. #endif
  377. events(),
  378. #ifndef BUILD_BRIDGE
  379. graph(engine),
  380. #endif
  381. time(timeInfo, options.transportMode),
  382. nextAction()
  383. {
  384. #ifdef BUILD_BRIDGE
  385. carla_zeroStructs(plugins, 1);
  386. #endif
  387. }
  388. CarlaEngine::ProtectedData::~ProtectedData() noexcept
  389. {
  390. CARLA_SAFE_ASSERT(curPluginCount == 0);
  391. CARLA_SAFE_ASSERT(maxPluginNumber == 0);
  392. CARLA_SAFE_ASSERT(nextPluginId == 0);
  393. CARLA_SAFE_ASSERT(isIdling == 0);
  394. #ifndef BUILD_BRIDGE
  395. CARLA_SAFE_ASSERT(plugins == nullptr);
  396. #endif
  397. }
  398. // -----------------------------------------------------------------------
  399. bool CarlaEngine::ProtectedData::init(const char* const clientName)
  400. {
  401. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(name.isEmpty(), "Invalid engine internal data (err #1)");
  402. #ifdef HAVE_LIBLO
  403. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(oscData == nullptr, "Invalid engine internal data (err #2)");
  404. #endif
  405. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(events.in == nullptr, "Invalid engine internal data (err #4)");
  406. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(events.out == nullptr, "Invalid engine internal data (err #5)");
  407. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(clientName != nullptr && clientName[0] != '\0', "Invalid client name");
  408. #ifndef BUILD_BRIDGE
  409. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(plugins == nullptr, "Invalid engine internal data (err #3)");
  410. #endif
  411. aboutToClose = false;
  412. curPluginCount = 0;
  413. nextPluginId = 0;
  414. switch (options.processMode)
  415. {
  416. case ENGINE_PROCESS_MODE_CONTINUOUS_RACK:
  417. maxPluginNumber = MAX_RACK_PLUGINS;
  418. options.forceStereo = true;
  419. break;
  420. case ENGINE_PROCESS_MODE_PATCHBAY:
  421. maxPluginNumber = MAX_PATCHBAY_PLUGINS;
  422. break;
  423. case ENGINE_PROCESS_MODE_BRIDGE:
  424. maxPluginNumber = 1;
  425. break;
  426. default:
  427. maxPluginNumber = MAX_DEFAULT_PLUGINS;
  428. break;
  429. }
  430. switch (options.processMode)
  431. {
  432. case ENGINE_PROCESS_MODE_CONTINUOUS_RACK:
  433. case ENGINE_PROCESS_MODE_PATCHBAY:
  434. case ENGINE_PROCESS_MODE_BRIDGE:
  435. events.in = new EngineEvent[kMaxEngineEventInternalCount];
  436. events.out = new EngineEvent[kMaxEngineEventInternalCount];
  437. break;
  438. default:
  439. break;
  440. }
  441. nextPluginId = maxPluginNumber;
  442. name = clientName;
  443. name.toBasic();
  444. timeInfo.clear();
  445. #ifdef HAVE_LIBLO
  446. osc.init(clientName);
  447. # ifndef BUILD_BRIDGE
  448. oscData = osc.getControlData();
  449. # endif
  450. #endif
  451. #ifndef BUILD_BRIDGE
  452. plugins = new EnginePluginData[maxPluginNumber];
  453. carla_zeroStructs(plugins, maxPluginNumber);
  454. #endif
  455. nextAction.clearAndReset();
  456. thread.startThread();
  457. return true;
  458. }
  459. void CarlaEngine::ProtectedData::close()
  460. {
  461. CARLA_SAFE_ASSERT(name.isNotEmpty());
  462. #ifndef BUILD_BRIDGE
  463. CARLA_SAFE_ASSERT(plugins != nullptr);
  464. CARLA_SAFE_ASSERT(nextPluginId == maxPluginNumber);
  465. #endif
  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(const uint pluginId) noexcept
  502. {
  503. CARLA_SAFE_ASSERT_RETURN(curPluginCount > 0,);
  504. CARLA_SAFE_ASSERT_RETURN(pluginId < curPluginCount,);
  505. --curPluginCount;
  506. // move all plugins 1 spot backwards
  507. for (uint i=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(const uint idA, const uint idB) noexcept
  527. {
  528. CARLA_SAFE_ASSERT_RETURN(curPluginCount >= 2,);
  529. CARLA_SAFE_ASSERT_RETURN(idA < curPluginCount,);
  530. CARLA_SAFE_ASSERT_RETURN(idB < curPluginCount,);
  531. CarlaPlugin* const pluginA(plugins[idA].plugin);
  532. CARLA_SAFE_ASSERT_RETURN(pluginA != nullptr,);
  533. CarlaPlugin* const pluginB(plugins[idB].plugin);
  534. CARLA_SAFE_ASSERT_RETURN(pluginB != nullptr,);
  535. pluginA->setId(idB);
  536. plugins[idA].plugin = pluginB;
  537. pluginB->setId(idA);
  538. plugins[idB].plugin = pluginA;
  539. }
  540. #endif
  541. void CarlaEngine::ProtectedData::doNextPluginAction() noexcept
  542. {
  543. if (! nextAction.mutex.tryLock())
  544. return;
  545. const EnginePostAction opcode = nextAction.opcode;
  546. const bool needsPost = nextAction.needsPost;
  547. #ifndef BUILD_BRIDGE
  548. const uint pluginId = nextAction.pluginId;
  549. const uint value = nextAction.value;
  550. #endif
  551. nextAction.opcode = kEnginePostActionNull;
  552. nextAction.pluginId = 0;
  553. nextAction.value = 0;
  554. nextAction.needsPost = false;
  555. nextAction.mutex.unlock();
  556. switch (opcode)
  557. {
  558. case kEnginePostActionNull:
  559. break;
  560. case kEnginePostActionZeroCount:
  561. curPluginCount = 0;
  562. break;
  563. #ifndef BUILD_BRIDGE
  564. case kEnginePostActionRemovePlugin:
  565. doPluginRemove(pluginId);
  566. break;
  567. case kEnginePostActionSwitchPlugins:
  568. doPluginsSwitch(pluginId, value);
  569. break;
  570. #endif
  571. }
  572. if (needsPost)
  573. {
  574. if (nextAction.sem != nullptr)
  575. carla_sem_post(*nextAction.sem);
  576. nextAction.postDone = true;
  577. }
  578. }
  579. // -----------------------------------------------------------------------
  580. // PendingRtEventsRunner
  581. PendingRtEventsRunner::PendingRtEventsRunner(CarlaEngine* const engine, const uint32_t frames) noexcept
  582. : pData(engine->pData)
  583. {
  584. pData->time.preProcess(frames);
  585. }
  586. PendingRtEventsRunner::~PendingRtEventsRunner() noexcept
  587. {
  588. pData->doNextPluginAction();
  589. }
  590. // -----------------------------------------------------------------------
  591. // ScopedActionLock
  592. ScopedActionLock::ScopedActionLock(CarlaEngine* const engine,
  593. const EnginePostAction action,
  594. const uint pluginId,
  595. const uint value) noexcept
  596. : pData(engine->pData)
  597. {
  598. CARLA_SAFE_ASSERT_RETURN(action != kEnginePostActionNull,);
  599. {
  600. const CarlaMutexLocker cml(pData->nextAction.mutex);
  601. CARLA_SAFE_ASSERT_RETURN(pData->nextAction.opcode == kEnginePostActionNull,);
  602. pData->nextAction.opcode = action;
  603. pData->nextAction.pluginId = pluginId;
  604. pData->nextAction.value = value;
  605. pData->nextAction.needsPost = engine->isRunning();
  606. pData->nextAction.postDone = false;
  607. }
  608. #ifdef BUILD_BRIDGE
  609. #define ACTION_MSG_PREFIX "Bridge: "
  610. #else
  611. #define ACTION_MSG_PREFIX ""
  612. #endif
  613. if (pData->nextAction.needsPost)
  614. {
  615. // block wait for unlock on processing side
  616. carla_stdout(ACTION_MSG_PREFIX "ScopedPluginAction(%i) - blocking START", pluginId);
  617. bool engineStoppedWhileWaiting = false;
  618. if (! pData->nextAction.postDone)
  619. {
  620. for (int i = 10; --i >= 0;)
  621. {
  622. if (pData->nextAction.sem != nullptr)
  623. {
  624. if (carla_sem_timedwait(*pData->nextAction.sem, 200))
  625. break;
  626. }
  627. else
  628. {
  629. carla_msleep(200);
  630. }
  631. if (! engine->isRunning())
  632. {
  633. engineStoppedWhileWaiting = true;
  634. break;
  635. }
  636. }
  637. }
  638. carla_stdout(ACTION_MSG_PREFIX "ScopedPluginAction(%i) - blocking DONE", pluginId);
  639. // check if anything went wrong...
  640. if (! pData->nextAction.postDone)
  641. {
  642. bool needsCorrection = false;
  643. {
  644. const CarlaMutexLocker cml(pData->nextAction.mutex);
  645. if (pData->nextAction.opcode != kEnginePostActionNull)
  646. {
  647. needsCorrection = true;
  648. pData->nextAction.needsPost = false;
  649. }
  650. }
  651. if (needsCorrection)
  652. {
  653. pData->doNextPluginAction();
  654. if (! engineStoppedWhileWaiting)
  655. carla_stderr2(ACTION_MSG_PREFIX "Failed to wait for engine, is audio not running?");
  656. }
  657. }
  658. }
  659. else
  660. {
  661. pData->doNextPluginAction();
  662. }
  663. }
  664. ScopedActionLock::~ScopedActionLock() noexcept
  665. {
  666. CARLA_SAFE_ASSERT(pData->nextAction.opcode == kEnginePostActionNull);
  667. }
  668. // -----------------------------------------------------------------------
  669. // ScopedThreadStopper
  670. ScopedThreadStopper::ScopedThreadStopper(CarlaEngine* const e) noexcept
  671. : engine(e),
  672. pData(e->pData)
  673. {
  674. pData->thread.stopThread(500);
  675. }
  676. ScopedThreadStopper::~ScopedThreadStopper() noexcept
  677. {
  678. if (engine->isRunning() && ! pData->aboutToClose)
  679. pData->thread.startThread();
  680. }
  681. // -----------------------------------------------------------------------
  682. // ScopedEngineEnvironmentLocker
  683. ScopedEngineEnvironmentLocker::ScopedEngineEnvironmentLocker(CarlaEngine* const engine) noexcept
  684. : pData(engine->pData)
  685. {
  686. pData->envMutex.lock();
  687. }
  688. ScopedEngineEnvironmentLocker::~ScopedEngineEnvironmentLocker() noexcept
  689. {
  690. pData->envMutex.unlock();
  691. }
  692. // -----------------------------------------------------------------------
  693. CARLA_BACKEND_END_NAMESPACE