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.

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