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.

524 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. };
  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