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.

456 lines
13KB

  1. // SPDX-FileCopyrightText: 2011-2025 Filipe Coelho <falktx@falktx.com>
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #ifndef CARLA_PLUGIN_INTERNAL_HPP_INCLUDED
  4. #define CARLA_PLUGIN_INTERNAL_HPP_INCLUDED
  5. #include "CarlaPlugin.hpp"
  6. #include "CarlaJuceUtils.hpp"
  7. #include "CarlaLibUtils.hpp"
  8. #include "CarlaStateUtils.hpp"
  9. #include "CarlaMIDI.h"
  10. #include "CarlaMutex.hpp"
  11. #include "RtLinkedList.hpp"
  12. #include "distrho/extra/String.hpp"
  13. CARLA_BACKEND_START_NAMESPACE
  14. // -----------------------------------------------------------------------
  15. // Engine helper macro, sets lastError and returns false/NULL
  16. #define CARLA_SAFE_ASSERT_RETURN_ERR(cond, err) if (! (cond)) { carla_safe_assert(#cond, __FILE__, __LINE__); pData->engine->setLastError(err); return false; }
  17. #define CARLA_SAFE_ASSERT_RETURN_ERRN(cond, err) if (! (cond)) { carla_safe_assert(#cond, __FILE__, __LINE__); pData->engine->setLastError(err); return nullptr; }
  18. #define CARLA_SAFE_EXCEPTION_RETURN_ERR(excptMsg, errMsg) catch(...) { carla_safe_exception(excptMsg, __FILE__, __LINE__); pData->engine->setLastError(errMsg); return false; }
  19. #define CARLA_SAFE_EXCEPTION_RETURN_ERRN(excptMsg, errMsg) catch(...) { carla_safe_exception(excptMsg, __FILE__, __LINE__); pData->engine->setLastError(errMsg); return nullptr; }
  20. // -----------------------------------------------------------------------
  21. // Maximum pre-allocated events for some plugin types
  22. constexpr const uint16_t kPluginMaxMidiEvents = 512;
  23. // -----------------------------------------------------------------------
  24. // Extra parameter hints, hidden from backend
  25. constexpr const uint PARAMETER_MAPPED_RANGES_SET = 0x10000;
  26. constexpr const uint PARAMETER_IS_STRICT_BOUNDS = 0x20000;
  27. constexpr const uint PARAMETER_IS_TRIGGER = 0x40000;
  28. // -----------------------------------------------------------------------
  29. // Extra plugin hints, hidden from backend
  30. constexpr const uint PLUGIN_EXTRA_HINT_HAS_MIDI_IN = 0x01;
  31. constexpr const uint PLUGIN_EXTRA_HINT_HAS_MIDI_OUT = 0x02;
  32. // -----------------------------------------------------------------------
  33. // Special parameters
  34. enum SpecialParameterType {
  35. PARAMETER_SPECIAL_NULL = 0,
  36. PARAMETER_SPECIAL_FREEWHEEL = 1,
  37. PARAMETER_SPECIAL_LATENCY = 2,
  38. PARAMETER_SPECIAL_SAMPLE_RATE = 3,
  39. PARAMETER_SPECIAL_TIME = 4
  40. };
  41. // -----------------------------------------------------------------------
  42. /*!
  43. * Post-RT event type.
  44. * These are events postponned from within the process function,
  45. *
  46. * During process, we cannot lock, allocate memory or do UI stuff.
  47. * Events have to be postponned to be executed later, on a separate thread.
  48. * @see PluginPostRtEvent
  49. */
  50. enum PluginPostRtEventType {
  51. kPluginPostRtEventNull = 0,
  52. kPluginPostRtEventParameterChange,
  53. kPluginPostRtEventProgramChange,
  54. kPluginPostRtEventMidiProgramChange,
  55. kPluginPostRtEventNoteOn,
  56. kPluginPostRtEventNoteOff,
  57. kPluginPostRtEventMidiLearn
  58. };
  59. /*!
  60. * A Post-RT event.
  61. * @see PluginPostRtEventType
  62. */
  63. struct PluginPostRtEvent {
  64. PluginPostRtEventType type;
  65. bool sendCallback;
  66. union {
  67. struct {
  68. int32_t index;
  69. float value;
  70. } parameter;
  71. struct {
  72. uint32_t index;
  73. } program;
  74. struct {
  75. uint8_t channel;
  76. uint8_t note;
  77. uint8_t velocity;
  78. } note;
  79. struct {
  80. uint32_t parameter;
  81. uint8_t cc;
  82. uint8_t channel;
  83. } midiLearn;
  84. };
  85. };
  86. // -----------------------------------------------------------------------
  87. struct ExternalMidiNote {
  88. int8_t channel; // invalid if -1
  89. uint8_t note; // 0 to 127
  90. uint8_t velo; // 1 to 127, 0 for note-off
  91. };
  92. // -----------------------------------------------------------------------
  93. struct PluginAudioPort {
  94. uint32_t rindex;
  95. CarlaEngineAudioPort* port;
  96. };
  97. struct PluginAudioData {
  98. uint32_t count;
  99. PluginAudioPort* ports;
  100. PluginAudioData() noexcept;
  101. ~PluginAudioData() noexcept;
  102. void createNew(uint32_t newCount);
  103. void clear() noexcept;
  104. void initBuffers() const noexcept;
  105. CARLA_DECLARE_NON_COPYABLE(PluginAudioData)
  106. };
  107. // -----------------------------------------------------------------------
  108. struct PluginCVPort {
  109. uint32_t rindex;
  110. //uint32_t param; // FIXME is this needed?
  111. CarlaEngineCVPort* port;
  112. };
  113. struct PluginCVData {
  114. uint32_t count;
  115. PluginCVPort* ports;
  116. PluginCVData() noexcept;
  117. ~PluginCVData() noexcept;
  118. void createNew(uint32_t newCount);
  119. void clear() noexcept;
  120. void initBuffers() const noexcept;
  121. CARLA_DECLARE_NON_COPYABLE(PluginCVData)
  122. };
  123. // -----------------------------------------------------------------------
  124. struct PluginEventData {
  125. CarlaEngineEventPort* portIn;
  126. CarlaEngineEventPort* portOut;
  127. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  128. CarlaEngineCVSourcePorts* cvSourcePorts;
  129. #endif
  130. PluginEventData() noexcept;
  131. ~PluginEventData() noexcept;
  132. void clear() noexcept;
  133. void initBuffers() const noexcept;
  134. CARLA_DECLARE_NON_COPYABLE(PluginEventData)
  135. };
  136. // -----------------------------------------------------------------------
  137. struct PluginParameterData {
  138. uint32_t count;
  139. ParameterData* data;
  140. ParameterRanges* ranges;
  141. SpecialParameterType* special;
  142. PluginParameterData() noexcept;
  143. ~PluginParameterData() noexcept;
  144. void createNew(uint32_t newCount, bool withSpecial);
  145. void clear() noexcept;
  146. float getFixedValue(uint32_t parameterId, float value) const noexcept;
  147. float getFinalUnnormalizedValue(uint32_t parameterId, float normalizedValue) const noexcept;
  148. float getFinalValueWithMidiDelta(uint32_t parameterId, float value, int8_t delta) const noexcept;
  149. CARLA_DECLARE_NON_COPYABLE(PluginParameterData)
  150. };
  151. // -----------------------------------------------------------------------
  152. typedef const char* ProgramName;
  153. struct PluginProgramData {
  154. uint32_t count;
  155. int32_t current;
  156. ProgramName* names;
  157. PluginProgramData() noexcept;
  158. ~PluginProgramData() noexcept;
  159. void createNew(uint32_t newCount);
  160. void clear() noexcept;
  161. CARLA_DECLARE_NON_COPYABLE(PluginProgramData)
  162. };
  163. // -----------------------------------------------------------------------
  164. struct PluginMidiProgramData {
  165. uint32_t count;
  166. int32_t current;
  167. MidiProgramData* data;
  168. PluginMidiProgramData() noexcept;
  169. ~PluginMidiProgramData() noexcept;
  170. void createNew(uint32_t newCount);
  171. void clear() noexcept;
  172. const MidiProgramData& getCurrent() const noexcept;
  173. CARLA_DECLARE_NON_COPYABLE(PluginMidiProgramData)
  174. };
  175. // -----------------------------------------------------------------------
  176. struct CarlaPlugin::ProtectedData {
  177. CarlaEngine* const engine;
  178. CarlaEngineClient* client;
  179. uint id;
  180. uint hints;
  181. uint options;
  182. uint32_t nodeId;
  183. bool active;
  184. bool enabled;
  185. bool needsReset;
  186. bool engineBridged;
  187. bool enginePlugin;
  188. lib_t lib;
  189. lib_t uiLib;
  190. // misc
  191. int8_t ctrlChannel;
  192. uint extraHints;
  193. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  194. int32_t midiLearnParameterIndex;
  195. uint transientTryCounter;
  196. bool transientFirstTry;
  197. #endif
  198. // data 1
  199. const char* name;
  200. const char* filename;
  201. const char* iconName;
  202. // data 2
  203. PluginAudioData audioIn;
  204. PluginAudioData audioOut;
  205. PluginCVData cvIn;
  206. PluginCVData cvOut;
  207. PluginEventData event;
  208. PluginParameterData param;
  209. PluginProgramData prog;
  210. PluginMidiProgramData midiprog;
  211. LinkedList<CustomData> custom;
  212. CarlaMutex masterMutex; // global master lock
  213. CarlaMutex singleMutex; // small lock used only in processSingle()
  214. CarlaStateSave stateSave;
  215. String uiTitle;
  216. struct ExternalNotes {
  217. CarlaMutex mutex;
  218. RtLinkedList<ExternalMidiNote>::Pool dataPool;
  219. RtLinkedList<ExternalMidiNote> data;
  220. ExternalNotes() noexcept;
  221. ~ExternalNotes() noexcept;
  222. void appendNonRT(const ExternalMidiNote& note) noexcept;
  223. void clear() noexcept;
  224. CARLA_DECLARE_NON_COPYABLE(ExternalNotes)
  225. } extNotes;
  226. struct Latency {
  227. uint32_t frames;
  228. #ifndef BUILD_BRIDGE
  229. uint32_t channels;
  230. float** buffers;
  231. #endif
  232. Latency() noexcept;
  233. #ifndef BUILD_BRIDGE
  234. ~Latency() noexcept;
  235. void clearBuffers() noexcept;
  236. void recreateBuffers(uint32_t newChannels, uint32_t newFrames);
  237. #endif
  238. CARLA_DECLARE_NON_COPYABLE(Latency)
  239. } latency;
  240. class PostRtEvents {
  241. public:
  242. PostRtEvents() noexcept;
  243. ~PostRtEvents() noexcept;
  244. void appendRT(const PluginPostRtEvent& event) noexcept;
  245. void trySplice() noexcept;
  246. struct Access {
  247. Access(PostRtEvents& e)
  248. : data2(e.dataPool),
  249. poolMutex(e.poolMutex)
  250. {
  251. const CarlaMutexLocker cml1(e.dataMutex);
  252. const CarlaMutexLocker cml2(e.poolMutex);
  253. if (e.data.isNotEmpty())
  254. e.data.moveTo(data2, true);
  255. }
  256. ~Access()
  257. {
  258. const CarlaMutexLocker cml(poolMutex);
  259. data2.clear();
  260. }
  261. inline RtLinkedList<PluginPostRtEvent>::Itenerator getDataIterator() const noexcept
  262. {
  263. return data2.begin2();
  264. }
  265. inline std::size_t isEmpty() const noexcept
  266. {
  267. return data2.isEmpty();
  268. }
  269. private:
  270. RtLinkedList<PluginPostRtEvent> data2;
  271. CarlaMutex& poolMutex;
  272. };
  273. private:
  274. RtLinkedList<PluginPostRtEvent>::Pool dataPool;
  275. RtLinkedList<PluginPostRtEvent> data, dataPendingRT;
  276. CarlaMutex dataMutex;
  277. CarlaMutex dataPendingMutex;
  278. CarlaMutex poolMutex;
  279. CARLA_DECLARE_NON_COPYABLE(PostRtEvents)
  280. } postRtEvents;
  281. struct PostUiEvents {
  282. CarlaMutex mutex;
  283. LinkedList<PluginPostRtEvent> data;
  284. PostUiEvents() noexcept;
  285. ~PostUiEvents() noexcept;
  286. void append(const PluginPostRtEvent& event) noexcept;
  287. void clear() noexcept;
  288. CARLA_DECLARE_NON_COPYABLE(PostUiEvents)
  289. } postUiEvents;
  290. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  291. struct PostProc {
  292. float dryWet;
  293. float volume;
  294. float balanceLeft;
  295. float balanceRight;
  296. float panning;
  297. float* extraBuffer;
  298. PostProc() noexcept;
  299. CARLA_DECLARE_NON_COPYABLE(PostProc)
  300. } postProc;
  301. #endif
  302. ProtectedData(CarlaEngine* engine, uint idx) noexcept;
  303. ~ProtectedData() noexcept;
  304. // -------------------------------------------------------------------
  305. // Buffer functions
  306. void clearBuffers() noexcept;
  307. // -------------------------------------------------------------------
  308. // Post-poned events
  309. void postponeRtEvent(const PluginPostRtEvent& rtEvent) noexcept;
  310. void postponeParameterChangeRtEvent(bool sendCallbackLater, int32_t index, float value) noexcept;
  311. void postponeProgramChangeRtEvent(bool sendCallbackLater, uint32_t index) noexcept;
  312. void postponeMidiProgramChangeRtEvent(bool sendCallbackLater, uint32_t index) noexcept;
  313. void postponeNoteOnRtEvent(bool sendCallbackLater, uint8_t channel, uint8_t note, uint8_t velocity) noexcept;
  314. void postponeNoteOffRtEvent(bool sendCallbackLater, uint8_t channel, uint8_t note) noexcept;
  315. void postponeMidiLearnRtEvent(bool sendCallbackLater, uint32_t parameter, uint8_t cc, uint8_t channel) noexcept;
  316. // -------------------------------------------------------------------
  317. // Library functions
  318. static const char* libError(const char* filename) noexcept;
  319. bool libOpen(const char* filename) noexcept;
  320. bool libClose() noexcept;
  321. void setCanDeleteLib(bool canDelete) noexcept;
  322. bool uiLibOpen(const char* filename, bool canDelete) noexcept;
  323. bool uiLibClose() noexcept;
  324. template<typename Func>
  325. Func libSymbol(const char* symbol) const noexcept
  326. {
  327. return lib_symbol<Func>(lib, symbol);
  328. }
  329. template<typename Func>
  330. Func uiLibSymbol(const char* symbol) const noexcept
  331. {
  332. return lib_symbol<Func>(uiLib, symbol);
  333. }
  334. // -------------------------------------------------------------------
  335. // Misc
  336. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  337. void tryTransient() noexcept;
  338. #endif
  339. void updateParameterValues(CarlaPlugin* plugin,
  340. bool sendCallback, bool sendOsc, bool useDefault) noexcept;
  341. void updateDefaultParameterValues(CarlaPlugin* plugin) noexcept;
  342. // -------------------------------------------------------------------
  343. #ifdef CARLA_PROPER_CPP11_SUPPORT
  344. ProtectedData() = delete;
  345. CARLA_DECLARE_NON_COPYABLE(ProtectedData);
  346. #endif
  347. CARLA_LEAK_DETECTOR(ProtectedData);
  348. };
  349. CARLA_BACKEND_END_NAMESPACE
  350. #endif // CARLA_PLUGIN_INTERNAL_HPP_INCLUDED