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.

522 lines
13KB

  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. #ifndef CARLA_ENGINE_INTERNAL_HPP_INCLUDED
  18. #define CARLA_ENGINE_INTERNAL_HPP_INCLUDED
  19. #include "CarlaEngine.hpp"
  20. #include "CarlaEngineOsc.hpp"
  21. #include "CarlaEngineThread.hpp"
  22. #include "CarlaMathUtils.hpp"
  23. #include "CarlaPatchbayUtils.hpp"
  24. #include "CarlaMutex.hpp"
  25. // -----------------------------------------------------------------------
  26. // Engine helper macro, sets lastError and returns false/NULL
  27. #define CARLA_SAFE_ASSERT_RETURN_ERR(cond, err) if (! (cond)) { carla_safe_assert(#cond, __FILE__, __LINE__); setLastError(err); return false; }
  28. #define CARLA_SAFE_ASSERT_RETURN_ERRN(cond, err) if (! (cond)) { carla_safe_assert(#cond, __FILE__, __LINE__); setLastError(err); return nullptr; }
  29. // -----------------------------------------------------------------------
  30. CARLA_BACKEND_START_NAMESPACE
  31. #if 0
  32. } // Fix editor indentation
  33. #endif
  34. // -----------------------------------------------------------------------
  35. // Maximum pre-allocated events for rack and bridge modes
  36. const ushort kMaxEngineEventInternalCount = 512;
  37. // -----------------------------------------------------------------------
  38. // Patchbay stuff
  39. struct GroupPort {
  40. uint group, port;
  41. };
  42. #ifndef BUILD_BRIDGE
  43. // -----------------------------------------------------------------------
  44. // Rack Graph stuff
  45. enum RackGraphGroupIds {
  46. RACK_GRAPH_GROUP_CARLA = 0,
  47. RACK_GRAPH_GROUP_AUDIO_IN = 1,
  48. RACK_GRAPH_GROUP_AUDIO_OUT = 2,
  49. RACK_GRAPH_GROUP_MIDI_IN = 3,
  50. RACK_GRAPH_GROUP_MIDI_OUT = 4,
  51. RACK_GRAPH_GROUP_MAX = 5
  52. };
  53. enum RackGraphCarlaPortIds {
  54. RACK_GRAPH_CARLA_PORT_NULL = 0,
  55. RACK_GRAPH_CARLA_PORT_AUDIO_IN1 = 1,
  56. RACK_GRAPH_CARLA_PORT_AUDIO_IN2 = 2,
  57. RACK_GRAPH_CARLA_PORT_AUDIO_OUT1 = 3,
  58. RACK_GRAPH_CARLA_PORT_AUDIO_OUT2 = 4,
  59. RACK_GRAPH_CARLA_PORT_MIDI_IN = 5,
  60. RACK_GRAPH_CARLA_PORT_MIDI_OUT = 6,
  61. RACK_GRAPH_CARLA_PORT_MAX = 7
  62. };
  63. // -----------------------------------------------------------------------
  64. // RackGraph
  65. struct RackGraph {
  66. PatchbayConnectionList connections;
  67. struct Audio {
  68. CarlaMutex mutex;
  69. LinkedList<uint> connectedIn1;
  70. LinkedList<uint> connectedIn2;
  71. LinkedList<uint> connectedOut1;
  72. LinkedList<uint> connectedOut2;
  73. } audio;
  74. struct MIDI {
  75. LinkedList<PortNameToId> ins;
  76. LinkedList<PortNameToId> outs;
  77. const char* getName(const bool isInput, const uint index) const noexcept;
  78. uint getPortId(const bool isInput, const char portName[]) const noexcept;
  79. } midi;
  80. RackGraph() noexcept {}
  81. ~RackGraph() noexcept
  82. {
  83. clear();
  84. }
  85. void clear() noexcept
  86. {
  87. connections.clear();
  88. audio.mutex.lock();
  89. audio.connectedIn1.clear();
  90. audio.connectedIn2.clear();
  91. audio.connectedOut1.clear();
  92. audio.connectedOut2.clear();
  93. audio.mutex.unlock();
  94. midi.ins.clear();
  95. midi.outs.clear();
  96. }
  97. bool connect(CarlaEngine* const engine, const uint groupA, const uint portA, const uint groupB, const uint portB) noexcept;
  98. bool disconnect(CarlaEngine* const engine, const uint connectionId) noexcept;
  99. const char* const* getConnections() const;
  100. bool getPortIdFromFullName(const char* const fullPortName, uint& groupId, uint& portId) const;
  101. };
  102. // -----------------------------------------------------------------------
  103. // PatchbayGraph
  104. struct PatchbayGraph {
  105. PatchbayGraph() noexcept {}
  106. ~PatchbayGraph() noexcept
  107. {
  108. clear();
  109. }
  110. void clear() noexcept
  111. {
  112. }
  113. bool connect(CarlaEngine* const engine, const uint groupA, const uint portA, const uint groupB, const uint portB) noexcept;
  114. bool disconnect(CarlaEngine* const engine, const uint connectionId) noexcept;
  115. const char* const* getConnections() const;
  116. bool getPortIdFromFullName(const char* const fullPortName, uint& groupId, uint& portId) const;
  117. };
  118. #endif
  119. // -----------------------------------------------------------------------
  120. // InternalAudio
  121. struct EngineInternalAudio {
  122. bool isReady;
  123. // always 2x2 in rack mode
  124. uint inCount;
  125. uint outCount;
  126. float** inBuf;
  127. float** outBuf;
  128. EngineInternalAudio() noexcept
  129. : isReady(false),
  130. inCount(0),
  131. outCount(0),
  132. inBuf(nullptr),
  133. outBuf(nullptr) {}
  134. ~EngineInternalAudio() noexcept
  135. {
  136. CARLA_SAFE_ASSERT(! isReady);
  137. CARLA_SAFE_ASSERT(inCount == 0);
  138. CARLA_SAFE_ASSERT(outCount == 0);
  139. CARLA_SAFE_ASSERT(inBuf == nullptr);
  140. CARLA_SAFE_ASSERT(outBuf == nullptr);
  141. }
  142. void clearBuffers() noexcept
  143. {
  144. for (uint32_t i=0; i < inCount; ++i)
  145. {
  146. if (inBuf[i] != nullptr)
  147. {
  148. delete[] inBuf[i];
  149. inBuf[i] = nullptr;
  150. }
  151. }
  152. for (uint32_t i=0; i < outCount; ++i)
  153. {
  154. if (outBuf[i] != nullptr)
  155. {
  156. delete[] outBuf[i];
  157. outBuf[i] = nullptr;
  158. }
  159. }
  160. }
  161. void clear() noexcept
  162. {
  163. isReady = false;
  164. clearBuffers();
  165. inCount = 0;
  166. outCount = 0;
  167. if (inBuf != nullptr)
  168. {
  169. delete[] inBuf;
  170. inBuf = nullptr;
  171. }
  172. if (outBuf != nullptr)
  173. {
  174. delete[] outBuf;
  175. outBuf = nullptr;
  176. }
  177. }
  178. void create(const uint32_t bufferSize)
  179. {
  180. CARLA_SAFE_ASSERT(! isReady);
  181. CARLA_SAFE_ASSERT(inBuf == nullptr);
  182. CARLA_SAFE_ASSERT(outBuf == nullptr);
  183. if (inCount > 0)
  184. {
  185. inBuf = new float*[inCount];
  186. for (uint32_t i=0; i < inCount; ++i)
  187. inBuf[i] = nullptr;
  188. }
  189. if (outCount > 0)
  190. {
  191. outBuf = new float*[outCount];
  192. for (uint32_t i=0; i < outCount; ++i)
  193. outBuf[i] = nullptr;
  194. }
  195. resize(bufferSize, false);
  196. }
  197. void resize(const uint32_t bufferSize, const bool doClear = true)
  198. {
  199. if (doClear)
  200. clearBuffers();
  201. CARLA_SAFE_ASSERT_RETURN(bufferSize != 0,);
  202. for (uint32_t i=0; i < inCount; ++i)
  203. {
  204. inBuf[i] = new float[bufferSize];
  205. FLOAT_CLEAR(inBuf[i], bufferSize);
  206. }
  207. for (uint32_t i=0; i < outCount; ++i)
  208. {
  209. outBuf[i] = new float[bufferSize];
  210. FLOAT_CLEAR(outBuf[i], bufferSize);
  211. }
  212. }
  213. CARLA_DECLARE_NON_COPY_STRUCT(EngineInternalAudio)
  214. };
  215. // -----------------------------------------------------------------------
  216. // InternalEvents
  217. struct EngineInternalEvents {
  218. EngineEvent* in;
  219. EngineEvent* out;
  220. EngineInternalEvents() noexcept
  221. : in(nullptr),
  222. out(nullptr) {}
  223. ~EngineInternalEvents() noexcept
  224. {
  225. CARLA_SAFE_ASSERT(in == nullptr);
  226. CARLA_SAFE_ASSERT(out == nullptr);
  227. }
  228. void clear() noexcept
  229. {
  230. if (in != nullptr)
  231. {
  232. delete[] in;
  233. in = nullptr;
  234. }
  235. if (out != nullptr)
  236. {
  237. delete[] out;
  238. out = nullptr;
  239. }
  240. }
  241. CARLA_DECLARE_NON_COPY_STRUCT(EngineInternalEvents)
  242. };
  243. #ifndef BUILD_BRIDGE
  244. // -----------------------------------------------------------------------
  245. // InternalGraph
  246. struct EngineInternalGraph {
  247. bool isRack;
  248. union {
  249. RackGraph* rack;
  250. PatchbayGraph* patchbay;
  251. };
  252. EngineInternalGraph() noexcept
  253. : isRack(true)
  254. {
  255. rack = nullptr;
  256. }
  257. ~EngineInternalGraph() noexcept
  258. {
  259. CARLA_SAFE_ASSERT(rack == nullptr);
  260. }
  261. void create()
  262. {
  263. if (isRack)
  264. {
  265. CARLA_SAFE_ASSERT_RETURN(rack == nullptr,);
  266. rack = new RackGraph();
  267. }
  268. else
  269. {
  270. CARLA_SAFE_ASSERT_RETURN(patchbay == nullptr,);
  271. patchbay = new PatchbayGraph();
  272. }
  273. }
  274. void clear()
  275. {
  276. if (isRack)
  277. {
  278. CARLA_SAFE_ASSERT_RETURN(rack != nullptr,);
  279. delete rack;
  280. rack = nullptr;
  281. }
  282. else
  283. {
  284. CARLA_SAFE_ASSERT_RETURN(patchbay != nullptr,);
  285. delete patchbay;
  286. patchbay = nullptr;
  287. }
  288. }
  289. CARLA_DECLARE_NON_COPY_STRUCT(EngineInternalGraph)
  290. };
  291. #endif
  292. // -----------------------------------------------------------------------
  293. // InternalTime
  294. struct EngineInternalTime {
  295. bool playing;
  296. uint64_t frame;
  297. EngineInternalTime() noexcept
  298. : playing(false),
  299. frame(0) {}
  300. CARLA_DECLARE_NON_COPY_STRUCT(EngineInternalTime)
  301. };
  302. // -----------------------------------------------------------------------
  303. // NextAction
  304. enum EnginePostAction {
  305. kEnginePostActionNull,
  306. kEnginePostActionZeroCount,
  307. kEnginePostActionRemovePlugin,
  308. kEnginePostActionSwitchPlugins
  309. };
  310. struct EngineNextAction {
  311. EnginePostAction opcode;
  312. uint pluginId;
  313. uint value;
  314. CarlaMutex mutex;
  315. EngineNextAction() noexcept
  316. : opcode(kEnginePostActionNull),
  317. pluginId(0),
  318. value(0) {}
  319. ~EngineNextAction() noexcept
  320. {
  321. CARLA_SAFE_ASSERT(opcode == kEnginePostActionNull);
  322. }
  323. void ready() const noexcept
  324. {
  325. mutex.lock();
  326. mutex.unlock();
  327. }
  328. CARLA_DECLARE_NON_COPY_STRUCT(EngineNextAction)
  329. };
  330. // -----------------------------------------------------------------------
  331. // EnginePluginData
  332. struct EnginePluginData {
  333. CarlaPlugin* plugin;
  334. float insPeak[2];
  335. float outsPeak[2];
  336. void clear() noexcept
  337. {
  338. plugin = nullptr;
  339. insPeak[0] = insPeak[1] = 0.0f;
  340. outsPeak[0] = outsPeak[1] = 0.0f;
  341. }
  342. };
  343. // -----------------------------------------------------------------------
  344. // CarlaEngineProtectedData
  345. struct CarlaEngine::ProtectedData {
  346. CarlaEngineOsc osc;
  347. CarlaEngineThread thread;
  348. const CarlaOscData* oscData;
  349. EngineCallbackFunc callback;
  350. void* callbackPtr;
  351. FileCallbackFunc fileCallback;
  352. void* fileCallbackPtr;
  353. uint hints;
  354. uint32_t bufferSize;
  355. double sampleRate;
  356. bool aboutToClose; // don't re-activate thread if true
  357. uint curPluginCount; // number of plugins loaded (0...max)
  358. uint maxPluginNumber; // number of plugins allowed (0, 16, 99 or 255)
  359. uint nextPluginId; // invalid if == maxPluginNumber
  360. CarlaString lastError;
  361. CarlaString name;
  362. EngineOptions options;
  363. EngineTimeInfo timeInfo;
  364. EnginePluginData* plugins;
  365. #ifndef BUILD_BRIDGE
  366. EngineInternalAudio audio;
  367. #endif
  368. EngineInternalEvents events;
  369. #ifndef BUILD_BRIDGE
  370. EngineInternalGraph graph;
  371. #endif
  372. EngineInternalTime time;
  373. EngineNextAction nextAction;
  374. // -------------------------------------------------------------------
  375. ProtectedData(CarlaEngine* const engine) noexcept;
  376. ~ProtectedData() noexcept;
  377. // -------------------------------------------------------------------
  378. void doPluginRemove() noexcept;
  379. void doPluginsSwitch() noexcept;
  380. void doNextPluginAction(const bool unlock) noexcept;
  381. #ifndef BUILD_BRIDGE
  382. // -------------------------------------------------------------------
  383. // the base, where plugins run
  384. void processRack(const float* inBufReal[2], float* outBuf[2], const uint32_t nframes, const bool isOffline);
  385. // extended, will call processRack() in the middle
  386. void processRackFull(const float* const* const inBuf, const uint32_t inCount, float* const* const outBuf, const uint32_t outCount, const uint32_t nframes, const bool isOffline);
  387. #endif
  388. // -------------------------------------------------------------------
  389. //friend class ScopedActionLock;
  390. #ifdef CARLA_PROPER_CPP11_SUPPORT
  391. ProtectedData() = delete;
  392. CARLA_DECLARE_NON_COPY_STRUCT(ProtectedData)
  393. #endif
  394. };
  395. // -----------------------------------------------------------------------
  396. class ScopedActionLock
  397. {
  398. public:
  399. ScopedActionLock(CarlaEngine::ProtectedData* const data, const EnginePostAction action, const uint pluginId, const uint value, const bool lockWait) noexcept;
  400. ~ScopedActionLock() noexcept;
  401. private:
  402. CarlaEngine::ProtectedData* const fData;
  403. CARLA_PREVENT_HEAP_ALLOCATION
  404. CARLA_DECLARE_NON_COPY_CLASS(ScopedActionLock)
  405. };
  406. // -----------------------------------------------------------------------
  407. CARLA_BACKEND_END_NAMESPACE
  408. #endif // CARLA_ENGINE_INTERNAL_HPP_INCLUDED