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.

CarlaEngineInternal.cpp 24KB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
6 years ago
10 years ago
6 years ago
6 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882
  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