truce_loader/
static_shell.rs1use std::sync::Arc;
7
8use truce_core::buffer::AudioBuffer;
9use truce_core::bus::BusLayout;
10use truce_core::editor::Editor;
11use truce_core::events::{EventBody, EventList};
12use truce_core::info::PluginInfo;
13use truce_core::meters::MeterStore;
14use truce_core::plugin::PluginRuntime;
15use truce_core::process::{ProcessContext, ProcessStatus};
16use truce_core::state::{ForeignState, MigratedState, StateLoadError};
17use truce_params::Params;
18use truce_params::sample::Sample;
19use truce_plugin::PluginLogicCore;
20
21pub struct StaticShell<P: Params, L: PluginLogicCore<S>, S: Sample = f32> {
31 pub params: Arc<P>,
32 logic: L,
33 meters: Arc<MeterStore>,
34 sample_rate: f64,
35 _sample: std::marker::PhantomData<fn() -> S>,
36}
37
38unsafe impl<P: Params, L: PluginLogicCore<S>, S: Sample> Send for StaticShell<P, L, S> {}
48
49impl<P: Params + Default + 'static, L: PluginLogicCore<S> + 'static, S: Sample>
50 StaticShell<P, L, S>
51{
52 pub fn from_parts(params: Arc<P>, logic: L) -> Self {
55 Self {
56 params,
57 logic,
58 meters: MeterStore::new(),
59 sample_rate: 44100.0,
60 _sample: std::marker::PhantomData,
61 }
62 }
63
64 pub fn meter_store(&self) -> Arc<MeterStore> {
67 Arc::clone(&self.meters)
68 }
69
70 pub fn logic_ref(&self) -> &L {
72 &self.logic
73 }
74
75 pub fn logic_ref_mut(&mut self) -> &mut L {
77 &mut self.logic
78 }
79}
80
81impl<P: Params + Default + 'static, L: PluginLogicCore<S> + 'static, S: Sample> PluginRuntime
82 for StaticShell<P, L, S>
83{
84 type Sample = S;
85
86 fn info() -> PluginInfo
87 where
88 Self: Sized,
89 {
90 unreachable!("StaticShell::info() should not be called statically")
91 }
92
93 fn bus_layouts() -> Vec<BusLayout>
94 where
95 Self: Sized,
96 {
97 unreachable!("StaticShell::bus_layouts() should not be called statically")
98 }
99
100 fn init(&mut self) {}
101
102 fn reset(&mut self, sample_rate: f64, max_block_size: usize) {
103 self.sample_rate = sample_rate;
104 self.params.set_sample_rate(sample_rate);
105 self.logic.reset(sample_rate, max_block_size);
106 }
107
108 fn process(
109 &mut self,
110 buffer: &mut AudioBuffer<S>,
111 events: &EventList,
112 context: &mut ProcessContext,
113 ) -> ProcessStatus {
114 for e in events.iter() {
118 if let EventBody::ParamChange { id, value } = &e.body {
119 self.params.set_plain(*id, *value);
120 }
121 }
122
123 let params = &self.params;
127 let meters = &self.meters;
128 let param_fn = |id: u32| -> f64 { params.get_plain(id).unwrap_or(0.0) };
129 let meter_fn = |id: u32, v: f32| meters.write(id, v);
130 let mut ctx = ProcessContext::new(
131 context.transport,
132 context.sample_rate,
133 buffer.num_samples(),
134 &mut *context.output_events,
135 )
136 .with_params(¶m_fn)
137 .with_meters(&meter_fn);
138
139 self.logic.process(buffer, events, &mut ctx)
140 }
141
142 fn save_state(&self) -> Vec<u8> {
143 self.logic.save_state()
144 }
145
146 fn load_state(&mut self, data: &[u8]) -> Result<(), StateLoadError> {
147 let result = self.logic.load_state(data);
148 PluginLogicCore::state_changed(&mut self.logic);
153 result
154 }
155
156 fn migrate_state(foreign: &ForeignState) -> Option<MigratedState>
157 where
158 Self: Sized,
159 {
160 <L as PluginLogicCore<S>>::migrate_state(foreign)
161 }
162
163 fn editor(&mut self) -> Option<Box<dyn Editor>> {
164 Some(PluginLogicCore::editor(&self.logic))
165 }
166
167 fn latency(&self) -> u32 {
168 self.logic.latency()
169 }
170 fn tail(&self) -> u32 {
171 self.logic.tail()
172 }
173
174 fn get_meter(&self, meter_id: u32) -> f32 {
175 self.meters.read(meter_id)
176 }
177}
178
179#[macro_export]
202macro_rules! export_static {
203 (
204 params: $params:ty,
205 info: $info:expr,
206 logic: $logic:ty,
207 ) => {
208 pub struct __HotShellWrapper {
209 inner: $crate::static_shell::StaticShell<$params, $logic, Sample>,
216 }
217
218 impl $crate::__macro_deps::truce_core::plugin::PluginRuntime for __HotShellWrapper {
219 type Sample = Sample;
220
221 fn supports_in_place() -> bool
222 where
223 Self: Sized,
224 {
225 <$logic as $crate::__macro_deps::truce_plugin::PluginLogicCore<Sample>>::supports_in_place()
234 }
235
236 fn info() -> $crate::__macro_deps::truce_core::info::PluginInfo
237 where
238 Self: Sized,
239 {
240 $info
241 }
242
243 fn bus_layouts() -> Vec<$crate::__macro_deps::truce_core::bus::BusLayout>
244 where
245 Self: Sized,
246 {
247 <$logic as $crate::__macro_deps::truce_plugin::PluginLogicCore<Sample>>::bus_layouts()
248 }
249
250 fn init(&mut self) {
251 self.inner.init();
252 }
253
254 fn reset(&mut self, sample_rate: f64, max_block_size: usize) {
255 self.inner.reset(sample_rate, max_block_size);
256 }
257
258 fn process(
259 &mut self,
260 buffer: &mut $crate::__macro_deps::truce_core::buffer::AudioBuffer<Sample>,
261 events: &$crate::__macro_deps::truce_core::events::EventList,
262 context: &mut $crate::__macro_deps::truce_core::process::ProcessContext,
263 ) -> $crate::__macro_deps::truce_core::process::ProcessStatus {
264 self.inner.process(buffer, events, context)
265 }
266
267 fn save_state(&self) -> Vec<u8> {
268 self.inner.save_state()
269 }
270
271 fn load_state(
272 &mut self,
273 data: &[u8],
274 ) -> Result<(), $crate::__macro_deps::truce_core::state::StateLoadError> {
275 self.inner.load_state(data)
276 }
277
278 fn migrate_state(
279 foreign: &$crate::__macro_deps::truce_core::state::ForeignState,
280 ) -> Option<$crate::__macro_deps::truce_core::state::MigratedState>
281 where
282 Self: Sized,
283 {
284 <$logic as $crate::__macro_deps::truce_plugin::PluginLogicCore<Sample>>::migrate_state(foreign)
285 }
286
287 fn editor(
288 &mut self,
289 ) -> Option<Box<dyn $crate::__macro_deps::truce_core::editor::Editor>> {
290 self.inner.editor()
291 }
292
293 fn latency(&self) -> u32 {
294 self.inner.latency()
295 }
296 fn tail(&self) -> u32 {
297 self.inner.tail()
298 }
299 fn get_meter(&self, meter_id: u32) -> f32 {
300 self.inner.get_meter(meter_id)
301 }
302 }
303
304 impl $crate::__macro_deps::truce_core::export::PluginExport for __HotShellWrapper {
305 type Params = $params;
306
307 fn create() -> Self {
308 let params = std::sync::Arc::new(<$params>::new());
309 let logic = <$logic>::new(std::sync::Arc::clone(¶ms));
310 Self {
311 inner: $crate::static_shell::StaticShell::from_parts(params, logic),
312 }
313 }
314
315 fn params(&self) -> &$params {
316 &self.inner.params
317 }
318
319 fn params_arc(&self) -> std::sync::Arc<$params> {
320 std::sync::Arc::clone(&self.inner.params)
321 }
322
323 fn meter_store(
324 &self,
325 ) -> std::sync::Arc<$crate::__macro_deps::truce_core::meters::MeterStore> {
326 self.inner.meter_store()
327 }
328 }
329 };
330}