Skip to main content

clack_plugin/
plugin.rs

1//! Core types and traits to implement a Clack plugin.
2//!
3//! The [`PluginAudioProcessor`] trait is the main one required to be implemented for a Clack plugin. It
4//! can also be associated to two more types, implementing [`PluginMainThread`] and [`PluginShared`],
5//! following the CLAP thread model, as described below.
6//!
7//! # Thread model
8//!
9//! CLAP's thread model for plugins is split into three classes of operations: those happening in an
10//! audio processing thread, those happening in the main thread, and thread-safe operations:
11//!
12//! * The *audio thread* (`[audio-thread]` in the CLAP specification): this is represented by a type
13//!   implementing the main [`PluginAudioProcessor`] trait (also named the audio processor), which is [`Send`] but
14//!   [`!Sync`](Sync), and is the only one required to implement a Clack plugin.
15//!
16//!   This type handles all DSP in one of the host's audio threads, of which there may be
17//!   multiple, if the host uses a thread pool for example.
18//!
19//!   The host is free to [`Send`] the [`PluginAudioProcessor`] type between any of its audio threads, but any
20//!   operation of this class is guaranteed to be exclusive (`&mut`) to a single audio thread.
21//!
22//!   One exception is for CLAP plugins' activation and deactivation (represented in Clack by the
23//!   plugin type's construction and destruction), which is guaranteed to happen in the Main Thread
24//!   instead. This allows the plugin's [`activate`](PluginAudioProcessor::activate) and
25//!   [`deactivate`](PluginAudioProcessor::deactivate) methods to receive temporary exclusive references to the
26//!   main thread type during its construction and destruction.
27//!
28//! * The *main thread* (`[main-thread]` in the CLAP specification): this is represented by a type
29//!   implementing the [`PluginMainThread`] trait, which is neither [`Send`] nor [`Sync`]. If
30//!   main-thread operations are not needed by a plugin implementation, `()` can be used instead.
31//!
32//!   This type can handle all non-thread-safe operations, such as those related to GUI handling,
33//!   however extensions can extend its use to more kinds of operations.
34//!
35//!   The host cannot [`Send`] this type to any other threads, and this type has to be constructed
36//!   before any other operation is done on the plugin.
37//!
38//! * *Thread-safe operations* (`[thread-safe]` in the CLAP specification) are represented by a type
39//!   implementing the [`PluginShared`] trait, which is both [`Send`] and [`Sync`], and will be
40//!   shared between the main thread and the audio thread. If it isn't needed , `()` can be used
41//!   instead.
42//!
43//!   It can be used to hold read-only data (such as all the detected host extensions), or to
44//!   hold any other kind of synchronized state.
45//!
46//!   However, it should be noted that this type *can* be used by the host simultaneously from
47//!   threads that are neither the main thread nor the audio thread.
48
49use crate::extensions::PluginExtensions;
50use crate::host::HostAudioProcessorHandle;
51use crate::process::{Audio, Events, PluginAudioConfiguration, Process, ProcessStatus};
52
53mod error;
54mod instance;
55pub(crate) mod logging;
56
57pub use error::PluginError;
58pub use instance::*;
59
60pub use clack_common::plugin::*;
61
62/// The part of the data and operations of a plugin that are thread-safe.
63///
64/// The associated lifetime `'a` represents the lifetime of the plugin itself, as well as the
65/// lifetime of the data exposed by the host.
66///
67/// This type requires to be both [`Send`] and [`Sync`]: it can be used simultaneously by multiple
68/// threads, including (but not limited to) the main thread and the audio thread.
69///
70/// See the [module documentation](crate::plugin) for more information on the thread model.
71pub trait PluginShared<'a>: Sized + Send + Sync + 'a {}
72
73impl PluginShared<'_> for () {}
74
75/// The part of the data and operation of a plugin that must be on the main thread.
76///
77/// The associated lifetime `'a` represents the lifetime of the plugin itself, as well as the
78/// lifetime of the data exposed by the host.
79///
80/// This type requires neither [`Send`] nor [`Sync`]: it is guaranteed to stay on the main thread
81/// at all times.
82///
83/// See the [module documentation](crate::plugin) for more information on the thread model.
84pub trait PluginMainThread<'a, S: PluginShared<'a>>: Sized + 'a {
85    /// This is called by the host on the main thread, in response to a previous call to
86    /// [`HostSharedHandle::request_callback`](crate::host::HostSharedHandle::request_callback).
87    ///
88    /// The default implementation of this method does nothing.
89    #[inline]
90    fn on_main_thread(&self) {}
91}
92
93impl<'a, S: PluginShared<'a>> PluginMainThread<'a, S> for () {}
94
95/// The main trait required to implement a CLAP plugin.
96///
97/// Types implementing this trait are never instantiated and are not meant to contain any data.
98///
99/// Their purpose is to tie together the various subtypes that will be instantiated and live across
100/// different threads.
101///
102/// # Plugin instantiation
103///
104/// Plugin instantiation and initialization is not covered by this trait. The [`Shared`] and
105/// [`MainThread`] components are created from a [`PluginFactory`] implementation
106/// (in [`PluginFactory::create_plugin`]) using the [`PluginInstance::new`] method.
107///
108/// Alternatively, if custom [`PluginFactory`] and [`Entry`] implementations are not needed, one
109/// can use a [`SinglePluginEntry`] and implement its companion trait [`DefaultPluginFactory`]
110/// to implement the instantiation instead.
111///
112/// [`Shared`]: Self::Shared
113/// [`MainThread`]: Self::MainThread
114/// [`PluginFactory`]: crate::factory::plugin::PluginFactoryImpl
115/// [`PluginFactory::create_plugin`]: crate::factory::plugin::PluginFactoryImpl::create_plugin
116/// [`Entry`]: crate::entry::Entry
117/// [`SinglePluginEntry`]: crate::entry::SinglePluginEntry
118/// [`DefaultPluginFactory`]: crate::entry::DefaultPluginFactory
119pub trait Plugin: 'static {
120    /// The type holding the plugin's data and operations that belong to the audio thread.
121    ///
122    /// See the [module documentation](crate::plugin) for more information on the thread model.
123    type AudioProcessor<'a>: PluginAudioProcessor<'a, Self::Shared<'a>, Self::MainThread<'a>>;
124
125    /// The type holding the plugin's thread-safe data and operations.
126    ///
127    /// If not needed, the empty `()` type can be used instead.
128    ///
129    /// See the [module documentation](crate::plugin) for more information on the thread model.
130    type Shared<'a>: PluginShared<'a>;
131
132    /// The type holding the plugin's data and operations that belong to the main thread.
133    ///
134    /// If not needed, the empty `()` type can be used instead.
135    ///
136    /// See the [module documentation](crate::plugin) for more information on the thread model.
137    type MainThread<'a>: PluginMainThread<'a, Self::Shared<'a>>;
138
139    /// Declares the extensions this plugin supports.
140    ///
141    /// This is implemented by calling [`register`] on the given [`PluginExtensions`]
142    /// builder for every extension type that is supported.
143    ///
144    /// A reference to the [`Shared`](Self::Shared) type is also given. However, it can be `None`,
145    /// as the host is allowed to query extensions before the plugin has finished initializing.
146    ///
147    /// [`register`]: PluginExtensions::register
148    #[inline]
149    #[allow(unused_variables)]
150    fn declare_extensions(builder: &mut PluginExtensions<Self>, shared: Option<&Self::Shared<'_>>) {
151    }
152}
153
154/// The audio processor and main part of a plugin.
155///
156/// This type implements all DSP-related operations, most notably [`process`](PluginAudioProcessor::process),
157/// which processes all input and output audio and events.
158///
159/// The associated lifetime `'a` represents the lifetime of the plugin itself, as well as the
160/// lifetime of the data exposed by the host.
161///
162/// This type requires to be [`Send`] but not [`Sync`]: it can be sent between any of the host's
163/// threads, but none of its operations will be performed on multiple threads simultaneously.
164///
165/// The audio processor can also define two associated types, [`Shared`](Plugin::Shared) and
166/// [`MainThread`](Plugin::MainThread), allowing to execute operations in and hold data belonging
167/// to other threads. If they are not needed, the empty `()` type can be used instead, for convenience.
168///
169/// See the [module documentation](crate::plugin) for more information on the thread model.
170pub trait PluginAudioProcessor<'a, S: PluginShared<'a>, M: PluginMainThread<'a, S>>:
171    Sized + Send + 'a
172{
173    /// Creates and activates the audio processor.
174    ///
175    /// This method serves as a constructor for the audio processor, in which it can perform
176    /// non-realtime-safe initialization operations, such as allocating audio buffers using the
177    /// provided [`PluginAudioConfiguration`].
178    ///
179    /// This method is always executed on the main thread, allowing it to temporarily access main
180    /// thread data.
181    ///
182    /// # Arguments
183    ///
184    /// * `host`: an exclusive host handle that can be stored for the lifetime of the plugin.
185    /// * `main_thread`: a temporary exclusive reference to the plugin's main thread data.
186    /// * `shared`: a reference to the plugin's shared data, that can be stored for the lifetime of the plugin.
187    /// * `audio_config`: the [`PluginAudioConfiguration`], valid throughout the audio processor's lifetime.
188    ///
189    /// # Errors
190    ///
191    /// This operation may fail for any reason, in which case `Err` is returned
192    /// and the plugin is not activated.
193    ///
194    /// # Realtime Safety
195    ///
196    /// This method is not realtime-safe: it may perform memory allocations of audio buffers, or any
197    /// other initialization the plugin may deem necessary.
198    fn activate(
199        host: HostAudioProcessorHandle<'a>,
200        main_thread: &M,
201        shared: &'a S,
202        audio_config: PluginAudioConfiguration,
203    ) -> Result<Self, PluginError>;
204
205    /// Processes a chunk of audio samples and events.
206    ///
207    /// This method returns a [`ProcessStatus`] as a hint towards whether the host can set this
208    /// plugin to sleep, or if the plugin wants to process more audio or events.
209    /// This is only a hint however, and the host is free to ignore it.
210    ///
211    /// # Arguments
212    ///
213    /// * `process` contains metadata about the current process call, including transport information and a steady sample counter.
214    /// * `audio` contains references to all the audio buffers for this block.
215    /// * `events` contains both the [`InputEvents`](crate::prelude::InputEvents) list and the [`OutputEvents`](crate::prelude::OutputEvents) queue.
216    ///
217    /// # Realtime Safety
218    ///
219    /// This method *MUST* be realtime-safe, and is in fact the most performance-sensitive part
220    /// of the whole plugin implementation.
221    ///
222    /// # Errors
223    ///
224    /// This method may fail for any reason, depending on the plugin's implementation.
225    fn process(
226        &mut self,
227        process: Process,
228        audio: Audio,
229        events: Events,
230    ) -> Result<ProcessStatus, PluginError>;
231
232    /// Deactivates the audio processor.
233    ///
234    /// This method can serve as a destructor for the audio processor.
235    ///
236    /// This method is always executed on the main thread, allowing it to temporarily access main
237    /// thread data.
238    ///
239    /// # Arguments
240    ///
241    /// * `main_thread`: a temporary exclusive reference to the plugin's main thread data.
242    ///
243    /// # Realtime Safety
244    ///
245    /// This method is not realtime-safe: it may perform memory de-allocations of audio buffers, or
246    /// any other un-initialization the plugin may deem necessary.
247    #[allow(unused)]
248    #[inline]
249    fn deactivate(self, main_thread: &M) {}
250
251    /// Resets the plugin's audio processing state.
252    ///
253    /// This clears all the plugin's internal buffers, kills all voices, and resets all processing
254    /// state such as envelopes, LFOs, oscillators, filters, etc.
255    ///
256    /// Calling this method allows the `steady_time` parameter passed to [`process`](Self::process)
257    /// to jump backwards.
258    #[allow(unused)]
259    #[inline]
260    fn reset(&mut self) {}
261
262    /// Starts the plugin's continuous audio processing.
263    ///
264    /// This is called when the plugin needs to wake up from sleep, or after it was [activated](Self::activate).
265    ///
266    /// # Errors
267    ///
268    /// This method may fail for any reason, depending on the plugin's implementation.
269    #[inline]
270    fn start_processing(&mut self) -> Result<(), PluginError> {
271        Ok(())
272    }
273
274    /// Stops the plugin's continuous audio processing, indicating it is being sent to sleep.
275    ///
276    /// When this is called, the plugin's audio processor cannot assume that the next block of audio
277    /// and events it receives (if any) is contiguous to the last one it [processed](Self::process).
278    #[inline]
279    fn stop_processing(&mut self) {}
280}
281
282impl<'a, M: PluginMainThread<'a, S>, S: PluginShared<'a>> PluginAudioProcessor<'a, S, M> for () {
283    #[inline]
284    fn activate(
285        _host: HostAudioProcessorHandle<'a>,
286        _main_thread: &M,
287        _shared: &'a S,
288        _audio_config: PluginAudioConfiguration,
289    ) -> Result<Self, PluginError> {
290        Ok(())
291    }
292
293    #[inline]
294    fn process(
295        &mut self,
296        _process: Process,
297        _audio: Audio,
298        _events: Events,
299    ) -> Result<ProcessStatus, PluginError> {
300        Ok(ProcessStatus::Sleep)
301    }
302}