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 23KB

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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872
  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. : thread(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. pluginsToDelete(),
  347. events(),
  348. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  349. graph(engine),
  350. #endif
  351. time(timeInfo, options.transportMode),
  352. nextAction()
  353. {
  354. #ifdef BUILD_BRIDGE_ALTERNATIVE_ARCH
  355. plugins[0].plugin = nullptr;
  356. carla_zeroStructs(plugins[0].peaks, 1);
  357. #endif
  358. }
  359. CarlaEngine::ProtectedData::~ProtectedData()
  360. {
  361. CARLA_SAFE_ASSERT(curPluginCount == 0);
  362. CARLA_SAFE_ASSERT(maxPluginNumber == 0);
  363. CARLA_SAFE_ASSERT(nextPluginId == 0);
  364. CARLA_SAFE_ASSERT(isIdling == 0);
  365. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  366. CARLA_SAFE_ASSERT(plugins == nullptr);
  367. #endif
  368. if (pluginsToDelete.size() != 0)
  369. {
  370. for (std::vector<CarlaPluginPtr>::iterator it = pluginsToDelete.begin(); it != pluginsToDelete.end(); ++it)
  371. {
  372. carla_stderr2("Plugin not yet deleted, name: '%s', usage count: '%u'",
  373. (*it)->getName(), it->use_count());
  374. }
  375. }
  376. pluginsToDelete.clear();
  377. }
  378. // -----------------------------------------------------------------------
  379. bool CarlaEngine::ProtectedData::init(const char* const clientName)
  380. {
  381. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(name.isEmpty(), "Invalid engine internal data (err #1)");
  382. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(events.in == nullptr, "Invalid engine internal data (err #4)");
  383. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(events.out == nullptr, "Invalid engine internal data (err #5)");
  384. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(clientName != nullptr && clientName[0] != '\0', "Invalid client name");
  385. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  386. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(plugins == nullptr, "Invalid engine internal data (err #3)");
  387. #endif
  388. aboutToClose = false;
  389. curPluginCount = 0;
  390. nextPluginId = 0;
  391. switch (options.processMode)
  392. {
  393. case ENGINE_PROCESS_MODE_CONTINUOUS_RACK:
  394. maxPluginNumber = MAX_RACK_PLUGINS;
  395. options.forceStereo = true;
  396. break;
  397. case ENGINE_PROCESS_MODE_PATCHBAY:
  398. maxPluginNumber = MAX_PATCHBAY_PLUGINS;
  399. break;
  400. case ENGINE_PROCESS_MODE_BRIDGE:
  401. maxPluginNumber = 1;
  402. break;
  403. default:
  404. maxPluginNumber = MAX_DEFAULT_PLUGINS;
  405. break;
  406. }
  407. switch (options.processMode)
  408. {
  409. case ENGINE_PROCESS_MODE_CONTINUOUS_RACK:
  410. case ENGINE_PROCESS_MODE_PATCHBAY:
  411. case ENGINE_PROCESS_MODE_BRIDGE:
  412. events.in = new EngineEvent[kMaxEngineEventInternalCount];
  413. events.out = new EngineEvent[kMaxEngineEventInternalCount];
  414. carla_zeroStructs(events.in, kMaxEngineEventInternalCount);
  415. carla_zeroStructs(events.out, kMaxEngineEventInternalCount);
  416. break;
  417. default:
  418. break;
  419. }
  420. nextPluginId = maxPluginNumber;
  421. name = clientName;
  422. name.toBasic();
  423. timeInfo.clear();
  424. #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
  425. if (options.oscEnabled)
  426. osc.init(clientName, options.oscPortTCP, options.oscPortUDP);
  427. #endif
  428. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  429. plugins = new EnginePluginData[maxPluginNumber];
  430. xruns = 0;
  431. dspLoad = 0.0f;
  432. #endif
  433. nextAction.clearAndReset();
  434. thread.startThread();
  435. return true;
  436. }
  437. void CarlaEngine::ProtectedData::close()
  438. {
  439. CARLA_SAFE_ASSERT(name.isNotEmpty());
  440. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  441. CARLA_SAFE_ASSERT(plugins != nullptr);
  442. CARLA_SAFE_ASSERT(nextPluginId == maxPluginNumber);
  443. #endif
  444. aboutToClose = true;
  445. thread.stopThread(500);
  446. nextAction.clearAndReset();
  447. #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
  448. osc.close();
  449. #endif
  450. aboutToClose = false;
  451. curPluginCount = 0;
  452. maxPluginNumber = 0;
  453. nextPluginId = 0;
  454. deletePluginsAsNeeded();
  455. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  456. if (plugins != nullptr)
  457. {
  458. delete[] plugins;
  459. plugins = nullptr;
  460. }
  461. #endif
  462. events.clear();
  463. name.clear();
  464. }
  465. void CarlaEngine::ProtectedData::initTime(const char* const features)
  466. {
  467. time.init(bufferSize, sampleRate);
  468. #if defined(HAVE_HYLIA) && !defined(BUILD_BRIDGE)
  469. const bool linkEnabled = features != nullptr && std::strstr(features, ":link:") != nullptr;
  470. time.enableLink(linkEnabled);
  471. #else
  472. return;
  473. // unused
  474. (void)features;
  475. #endif
  476. }
  477. // -----------------------------------------------------------------------
  478. void CarlaEngine::ProtectedData::deletePluginsAsNeeded()
  479. {
  480. for (bool stop;;)
  481. {
  482. stop = true;
  483. for (std::vector<CarlaPluginPtr>::iterator it = pluginsToDelete.begin(); it != pluginsToDelete.end(); ++it)
  484. {
  485. if (it->use_count() == 1)
  486. {
  487. stop = false;
  488. pluginsToDelete.erase(it);
  489. break;
  490. }
  491. }
  492. if (stop)
  493. break;
  494. }
  495. }
  496. // -----------------------------------------------------------------------
  497. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  498. void CarlaEngine::ProtectedData::doPluginRemove(const uint pluginId) noexcept
  499. {
  500. CARLA_SAFE_ASSERT_RETURN(curPluginCount > 0,);
  501. CARLA_SAFE_ASSERT_RETURN(pluginId < curPluginCount,);
  502. --curPluginCount;
  503. // move all plugins 1 spot backwards
  504. for (uint i=pluginId; i < curPluginCount; ++i)
  505. {
  506. const CarlaPluginPtr plugin = plugins[i+1].plugin;
  507. CARLA_SAFE_ASSERT_BREAK(plugin.get() != nullptr);
  508. plugin->setId(i);
  509. plugins[i].plugin = plugin;
  510. carla_zeroStruct(plugins[i].peaks);
  511. }
  512. const uint id = curPluginCount;
  513. // reset last plugin (now removed)
  514. plugins[id].plugin.reset();
  515. carla_zeroFloats(plugins[id].peaks, 4);
  516. }
  517. void CarlaEngine::ProtectedData::doPluginsSwitch(const uint idA, const uint idB) noexcept
  518. {
  519. CARLA_SAFE_ASSERT_RETURN(curPluginCount >= 2,);
  520. CARLA_SAFE_ASSERT_RETURN(idA < curPluginCount,);
  521. CARLA_SAFE_ASSERT_RETURN(idB < curPluginCount,);
  522. const CarlaPluginPtr pluginA = plugins[idA].plugin;
  523. CARLA_SAFE_ASSERT_RETURN(pluginA.get() != nullptr,);
  524. const CarlaPluginPtr pluginB = plugins[idB].plugin;
  525. CARLA_SAFE_ASSERT_RETURN(pluginB.get() != nullptr,);
  526. pluginA->setId(idB);
  527. plugins[idA].plugin = pluginB;
  528. pluginB->setId(idA);
  529. plugins[idB].plugin = pluginA;
  530. }
  531. #endif
  532. void CarlaEngine::ProtectedData::doNextPluginAction() noexcept
  533. {
  534. if (! nextAction.mutex.tryLock())
  535. return;
  536. const EnginePostAction opcode = nextAction.opcode;
  537. const bool needsPost = nextAction.needsPost;
  538. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  539. const uint pluginId = nextAction.pluginId;
  540. const uint value = nextAction.value;
  541. #endif
  542. nextAction.opcode = kEnginePostActionNull;
  543. nextAction.pluginId = 0;
  544. nextAction.value = 0;
  545. nextAction.needsPost = false;
  546. nextAction.mutex.unlock();
  547. switch (opcode)
  548. {
  549. case kEnginePostActionNull:
  550. break;
  551. case kEnginePostActionZeroCount:
  552. curPluginCount = 0;
  553. break;
  554. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  555. case kEnginePostActionRemovePlugin:
  556. doPluginRemove(pluginId);
  557. break;
  558. case kEnginePostActionSwitchPlugins:
  559. doPluginsSwitch(pluginId, value);
  560. break;
  561. #endif
  562. }
  563. if (needsPost)
  564. {
  565. if (nextAction.sem != nullptr)
  566. carla_sem_post(*nextAction.sem);
  567. nextAction.postDone = true;
  568. }
  569. }
  570. // -----------------------------------------------------------------------
  571. // PendingRtEventsRunner
  572. static int64_t getTimeInMicroseconds() noexcept
  573. {
  574. #if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
  575. struct timeval tv;
  576. gettimeofday(&tv, nullptr);
  577. return (tv.tv_sec * 1000000) + tv.tv_usec;
  578. #else
  579. struct timespec ts;
  580. # ifdef CLOCK_MONOTONIC_RAW
  581. clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
  582. # else
  583. clock_gettime(CLOCK_MONOTONIC, &ts);
  584. # endif
  585. return (ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
  586. #endif
  587. }
  588. PendingRtEventsRunner::PendingRtEventsRunner(CarlaEngine* const engine,
  589. const uint32_t frames,
  590. const bool calcDSPLoad) noexcept
  591. : pData(engine->pData),
  592. prevTime(calcDSPLoad ? getTimeInMicroseconds() : 0)
  593. {
  594. pData->time.preProcess(frames);
  595. }
  596. PendingRtEventsRunner::~PendingRtEventsRunner() noexcept
  597. {
  598. pData->doNextPluginAction();
  599. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  600. if (prevTime > 0)
  601. {
  602. const int64_t newTime = getTimeInMicroseconds();
  603. if (newTime < prevTime)
  604. return;
  605. const double timeDiff = static_cast<double>(newTime - prevTime) / 1000000.0;
  606. const double maxTime = pData->bufferSize / pData->sampleRate;
  607. const float dspLoad = static_cast<float>(timeDiff / maxTime) * 100.0f;
  608. if (dspLoad > pData->dspLoad)
  609. pData->dspLoad = std::min(100.0f, dspLoad);
  610. else
  611. pData->dspLoad *= static_cast<float>(1.0 - maxTime) + 1e-12f;
  612. }
  613. #endif
  614. }
  615. // -----------------------------------------------------------------------
  616. // ScopedActionLock
  617. ScopedActionLock::ScopedActionLock(CarlaEngine* const engine,
  618. const EnginePostAction action,
  619. const uint pluginId,
  620. const uint value) noexcept
  621. : pData(engine->pData)
  622. {
  623. CARLA_SAFE_ASSERT_RETURN(action != kEnginePostActionNull,);
  624. {
  625. const CarlaMutexLocker cml(pData->nextAction.mutex);
  626. CARLA_SAFE_ASSERT_RETURN(pData->nextAction.opcode == kEnginePostActionNull,);
  627. pData->nextAction.opcode = action;
  628. pData->nextAction.pluginId = pluginId;
  629. pData->nextAction.value = value;
  630. pData->nextAction.needsPost = engine->isRunning();
  631. pData->nextAction.postDone = false;
  632. }
  633. #ifdef BUILD_BRIDGE
  634. #define ACTION_MSG_PREFIX "Bridge: "
  635. #else
  636. #define ACTION_MSG_PREFIX ""
  637. #endif
  638. if (pData->nextAction.needsPost)
  639. {
  640. #if defined(DEBUG) || defined(BUILD_BRIDGE)
  641. // block wait for unlock on processing side
  642. carla_stdout(ACTION_MSG_PREFIX "ScopedPluginAction(%i) - blocking START", pluginId);
  643. #endif
  644. bool engineStoppedWhileWaiting = false;
  645. if (! pData->nextAction.postDone)
  646. {
  647. for (int i = 10; --i >= 0;)
  648. {
  649. if (pData->nextAction.sem != nullptr)
  650. {
  651. if (carla_sem_timedwait(*pData->nextAction.sem, 200))
  652. break;
  653. }
  654. else
  655. {
  656. carla_msleep(200);
  657. }
  658. if (! engine->isRunning())
  659. {
  660. engineStoppedWhileWaiting = true;
  661. break;
  662. }
  663. }
  664. }
  665. #if defined(DEBUG) || defined(BUILD_BRIDGE)
  666. carla_stdout(ACTION_MSG_PREFIX "ScopedPluginAction(%i) - blocking DONE", pluginId);
  667. #endif
  668. // check if anything went wrong...
  669. if (! pData->nextAction.postDone)
  670. {
  671. bool needsCorrection = false;
  672. {
  673. const CarlaMutexLocker cml(pData->nextAction.mutex);
  674. if (pData->nextAction.opcode != kEnginePostActionNull)
  675. {
  676. needsCorrection = true;
  677. pData->nextAction.needsPost = false;
  678. }
  679. }
  680. if (needsCorrection)
  681. {
  682. pData->doNextPluginAction();
  683. if (! engineStoppedWhileWaiting)
  684. carla_stderr2(ACTION_MSG_PREFIX "Failed to wait for engine, is audio not running?");
  685. }
  686. }
  687. }
  688. else
  689. {
  690. pData->doNextPluginAction();
  691. }
  692. }
  693. ScopedActionLock::~ScopedActionLock() noexcept
  694. {
  695. CARLA_SAFE_ASSERT(pData->nextAction.opcode == kEnginePostActionNull);
  696. }
  697. // -----------------------------------------------------------------------
  698. // ScopedThreadStopper
  699. ScopedThreadStopper::ScopedThreadStopper(CarlaEngine* const e) noexcept
  700. : engine(e),
  701. pData(e->pData)
  702. {
  703. pData->thread.stopThread(500);
  704. }
  705. ScopedThreadStopper::~ScopedThreadStopper() noexcept
  706. {
  707. if (engine->isRunning() && ! pData->aboutToClose)
  708. pData->thread.startThread();
  709. }
  710. // -----------------------------------------------------------------------
  711. // ScopedEngineEnvironmentLocker
  712. ScopedEngineEnvironmentLocker::ScopedEngineEnvironmentLocker(CarlaEngine* const engine) noexcept
  713. : pData(engine->pData)
  714. {
  715. pData->envMutex.lock();
  716. }
  717. ScopedEngineEnvironmentLocker::~ScopedEngineEnvironmentLocker() noexcept
  718. {
  719. pData->envMutex.unlock();
  720. }
  721. // -----------------------------------------------------------------------
  722. CARLA_BACKEND_END_NAMESPACE