Zrythm v2.0.0-DEV
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
plugin.h
1// SPDX-FileCopyrightText: © 2018-2022, 2024-2025 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include <memory>
7#include <vector>
8
9#include "dsp/parameter.h"
10#include "dsp/port_all.h"
11#include "dsp/port_span.h"
12#include "dsp/processor_base.h"
13#include "plugins/iplugin_host_window.h"
14#include "plugins/plugin_configuration.h"
15#include "plugins/plugin_descriptor.h"
16#include "plugins/plugin_slot.h"
17
18namespace zrythm::plugins
19{
20
26class Plugin
27 : public QObject,
28 public dsp::ProcessorBase,
30{
31 Q_OBJECT
32 Q_PROPERTY (
33 int programIndex READ programIndex WRITE setProgramIndex NOTIFY
35 Q_PROPERTY (
36 zrythm::plugins::PluginConfiguration * configuration READ configuration
38 Q_PROPERTY (
39 zrythm::dsp::ProcessorParameter * bypassParameter READ bypassParameter
40 CONSTANT)
41 Q_PROPERTY (
42 zrythm::dsp::ProcessorParameter * gainParameter READ gainParameter CONSTANT)
43 Q_PROPERTY (
44 bool uiVisible READ uiVisible WRITE setUiVisible NOTIFY uiVisibleChanged)
45 Q_PROPERTY (
46 InstantiationStatus instantiationStatus READ instantiationStatus NOTIFY
47 instantiationStatusChanged)
48 QML_ELEMENT
49 QML_UNCREATABLE ("")
51 Z_DISABLE_COPY_MOVE (Plugin)
52public:
56
57 using StateDirectoryParentPathProvider = std::function<fs::path ()>;
58
59 enum class InstantiationStatus : std::uint8_t
60 {
61 Pending,
63 Failed
64 };
65 Q_ENUM (InstantiationStatus)
66
67 ~Plugin () override;
68
69 // ============================================================================
70 // QML Interface
71 // ============================================================================
72
76 int programIndex () const { return program_index_.value_or (-1); }
77 void setProgramIndex (int index)
78 {
79 if (program_index_.value_or (-1) == index)
80 return;
81
82 if (index >= 0)
83 {
84 program_index_.emplace (index);
85 }
86 else
87 {
88 program_index_.reset ();
89 }
90
91 Q_EMIT programIndexChanged (index);
92 }
93
97 Q_SIGNAL void programIndexChanged (int index);
98
99 PluginConfiguration * configuration () const { return configuration_.get (); }
106 Q_SIGNAL void configurationChanged (PluginConfiguration * configuration);
107
108 dsp::ProcessorParameter * bypassParameter () const
109 {
110 return std::get<dsp::ProcessorParameter *> (
111 dependencies ().param_registry_.find_by_id_or_throw (bypass_id_.value ()));
112 }
113 dsp::ProcessorParameter * gainParameter () const
114 {
115 return std::get<dsp::ProcessorParameter *> (
116 dependencies ().param_registry_.find_by_id_or_throw (gain_id_.value ()));
117 }
118
119 bool uiVisible () const { return visible_; }
120 void setUiVisible (bool visible)
121 {
122 if (visible == visible_)
123 return;
125 visible_ = visible;
126 Q_EMIT uiVisibleChanged (visible);
127 }
128
133 Q_SIGNAL void uiVisibleChanged (bool visible);
134
135 InstantiationStatus instantiationStatus () const
136 {
137 return instantiation_status_;
138 }
139 Q_SIGNAL void instantiationStatusChanged (InstantiationStatus status);
149 Q_SIGNAL void instantiationFinished (bool successful, const QString &error);
150
151 // ============================================================================
152
153 PluginDescriptor &get_descriptor () const
154 {
155 return *configuration ()->descr_;
156 }
157 utils::Utf8String get_name () const
158 {
159 return configuration ()->descr_->name_;
160 }
161 Protocol::ProtocolType get_protocol () const
162 {
163 return configuration ()->descr_->protocol_;
164 }
174 void set_configuration (const PluginConfiguration &setting);
175
176 // ============================================================================
177 // IProcessable Interface
178 // ============================================================================
179
180 void custom_prepare_for_processing (
181 const dsp::graph::GraphNode * node,
182 units::sample_rate_t sample_rate,
183 nframes_t max_block_length) final;
184
185 [[gnu::hot]] void custom_process_block (
186 EngineProcessTimeInfo time_nfo,
187 const dsp::ITransport &transport,
188 const dsp::TempoMap &tempo_map) noexcept final;
189
190 void custom_release_resources () final;
191
192 // ============================================================================
193
194 fs::path get_state_directory () const
195 {
197 / fs::path (
198 type_safe::get (get_uuid ())
199 .toString (QUuid::WithoutBraces)
200 .toStdString ());
201 }
202
206 bool currently_enabled () const
207 {
208 const auto * bypass = bypassParameter ();
209 return !bypass->range ().is_toggled (bypass->currentValue ());
210 }
211
212 bool currently_enabled_rt () const noexcept [[clang::nonblocking]]
213 {
214 const auto * bypass = bypass_param_rt_;
215 return !bypass->range ().is_toggled (bypass->currentValue ());
216 }
217
218 // ============================================================================
219 // Implementation Interface
220 // ============================================================================
221
222public:
232 virtual void save_state (std::optional<fs::path> abs_state_dir) = 0;
233
239 virtual void load_state (std::optional<fs::path> abs_state_dir) = 0;
240
241private:
242 virtual void prepare_for_processing_impl (
243 units::sample_rate_t sample_rate,
244 nframes_t max_block_length) { };
245
246 virtual void process_impl (EngineProcessTimeInfo time_info) noexcept = 0;
247
248 virtual void release_resources_impl () { }
249
258 [[gnu::hot]] virtual void process_passthrough_impl (
259 EngineProcessTimeInfo time_nfo,
260 const dsp::ITransport &transport,
261 const dsp::TempoMap &tempo_map) noexcept;
262
263 // ============================================================================
264
271 void init_param_caches ();
272
273protected:
281 ProcessorBaseDependencies dependencies,
282 StateDirectoryParentPathProvider state_path_provider,
283 QObject * parent);
284
289 dsp::ProcessorParameterUuidReference generate_default_bypass_param () const;
290
295 dsp::ProcessorParameterUuidReference generate_default_gain_param () const;
296
297private:
298 static constexpr auto kSettingKey = "setting"sv;
299 static constexpr auto kProgramIndexKey = "programIndex"sv;
300 static constexpr auto kVisibleKey = "visible"sv;
301 friend void to_json (nlohmann::json &j, const Plugin &p)
302 {
303 to_json (j, static_cast<const UuidIdentifiableObject &> (p));
304 to_json (j, static_cast<const dsp::ProcessorBase &> (p));
305 j[kSettingKey] = p.configuration_;
306 j[kProgramIndexKey] = p.program_index_;
307 j[kVisibleKey] = p.visible_;
308 }
309 friend void from_json (const nlohmann::json &j, Plugin &p);
310
311protected:
314 bool instantiation_failed_ = false;
315
321
322 // ============================================================================
323 // DSP Caches
324 // ============================================================================
325
332 std::optional<dsp::ProcessorParameter::Uuid> bypass_id_;
333
337 std::optional<dsp::ProcessorParameter::Uuid> gain_id_;
338
339 /* Realtime caches */
340 std::vector<dsp::AudioPort *> audio_in_ports_;
341 std::vector<dsp::AudioPort *> audio_out_ports_;
342 std::vector<dsp::CVPort *> cv_in_ports_;
343 dsp::MidiPort * midi_in_port_{};
344 dsp::MidiPort * midi_out_port_{};
345 dsp::ProcessorParameter * bypass_param_rt_{};
346
347 // ============================================================================
348
349private:
351 std::unique_ptr<PluginConfiguration> configuration_;
352
356 std::optional<int> program_index_;
357
358 InstantiationStatus instantiation_status_{ InstantiationStatus::Pending };
359
361 bool visible_ = false;
362
366 bool set_configuration_called_{};
367};
368
370class JucePlugin;
371class ClapPlugin;
373
374using PluginVariant = std::variant<JucePlugin, ClapPlugin, InternalPluginBase>;
375using PluginPtrVariant = to_pointer_variant<PluginVariant>;
376
377// TODO: consider having a ProcessorRegistry instead for all
378// ProcessorBase-derived classes
379using PluginRegistry = utils::OwningObjectRegistry<PluginPtrVariant, Plugin>;
380using PluginUuidReference = utils::UuidReference<PluginRegistry>;
381
382using PluginHostWindowFactory =
383 std::function<std::unique_ptr<plugins::IPluginHostWindow> (Plugin &)>;
384
385} // namespace zrythm::plugins
386
387DEFINE_UUID_HASH_SPECIALIZATION (zrythm::plugins::Plugin::Uuid)
388
389void
390from_json (const nlohmann::json &j, zrythm::plugins::PluginRegistry &registry);
Interface for transport.
Definition itransport.h:17
MIDI port specifics.
Definition midi_port.h:22
A base class for processors in the DSP graph.
Processor parameter that accepts automation and modulation sources and integrates with QML and the DS...
Definition parameter.h:220
Represents a node in a DSP graph.
Definition graph_node.h:131
CLAP-based plugin host implementation.
Definition clap_plugin.h:24
A base class for internal plugins.
JUCE-based plugin host implementation.
Definition juce_plugin.h:20
Configuration for instantiating a plugin descriptor.
std::unique_ptr< zrythm::plugins::PluginDescriptor > descr_
The descriptor of the plugin this setting is for.
The PluginDescriptor class provides a set of static utility functions and member functions to work wi...
DSP processing plugin.
Definition plugin.h:30
bool instantiation_failed_
Set to true if instantiation failed and the plugin will be treated as disabled.
Definition plugin.h:305
std::optional< dsp::ProcessorParameter::Uuid > gain_id_
Zrythm-provided plugin gain parameter.
Definition plugin.h:328
virtual void load_state(std::optional< fs::path > abs_state_dir)=0
Load the state from the default directory or from abs_state_dir if given.
Plugin(ProcessorBaseDependencies dependencies, StateDirectoryParentPathProvider state_path_provider, QObject *parent)
Creates/initializes a plugin and its internal plugin (LV2, etc.) using the given setting.
int programIndex() const
Returns the current program index, or -1 if no program exists.
Definition plugin.h:67
bool currently_enabled() const
Returns whether the plugin is enabled (not bypassed).
Definition plugin.h:197
dsp::ProcessorParameterUuidReference generate_default_gain_param() const
To be called by implementations to generate the default gain parameter if the plugin does not provide...
Q_SIGNAL void uiVisibleChanged(bool visible)
Implementations should listen to this and show/hide the plugin UI accordingly.
virtual void save_state(std::optional< fs::path > abs_state_dir)=0
Saves the state inside the standard state directory.
@ Pending
Instantiation underway.
Definition plugin.h:52
@ Successful
Instantiation successful.
Definition plugin.h:53
void custom_process_block(EngineProcessTimeInfo time_nfo, const dsp::ITransport &transport, const dsp::TempoMap &tempo_map) noexcept final
Custom processor logic after processing all owned parameters.
std::optional< dsp::ProcessorParameter::Uuid > bypass_id_
Bypass toggle parameter,.
Definition plugin.h:323
std::function< fs::path()> StateDirectoryParentPathProvider
Returns the parent path where the plugin should save its state directory in (or load it).
Definition plugin.h:48
dsp::ProcessorParameterUuidReference generate_default_bypass_param() const
To be called by implementations to generate the default bypass parameter if the plugin does not provi...
Q_SIGNAL void instantiationFinished(bool successful, const QString &error)
To be emitted by implementations when instantiation finished.
StateDirectoryParentPathProvider state_dir_parent_path_provider_
Plugins should create a state directory with their UUID as the directory name under the path provided...
Definition plugin.h:311
Q_SIGNAL void programIndexChanged(int index)
Implementations should attach to this and set the program.
Q_SIGNAL void configurationChanged(PluginConfiguration *configuration)
Emitted when the configuration is set on the plugin.
void set_configuration(const PluginConfiguration &setting)
Sets the plugin setting to use.
Lightweight UTF-8 string wrapper with safe conversions.
Definition utf8_string.h:38
Base class for objects that need to be uniquely identified by UUID.
uint32_t nframes_t
Frame count.
Definition types.h:58
Common struct to pass around during processing to avoid repeating the data in function arguments.
Definition types.h:133