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.

359 lines
9.5KB

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