Skip to content

Commit d28f7b5

Browse files
committed
Implement audio ports activation extension
1 parent edff7f4 commit d28f7b5

File tree

1 file changed

+152
-1
lines changed

1 file changed

+152
-1
lines changed

extensions/src/audio_ports_activation.rs

Lines changed: 152 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,39 @@ use clack_common::extensions::*;
22
use clap_sys::ext::audio_ports_activation::{
33
clap_plugin_audio_ports_activation, CLAP_EXT_AUDIO_PORTS_ACTIVATION,
44
};
5+
use std::fmt::Display;
6+
7+
#[repr(u32)]
8+
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
9+
pub enum SampleSize {
10+
Unspecified = 0,
11+
Float32 = 32,
12+
Float64 = 64,
13+
}
14+
15+
impl SampleSize {
16+
pub fn from_raw(raw: u32) -> Option<Self> {
17+
use SampleSize::*;
18+
match raw {
19+
0 => Some(Unspecified),
20+
32 => Some(Float32),
21+
64 => Some(Float64),
22+
_ => None,
23+
}
24+
}
25+
}
26+
27+
impl Display for SampleSize {
28+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29+
let display_str = match self {
30+
Self::Unspecified => "Unspecified",
31+
Self::Float32 => "32-bit",
32+
Self::Float64 => "64-bit",
33+
};
34+
35+
f.write_str(display_str)
36+
}
37+
}
538

639
#[derive(Copy, Clone)]
740
#[allow(dead_code)]
@@ -19,4 +52,122 @@ unsafe impl Extension for PluginAudioPortsActivation {
1952
}
2053
}
2154

22-
// TODO: stub
55+
#[cfg(feature = "clack-host")]
56+
mod host {
57+
use super::*;
58+
use clack_host::extensions::prelude::*;
59+
60+
impl PluginAudioPortsActivation {
61+
#[inline]
62+
pub fn can_activate_while_processing(&self, plugin: &mut PluginMainThreadHandle) -> bool {
63+
match plugin.use_extension(&self.0).can_activate_while_processing {
64+
None => false,
65+
Some(can_activate_while_processing) => {
66+
#[allow(clippy::undocumented_unsafe_blocks)]
67+
unsafe {
68+
can_activate_while_processing(plugin.as_raw())
69+
}
70+
}
71+
}
72+
}
73+
74+
#[inline]
75+
pub fn set_active(
76+
&self,
77+
plugin: &mut PluginSharedHandle,
78+
is_input: bool,
79+
port_index: u32,
80+
is_active: bool,
81+
sample_size: u32,
82+
) -> bool {
83+
match plugin.use_extension(&self.0).set_active {
84+
None => false,
85+
Some(set_active) => {
86+
#[allow(clippy::undocumented_unsafe_blocks)]
87+
unsafe {
88+
set_active(
89+
plugin.as_raw(),
90+
is_input,
91+
port_index,
92+
is_active,
93+
sample_size,
94+
)
95+
}
96+
}
97+
}
98+
}
99+
}
100+
}
101+
102+
#[cfg(feature = "clack-plugin")]
103+
mod plugin {
104+
use super::*;
105+
use clack_plugin::extensions::prelude::*;
106+
107+
pub trait PluginAudioPortsActivationImpl {
108+
fn can_activate_while_processing(&mut self) -> bool;
109+
}
110+
111+
// NOTE: we have this trait split b/c if `PluginAudioPortsActivationImpl::can_activate_while_processing` is true,
112+
// then `set_active` is called from the audio thread (otherwise it is called from the main thread).
113+
pub trait PluginAudioPortsActivationSharedImpl {
114+
fn set_active(
115+
&self,
116+
is_input: bool,
117+
port_index: u32,
118+
is_active: bool,
119+
sample_size: SampleSize,
120+
) -> bool;
121+
}
122+
123+
// SAFETY: The given struct is the CLAP extension struct for the matching side of this extension.
124+
unsafe impl<P: Plugin> ExtensionImplementation<P> for PluginAudioPortsActivation
125+
where
126+
for<'a> P::Shared<'a>: PluginAudioPortsActivationSharedImpl,
127+
for<'a> P::MainThread<'a>: PluginAudioPortsActivationImpl,
128+
{
129+
const IMPLEMENTATION: RawExtensionImplementation =
130+
RawExtensionImplementation::new(&clap_plugin_audio_ports_activation {
131+
can_activate_while_processing: Some(can_activate_while_processing::<P>),
132+
set_active: Some(set_active::<P>),
133+
});
134+
}
135+
136+
#[allow(clippy::missing_safety_doc)]
137+
unsafe extern "C" fn can_activate_while_processing<P: Plugin>(
138+
plugin: *const clap_plugin,
139+
) -> bool
140+
where
141+
for<'a> P::MainThread<'a>: PluginAudioPortsActivationImpl,
142+
{
143+
PluginWrapper::<P>::handle(plugin, |plugin| {
144+
Ok(plugin
145+
.main_thread()
146+
.as_mut()
147+
.can_activate_while_processing())
148+
})
149+
.unwrap_or(false)
150+
}
151+
152+
#[allow(clippy::missing_safety_doc)]
153+
unsafe extern "C" fn set_active<P: Plugin>(
154+
plugin: *const clap_plugin,
155+
is_input: bool,
156+
port_index: u32,
157+
is_active: bool,
158+
sample_size: u32,
159+
) -> bool
160+
where
161+
for<'a> P::Shared<'a>: PluginAudioPortsActivationSharedImpl,
162+
{
163+
let sample_size = SampleSize::from_raw(sample_size).unwrap();
164+
PluginWrapper::<P>::handle(plugin, |plugin| {
165+
Ok(plugin
166+
.shared()
167+
.set_active(is_input, port_index, is_active, sample_size))
168+
})
169+
.unwrap_or(false)
170+
}
171+
}
172+
#[cfg(feature = "clack-plugin")]
173+
pub use plugin::*;

0 commit comments

Comments
 (0)