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.

340 lines
9.2KB

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