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.

378 lines
9.8KB

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