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 12KB

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