Dusk Audio Framework
Loading...
Searching...
No Matches
DafPlugin.hpp
1/*
2 * DISTRHO Plugin Framework (DPF)
3 * Copyright (C) 2012-2024 Filipe Coelho <falktx@falktx.com>
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any purpose with
6 * or without fee is hereby granted, provided that the above copyright notice and this
7 * permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
10 * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
11 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
13 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef DAF_PLUGIN_HPP_INCLUDED
18#define DAF_PLUGIN_HPP_INCLUDED
19
20#include "DafDetails.hpp"
21#include "extra/LeakDetector.hpp"
22#include "src/DafPluginChecks.h"
23
25
26/* ------------------------------------------------------------------------------------------------------------
27 * DAF Plugin */
28
29/**
30 @defgroup MainClasses Main Classes
31 @{
32 */
33
34/**
35 DAF Plugin class from where plugin instances are created.
36
37 The public methods (Host state) are called from the plugin to get or set host information.@n
38 They can be called from a plugin instance at anytime unless stated otherwise.@n
39 All other methods are to be implemented by the plugin and will be called by the host.
40
41 Shortly after a plugin instance is created, the various init* functions will be called by the host.@n
42 Host will call activate() before run(), and deactivate() before the plugin instance is destroyed.@n
43 The host may call deactivate right after activate and vice-versa, but never activate/deactivate consecutively.@n
44 There is no limit on how many times run() is called, only that activate/deactivate will be called in between.
45
46 The buffer size and sample rate values will remain constant between activate and deactivate.@n
47 Buffer size is only a hint though, the host might call run() with a higher or lower number of frames.
48
49 Some of this class functions are only available according to some macros.
50
51 DAF_PLUGIN_WANT_PROGRAMS activates program related features.@n
52 When enabled you need to implement initProgramName() and loadProgram().
53
54 DAF_PLUGIN_WANT_STATE activates internal state features.@n
55 When enabled you need to implement initState() and setState().
56
57 The process function run() changes wherever DAF_PLUGIN_WANT_MIDI_INPUT is enabled or not.@n
58 When enabled it provides midi input events.
59 */
60class Plugin
61{
62public:
63 /**
64 Plugin class constructor.@n
65 You must set all parameter values to their defaults, matching ParameterRanges::def.
66 */
67 Plugin(uint32_t parameterCount, uint32_t programCount, uint32_t stateCount);
68
69 /**
70 Destructor.
71 */
72 virtual ~Plugin();
73
74 /* --------------------------------------------------------------------------------------------------------
75 * Host state */
76
77 /**
78 Get the current buffer size that will probably be used during processing, in frames.@n
79 This value will remain constant between activate and deactivate.
80 @note This value is only a hint!@n
81 Hosts might call run() with a higher or lower number of frames.
82 @see bufferSizeChanged(uint32_t)
83 */
84 uint32_t getBufferSize() const noexcept;
85
86 /**
87 Get the current sample rate that will be used during processing.@n
88 This value will remain constant between activate and deactivate.
89 @see sampleRateChanged(double)
90 */
91 double getSampleRate() const noexcept;
92
93 /**
94 Get the bundle path where the plugin resides.
95 Can return null if the plugin is not available in a bundle (if it is a single binary).
96 @see getBinaryFilename
97 @see getResourcePath
98 */
99 const char* getBundlePath() const noexcept;
100
101 /**
102 Check if this plugin instance is a "dummy" one used for plugin meta-data/information export.@n
103 When true no processing will be done, the plugin is created only to extract information.@n
104 In DAF, LADSPA/DSSI, VST2 and VST3 formats create one global instance per plugin binary
105 while LV2 creates one when generating turtle meta-data.
106 */
107 bool isDummyInstance() const noexcept;
108
109 /**
110 Check if this plugin instance is a "selftest" one used for automated plugin tests.@n
111 To enable this mode build with `DAF_RUNTIME_TESTING` macro defined (i.e. set as compiler build flag),
112 and run the JACK/Standalone executable with "selftest" as its only and single argument.
113
114 A few basic DSP and UI tests will run in self-test mode, with once instance having this function returning true.@n
115 You can use this chance to do a few tests of your own as well.
116 */
117 bool isSelfTestInstance() const noexcept;
118
119#if DAF_PLUGIN_WANT_TIMEPOS
120 /**
121 Get the current host transport time position.@n
122 This function should only be called during run().@n
123 You can call this during other times, but the returned position is not guaranteed to be in sync.
124 @note TimePosition is not supported in LADSPA and DSSI plugin formats.
125 */
126 const TimePosition& getTimePosition() const noexcept;
127#endif
128
129#if DAF_PLUGIN_WANT_LATENCY
130 /**
131 Change the plugin audio output latency to @a frames.@n
132 This function should only be called in the constructor, activate() and run().
133 @note This function is only available if DAF_PLUGIN_WANT_LATENCY is enabled.
134 */
135 void setLatency(uint32_t frames) noexcept;
136#endif
137
138#if DAF_PLUGIN_WANT_TAIL
139 /**
140 Tail length value meaning "the tail never ends" (a freeze, a feedback loop at unity).
141 */
142 static constexpr uint32_t kTailInfinite = 0xffffffffU;
143
144 /**
145 Change the plugin audio tail length to @a frames.@n
146 The tail is how long the output keeps carrying signal after the input goes silent
147 (a reverb decay, a delay feedback path); hosts use it to decide when a bounce may
148 stop and when an idle plugin may be suspended. Pass @ref kTailInfinite for a tail
149 that never ends. 0 means no tail.@n
150 This function should only be called in the constructor, activate() and run().
151 Report it in frames at the sample rate passed to activate().
152 @note This function is only available if DAF_PLUGIN_WANT_TAIL is enabled.
153 @note VST3, AU and CLAP report the tail to the host; LV2 has no tail concept.
154 */
155 void setTail(uint32_t frames) noexcept;
156#endif
157
158#if DAF_PLUGIN_WANT_MIDI_OUTPUT
159 /**
160 Write a MIDI output event.@n
161 This function must only be called during run().@n
162 Returns false when the host buffer is full, in which case do not call this again until the next run().
163 */
164 bool writeMidiEvent(const MidiEvent& midiEvent) noexcept;
165#endif
166
167#if DAF_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST
168 /**
169 Check if parameter value change requests will work with the current plugin host.
170 @note This function is only available if DAF_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST is enabled.
171 @see requestParameterValueChange(uint32_t, float)
172 */
173 bool canRequestParameterValueChanges() const noexcept;
174
175 /**
176 Request a parameter value change from the host.
177 If successful, this function will automatically trigger a parameter update on the UI side as well.
178 This function can fail, for example if the host is busy with the parameter for read-only automation.
179 Some hosts simply do not have this functionality, which can be verified with canRequestParameterValueChanges().
180 @note This function is only available if DAF_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST is enabled.
181 */
182 bool requestParameterValueChange(uint32_t index, float value) noexcept;
183#endif
184
185#if DAF_PLUGIN_WANT_STATE
186 /**
187 Set state value and notify the host about the change.@n
188 This function will call `setState()` and also trigger an update on the UI side as necessary.@n
189 It must not be called during run.@n
190 The state must be host readable.@n
191 Returns false for an unknown key.@n
192 On CLAP, VST2, VST3 and JACK it may be called from any thread other than the audio one:
193 `setState()` is called right away, while the UI and the host's "modified" flag are updated
194 later on the host's main thread. A state the host saves in the meantime has the new value.
195 VST2 and VST3 get there on the editor's idle, so with the editor closed the host is not told before it
196 opens; a VST3 plugin without a UI tells the host on its next setActive instead.@n
197 Until the plugin is fully constructed, that is from its constructor and from initState() and the other
198 init functions, there is no host to tell yet: the call does nothing and returns false.
199 @note this function does nothing on DSSI plugin format, as DSSI only supports UI->DSP messages.
200
201 TODO API under construction
202 */
203 bool updateStateValue(const char* key, const char* value) noexcept;
204#endif
205
206protected:
207 /* --------------------------------------------------------------------------------------------------------
208 * Information */
209
210 /**
211 Get the plugin name.@n
212 Returns DAF_PLUGIN_NAME by default.
213 */
214 virtual const char* getName() const { return DAF_PLUGIN_NAME; }
215
216 /**
217 Get the plugin label.@n
218 This label is a short restricted name consisting of only _, a-z, A-Z and 0-9 characters.
219 */
220 #ifdef DAF_PLUGIN_LABEL
221 virtual const char* getLabel() const
222 {
223 return DAF_PLUGIN_LABEL;
224 }
225 #else
226 virtual const char* getLabel() const = 0;
227 #endif
228
229 /**
230 Get an extensive comment/description about the plugin.@n
231 Optional, returns nothing by default.
232 */
233 virtual const char* getDescription() const
234 {
235 #ifdef DAF_PLUGIN_DESCRIPTION
236 return DAF_PLUGIN_DESCRIPTION;
237 #else
238 return "";
239 #endif
240 }
241
242 /**
243 Get the plugin author/maker.
244 */
245 #ifdef DAF_PLUGIN_MAKER
246 virtual const char* getMaker() const
247 {
248 return DAF_PLUGIN_MAKER;
249 }
250 #else
251 virtual const char* getMaker() const = 0;
252 #endif
253
254 /**
255 Get the plugin homepage.@n
256 Optional, returns nothing by default.
257 */
258 virtual const char* getHomePage() const
259 {
260 #ifdef DAF_PLUGIN_HOMEPAGE
261 return DAF_PLUGIN_HOMEPAGE;
262 #else
263 return "";
264 #endif
265 }
266
267 /**
268 Get the plugin license (a single line of text or a URL).@n
269 For commercial plugins this should return some short copyright information.
270 */
271 #ifdef DAF_PLUGIN_LICENSE
272 virtual const char* getLicense() const
273 {
274 return DAF_PLUGIN_LICENSE;
275 }
276 #else
277 virtual const char* getLicense() const = 0;
278 #endif
279
280 /**
281 Get the plugin version, in hexadecimal.
282 @see d_version()
283 */
284 virtual uint32_t getVersion() const = 0;
285
286 /**
287 Get the plugin unique Id.@n
288 This value is used by LADSPA, DSSI, VST2, VST3 and AUv2 plugin formats.@n
289 @note It is preferred that you set DAF_PLUGIN_UNIQUE_ID macro instead of overriding this call,
290 as that is required for AUv2 plugins anyhow.
291 @see d_cconst()
292 */
293 #ifdef DAF_PLUGIN_UNIQUE_ID
294 virtual int64_t getUniqueId() const
295 {
296 return d_cconst(STRINGIFY(DAF_PLUGIN_UNIQUE_ID));
297 }
298 #else
299 virtual int64_t getUniqueId() const = 0;
300 #endif
301
302 /* --------------------------------------------------------------------------------------------------------
303 * Init */
304
305 /**
306 Initialize the audio port @a index.@n
307 This function will be called once, shortly after the plugin is created.
308 */
309 virtual void initAudioPort(bool input, uint32_t index, AudioPort& port);
310
311 /**
312 Initialize the parameter @a index.@n
313 This function will be called once, shortly after the plugin is created.
314 */
315 virtual void initParameter(uint32_t index, Parameter& parameter);
316
317 /**
318 Initialize the port group @a groupId.@n
319 This function will be called once,
320 shortly after the plugin is created and all audio ports and parameters have been enumerated.
321 */
322 virtual void initPortGroup(uint32_t groupId, PortGroup& portGroup);
323
324#if DAF_PLUGIN_WANT_PROGRAMS
325 /**
326 Set the name of the program @a index.@n
327 This function will be called once, shortly after the plugin is created.@n
328 Must be implemented by your plugin class only if DAF_PLUGIN_WANT_PROGRAMS is enabled.
329 */
330 virtual void initProgramName(uint32_t index, String& programName) = 0;
331#endif
332
333#if DAF_PLUGIN_WANT_STATE
334 /**
335 Initialize the state @a index.@n
336 This function will be called once, shortly after the plugin is created.@n
337 Must be implemented by your plugin class only if DAF_PLUGIN_WANT_STATE is enabled.
338 */
339 virtual void initState(uint32_t index, State& state);
340
341 DAF_DEPRECATED_BY("initState(uint32_t,State&)")
342 virtual void initState(uint32_t, String&, String&) {}
343
344 DAF_DEPRECATED_BY("initState(uint32_t,State&)")
345 virtual bool isStateFile(uint32_t) { return false; }
346#endif
347
348 /* --------------------------------------------------------------------------------------------------------
349 * Internal data */
350
351 /**
352 Get the current value of a parameter.@n
353 The host may call this function from any context, including realtime processing.
354 */
355 virtual float getParameterValue(uint32_t index) const;
356
357 /**
358 Whether this parameter supplies custom text conversion callbacks.
359 Custom conversion callbacks must be nonallocating and safe to call concurrently.
360 When true, a callback returning false reports invalid conversion; adapters must not
361 fall back to generic numeric parsing or formatting.
362 */
363 virtual bool hasCustomParameterText(uint32_t) const { return false; }
364
365 /**
366 Format a parameter-domain value into @a text without allocating.
367 Null text or zero capacity must be handled safely by the override. Returns false
368 when conversion is unavailable or the buffer is insufficient.
369 */
370 virtual bool getParameterValueText(uint32_t, float, char*, uint32_t) const
371 {
372 return false;
373 }
374
375 /**
376 Parse @a text into a parameter-domain value without allocating.
377 Null text must be handled safely by the override. Returns false when conversion is
378 unavailable or invalid.
379 */
380 virtual bool getParameterValueFromText(uint32_t, const char*, float&) const
381 {
382 return false;
383 }
384
385 /**
386 Change a parameter value.@n
387 The host may call this function from any context, including realtime processing.@n
388 When a parameter is marked as automatable, you must ensure no non-realtime operations are performed.
389 @note This function will only be called for parameter inputs.
390 */
391 virtual void setParameterValue(uint32_t index, float value);
392
393#if DAF_PLUGIN_WANT_PROGRAMS
394 /**
395 Load a program.@n
396 The host may call this function from any context, including realtime processing.@n
397 Must be implemented by your plugin class only if DAF_PLUGIN_WANT_PROGRAMS is enabled.
398 */
399 virtual void loadProgram(uint32_t index);
400
401 /**
402 Optional identity readback after a complete state recall.@n
403 Return the current factory program, or -1 when no program is known.
404 This getter must be safe to call concurrently with processing.
405 */
406 virtual int32_t getCurrentProgram() const { return -1; }
407#endif
408
409#if DAF_PLUGIN_WANT_FULL_STATE
410 /**
411 Get the value of an internal state.@n
412 The host may call this function from any non-realtime context.@n
413 Must be implemented by your plugin class if DAF_PLUGIN_WANT_FULL_STATE is enabled.
414 @note The use of this function breaks compatibility with the DSSI format.
415 */
416 virtual String getState(const char* key) const;
417#endif
418
419#if DAF_PLUGIN_WANT_STATE
420 /**
421 Change an internal state @a key to @a value.@n
422 Must be implemented by your plugin class only if DAF_PLUGIN_WANT_STATE is enabled.
423 */
424 virtual void setState(const char* key, const char* value);
425
426 /** Validate a state value without changing the plugin. Called outside the audio callback.
427 Override for complete sound snapshots so wrappers can reject a malformed recall before
428 applying its program or parameters. The default preserves existing plugin behavior. */
429 virtual bool validateStateValue(const char*, const char*) const { return true; }
430#endif
431
432 /* --------------------------------------------------------------------------------------------------------
433 * Audio/MIDI Processing */
434
435 /**
436 Activate this plugin.
437 */
438 virtual void activate() {}
439
440 /**
441 Deactivate this plugin.
442 */
443 virtual void deactivate() {}
444
445#if DAF_PLUGIN_WANT_MIDI_INPUT
446 /**
447 Run/process function for plugins with MIDI input.
448 @note Some parameters might be null if there are no audio inputs/outputs or MIDI events.
449 */
450 virtual void run(const float** inputs, float** outputs, uint32_t frames,
451 const MidiEvent* midiEvents, uint32_t midiEventCount) = 0;
452#else
453 /**
454 Run/process function for plugins without MIDI input.
455 @note Some parameters might be null if there are no audio inputs or outputs.
456 */
457 virtual void run(const float** inputs, float** outputs, uint32_t frames) = 0;
458#endif
459
460 /* --------------------------------------------------------------------------------------------------------
461 * Callbacks (optional) */
462
463 /**
464 Optional callback to inform the plugin about a buffer size change.@n
465 This function will only be called when the plugin is deactivated.
466 @note This value is only a hint!@n
467 Hosts might call run() with a higher or lower number of frames.
468 @see getBufferSize()
469 */
470 virtual void bufferSizeChanged(uint32_t newBufferSize);
471
472 /**
473 Optional callback to inform the plugin about a sample rate change.@n
474 This function will only be called when the plugin is deactivated.
475 @see getSampleRate()
476 */
477 virtual void sampleRateChanged(double newSampleRate);
478
479 /**
480 Optional callback to inform the plugin about audio port IO changes.@n
481 This function will only be called when the plugin is deactivated.@n
482 Used by AU, and by CLAP/VST3 for supported main-bus configurations
483 declared with DAF_PLUGIN_EXTRA_IO.@n
484 With DAF_PLUGIN_SIDECHAIN_ON_EXTRA_IO (AU), @a numInputs can also be the declared main-bus layout for
485 @a numOutputs plus a connected sidechain at its declared width or narrower (e.g. 1 + 1 = 2 with 1 output on a
486 Logic mono track, 1 + 2 = 3 for a mono track keyed by a stereo sidechain). This applies only to a plugin with
487 one sidechain bus, and to output counts whose declared combinations all put the same width on the main bus, so
488 the main width follows from @a numOutputs. The input ports keep their declared positions: the sidechain stays
489 on its own ports, and the channels a connected bus does not carry read silence.
490 @see DAF_PLUGIN_EXTRA_IO
491 */
492 virtual void ioChanged(uint16_t numInputs, uint16_t numOutputs);
493
494 // -------------------------------------------------------------------------------------------------------
495
496private:
497 struct PrivateData;
498 PrivateData* const pData;
499 friend class PluginExporter;
500
501 DAF_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Plugin)
502};
503
504/** @} */
505
506/* ------------------------------------------------------------------------------------------------------------
507 * Create plugin, entry point */
508
509/**
510 @defgroup EntryPoints Entry Points
511 @{
512 */
513
514/**
515 Create an instance of the Plugin class.@n
516 This is the entry point for DAF plugins.@n
517 DAF will call this to either create an instance of your plugin for the host
518 or to fetch some initial information for internal caching.
519 */
521
522/** @} */
523
524// -----------------------------------------------------------------------------------------------------------
525
527
528#endif // DAF_PLUGIN_HPP_INCLUDED
Definition DafPlugin.hpp:61
virtual const char * getDescription() const
Definition DafPlugin.hpp:233
bool writeMidiEvent(const MidiEvent &midiEvent) noexcept
const char * getBundlePath() const noexcept
virtual void run(const float **inputs, float **outputs, uint32_t frames, const MidiEvent *midiEvents, uint32_t midiEventCount)=0
uint32_t getBufferSize() const noexcept
void setLatency(uint32_t frames) noexcept
virtual void sampleRateChanged(double newSampleRate)
double getSampleRate() const noexcept
virtual void loadProgram(uint32_t index)
virtual const char * getHomePage() const
Definition DafPlugin.hpp:258
virtual void initProgramName(uint32_t index, String &programName)=0
bool canRequestParameterValueChanges() const noexcept
virtual void initPortGroup(uint32_t groupId, PortGroup &portGroup)
virtual bool getParameterValueText(uint32_t, float, char *, uint32_t) const
Definition DafPlugin.hpp:370
virtual const char * getLabel() const =0
const TimePosition & getTimePosition() const noexcept
virtual void initAudioPort(bool input, uint32_t index, AudioPort &port)
virtual void setParameterValue(uint32_t index, float value)
virtual ~Plugin()
bool isSelfTestInstance() const noexcept
virtual bool hasCustomParameterText(uint32_t) const
Definition DafPlugin.hpp:363
virtual String getState(const char *key) const
virtual void bufferSizeChanged(uint32_t newBufferSize)
virtual void deactivate()
Definition DafPlugin.hpp:443
virtual void activate()
Definition DafPlugin.hpp:438
bool updateStateValue(const char *key, const char *value) noexcept
virtual const char * getName() const
Definition DafPlugin.hpp:214
virtual void initParameter(uint32_t index, Parameter &parameter)
bool isDummyInstance() const noexcept
virtual uint32_t getVersion() const =0
virtual bool validateStateValue(const char *, const char *) const
Definition DafPlugin.hpp:429
virtual void ioChanged(uint16_t numInputs, uint16_t numOutputs)
Plugin(uint32_t parameterCount, uint32_t programCount, uint32_t stateCount)
virtual void initState(uint32_t index, State &state)
virtual int64_t getUniqueId() const =0
virtual bool getParameterValueFromText(uint32_t, const char *, float &) const
Definition DafPlugin.hpp:380
bool requestParameterValueChange(uint32_t index, float value) noexcept
virtual int32_t getCurrentProgram() const
Definition DafPlugin.hpp:406
virtual const char * getMaker() const =0
virtual const char * getLicense() const =0
virtual float getParameterValue(uint32_t index) const
virtual void setState(const char *key, const char *value)
Definition String.hpp:35
Plugin * createPlugin()
#define END_NAMESPACE_DAF
Definition DafInfo.hpp:996
#define START_NAMESPACE_DAF
Definition DafInfo.hpp:990
#define DAF_PLUGIN_UNIQUE_ID
Definition DafInfo.hpp:722
#define DAF_PLUGIN_NAME
Definition DafInfo.hpp:488
Definition DafDetails.hpp:303
Definition DafDetails.hpp:939
Definition DafDetails.hpp:607
Definition DafDetails.hpp:845
Definition DafDetails.hpp:871
Definition DafDetails.hpp:973