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