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.

813 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 "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. CARLA_SAFE_ASSERT_RETURN(plugins[idA].plugin != nullptr,);
  532. CARLA_SAFE_ASSERT_RETURN(plugins[idB].plugin != nullptr,);
  533. #if 0
  534. std::swap(plugins[idA].plugin, plugins[idB].plugin);
  535. #else
  536. CarlaPlugin* const tmp(plugins[idA].plugin);
  537. plugins[idA].plugin = plugins[idB].plugin;
  538. plugins[idB].plugin = tmp;
  539. #endif
  540. }
  541. #endif
  542. void CarlaEngine::ProtectedData::doNextPluginAction() noexcept
  543. {
  544. if (! nextAction.mutex.tryLock())
  545. return;
  546. const EnginePostAction opcode = nextAction.opcode;
  547. const bool needsPost = nextAction.needsPost;
  548. #ifndef BUILD_BRIDGE
  549. const uint pluginId = nextAction.pluginId;
  550. const uint value = nextAction.value;
  551. #endif
  552. nextAction.opcode = kEnginePostActionNull;
  553. nextAction.pluginId = 0;
  554. nextAction.value = 0;
  555. nextAction.needsPost = false;
  556. nextAction.mutex.unlock();
  557. switch (opcode)
  558. {
  559. case kEnginePostActionNull:
  560. break;
  561. case kEnginePostActionZeroCount:
  562. curPluginCount = 0;
  563. break;
  564. #ifndef BUILD_BRIDGE
  565. case kEnginePostActionRemovePlugin:
  566. doPluginRemove(pluginId);
  567. break;
  568. case kEnginePostActionSwitchPlugins:
  569. doPluginsSwitch(pluginId, value);
  570. break;
  571. #endif
  572. }
  573. if (needsPost)
  574. {
  575. if (nextAction.sem != nullptr)
  576. carla_sem_post(*nextAction.sem);
  577. nextAction.postDone = true;
  578. }
  579. }
  580. // -----------------------------------------------------------------------
  581. // PendingRtEventsRunner
  582. PendingRtEventsRunner::PendingRtEventsRunner(CarlaEngine* const engine, const uint32_t frames) noexcept
  583. : pData(engine->pData)
  584. {
  585. pData->time.preProcess(frames);
  586. }
  587. PendingRtEventsRunner::~PendingRtEventsRunner() noexcept
  588. {
  589. pData->doNextPluginAction();
  590. }
  591. // -----------------------------------------------------------------------
  592. // ScopedActionLock
  593. ScopedActionLock::ScopedActionLock(CarlaEngine* const engine,
  594. const EnginePostAction action,
  595. const uint pluginId,
  596. const uint value,
  597. const bool lockWait) noexcept
  598. : pData(engine->pData)
  599. {
  600. CARLA_SAFE_ASSERT_RETURN(action != kEnginePostActionNull,);
  601. {
  602. const CarlaMutexLocker cml(pData->nextAction.mutex);
  603. CARLA_SAFE_ASSERT_RETURN(pData->nextAction.opcode == kEnginePostActionNull,);
  604. pData->nextAction.opcode = action;
  605. pData->nextAction.pluginId = pluginId;
  606. pData->nextAction.value = value;
  607. pData->nextAction.needsPost = lockWait;
  608. pData->nextAction.postDone = false;
  609. }
  610. if (lockWait)
  611. {
  612. // block wait for unlock on processing side
  613. carla_stdout("ScopedPluginAction(%i) - blocking START", pluginId);
  614. if (! pData->nextAction.postDone)
  615. {
  616. if (pData->nextAction.sem != nullptr)
  617. carla_sem_timedwait(*pData->nextAction.sem, 2000);
  618. else
  619. carla_sleep(2);
  620. }
  621. carla_stdout("ScopedPluginAction(%i) - blocking DONE", pluginId);
  622. // check if anything went wrong...
  623. if (! pData->nextAction.postDone)
  624. {
  625. bool needsCorrection = false;
  626. {
  627. const CarlaMutexLocker cml(pData->nextAction.mutex);
  628. if (pData->nextAction.opcode != kEnginePostActionNull)
  629. {
  630. needsCorrection = true;
  631. pData->nextAction.needsPost = false;
  632. }
  633. }
  634. if (needsCorrection)
  635. {
  636. pData->doNextPluginAction();
  637. carla_stderr2("Failed to wait for engine, is audio not running?");
  638. }
  639. }
  640. }
  641. else
  642. {
  643. pData->doNextPluginAction();
  644. }
  645. }
  646. ScopedActionLock::~ScopedActionLock() noexcept
  647. {
  648. CARLA_SAFE_ASSERT(pData->nextAction.opcode == kEnginePostActionNull);
  649. }
  650. // -----------------------------------------------------------------------
  651. // ScopedThreadStopper
  652. ScopedThreadStopper::ScopedThreadStopper(CarlaEngine* const e) noexcept
  653. : engine(e),
  654. pData(e->pData)
  655. {
  656. pData->thread.stopThread(500);
  657. }
  658. ScopedThreadStopper::~ScopedThreadStopper() noexcept
  659. {
  660. if (engine->isRunning() && ! pData->aboutToClose)
  661. pData->thread.startThread();
  662. }
  663. // -----------------------------------------------------------------------
  664. // ScopedEngineEnvironmentLocker
  665. ScopedEngineEnvironmentLocker::ScopedEngineEnvironmentLocker(CarlaEngine* const engine) noexcept
  666. : pData(engine->pData)
  667. {
  668. pData->envMutex.lock();
  669. }
  670. ScopedEngineEnvironmentLocker::~ScopedEngineEnvironmentLocker() noexcept
  671. {
  672. pData->envMutex.unlock();
  673. }
  674. // -----------------------------------------------------------------------
  675. CARLA_BACKEND_END_NAMESPACE