Implement LV2 ControlInputPort change request feature
[carla.git] / source / backend / plugin / CarlaPluginInternal.hpp
blob5d8c2e00b4f8016aef75a0be037ab4e1a70f1789
1 /*
2 * Carla Plugin
3 * Copyright (C) 2011-2022 Filipe Coelho <falktx@falktx.com>
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.
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.
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
18 #ifndef CARLA_PLUGIN_INTERNAL_HPP_INCLUDED
19 #define CARLA_PLUGIN_INTERNAL_HPP_INCLUDED
21 #include "CarlaPlugin.hpp"
23 #include "CarlaJuceUtils.hpp"
24 #include "CarlaLibUtils.hpp"
25 #include "CarlaStateUtils.hpp"
27 #include "CarlaMIDI.h"
28 #include "CarlaMutex.hpp"
29 #include "CarlaString.hpp"
30 #include "RtLinkedList.hpp"
32 CARLA_BACKEND_START_NAMESPACE
34 // -----------------------------------------------------------------------
35 // Engine helper macro, sets lastError and returns false/NULL
37 #define CARLA_SAFE_ASSERT_RETURN_ERR(cond, err) if (! (cond)) { carla_safe_assert(#cond, __FILE__, __LINE__); pData->engine->setLastError(err); return false; }
38 #define CARLA_SAFE_ASSERT_RETURN_ERRN(cond, err) if (! (cond)) { carla_safe_assert(#cond, __FILE__, __LINE__); pData->engine->setLastError(err); return nullptr; }
40 #define CARLA_SAFE_EXCEPTION_RETURN_ERR(excptMsg, errMsg) catch(...) { carla_safe_exception(excptMsg, __FILE__, __LINE__); pData->engine->setLastError(errMsg); return false; }
41 #define CARLA_SAFE_EXCEPTION_RETURN_ERRN(excptMsg, errMsg) catch(...) { carla_safe_exception(excptMsg, __FILE__, __LINE__); pData->engine->setLastError(errMsg); return nullptr; }
43 // -----------------------------------------------------------------------
44 // Maximum pre-allocated events for some plugin types
46 constexpr const uint16_t kPluginMaxMidiEvents = 512;
48 // -----------------------------------------------------------------------
49 // Extra parameter hints, hidden from backend
51 constexpr const uint PARAMETER_MAPPED_RANGES_SET = 0x10000;
52 constexpr const uint PARAMETER_IS_STRICT_BOUNDS = 0x20000;
53 constexpr const uint PARAMETER_IS_TRIGGER = 0x40000;
55 // -----------------------------------------------------------------------
56 // Extra plugin hints, hidden from backend
58 constexpr const uint PLUGIN_EXTRA_HINT_HAS_MIDI_IN = 0x01;
59 constexpr const uint PLUGIN_EXTRA_HINT_HAS_MIDI_OUT = 0x02;
61 // -----------------------------------------------------------------------
62 // Special parameters
64 enum SpecialParameterType {
65 PARAMETER_SPECIAL_NULL = 0,
66 PARAMETER_SPECIAL_FREEWHEEL = 1,
67 PARAMETER_SPECIAL_LATENCY = 2,
68 PARAMETER_SPECIAL_SAMPLE_RATE = 3,
69 PARAMETER_SPECIAL_TIME = 4
72 // -----------------------------------------------------------------------
74 /*!
75 * Post-RT event type.
76 * These are events postponned from within the process function,
78 * During process, we cannot lock, allocate memory or do UI stuff.
79 * Events have to be postponned to be executed later, on a separate thread.
80 * @see PluginPostRtEvent
82 enum PluginPostRtEventType {
83 kPluginPostRtEventNull = 0,
84 kPluginPostRtEventParameterChange,
85 kPluginPostRtEventProgramChange,
86 kPluginPostRtEventMidiProgramChange,
87 kPluginPostRtEventNoteOn,
88 kPluginPostRtEventNoteOff,
89 kPluginPostRtEventMidiLearn
92 /*!
93 * A Post-RT event.
94 * @see PluginPostRtEventType
96 struct PluginPostRtEvent {
97 PluginPostRtEventType type;
98 bool sendCallback;
99 union {
100 struct {
101 int32_t index;
102 float value;
103 } parameter;
104 struct {
105 uint32_t index;
106 } program;
107 struct {
108 uint8_t channel;
109 uint8_t note;
110 uint8_t velocity;
111 } note;
112 struct {
113 uint32_t parameter;
114 uint8_t cc;
115 uint8_t channel;
116 } midiLearn;
120 // -----------------------------------------------------------------------
122 struct ExternalMidiNote {
123 int8_t channel; // invalid if -1
124 uint8_t note; // 0 to 127
125 uint8_t velo; // 1 to 127, 0 for note-off
128 // -----------------------------------------------------------------------
130 struct PluginAudioPort {
131 uint32_t rindex;
132 CarlaEngineAudioPort* port;
135 struct PluginAudioData {
136 uint32_t count;
137 PluginAudioPort* ports;
139 PluginAudioData() noexcept;
140 ~PluginAudioData() noexcept;
141 void createNew(uint32_t newCount);
142 void clear() noexcept;
143 void initBuffers() const noexcept;
145 CARLA_DECLARE_NON_COPYABLE(PluginAudioData)
148 // -----------------------------------------------------------------------
150 struct PluginCVPort {
151 uint32_t rindex;
152 //uint32_t param; // FIXME is this needed?
153 CarlaEngineCVPort* port;
156 struct PluginCVData {
157 uint32_t count;
158 PluginCVPort* ports;
160 PluginCVData() noexcept;
161 ~PluginCVData() noexcept;
162 void createNew(uint32_t newCount);
163 void clear() noexcept;
164 void initBuffers() const noexcept;
166 CARLA_DECLARE_NON_COPYABLE(PluginCVData)
169 // -----------------------------------------------------------------------
171 struct PluginEventData {
172 CarlaEngineEventPort* portIn;
173 CarlaEngineEventPort* portOut;
174 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
175 CarlaEngineCVSourcePorts* cvSourcePorts;
176 #endif
178 PluginEventData() noexcept;
179 ~PluginEventData() noexcept;
180 void clear() noexcept;
181 void initBuffers() const noexcept;
183 CARLA_DECLARE_NON_COPYABLE(PluginEventData)
186 // -----------------------------------------------------------------------
188 struct PluginParameterData {
189 uint32_t count;
190 ParameterData* data;
191 ParameterRanges* ranges;
192 SpecialParameterType* special;
194 PluginParameterData() noexcept;
195 ~PluginParameterData() noexcept;
196 void createNew(uint32_t newCount, bool withSpecial);
197 void clear() noexcept;
198 float getFixedValue(uint32_t parameterId, float value) const noexcept;
199 float getFinalUnnormalizedValue(uint32_t parameterId, float normalizedValue) const noexcept;
200 float getFinalValueWithMidiDelta(uint32_t parameterId, float value, int8_t delta) const noexcept;
202 CARLA_DECLARE_NON_COPYABLE(PluginParameterData)
205 // -----------------------------------------------------------------------
207 typedef const char* ProgramName;
209 struct PluginProgramData {
210 uint32_t count;
211 int32_t current;
212 ProgramName* names;
214 PluginProgramData() noexcept;
215 ~PluginProgramData() noexcept;
216 void createNew(uint32_t newCount);
217 void clear() noexcept;
219 CARLA_DECLARE_NON_COPYABLE(PluginProgramData)
222 // -----------------------------------------------------------------------
224 struct PluginMidiProgramData {
225 uint32_t count;
226 int32_t current;
227 MidiProgramData* data;
229 PluginMidiProgramData() noexcept;
230 ~PluginMidiProgramData() noexcept;
231 void createNew(uint32_t newCount);
232 void clear() noexcept;
233 const MidiProgramData& getCurrent() const noexcept;
235 CARLA_DECLARE_NON_COPYABLE(PluginMidiProgramData)
238 // -----------------------------------------------------------------------
240 struct CarlaPlugin::ProtectedData {
241 CarlaEngine* const engine;
242 CarlaEngineClient* client;
244 uint id;
245 uint hints;
246 uint options;
247 uint32_t nodeId;
249 bool active;
250 bool enabled;
251 bool needsReset;
253 bool engineBridged;
254 bool enginePlugin;
256 lib_t lib;
257 lib_t uiLib;
259 // misc
260 int8_t ctrlChannel;
261 uint extraHints;
262 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
263 int32_t midiLearnParameterIndex;
264 uint transientTryCounter;
265 bool transientFirstTry;
266 #endif
268 // data 1
269 const char* name;
270 const char* filename;
271 const char* iconName;
273 // data 2
274 PluginAudioData audioIn;
275 PluginAudioData audioOut;
276 PluginCVData cvIn;
277 PluginCVData cvOut;
278 PluginEventData event;
279 PluginParameterData param;
280 PluginProgramData prog;
281 PluginMidiProgramData midiprog;
282 LinkedList<CustomData> custom;
284 CarlaMutex masterMutex; // global master lock
285 CarlaMutex singleMutex; // small lock used only in processSingle()
287 CarlaStateSave stateSave;
289 CarlaString uiTitle;
291 struct ExternalNotes {
292 CarlaMutex mutex;
293 RtLinkedList<ExternalMidiNote>::Pool dataPool;
294 RtLinkedList<ExternalMidiNote> data;
296 ExternalNotes() noexcept;
297 ~ExternalNotes() noexcept;
298 void appendNonRT(const ExternalMidiNote& note) noexcept;
299 void clear() noexcept;
301 CARLA_DECLARE_NON_COPYABLE(ExternalNotes)
303 } extNotes;
305 struct Latency {
306 uint32_t frames;
307 #ifndef BUILD_BRIDGE
308 uint32_t channels;
309 float** buffers;
310 #endif
312 Latency() noexcept;
313 #ifndef BUILD_BRIDGE
314 ~Latency() noexcept;
315 void clearBuffers() noexcept;
316 void recreateBuffers(uint32_t newChannels, uint32_t newFrames);
317 #endif
319 CARLA_DECLARE_NON_COPYABLE(Latency)
321 } latency;
323 class PostRtEvents {
324 public:
325 PostRtEvents() noexcept;
326 ~PostRtEvents() noexcept;
327 void appendRT(const PluginPostRtEvent& event) noexcept;
328 void trySplice() noexcept;
330 struct Access {
331 Access(PostRtEvents& e)
332 : data2(e.dataPool),
333 poolMutex(e.poolMutex)
335 const CarlaMutexLocker cml1(e.dataMutex);
336 const CarlaMutexLocker cml2(e.poolMutex);
338 if (e.data.isNotEmpty())
339 e.data.moveTo(data2, true);
342 ~Access()
344 const CarlaMutexLocker cml(poolMutex);
346 data2.clear();
349 inline RtLinkedList<PluginPostRtEvent>::Itenerator getDataIterator() const noexcept
351 return data2.begin2();
354 inline std::size_t isEmpty() const noexcept
356 return data2.isEmpty();
359 private:
360 RtLinkedList<PluginPostRtEvent> data2;
361 CarlaMutex& poolMutex;
364 private:
365 RtLinkedList<PluginPostRtEvent>::Pool dataPool;
366 RtLinkedList<PluginPostRtEvent> data, dataPendingRT;
367 CarlaMutex dataMutex;
368 CarlaMutex dataPendingMutex;
369 CarlaMutex poolMutex;
371 CARLA_DECLARE_NON_COPYABLE(PostRtEvents)
373 } postRtEvents;
375 struct PostUiEvents {
376 CarlaMutex mutex;
377 LinkedList<PluginPostRtEvent> data;
379 PostUiEvents() noexcept;
380 ~PostUiEvents() noexcept;
381 void append(const PluginPostRtEvent& event) noexcept;
382 void clear() noexcept;
384 CARLA_DECLARE_NON_COPYABLE(PostUiEvents)
386 } postUiEvents;
388 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
389 struct PostProc {
390 float dryWet;
391 float volume;
392 float balanceLeft;
393 float balanceRight;
394 float panning;
395 float* extraBuffer;
397 PostProc() noexcept;
399 CARLA_DECLARE_NON_COPYABLE(PostProc)
401 } postProc;
402 #endif
404 ProtectedData(CarlaEngine* engine, uint idx) noexcept;
405 ~ProtectedData() noexcept;
407 // -------------------------------------------------------------------
408 // Buffer functions
410 void clearBuffers() noexcept;
412 // -------------------------------------------------------------------
413 // Post-poned events
415 void postponeRtEvent(const PluginPostRtEvent& rtEvent) noexcept;
416 void postponeParameterChangeRtEvent(bool sendCallbackLater, int32_t index, float value) noexcept;
417 void postponeProgramChangeRtEvent(bool sendCallbackLater, uint32_t index) noexcept;
418 void postponeMidiProgramChangeRtEvent(bool sendCallbackLater, uint32_t index) noexcept;
419 void postponeNoteOnRtEvent(bool sendCallbackLater, uint8_t channel, uint8_t note, uint8_t velocity) noexcept;
420 void postponeNoteOffRtEvent(bool sendCallbackLater, uint8_t channel, uint8_t note) noexcept;
421 void postponeMidiLearnRtEvent(bool sendCallbackLater, uint32_t parameter, uint8_t cc, uint8_t channel) noexcept;
423 // -------------------------------------------------------------------
424 // Library functions
426 static const char* libError(const char* filename) noexcept;
428 bool libOpen(const char* filename) noexcept;
429 bool libClose() noexcept;
430 void setCanDeleteLib(bool canDelete) noexcept;
432 bool uiLibOpen(const char* filename, bool canDelete) noexcept;
433 bool uiLibClose() noexcept;
435 template<typename Func>
436 Func libSymbol(const char* symbol) const noexcept
438 return lib_symbol<Func>(lib, symbol);
441 template<typename Func>
442 Func uiLibSymbol(const char* symbol) const noexcept
444 return lib_symbol<Func>(uiLib, symbol);
447 // -------------------------------------------------------------------
448 // Misc
450 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
451 void tryTransient() noexcept;
452 #endif
453 void updateParameterValues(CarlaPlugin* plugin,
454 bool sendCallback, bool sendOsc, bool useDefault) noexcept;
455 void updateDefaultParameterValues(CarlaPlugin* plugin) noexcept;
457 // -------------------------------------------------------------------
459 #ifdef CARLA_PROPER_CPP11_SUPPORT
460 ProtectedData() = delete;
461 CARLA_DECLARE_NON_COPYABLE(ProtectedData);
462 #endif
463 CARLA_LEAK_DETECTOR(ProtectedData);
466 CARLA_BACKEND_END_NAMESPACE
468 #endif // CARLA_PLUGIN_INTERNAL_HPP_INCLUDED