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) noexcept final;
188
189 void custom_release_resources () final;
190
191 // ============================================================================
192
193 fs::path get_state_directory () const
194 {
196 / fs::path (
197 type_safe::get (get_uuid ())
198 .toString (QUuid::WithoutBraces)
199 .toStdString ());
200 }
201
205 bool currently_enabled () const
206 {
207 const auto * bypass = bypassParameter ();
208 return !bypass->range ().is_toggled (bypass->currentValue ());
209 }
210
211 bool currently_enabled_rt () const noexcept [[clang::nonblocking]]
212 {
213 const auto * bypass = bypass_param_rt_;
214 return !bypass->range ().is_toggled (bypass->currentValue ());
215 }
216
217 // ============================================================================
218 // Implementation Interface
219 // ============================================================================
220
221public:
231 virtual void save_state (std::optional<fs::path> abs_state_dir) = 0;
232
238 virtual void load_state (std::optional<fs::path> abs_state_dir) = 0;
239
240private:
241 virtual void prepare_for_processing_impl (
242 units::sample_rate_t sample_rate,
243 nframes_t max_block_length) { };
244
245 virtual void process_impl (EngineProcessTimeInfo time_info) noexcept = 0;
246
247 virtual void release_resources_impl () { }
248
257 [[gnu::hot]] virtual void process_passthrough_impl (
258 EngineProcessTimeInfo time_nfo,
259 const dsp::ITransport &transport) noexcept;
260
261 // ============================================================================
262
269 void init_param_caches ();
270
271protected:
279 ProcessorBaseDependencies dependencies,
280 StateDirectoryParentPathProvider state_path_provider,
281 QObject * parent);
282
287 dsp::ProcessorParameterUuidReference generate_default_bypass_param () const;
288
293 dsp::ProcessorParameterUuidReference generate_default_gain_param () const;
294
295private:
296 static constexpr auto kSettingKey = "setting"sv;
297 static constexpr auto kProgramIndexKey = "programIndex"sv;
298 static constexpr auto kVisibleKey = "visible"sv;
299 friend void to_json (nlohmann::json &j, const Plugin &p)
300 {
301 to_json (j, static_cast<const UuidIdentifiableObject &> (p));
302 to_json (j, static_cast<const dsp::ProcessorBase &> (p));
303 j[kSettingKey] = p.configuration_;
304 j[kProgramIndexKey] = p.program_index_;
305 j[kVisibleKey] = p.visible_;
306 }
307 friend void from_json (const nlohmann::json &j, Plugin &p);
308
309protected:
312 bool instantiation_failed_ = false;
313
319
320 // ============================================================================
321 // DSP Caches
322 // ============================================================================
323
330 std::optional<dsp::ProcessorParameter::Uuid> bypass_id_;
331
335 std::optional<dsp::ProcessorParameter::Uuid> gain_id_;
336
337 /* Realtime caches */
338 std::vector<dsp::AudioPort *> audio_in_ports_;
339 std::vector<dsp::AudioPort *> audio_out_ports_;
340 std::vector<dsp::CVPort *> cv_in_ports_;
341 dsp::MidiPort * midi_in_port_{};
342 dsp::MidiPort * midi_out_port_{};
343 dsp::ProcessorParameter * bypass_param_rt_{};
344
345 // ============================================================================
346
347private:
349 std::unique_ptr<PluginConfiguration> configuration_;
350
354 std::optional<int> program_index_;
355
356 InstantiationStatus instantiation_status_{ InstantiationStatus::Pending };
357
359 bool visible_ = false;
360
364 bool set_configuration_called_{};
365};
366
368class JucePlugin;
369class ClapPlugin;
371
372using PluginVariant = std::variant<JucePlugin, ClapPlugin, InternalPluginBase>;
373using PluginPtrVariant = to_pointer_variant<PluginVariant>;
374
375// TODO: consider having a ProcessorRegistry instead for all
376// ProcessorBase-derived classes
377using PluginRegistry = utils::OwningObjectRegistry<PluginPtrVariant, Plugin>;
378using PluginUuidReference = utils::UuidReference<PluginRegistry>;
379
380using PluginHostWindowFactory =
381 std::function<std::unique_ptr<plugins::IPluginHostWindow> (Plugin &)>;
382
383} // namespace zrythm::plugins
384
385DEFINE_UUID_HASH_SPECIALIZATION (zrythm::plugins::Plugin::Uuid)
386
387void
388from_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:225
Represents a node in a DSP graph.
Definition graph_node.h:129
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:303
std::optional< dsp::ProcessorParameter::Uuid > gain_id_
Zrythm-provided plugin gain parameter.
Definition plugin.h:326
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.
void custom_process_block(EngineProcessTimeInfo time_nfo, const dsp::ITransport &transport) noexcept final
Custom processor logic after processing all owned parameters.
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:196
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
std::optional< dsp::ProcessorParameter::Uuid > bypass_id_
Bypass toggle parameter,.
Definition plugin.h:321
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:309
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