clack_common/process.rs
1//! Types exposing data and metadata to be used by plugins during audio processing.
2
3use clap_sys::process::*;
4use std::fmt::Debug;
5
6mod constant_mask;
7pub use constant_mask::*;
8
9/// Status returned by a plugin after processing.
10///
11/// This is mainly used as a way for the plugin to tell the host when it can be safely put to sleep.
12///
13/// Note that Clack uses a [`Result`] enum for relaying a failed processing to the host,
14/// unlike the C CLAP API which uses an extra state in enum (`CLAP_PROCESS_ERROR`) to indicate failure.
15#[repr(i32)]
16#[derive(Debug, Copy, Clone, Eq, PartialEq)]
17pub enum ProcessStatus {
18 /// Processing should continue: the plugin has no desire to be put to sleep.
19 Continue = CLAP_PROCESS_CONTINUE,
20 /// Processing should continue, unless all outputs are quiet.
21 ContinueIfNotQuiet = CLAP_PROCESS_CONTINUE_IF_NOT_QUIET,
22 /// The plugin is currently processing its tail (e.g. release, reverb, etc.).
23 ///
24 /// Use the `tail` extension to query the plugin for its current tail length.
25 Tail = CLAP_PROCESS_TAIL,
26 /// No more processing is required until the next event or variation in audio input.
27 Sleep = CLAP_PROCESS_SLEEP,
28}
29
30impl ProcessStatus {
31 /// Gets a [`ProcessStatus`] from the raw, C-FFI compatible value.
32 ///
33 /// In order to match Clack's APIs, this returns `Some(Err(()))` if the value is
34 /// `CLAP_PROCESS_ERROR`.
35 ///
36 /// If the given integer does not match any known CLAP Processing status codes, [`None`] is
37 /// returned.
38 #[inline]
39 pub fn from_raw(raw: clap_process_status) -> Option<Result<Self, ()>> {
40 use ProcessStatus::*;
41
42 match raw {
43 CLAP_PROCESS_CONTINUE => Some(Ok(Continue)),
44 CLAP_PROCESS_CONTINUE_IF_NOT_QUIET => Some(Ok(ContinueIfNotQuiet)),
45 CLAP_PROCESS_SLEEP => Some(Ok(Sleep)),
46 CLAP_PROCESS_TAIL => Some(Ok(Tail)),
47 CLAP_PROCESS_ERROR => Some(Err(())),
48 _ => None,
49 }
50 }
51
52 /// Combines two [`ProcessStatus`]es, returning one that meets the minimum processing requirements
53 /// of both statuses.
54 #[inline]
55 pub fn combined_with(self, other: ProcessStatus) -> ProcessStatus {
56 use ProcessStatus::*;
57
58 match (self, other) {
59 (Continue, _) | (_, Continue) => Continue,
60 (ContinueIfNotQuiet, _) | (_, ContinueIfNotQuiet) => ContinueIfNotQuiet,
61 (Tail, _) | (_, Tail) => Tail,
62 (Sleep, Sleep) => Sleep,
63 }
64 }
65}
66
67/// The audio configuration passed to a plugin's audio processor upon activation.
68///
69/// Those settings are constant throughout the audio processor's lifetime,
70/// i.e. from a plugin's activation until its deactivation.
71#[derive(Copy, Clone, Debug, PartialEq)]
72pub struct PluginAudioConfiguration {
73 /// The audio's sample rate.
74 pub sample_rate: f64,
75 /// The minimum amount of frames that will be processed at once.
76 pub min_frames_count: u32,
77 /// The maximum amount of frames that will be processed at once.
78 pub max_frames_count: u32,
79}
80
81impl PluginAudioConfiguration {
82 /// Validates this [`PluginAudioConfiguration`].
83 ///
84 /// # Panics
85 ///
86 /// This function will panic if either `min_frames_count` or `max_frames_count` is 0, or if
87 /// `min_frames_count` is greater than `max_frames_count`.
88 pub fn validate(&self) {
89 static MIN: &str = "min_frames_count";
90 static MAX: &str = "max_frames_count";
91 static INVALID: &str = "Invalid PluginAudioConfiguration: ";
92 static ZERO: &str = " cannot be 0";
93
94 if self.min_frames_count == 0 {
95 invalid();
96 #[cold]
97 fn invalid() -> ! {
98 panic!("{INVALID}{MIN}{ZERO}");
99 }
100 }
101
102 if self.max_frames_count == 0 {
103 invalid();
104 #[cold]
105 fn invalid() -> ! {
106 panic!("{INVALID}{MAX}{ZERO}");
107 }
108 }
109
110 if self.min_frames_count > self.max_frames_count {
111 invalid(self);
112 #[cold]
113 fn invalid(cfg: &PluginAudioConfiguration) -> ! {
114 panic!(
115 "{INVALID}{MIN} ({}) is greater than {MAX} ({})",
116 cfg.min_frames_count, cfg.max_frames_count
117 );
118 }
119 }
120 }
121}
122
123use clap_sys::audio_buffer::clap_audio_buffer;
124
125/// Processing-related information about an audio port.
126pub struct AudioPortProcessingInfo {
127 channel_count: u32,
128 latency: u32,
129 constant_mask: ConstantMask,
130}
131
132impl AudioPortProcessingInfo {
133 /// Extracts the processing-related information from a raw, C-FFI compatible audio buffer
134 /// descriptor.
135 #[inline]
136 pub fn from_raw(raw: &clap_audio_buffer) -> Self {
137 Self {
138 channel_count: raw.channel_count,
139 latency: raw.latency,
140 constant_mask: ConstantMask::from_bits(raw.constant_mask),
141 }
142 }
143
144 /// Returns the number of audio channels this port provides.
145 #[inline]
146 pub fn channel_count(&self) -> u32 {
147 self.channel_count
148 }
149
150 /// Returns the latency to or from the audio interface, in samples.
151 ///
152 /// Whether this latency is to or from the audio interface depends on which kind of port
153 /// this describes, an output port or an input port respectively
154 #[inline]
155 pub fn latency(&self) -> u32 {
156 self.latency
157 }
158
159 /// Returns the [`ConstantMask`] of this port, hinting which audio channels are constant.
160 #[inline]
161 pub fn constant_mask(&self) -> ConstantMask {
162 self.constant_mask
163 }
164}