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.

870 lines
23KB

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