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.

468 lines
13KB

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