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.

347 lines
9.4KB

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