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.

836 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 = 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 = 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. #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
  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. 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. #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
  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. #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
  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. aboutToClose = true;
  466. thread.stopThread(500);
  467. nextAction.clearAndReset();
  468. #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
  469. osc.close();
  470. oscData = nullptr;
  471. #endif
  472. aboutToClose = false;
  473. curPluginCount = 0;
  474. maxPluginNumber = 0;
  475. nextPluginId = 0;
  476. #ifndef BUILD_BRIDGE
  477. if (plugins != nullptr)
  478. {
  479. delete[] plugins;
  480. plugins = nullptr;
  481. }
  482. #endif
  483. events.clear();
  484. name.clear();
  485. }
  486. void CarlaEngine::ProtectedData::initTime(const char* const features)
  487. {
  488. time.init(bufferSize, sampleRate);
  489. #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
  490. const bool linkEnabled = features != nullptr && std::strstr(features, ":link:") != nullptr;
  491. time.enableLink(linkEnabled);
  492. #else
  493. return;
  494. // unused
  495. (void)features;
  496. #endif
  497. }
  498. // -----------------------------------------------------------------------
  499. #ifndef BUILD_BRIDGE
  500. void CarlaEngine::ProtectedData::doPluginRemove(const uint pluginId) noexcept
  501. {
  502. CARLA_SAFE_ASSERT_RETURN(curPluginCount > 0,);
  503. CARLA_SAFE_ASSERT_RETURN(pluginId < curPluginCount,);
  504. --curPluginCount;
  505. // move all plugins 1 spot backwards
  506. for (uint i=pluginId; i < curPluginCount; ++i)
  507. {
  508. CarlaPlugin* const plugin(plugins[i+1].plugin);
  509. CARLA_SAFE_ASSERT_BREAK(plugin != nullptr);
  510. plugin->setId(i);
  511. plugins[i].plugin = plugin;
  512. plugins[i].insPeak[0] = 0.0f;
  513. plugins[i].insPeak[1] = 0.0f;
  514. plugins[i].outsPeak[0] = 0.0f;
  515. plugins[i].outsPeak[1] = 0.0f;
  516. }
  517. const uint id(curPluginCount);
  518. // reset last plugin (now removed)
  519. plugins[id].plugin = nullptr;
  520. plugins[id].insPeak[0] = 0.0f;
  521. plugins[id].insPeak[1] = 0.0f;
  522. plugins[id].outsPeak[0] = 0.0f;
  523. plugins[id].outsPeak[1] = 0.0f;
  524. }
  525. void CarlaEngine::ProtectedData::doPluginsSwitch(const uint idA, const uint idB) noexcept
  526. {
  527. CARLA_SAFE_ASSERT_RETURN(curPluginCount >= 2,);
  528. CARLA_SAFE_ASSERT_RETURN(idA < curPluginCount,);
  529. CARLA_SAFE_ASSERT_RETURN(idB < curPluginCount,);
  530. CarlaPlugin* const pluginA(plugins[idA].plugin);
  531. CARLA_SAFE_ASSERT_RETURN(pluginA != nullptr,);
  532. CarlaPlugin* const pluginB(plugins[idB].plugin);
  533. CARLA_SAFE_ASSERT_RETURN(pluginB != nullptr,);
  534. pluginA->setId(idB);
  535. plugins[idA].plugin = pluginB;
  536. pluginB->setId(idA);
  537. plugins[idB].plugin = pluginA;
  538. }
  539. #endif
  540. void CarlaEngine::ProtectedData::doNextPluginAction() noexcept
  541. {
  542. if (! nextAction.mutex.tryLock())
  543. return;
  544. const EnginePostAction opcode = nextAction.opcode;
  545. const bool needsPost = nextAction.needsPost;
  546. #ifndef BUILD_BRIDGE
  547. const uint pluginId = nextAction.pluginId;
  548. const uint value = nextAction.value;
  549. #endif
  550. nextAction.opcode = kEnginePostActionNull;
  551. nextAction.pluginId = 0;
  552. nextAction.value = 0;
  553. nextAction.needsPost = false;
  554. nextAction.mutex.unlock();
  555. switch (opcode)
  556. {
  557. case kEnginePostActionNull:
  558. break;
  559. case kEnginePostActionZeroCount:
  560. curPluginCount = 0;
  561. break;
  562. #ifndef BUILD_BRIDGE
  563. case kEnginePostActionRemovePlugin:
  564. doPluginRemove(pluginId);
  565. break;
  566. case kEnginePostActionSwitchPlugins:
  567. doPluginsSwitch(pluginId, value);
  568. break;
  569. #endif
  570. }
  571. if (needsPost)
  572. {
  573. if (nextAction.sem != nullptr)
  574. carla_sem_post(*nextAction.sem);
  575. nextAction.postDone = true;
  576. }
  577. }
  578. // -----------------------------------------------------------------------
  579. // PendingRtEventsRunner
  580. PendingRtEventsRunner::PendingRtEventsRunner(CarlaEngine* const engine, const uint32_t frames) noexcept
  581. : pData(engine->pData)
  582. {
  583. pData->time.preProcess(frames);
  584. }
  585. PendingRtEventsRunner::~PendingRtEventsRunner() noexcept
  586. {
  587. pData->doNextPluginAction();
  588. }
  589. // -----------------------------------------------------------------------
  590. // ScopedActionLock
  591. ScopedActionLock::ScopedActionLock(CarlaEngine* const engine,
  592. const EnginePostAction action,
  593. const uint pluginId,
  594. const uint value) noexcept
  595. : pData(engine->pData)
  596. {
  597. CARLA_SAFE_ASSERT_RETURN(action != kEnginePostActionNull,);
  598. {
  599. const CarlaMutexLocker cml(pData->nextAction.mutex);
  600. CARLA_SAFE_ASSERT_RETURN(pData->nextAction.opcode == kEnginePostActionNull,);
  601. pData->nextAction.opcode = action;
  602. pData->nextAction.pluginId = pluginId;
  603. pData->nextAction.value = value;
  604. pData->nextAction.needsPost = engine->isRunning();
  605. pData->nextAction.postDone = false;
  606. }
  607. #ifdef BUILD_BRIDGE
  608. #define ACTION_MSG_PREFIX "Bridge: "
  609. #else
  610. #define ACTION_MSG_PREFIX ""
  611. #endif
  612. if (pData->nextAction.needsPost)
  613. {
  614. // block wait for unlock on processing side
  615. carla_stdout(ACTION_MSG_PREFIX "ScopedPluginAction(%i) - blocking START", pluginId);
  616. bool engineStoppedWhileWaiting = false;
  617. if (! pData->nextAction.postDone)
  618. {
  619. for (int i = 10; --i >= 0;)
  620. {
  621. if (pData->nextAction.sem != nullptr)
  622. {
  623. if (carla_sem_timedwait(*pData->nextAction.sem, 200))
  624. break;
  625. }
  626. else
  627. {
  628. carla_msleep(200);
  629. }
  630. if (! engine->isRunning())
  631. {
  632. engineStoppedWhileWaiting = true;
  633. break;
  634. }
  635. }
  636. }
  637. carla_stdout(ACTION_MSG_PREFIX "ScopedPluginAction(%i) - blocking DONE", pluginId);
  638. // check if anything went wrong...
  639. if (! pData->nextAction.postDone)
  640. {
  641. bool needsCorrection = false;
  642. {
  643. const CarlaMutexLocker cml(pData->nextAction.mutex);
  644. if (pData->nextAction.opcode != kEnginePostActionNull)
  645. {
  646. needsCorrection = true;
  647. pData->nextAction.needsPost = false;
  648. }
  649. }
  650. if (needsCorrection)
  651. {
  652. pData->doNextPluginAction();
  653. if (! engineStoppedWhileWaiting)
  654. carla_stderr2(ACTION_MSG_PREFIX "Failed to wait for engine, is audio not running?");
  655. }
  656. }
  657. }
  658. else
  659. {
  660. pData->doNextPluginAction();
  661. }
  662. }
  663. ScopedActionLock::~ScopedActionLock() noexcept
  664. {
  665. CARLA_SAFE_ASSERT(pData->nextAction.opcode == kEnginePostActionNull);
  666. }
  667. // -----------------------------------------------------------------------
  668. // ScopedThreadStopper
  669. ScopedThreadStopper::ScopedThreadStopper(CarlaEngine* const e) noexcept
  670. : engine(e),
  671. pData(e->pData)
  672. {
  673. pData->thread.stopThread(500);
  674. }
  675. ScopedThreadStopper::~ScopedThreadStopper() noexcept
  676. {
  677. if (engine->isRunning() && ! pData->aboutToClose)
  678. pData->thread.startThread();
  679. }
  680. // -----------------------------------------------------------------------
  681. // ScopedEngineEnvironmentLocker
  682. ScopedEngineEnvironmentLocker::ScopedEngineEnvironmentLocker(CarlaEngine* const engine) noexcept
  683. : pData(engine->pData)
  684. {
  685. pData->envMutex.lock();
  686. }
  687. ScopedEngineEnvironmentLocker::~ScopedEngineEnvironmentLocker() noexcept
  688. {
  689. pData->envMutex.unlock();
  690. }
  691. // -----------------------------------------------------------------------
  692. CARLA_BACKEND_END_NAMESPACE