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.

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