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

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