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.

368 lines
9.6KB

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