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.

CarlaEngineInternal.hpp 13KB

11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  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