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.

883 lines
24KB

  1. /*
  2. * Carla Plugin Host
  3. * Copyright (C) 2011-2020 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. #include <ctime>
  22. #include <sys/time.h>
  23. CARLA_BACKEND_START_NAMESPACE
  24. // -----------------------------------------------------------------------
  25. // Engine Internal helper macro, sets lastError and returns false/NULL
  26. #define CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(cond, err) if (! (cond)) { carla_safe_assert(#cond, __FILE__, __LINE__); lastError = err; return false; }
  27. #define CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERRN(cond, err) if (! (cond)) { carla_safe_assert(#cond, __FILE__, __LINE__); lastError = err; return nullptr; }
  28. // -----------------------------------------------------------------------
  29. // InternalEvents
  30. EngineInternalEvents::EngineInternalEvents() noexcept
  31. : in(nullptr),
  32. out(nullptr) {}
  33. EngineInternalEvents::~EngineInternalEvents() noexcept
  34. {
  35. CARLA_SAFE_ASSERT(in == nullptr);
  36. CARLA_SAFE_ASSERT(out == nullptr);
  37. }
  38. void EngineInternalEvents::clear() noexcept
  39. {
  40. if (in != nullptr)
  41. {
  42. delete[] in;
  43. in = nullptr;
  44. }
  45. if (out != nullptr)
  46. {
  47. delete[] out;
  48. out = nullptr;
  49. }
  50. }
  51. // -----------------------------------------------------------------------
  52. // InternalTime
  53. static const double kTicksPerBeat = 1920.0;
  54. #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
  55. static uint32_t calculate_link_latency(const double bufferSize, const double sampleRate) noexcept
  56. {
  57. CARLA_SAFE_ASSERT_RETURN(carla_isNotZero(sampleRate), 0);
  58. const long long int latency = llround(1.0e6 * bufferSize / sampleRate);
  59. CARLA_SAFE_ASSERT_RETURN(latency >= 0 && latency < UINT32_MAX, 0);
  60. return static_cast<uint32_t>(latency);
  61. }
  62. #endif
  63. EngineInternalTime::EngineInternalTime(EngineTimeInfo& ti, const EngineTransportMode& tm) noexcept
  64. : beatsPerBar(4.0),
  65. beatsPerMinute(120.0),
  66. bufferSize(0.0),
  67. sampleRate(0.0),
  68. needsReset(false),
  69. nextFrame(0),
  70. #ifndef BUILD_BRIDGE
  71. hylia(),
  72. #endif
  73. timeInfo(ti),
  74. transportMode(tm) {}
  75. void EngineInternalTime::init(const uint32_t bsize, const double srate)
  76. {
  77. bufferSize = bsize;
  78. sampleRate = srate;
  79. #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
  80. if (hylia.instance != nullptr)
  81. {
  82. hylia_set_beats_per_bar(hylia.instance, beatsPerBar);
  83. hylia_set_beats_per_minute(hylia.instance, beatsPerMinute);
  84. hylia_set_output_latency(hylia.instance, calculate_link_latency(bsize, srate));
  85. if (hylia.enabled)
  86. hylia_enable(hylia.instance, true);
  87. }
  88. #endif
  89. needsReset = true;
  90. }
  91. void EngineInternalTime::updateAudioValues(const uint32_t bsize, const double srate)
  92. {
  93. bufferSize = bsize;
  94. sampleRate = srate;
  95. #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
  96. if (hylia.instance != nullptr)
  97. hylia_set_output_latency(hylia.instance, calculate_link_latency(bsize, srate));
  98. #endif
  99. needsReset = true;
  100. }
  101. void EngineInternalTime::enableLink(const bool enable)
  102. {
  103. #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
  104. if (hylia.enabled == enable)
  105. return;
  106. if (hylia.instance != nullptr)
  107. {
  108. hylia.enabled = enable;
  109. hylia_enable(hylia.instance, enable);
  110. }
  111. #else
  112. // unused
  113. (void)enable;
  114. #endif
  115. needsReset = true;
  116. }
  117. void EngineInternalTime::setBPM(const double bpm)
  118. {
  119. beatsPerMinute = bpm;
  120. #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
  121. if (hylia.instance != nullptr)
  122. hylia_set_beats_per_minute(hylia.instance, bpm);
  123. #endif
  124. }
  125. void EngineInternalTime::setNeedsReset() noexcept
  126. {
  127. needsReset = true;
  128. }
  129. void EngineInternalTime::pause() noexcept
  130. {
  131. timeInfo.playing = false;
  132. nextFrame = timeInfo.frame;
  133. needsReset = true;
  134. }
  135. void EngineInternalTime::relocate(const uint64_t frame) noexcept
  136. {
  137. timeInfo.frame = frame;
  138. nextFrame = frame;
  139. needsReset = true;
  140. }
  141. void EngineInternalTime::fillEngineTimeInfo(const uint32_t newFrames) noexcept
  142. {
  143. CARLA_SAFE_ASSERT_RETURN(carla_isNotZero(sampleRate),);
  144. CARLA_SAFE_ASSERT_RETURN(newFrames > 0,);
  145. double ticktmp;
  146. if (transportMode == ENGINE_TRANSPORT_MODE_INTERNAL)
  147. {
  148. timeInfo.usecs = 0;
  149. timeInfo.frame = nextFrame;
  150. }
  151. if (needsReset)
  152. {
  153. timeInfo.bbt.valid = true;
  154. timeInfo.bbt.beatType = 4.0f;
  155. timeInfo.bbt.ticksPerBeat = kTicksPerBeat;
  156. double abs_beat, abs_tick;
  157. #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
  158. if (hylia.enabled)
  159. {
  160. if (hylia.timeInfo.beat >= 0.0)
  161. {
  162. abs_beat = hylia.timeInfo.beat;
  163. abs_tick = abs_beat * kTicksPerBeat;
  164. }
  165. else
  166. {
  167. abs_beat = 0.0;
  168. abs_tick = 0.0;
  169. timeInfo.playing = false;
  170. }
  171. }
  172. else
  173. #endif
  174. {
  175. const double min = static_cast<double>(timeInfo.frame) / (sampleRate * 60.0);
  176. abs_beat = min * beatsPerMinute;
  177. abs_tick = abs_beat * kTicksPerBeat;
  178. needsReset = false;
  179. }
  180. const double bar = std::floor(abs_beat / beatsPerBar);
  181. const double beat = std::floor(std::fmod(abs_beat, beatsPerBar));
  182. timeInfo.bbt.bar = static_cast<int32_t>(bar) + 1;
  183. timeInfo.bbt.beat = static_cast<int32_t>(beat) + 1;
  184. timeInfo.bbt.barStartTick = ((bar * beatsPerBar) + beat) * kTicksPerBeat;
  185. ticktmp = abs_tick - timeInfo.bbt.barStartTick;
  186. }
  187. else if (timeInfo.playing)
  188. {
  189. ticktmp = timeInfo.bbt.tick + (newFrames * kTicksPerBeat * beatsPerMinute / (sampleRate * 60));
  190. while (ticktmp >= kTicksPerBeat)
  191. {
  192. ticktmp -= kTicksPerBeat;
  193. if (++timeInfo.bbt.beat > beatsPerBar)
  194. {
  195. ++timeInfo.bbt.bar;
  196. timeInfo.bbt.beat = 1;
  197. timeInfo.bbt.barStartTick += beatsPerBar * kTicksPerBeat;
  198. }
  199. }
  200. }
  201. else
  202. {
  203. ticktmp = timeInfo.bbt.tick;
  204. }
  205. timeInfo.bbt.beatsPerBar = static_cast<float>(beatsPerBar);
  206. timeInfo.bbt.beatsPerMinute = beatsPerMinute;
  207. timeInfo.bbt.tick = ticktmp;
  208. if (transportMode == ENGINE_TRANSPORT_MODE_INTERNAL && timeInfo.playing)
  209. nextFrame += newFrames;
  210. }
  211. void EngineInternalTime::fillJackTimeInfo(jack_position_t* const pos, const uint32_t newFrames) noexcept
  212. {
  213. CARLA_SAFE_ASSERT_RETURN(carla_isNotZero(sampleRate),);
  214. CARLA_SAFE_ASSERT_RETURN(newFrames > 0,);
  215. CARLA_SAFE_ASSERT(transportMode == ENGINE_TRANSPORT_MODE_JACK);
  216. fillEngineTimeInfo(newFrames);
  217. pos->bar = timeInfo.bbt.bar;
  218. pos->beat = timeInfo.bbt.beat;
  219. pos->tick = static_cast<int32_t>(timeInfo.bbt.tick + 0.5);
  220. pos->bar_start_tick = timeInfo.bbt.barStartTick;
  221. pos->beats_per_bar = timeInfo.bbt.beatsPerBar;
  222. pos->beat_type = timeInfo.bbt.beatType;
  223. pos->ticks_per_beat = kTicksPerBeat;
  224. pos->beats_per_minute = beatsPerMinute;
  225. #ifdef JACK_TICK_DOUBLE
  226. pos->tick_double = timeInfo.bbt.tick;
  227. pos->valid = static_cast<jack_position_bits_t>(JackPositionBBT|JackTickDouble);
  228. #else
  229. pos->valid = JackPositionBBT;
  230. #endif
  231. }
  232. void EngineInternalTime::preProcess(const uint32_t numFrames)
  233. {
  234. #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
  235. if (hylia.enabled)
  236. {
  237. hylia_process(hylia.instance, numFrames, &hylia.timeInfo);
  238. const double new_bpb = hylia.timeInfo.beatsPerBar;
  239. const double new_bpm = hylia.timeInfo.beatsPerMinute;
  240. if (new_bpb >= 1.0 && carla_isNotEqual(beatsPerBar, new_bpb))
  241. {
  242. beatsPerBar = new_bpb;
  243. needsReset = true;
  244. }
  245. if (new_bpm > 0.0 && carla_isNotEqual(beatsPerMinute, new_bpm))
  246. {
  247. beatsPerMinute = new_bpm;
  248. needsReset = true;
  249. }
  250. }
  251. #endif
  252. if (transportMode == ENGINE_TRANSPORT_MODE_INTERNAL)
  253. fillEngineTimeInfo(numFrames);
  254. }
  255. // -----------------------------------------------------------------------
  256. // EngineInternalTime::Hylia
  257. #ifndef BUILD_BRIDGE
  258. EngineInternalTime::Hylia::Hylia()
  259. : enabled(false),
  260. instance(nullptr),
  261. timeInfo()
  262. {
  263. carla_zeroStruct(timeInfo);
  264. # ifdef HAVE_HYLIA
  265. instance = hylia_create();
  266. # endif
  267. }
  268. EngineInternalTime::Hylia::~Hylia()
  269. {
  270. # ifdef HAVE_HYLIA
  271. hylia_cleanup(instance);
  272. # endif
  273. }
  274. #endif
  275. // -----------------------------------------------------------------------
  276. // NextAction
  277. EngineNextAction::EngineNextAction() noexcept
  278. : opcode(kEnginePostActionNull),
  279. pluginId(0),
  280. value(0),
  281. mutex(),
  282. needsPost(false),
  283. postDone(false),
  284. sem(carla_sem_create(false)) {}
  285. EngineNextAction::~EngineNextAction() noexcept
  286. {
  287. CARLA_SAFE_ASSERT(opcode == kEnginePostActionNull);
  288. if (sem != nullptr)
  289. {
  290. carla_sem_destroy(sem);
  291. sem = nullptr;
  292. }
  293. }
  294. void EngineNextAction::clearAndReset() noexcept
  295. {
  296. mutex.lock();
  297. CARLA_SAFE_ASSERT(opcode == kEnginePostActionNull);
  298. opcode = kEnginePostActionNull;
  299. pluginId = 0;
  300. value = 0;
  301. needsPost = false;
  302. postDone = false;
  303. mutex.unlock();
  304. }
  305. // -----------------------------------------------------------------------
  306. // Helper functions
  307. EngineEvent* CarlaEngine::getInternalEventBuffer(const bool isInput) const noexcept
  308. {
  309. return isInput ? pData->events.in : pData->events.out;
  310. }
  311. // -----------------------------------------------------------------------
  312. // CarlaEngine::ProtectedData
  313. CarlaEngine::ProtectedData::ProtectedData(CarlaEngine* const engine)
  314. : runner(engine),
  315. #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
  316. osc(engine),
  317. #endif
  318. callback(nullptr),
  319. callbackPtr(nullptr),
  320. fileCallback(nullptr),
  321. fileCallbackPtr(nullptr),
  322. actionCanceled(false),
  323. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  324. loadingProject(false),
  325. ignoreClientPrefix(false),
  326. currentProjectFilename(),
  327. currentProjectFolder(),
  328. #endif
  329. bufferSize(0),
  330. sampleRate(0.0),
  331. aboutToClose(false),
  332. isIdling(0),
  333. curPluginCount(0),
  334. maxPluginNumber(0),
  335. nextPluginId(0),
  336. envMutex(),
  337. lastError(),
  338. name(),
  339. options(),
  340. timeInfo(),
  341. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  342. plugins(nullptr),
  343. xruns(0),
  344. dspLoad(0.0f),
  345. #endif
  346. pluginsToDeleteMutex(),
  347. pluginsToDelete(),
  348. events(),
  349. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  350. graph(engine),
  351. #endif
  352. time(timeInfo, options.transportMode),
  353. nextAction()
  354. {
  355. #ifdef BUILD_BRIDGE_ALTERNATIVE_ARCH
  356. plugins[0].plugin = nullptr;
  357. carla_zeroStructs(plugins[0].peaks, 1);
  358. #endif
  359. }
  360. CarlaEngine::ProtectedData::~ProtectedData()
  361. {
  362. CARLA_SAFE_ASSERT(curPluginCount == 0);
  363. CARLA_SAFE_ASSERT(maxPluginNumber == 0);
  364. CARLA_SAFE_ASSERT(nextPluginId == 0);
  365. CARLA_SAFE_ASSERT(isIdling == 0);
  366. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  367. CARLA_SAFE_ASSERT(plugins == nullptr);
  368. #endif
  369. const CarlaMutexLocker cml(pluginsToDeleteMutex);
  370. if (pluginsToDelete.size() != 0)
  371. {
  372. for (std::vector<CarlaPluginPtr>::iterator it = pluginsToDelete.begin(); it != pluginsToDelete.end(); ++it)
  373. {
  374. carla_stderr2("Plugin not yet deleted, name: '%s', usage count: '%u'",
  375. (*it)->getName(), it->use_count());
  376. }
  377. }
  378. pluginsToDelete.clear();
  379. }
  380. // -----------------------------------------------------------------------
  381. bool CarlaEngine::ProtectedData::init(const char* const clientName)
  382. {
  383. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(name.isEmpty(), "Invalid engine internal data (err #1)");
  384. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(events.in == nullptr, "Invalid engine internal data (err #4)");
  385. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(events.out == nullptr, "Invalid engine internal data (err #5)");
  386. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(clientName != nullptr && clientName[0] != '\0', "Invalid client name");
  387. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  388. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(plugins == nullptr, "Invalid engine internal data (err #3)");
  389. #endif
  390. aboutToClose = false;
  391. curPluginCount = 0;
  392. nextPluginId = 0;
  393. switch (options.processMode)
  394. {
  395. case ENGINE_PROCESS_MODE_CONTINUOUS_RACK:
  396. maxPluginNumber = MAX_RACK_PLUGINS;
  397. options.forceStereo = true;
  398. break;
  399. case ENGINE_PROCESS_MODE_PATCHBAY:
  400. maxPluginNumber = MAX_PATCHBAY_PLUGINS;
  401. break;
  402. case ENGINE_PROCESS_MODE_BRIDGE:
  403. maxPluginNumber = 1;
  404. break;
  405. default:
  406. maxPluginNumber = MAX_DEFAULT_PLUGINS;
  407. break;
  408. }
  409. switch (options.processMode)
  410. {
  411. case ENGINE_PROCESS_MODE_CONTINUOUS_RACK:
  412. case ENGINE_PROCESS_MODE_PATCHBAY:
  413. case ENGINE_PROCESS_MODE_BRIDGE:
  414. events.in = new EngineEvent[kMaxEngineEventInternalCount];
  415. events.out = new EngineEvent[kMaxEngineEventInternalCount];
  416. carla_zeroStructs(events.in, kMaxEngineEventInternalCount);
  417. carla_zeroStructs(events.out, kMaxEngineEventInternalCount);
  418. break;
  419. default:
  420. break;
  421. }
  422. nextPluginId = maxPluginNumber;
  423. name = clientName;
  424. name.toBasic();
  425. timeInfo.clear();
  426. #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
  427. if (options.oscEnabled)
  428. osc.init(clientName, options.oscPortTCP, options.oscPortUDP);
  429. #endif
  430. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  431. plugins = new EnginePluginData[maxPluginNumber];
  432. xruns = 0;
  433. dspLoad = 0.0f;
  434. #endif
  435. nextAction.clearAndReset();
  436. runner.start();
  437. return true;
  438. }
  439. void CarlaEngine::ProtectedData::close()
  440. {
  441. CARLA_SAFE_ASSERT(name.isNotEmpty());
  442. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  443. CARLA_SAFE_ASSERT(plugins != nullptr);
  444. CARLA_SAFE_ASSERT(nextPluginId == maxPluginNumber);
  445. #endif
  446. aboutToClose = true;
  447. runner.stop();
  448. nextAction.clearAndReset();
  449. #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
  450. osc.close();
  451. #endif
  452. aboutToClose = false;
  453. curPluginCount = 0;
  454. maxPluginNumber = 0;
  455. nextPluginId = 0;
  456. deletePluginsAsNeeded();
  457. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  458. if (plugins != nullptr)
  459. {
  460. delete[] plugins;
  461. plugins = nullptr;
  462. }
  463. #endif
  464. events.clear();
  465. name.clear();
  466. }
  467. void CarlaEngine::ProtectedData::initTime(const char* const features)
  468. {
  469. time.init(bufferSize, sampleRate);
  470. #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
  471. const bool linkEnabled = features != nullptr && std::strstr(features, ":link:") != nullptr;
  472. time.enableLink(linkEnabled);
  473. #else
  474. return;
  475. // unused
  476. (void)features;
  477. #endif
  478. }
  479. // -----------------------------------------------------------------------
  480. void CarlaEngine::ProtectedData::deletePluginsAsNeeded()
  481. {
  482. std::vector<CarlaPluginPtr> safePluginListToDelete;
  483. if (const size_t size = pluginsToDelete.size())
  484. safePluginListToDelete.reserve(size);
  485. {
  486. const CarlaMutexLocker cml(pluginsToDeleteMutex);
  487. for (std::vector<CarlaPluginPtr>::iterator it = pluginsToDelete.begin(); it != pluginsToDelete.end();)
  488. {
  489. if (it->use_count() == 1)
  490. {
  491. const CarlaPluginPtr plugin = *it;
  492. safePluginListToDelete.push_back(plugin);
  493. pluginsToDelete.erase(it);
  494. }
  495. else
  496. {
  497. ++it;
  498. }
  499. }
  500. }
  501. }
  502. // -----------------------------------------------------------------------
  503. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  504. void CarlaEngine::ProtectedData::doPluginRemove(const uint pluginId) noexcept
  505. {
  506. CARLA_SAFE_ASSERT_RETURN(curPluginCount > 0,);
  507. CARLA_SAFE_ASSERT_RETURN(pluginId < curPluginCount,);
  508. --curPluginCount;
  509. // move all plugins 1 spot backwards
  510. for (uint i=pluginId; i < curPluginCount; ++i)
  511. {
  512. const CarlaPluginPtr plugin = plugins[i+1].plugin;
  513. CARLA_SAFE_ASSERT_BREAK(plugin.get() != nullptr);
  514. plugin->setId(i);
  515. plugins[i].plugin = plugin;
  516. carla_zeroStruct(plugins[i].peaks);
  517. }
  518. const uint id = curPluginCount;
  519. // reset last plugin (now removed)
  520. plugins[id].plugin.reset();
  521. carla_zeroFloats(plugins[id].peaks, 4);
  522. }
  523. void CarlaEngine::ProtectedData::doPluginsSwitch(const uint idA, const uint idB) noexcept
  524. {
  525. CARLA_SAFE_ASSERT_RETURN(curPluginCount >= 2,);
  526. CARLA_SAFE_ASSERT_RETURN(idA < curPluginCount,);
  527. CARLA_SAFE_ASSERT_RETURN(idB < curPluginCount,);
  528. const CarlaPluginPtr pluginA = plugins[idA].plugin;
  529. CARLA_SAFE_ASSERT_RETURN(pluginA.get() != nullptr,);
  530. const CarlaPluginPtr pluginB = plugins[idB].plugin;
  531. CARLA_SAFE_ASSERT_RETURN(pluginB.get() != nullptr,);
  532. pluginA->setId(idB);
  533. plugins[idA].plugin = pluginB;
  534. pluginB->setId(idA);
  535. plugins[idB].plugin = pluginA;
  536. }
  537. #endif
  538. void CarlaEngine::ProtectedData::doNextPluginAction() noexcept
  539. {
  540. if (! nextAction.mutex.tryLock())
  541. return;
  542. const EnginePostAction opcode = nextAction.opcode;
  543. const bool needsPost = nextAction.needsPost;
  544. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  545. const uint pluginId = nextAction.pluginId;
  546. const uint value = nextAction.value;
  547. #endif
  548. nextAction.opcode = kEnginePostActionNull;
  549. nextAction.pluginId = 0;
  550. nextAction.value = 0;
  551. nextAction.needsPost = false;
  552. nextAction.mutex.unlock();
  553. switch (opcode)
  554. {
  555. case kEnginePostActionNull:
  556. break;
  557. case kEnginePostActionZeroCount:
  558. curPluginCount = 0;
  559. break;
  560. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  561. case kEnginePostActionRemovePlugin:
  562. doPluginRemove(pluginId);
  563. break;
  564. case kEnginePostActionSwitchPlugins:
  565. doPluginsSwitch(pluginId, value);
  566. break;
  567. #endif
  568. }
  569. if (needsPost)
  570. {
  571. if (nextAction.sem != nullptr)
  572. carla_sem_post(*nextAction.sem);
  573. nextAction.postDone = true;
  574. }
  575. }
  576. // -----------------------------------------------------------------------
  577. // PendingRtEventsRunner
  578. static int64_t getTimeInMicroseconds() noexcept
  579. {
  580. #if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
  581. struct timeval tv;
  582. gettimeofday(&tv, nullptr);
  583. return (tv.tv_sec * 1000000) + tv.tv_usec;
  584. #else
  585. struct timespec ts;
  586. # ifdef CLOCK_MONOTONIC_RAW
  587. clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
  588. # else
  589. clock_gettime(CLOCK_MONOTONIC, &ts);
  590. # endif
  591. return (ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
  592. #endif
  593. }
  594. PendingRtEventsRunner::PendingRtEventsRunner(CarlaEngine* const engine,
  595. const uint32_t frames,
  596. const bool calcDSPLoad) noexcept
  597. : pData(engine->pData),
  598. prevTime(calcDSPLoad ? getTimeInMicroseconds() : 0)
  599. {
  600. pData->time.preProcess(frames);
  601. }
  602. PendingRtEventsRunner::~PendingRtEventsRunner() noexcept
  603. {
  604. pData->doNextPluginAction();
  605. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  606. if (prevTime > 0)
  607. {
  608. const int64_t newTime = getTimeInMicroseconds();
  609. if (newTime < prevTime)
  610. return;
  611. const double timeDiff = static_cast<double>(newTime - prevTime) / 1000000.0;
  612. const double maxTime = pData->bufferSize / pData->sampleRate;
  613. const float dspLoad = static_cast<float>(timeDiff / maxTime) * 100.0f;
  614. if (dspLoad > pData->dspLoad)
  615. pData->dspLoad = std::min(100.0f, dspLoad);
  616. else
  617. pData->dspLoad *= static_cast<float>(1.0 - maxTime) + 1e-12f;
  618. }
  619. #endif
  620. }
  621. // -----------------------------------------------------------------------
  622. // ScopedActionLock
  623. ScopedActionLock::ScopedActionLock(CarlaEngine* const engine,
  624. const EnginePostAction action,
  625. const uint pluginId,
  626. const uint value) noexcept
  627. : pData(engine->pData)
  628. {
  629. CARLA_SAFE_ASSERT_RETURN(action != kEnginePostActionNull,);
  630. {
  631. const CarlaMutexLocker cml(pData->nextAction.mutex);
  632. CARLA_SAFE_ASSERT_RETURN(pData->nextAction.opcode == kEnginePostActionNull,);
  633. pData->nextAction.opcode = action;
  634. pData->nextAction.pluginId = pluginId;
  635. pData->nextAction.value = value;
  636. pData->nextAction.needsPost = engine->isRunning();
  637. pData->nextAction.postDone = false;
  638. }
  639. #ifdef BUILD_BRIDGE
  640. #define ACTION_MSG_PREFIX "Bridge: "
  641. #else
  642. #define ACTION_MSG_PREFIX ""
  643. #endif
  644. if (pData->nextAction.needsPost)
  645. {
  646. bool engineStoppedWhileWaiting = false;
  647. #ifndef CARLA_OS_WASM
  648. #if defined(DEBUG) || defined(BUILD_BRIDGE)
  649. // block wait for unlock on processing side
  650. carla_stdout(ACTION_MSG_PREFIX "ScopedPluginAction(%i) - blocking START", pluginId);
  651. #endif
  652. if (! pData->nextAction.postDone)
  653. {
  654. for (int i = 10; --i >= 0;)
  655. {
  656. if (pData->nextAction.sem != nullptr)
  657. {
  658. if (carla_sem_timedwait(*pData->nextAction.sem, 200))
  659. break;
  660. }
  661. else
  662. {
  663. carla_msleep(200);
  664. }
  665. if (! engine->isRunning())
  666. {
  667. engineStoppedWhileWaiting = true;
  668. break;
  669. }
  670. }
  671. }
  672. #if defined(DEBUG) || defined(BUILD_BRIDGE)
  673. carla_stdout(ACTION_MSG_PREFIX "ScopedPluginAction(%i) - blocking DONE", pluginId);
  674. #endif
  675. #endif
  676. // check if anything went wrong...
  677. if (! pData->nextAction.postDone)
  678. {
  679. bool needsCorrection = false;
  680. {
  681. const CarlaMutexLocker cml(pData->nextAction.mutex);
  682. if (pData->nextAction.opcode != kEnginePostActionNull)
  683. {
  684. needsCorrection = true;
  685. pData->nextAction.needsPost = false;
  686. }
  687. }
  688. if (needsCorrection)
  689. {
  690. pData->doNextPluginAction();
  691. if (! engineStoppedWhileWaiting)
  692. carla_stderr2(ACTION_MSG_PREFIX "Failed to wait for engine, is audio not running?");
  693. }
  694. }
  695. }
  696. else
  697. {
  698. pData->doNextPluginAction();
  699. }
  700. }
  701. ScopedActionLock::~ScopedActionLock() noexcept
  702. {
  703. CARLA_SAFE_ASSERT(pData->nextAction.opcode == kEnginePostActionNull);
  704. }
  705. // -----------------------------------------------------------------------
  706. // ScopedRunnerStopper
  707. ScopedRunnerStopper::ScopedRunnerStopper(CarlaEngine* const e) noexcept
  708. : engine(e),
  709. pData(e->pData)
  710. {
  711. pData->runner.stop();
  712. }
  713. ScopedRunnerStopper::~ScopedRunnerStopper() noexcept
  714. {
  715. if (engine->isRunning() && ! pData->aboutToClose)
  716. pData->runner.start();
  717. }
  718. // -----------------------------------------------------------------------
  719. // ScopedEngineEnvironmentLocker
  720. ScopedEngineEnvironmentLocker::ScopedEngineEnvironmentLocker(CarlaEngine* const engine) noexcept
  721. : pData(engine->pData)
  722. {
  723. pData->envMutex.lock();
  724. }
  725. ScopedEngineEnvironmentLocker::~ScopedEngineEnvironmentLocker() noexcept
  726. {
  727. pData->envMutex.unlock();
  728. }
  729. // -----------------------------------------------------------------------
  730. CARLA_BACKEND_END_NAMESPACE