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

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
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /*
  2. * Carla Plugin Host
  3. * Copyright (C) 2011-2014 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. CARLA_BACKEND_START_NAMESPACE
  20. // -----------------------------------------------------------------------
  21. // Engine Internal helper macro, sets lastError and returns false/NULL
  22. #define CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(cond, err) if (! (cond)) { carla_safe_assert(#cond, __FILE__, __LINE__); lastError = err; return false; }
  23. #define CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERRN(cond, err) if (! (cond)) { carla_safe_assert(#cond, __FILE__, __LINE__); lastError = err; return nullptr; }
  24. // -----------------------------------------------------------------------
  25. // InternalEvents
  26. EngineInternalEvents::EngineInternalEvents() noexcept
  27. : in(nullptr),
  28. out(nullptr) {}
  29. EngineInternalEvents::~EngineInternalEvents() noexcept
  30. {
  31. CARLA_SAFE_ASSERT(in == nullptr);
  32. CARLA_SAFE_ASSERT(out == nullptr);
  33. }
  34. void EngineInternalEvents::clear() noexcept
  35. {
  36. if (in != nullptr)
  37. {
  38. delete[] in;
  39. in = nullptr;
  40. }
  41. if (out != nullptr)
  42. {
  43. delete[] out;
  44. out = nullptr;
  45. }
  46. }
  47. // -----------------------------------------------------------------------
  48. // InternalTime
  49. EngineInternalTime::EngineInternalTime() noexcept
  50. : playing(false),
  51. frame(0) {}
  52. // -----------------------------------------------------------------------
  53. // NextAction
  54. EngineNextAction::EngineNextAction() noexcept
  55. : opcode(kEnginePostActionNull),
  56. pluginId(0),
  57. value(0),
  58. waitEvent() {}
  59. EngineNextAction::~EngineNextAction() noexcept
  60. {
  61. CARLA_SAFE_ASSERT(opcode.get() == kEnginePostActionNull);
  62. }
  63. void EngineNextAction::ready() const noexcept
  64. {
  65. waitEvent.reset();
  66. }
  67. // -----------------------------------------------------------------------
  68. // CarlaEngine::ProtectedData
  69. CarlaEngine::ProtectedData::ProtectedData(CarlaEngine* const engine) noexcept
  70. : osc(engine),
  71. thread(engine),
  72. oscData(nullptr),
  73. callback(nullptr),
  74. callbackPtr(nullptr),
  75. fileCallback(nullptr),
  76. fileCallbackPtr(nullptr),
  77. hints(0x0),
  78. bufferSize(0),
  79. sampleRate(0.0),
  80. aboutToClose(false),
  81. isIdling(0),
  82. curPluginCount(0),
  83. maxPluginNumber(0),
  84. nextPluginId(0),
  85. lastError(),
  86. name(),
  87. options(),
  88. timeInfo(),
  89. #ifndef BUILD_BRIDGE
  90. plugins(nullptr),
  91. #endif
  92. events(),
  93. #ifndef BUILD_BRIDGE
  94. graph(),
  95. #endif
  96. time(),
  97. nextAction()
  98. {
  99. #ifdef BUILD_BRIDGE
  100. carla_zeroStruct(plugins, 1);
  101. #endif
  102. }
  103. CarlaEngine::ProtectedData::~ProtectedData() noexcept
  104. {
  105. CARLA_SAFE_ASSERT(curPluginCount == 0);
  106. CARLA_SAFE_ASSERT(maxPluginNumber == 0);
  107. CARLA_SAFE_ASSERT(nextPluginId == 0);
  108. CARLA_SAFE_ASSERT(isIdling == 0);
  109. #ifndef BUILD_BRIDGE
  110. CARLA_SAFE_ASSERT(plugins == nullptr);
  111. #endif
  112. }
  113. // -----------------------------------------------------------------------
  114. bool CarlaEngine::ProtectedData::init(const char* const clientName)
  115. {
  116. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(name.isEmpty(), "Invalid engine internal data (err #1)");
  117. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(oscData == nullptr, "Invalid engine internal data (err #2)");
  118. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(events.in == nullptr, "Invalid engine internal data (err #4)");
  119. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(events.out == nullptr, "Invalid engine internal data (err #5)");
  120. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(clientName != nullptr && clientName[0] != '\0', "Invalid client name");
  121. #ifndef BUILD_BRIDGE
  122. CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(plugins == nullptr, "Invalid engine internal data (err #3)");
  123. #endif
  124. aboutToClose = false;
  125. curPluginCount = 0;
  126. nextPluginId = 0;
  127. switch (options.processMode)
  128. {
  129. case ENGINE_PROCESS_MODE_CONTINUOUS_RACK:
  130. maxPluginNumber = MAX_RACK_PLUGINS;
  131. break;
  132. case ENGINE_PROCESS_MODE_PATCHBAY:
  133. maxPluginNumber = MAX_PATCHBAY_PLUGINS;
  134. break;
  135. case ENGINE_PROCESS_MODE_BRIDGE:
  136. maxPluginNumber = 1;
  137. break;
  138. default:
  139. maxPluginNumber = MAX_DEFAULT_PLUGINS;
  140. break;
  141. }
  142. switch (options.processMode)
  143. {
  144. case ENGINE_PROCESS_MODE_CONTINUOUS_RACK:
  145. case ENGINE_PROCESS_MODE_PATCHBAY:
  146. case ENGINE_PROCESS_MODE_BRIDGE:
  147. events.in = new EngineEvent[kMaxEngineEventInternalCount];
  148. events.out = new EngineEvent[kMaxEngineEventInternalCount];
  149. break;
  150. default:
  151. break;
  152. }
  153. nextPluginId = maxPluginNumber;
  154. name = clientName;
  155. name.toBasic();
  156. timeInfo.clear();
  157. osc.init(clientName);
  158. #ifndef BUILD_BRIDGE
  159. oscData = osc.getControlData();
  160. plugins = new EnginePluginData[maxPluginNumber];
  161. carla_zeroStruct(plugins, maxPluginNumber);
  162. #endif
  163. nextAction.ready();
  164. thread.startThread();
  165. return true;
  166. }
  167. void CarlaEngine::ProtectedData::close()
  168. {
  169. CARLA_SAFE_ASSERT(name.isNotEmpty());
  170. CARLA_SAFE_ASSERT(plugins != nullptr);
  171. CARLA_SAFE_ASSERT(nextPluginId == maxPluginNumber);
  172. CARLA_SAFE_ASSERT(nextAction.opcode.get() == kEnginePostActionNull);
  173. aboutToClose = true;
  174. thread.stopThread(500);
  175. nextAction.ready();
  176. osc.close();
  177. oscData = nullptr;
  178. aboutToClose = false;
  179. curPluginCount = 0;
  180. maxPluginNumber = 0;
  181. nextPluginId = 0;
  182. #ifndef BUILD_BRIDGE
  183. if (plugins != nullptr)
  184. {
  185. delete[] plugins;
  186. plugins = nullptr;
  187. }
  188. #endif
  189. events.clear();
  190. name.clear();
  191. }
  192. // -----------------------------------------------------------------------
  193. #ifndef BUILD_BRIDGE
  194. void CarlaEngine::ProtectedData::doPluginRemove() noexcept
  195. {
  196. CARLA_SAFE_ASSERT_RETURN(curPluginCount > 0,);
  197. CARLA_SAFE_ASSERT_RETURN(nextAction.pluginId < curPluginCount,);
  198. --curPluginCount;
  199. // move all plugins 1 spot backwards
  200. for (uint i=nextAction.pluginId; i < curPluginCount; ++i)
  201. {
  202. CarlaPlugin* const plugin(plugins[i+1].plugin);
  203. CARLA_SAFE_ASSERT_BREAK(plugin != nullptr);
  204. plugin->setId(i);
  205. plugins[i].plugin = plugin;
  206. plugins[i].insPeak[0] = 0.0f;
  207. plugins[i].insPeak[1] = 0.0f;
  208. plugins[i].outsPeak[0] = 0.0f;
  209. plugins[i].outsPeak[1] = 0.0f;
  210. }
  211. const uint id(curPluginCount);
  212. // reset last plugin (now removed)
  213. plugins[id].plugin = nullptr;
  214. plugins[id].insPeak[0] = 0.0f;
  215. plugins[id].insPeak[1] = 0.0f;
  216. plugins[id].outsPeak[0] = 0.0f;
  217. plugins[id].outsPeak[1] = 0.0f;
  218. }
  219. void CarlaEngine::ProtectedData::doPluginsSwitch() noexcept
  220. {
  221. CARLA_SAFE_ASSERT_RETURN(curPluginCount >= 2,);
  222. const uint idA(nextAction.pluginId);
  223. const uint idB(nextAction.value);
  224. CARLA_SAFE_ASSERT_RETURN(idA < curPluginCount,);
  225. CARLA_SAFE_ASSERT_RETURN(idB < curPluginCount,);
  226. CARLA_SAFE_ASSERT_RETURN(plugins[idA].plugin != nullptr,);
  227. CARLA_SAFE_ASSERT_RETURN(plugins[idB].plugin != nullptr,);
  228. #if 0
  229. std::swap(plugins[idA].plugin, plugins[idB].plugin);
  230. #else
  231. CarlaPlugin* const tmp(plugins[idA].plugin);
  232. plugins[idA].plugin = plugins[idB].plugin;
  233. plugins[idB].plugin = tmp;
  234. #endif
  235. }
  236. #endif
  237. void CarlaEngine::ProtectedData::doNextPluginAction(const bool unlock) noexcept
  238. {
  239. const EnginePostAction action(nextAction.opcode.exchange(kEnginePostActionNull));
  240. switch (action)
  241. {
  242. case kEnginePostActionNull:
  243. break;
  244. case kEnginePostActionZeroCount:
  245. curPluginCount = 0;
  246. break;
  247. #ifndef BUILD_BRIDGE
  248. case kEnginePostActionRemovePlugin:
  249. doPluginRemove();
  250. break;
  251. case kEnginePostActionSwitchPlugins:
  252. doPluginsSwitch();
  253. break;
  254. #endif
  255. }
  256. nextAction.opcode = kEnginePostActionNull;
  257. nextAction.pluginId = 0;
  258. nextAction.value = 0;
  259. if (unlock && action != kEnginePostActionNull)
  260. nextAction.waitEvent.signal();
  261. }
  262. // -----------------------------------------------------------------------
  263. // ScopedActionLock
  264. ScopedActionLock::ScopedActionLock(CarlaEngine::ProtectedData* const data, const EnginePostAction action, const uint pluginId, const uint value, const bool lockWait) noexcept
  265. : fData(data)
  266. {
  267. CARLA_SAFE_ASSERT_RETURN(action != kEnginePostActionNull,);
  268. CARLA_SAFE_ASSERT_RETURN(fData->nextAction.opcode.get() == kEnginePostActionNull,);
  269. fData->nextAction.pluginId = pluginId;
  270. fData->nextAction.value = value;
  271. fData->nextAction.opcode = action;
  272. if (lockWait)
  273. {
  274. // block wait for unlock on processing side
  275. carla_stdout("ScopedPluginAction(%i) - blocking START", pluginId);
  276. fData->nextAction.waitEvent.wait(2000);
  277. carla_stdout("ScopedPluginAction(%i) - blocking DONE", pluginId);
  278. }
  279. else
  280. {
  281. fData->doNextPluginAction(false);
  282. }
  283. }
  284. ScopedActionLock::~ScopedActionLock() noexcept
  285. {
  286. //fData->nextAction.mutex.unlock();
  287. }
  288. // -----------------------------------------------------------------------
  289. CARLA_BACKEND_END_NAMESPACE