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.

443 lines
12KB

  1. /*
  2. * Carla Plugin
  3. * Copyright (C) 2011-2019 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. const ushort kPluginMaxMidiEvents = 512;
  37. // -----------------------------------------------------------------------
  38. // Extra parameter hints, hidden from backend
  39. const uint PARAMETER_MAPPED_RANGES_SET = 0x1000;
  40. const uint PARAMETER_IS_STRICT_BOUNDS = 0x2000;
  41. const uint PARAMETER_IS_TRIGGER = 0x4000;
  42. // -----------------------------------------------------------------------
  43. // Extra plugin hints, hidden from backend
  44. const uint PLUGIN_EXTRA_HINT_HAS_MIDI_IN = 0x01;
  45. 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. kPluginPostRtEventDebug,
  67. kPluginPostRtEventParameterChange, // param, (unused), (unused), value
  68. kPluginPostRtEventProgramChange, // index
  69. kPluginPostRtEventMidiProgramChange, // index
  70. kPluginPostRtEventNoteOn, // channel, note, velo
  71. kPluginPostRtEventNoteOff, // channel, note
  72. kPluginPostRtEventMidiLearn // param, cc, channel
  73. };
  74. /*!
  75. * A Post-RT event.
  76. * @see PluginPostRtEventType
  77. */
  78. struct PluginPostRtEvent {
  79. PluginPostRtEventType type;
  80. bool sendCallback;
  81. int32_t value1;
  82. int32_t value2;
  83. int32_t value3;
  84. float valuef;
  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_COPY_STRUCT(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_COPY_STRUCT(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_COPY_STRUCT(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 value) const noexcept;
  148. CARLA_DECLARE_NON_COPY_STRUCT(PluginParameterData)
  149. };
  150. // -----------------------------------------------------------------------
  151. typedef const char* ProgramName;
  152. struct PluginProgramData {
  153. uint32_t count;
  154. int32_t current;
  155. ProgramName* names;
  156. PluginProgramData() noexcept;
  157. ~PluginProgramData() noexcept;
  158. void createNew(uint32_t newCount);
  159. void clear() noexcept;
  160. CARLA_DECLARE_NON_COPY_STRUCT(PluginProgramData)
  161. };
  162. // -----------------------------------------------------------------------
  163. struct PluginMidiProgramData {
  164. uint32_t count;
  165. int32_t current;
  166. MidiProgramData* data;
  167. PluginMidiProgramData() noexcept;
  168. ~PluginMidiProgramData() noexcept;
  169. void createNew(uint32_t newCount);
  170. void clear() noexcept;
  171. const MidiProgramData& getCurrent() const noexcept;
  172. CARLA_DECLARE_NON_COPY_STRUCT(PluginMidiProgramData)
  173. };
  174. // -----------------------------------------------------------------------
  175. struct CarlaPlugin::ProtectedData {
  176. CarlaEngine* const engine;
  177. CarlaEngineClient* client;
  178. uint id;
  179. uint hints;
  180. uint options;
  181. uint32_t nodeId;
  182. bool active;
  183. bool enabled;
  184. bool needsReset;
  185. bool engineBridged;
  186. bool enginePlugin;
  187. lib_t lib;
  188. lib_t uiLib;
  189. // misc
  190. int8_t ctrlChannel;
  191. uint extraHints;
  192. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  193. int32_t midiLearnParameterIndex;
  194. uint transientTryCounter;
  195. bool transientFirstTry;
  196. #endif
  197. // data 1
  198. const char* name;
  199. const char* filename;
  200. const char* iconName;
  201. // data 2
  202. PluginAudioData audioIn;
  203. PluginAudioData audioOut;
  204. PluginCVData cvIn;
  205. PluginCVData cvOut;
  206. PluginEventData event;
  207. PluginParameterData param;
  208. PluginProgramData prog;
  209. PluginMidiProgramData midiprog;
  210. LinkedList<CustomData> custom;
  211. CarlaMutex masterMutex; // global master lock
  212. CarlaMutex singleMutex; // small lock used only in processSingle()
  213. CarlaStateSave stateSave;
  214. CarlaString uiTitle;
  215. struct ExternalNotes {
  216. CarlaMutex mutex;
  217. RtLinkedList<ExternalMidiNote>::Pool dataPool;
  218. RtLinkedList<ExternalMidiNote> data;
  219. ExternalNotes() noexcept;
  220. ~ExternalNotes() noexcept;
  221. void appendNonRT(const ExternalMidiNote& note) noexcept;
  222. void clear() noexcept;
  223. CARLA_DECLARE_NON_COPY_STRUCT(ExternalNotes)
  224. } extNotes;
  225. struct Latency {
  226. uint32_t frames;
  227. #ifndef BUILD_BRIDGE
  228. uint32_t channels;
  229. float** buffers;
  230. #endif
  231. Latency() noexcept;
  232. #ifndef BUILD_BRIDGE
  233. ~Latency() noexcept;
  234. void clearBuffers() noexcept;
  235. void recreateBuffers(uint32_t newChannels, uint32_t newFrames);
  236. #endif
  237. CARLA_DECLARE_NON_COPY_STRUCT(Latency)
  238. } latency;
  239. class PostRtEvents {
  240. public:
  241. PostRtEvents() noexcept;
  242. ~PostRtEvents() noexcept;
  243. void appendRT(const PluginPostRtEvent& event) noexcept;
  244. void trySplice() noexcept;
  245. struct Access {
  246. Access(PostRtEvents& e)
  247. : data2(e.dataPool)
  248. {
  249. const CarlaMutexLocker cml(e.dataMutex);
  250. if (e.data.isNotEmpty())
  251. e.data.moveTo(data2, true);
  252. }
  253. ~Access()
  254. {
  255. data2.clear();
  256. }
  257. inline RtLinkedList<PluginPostRtEvent>::Itenerator getDataIterator() const noexcept
  258. {
  259. return data2.begin2();
  260. }
  261. inline std::size_t isEmpty() const noexcept
  262. {
  263. return data2.isEmpty();
  264. }
  265. private:
  266. RtLinkedList<PluginPostRtEvent> data2;
  267. };
  268. private:
  269. RtLinkedList<PluginPostRtEvent>::Pool dataPool;
  270. RtLinkedList<PluginPostRtEvent> data, dataPendingRT;
  271. CarlaMutex dataMutex;
  272. CarlaMutex dataPendingMutex;
  273. CARLA_DECLARE_NON_COPY_CLASS(PostRtEvents)
  274. } postRtEvents;
  275. struct PostUiEvents {
  276. CarlaMutex mutex;
  277. LinkedList<PluginPostRtEvent> data;
  278. PostUiEvents() noexcept;
  279. ~PostUiEvents() noexcept;
  280. void append(const PluginPostRtEvent& event) noexcept;
  281. void clear() noexcept;
  282. CARLA_DECLARE_NON_COPY_STRUCT(PostUiEvents)
  283. } postUiEvents;
  284. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  285. struct PostProc {
  286. float dryWet;
  287. float volume;
  288. float balanceLeft;
  289. float balanceRight;
  290. float panning;
  291. PostProc() noexcept;
  292. CARLA_DECLARE_NON_COPY_STRUCT(PostProc)
  293. } postProc;
  294. #endif
  295. ProtectedData(CarlaEngine* engine, uint idx) noexcept;
  296. ~ProtectedData() noexcept;
  297. // -------------------------------------------------------------------
  298. // Buffer functions
  299. void clearBuffers() noexcept;
  300. // -------------------------------------------------------------------
  301. // Post-poned events
  302. void postponeRtEvent(const PluginPostRtEvent& rtEvent) noexcept;
  303. void postponeRtEvent(PluginPostRtEventType type, bool sendCallbackLater,
  304. int32_t value1, int32_t value2, int32_t value3, float valuef) noexcept;
  305. // -------------------------------------------------------------------
  306. // Library functions
  307. static const char* libError(const char* filename) noexcept;
  308. bool libOpen(const char* filename) noexcept;
  309. bool libClose() noexcept;
  310. void setCanDeleteLib(bool canDelete) noexcept;
  311. bool uiLibOpen(const char* filename, bool canDelete) noexcept;
  312. bool uiLibClose() noexcept;
  313. template<typename Func>
  314. Func libSymbol(const char* symbol) const noexcept
  315. {
  316. return lib_symbol<Func>(lib, symbol);
  317. }
  318. template<typename Func>
  319. Func uiLibSymbol(const char* symbol) const noexcept
  320. {
  321. return lib_symbol<Func>(uiLib, symbol);
  322. }
  323. // -------------------------------------------------------------------
  324. // Misc
  325. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  326. void tryTransient() noexcept;
  327. #endif
  328. void updateParameterValues(CarlaPlugin* plugin,
  329. bool sendCallback, bool sendOsc, bool useDefault) noexcept;
  330. void updateDefaultParameterValues(CarlaPlugin* plugin) noexcept;
  331. // -------------------------------------------------------------------
  332. #ifdef CARLA_PROPER_CPP11_SUPPORT
  333. ProtectedData() = delete;
  334. CARLA_DECLARE_NON_COPY_STRUCT(ProtectedData);
  335. #endif
  336. CARLA_LEAK_DETECTOR(ProtectedData);
  337. };
  338. CARLA_BACKEND_END_NAMESPACE
  339. #endif // CARLA_PLUGIN_INTERNAL_HPP_INCLUDED