Skip to main content

sim_lib_plugin_lv2/
adapter.rs

1use sim_kernel::Result;
2use sim_lib_audio_dsp::Gain;
3use sim_lib_audio_graph_core::{PrepareConfig, ProcessBlock, Processor};
4use sim_lib_plugin_core::{
5    HostedPluginProcessor, PluginDescriptor, PluginInstance, PluginState, ProcessorPlugin,
6};
7
8use crate::lv2_gain_descriptor;
9
10/// Graph [`Processor`] that drives an LV2-shaped plugin instance.
11///
12/// Wraps the shared `HostedPluginProcessor` from `sim-lib-plugin-core` so that
13/// any `PluginInstance` (such as an [`Lv2ExportedProcessor`]) participates in
14/// the audio graph through the standard [`Processor`] contract.
15#[derive(Clone, Debug)]
16pub struct Lv2HostProcessor<I> {
17    hosted: HostedPluginProcessor<I>,
18}
19
20impl<I> Lv2HostProcessor<I> {
21    /// Hosts `instance` as a graph processor.
22    pub fn new(instance: I) -> Self {
23        Self {
24            hosted: HostedPluginProcessor::new(instance),
25        }
26    }
27
28    /// Returns a shared reference to the hosted plugin instance.
29    pub fn instance(&self) -> &I {
30        self.hosted.instance()
31    }
32
33    /// Returns a mutable reference to the hosted plugin instance.
34    pub fn instance_mut(&mut self) -> &mut I {
35        self.hosted.instance_mut()
36    }
37}
38
39impl<I: PluginInstance> Processor for Lv2HostProcessor<I> {
40    fn prepare(&mut self, cfg: PrepareConfig) {
41        self.hosted.prepare(cfg);
42    }
43
44    fn reset(&mut self) {
45        self.hosted.reset();
46    }
47
48    fn process(&mut self, block: &mut ProcessBlock<'_>) {
49        self.hosted.process(block);
50    }
51
52    fn tail_frames(&self) -> u64 {
53        self.hosted.tail_frames()
54    }
55}
56
57impl<I: PluginInstance> PluginInstance for Lv2HostProcessor<I> {
58    fn descriptor(&self) -> &PluginDescriptor {
59        self.hosted.instance().descriptor()
60    }
61
62    fn state(&self) -> PluginState {
63        self.hosted.instance().state()
64    }
65
66    fn set_state(&mut self, state: PluginState) {
67        self.hosted.instance_mut().set_state(state);
68    }
69
70    fn prepare(&mut self, cfg: PrepareConfig) {
71        self.hosted.prepare(cfg);
72    }
73
74    fn reset(&mut self) {
75        self.hosted.reset();
76    }
77
78    fn process(&mut self, block: &mut ProcessBlock<'_>) {
79        self.hosted.process(block);
80    }
81
82    fn take_last_error(&mut self) -> Option<String> {
83        self.hosted.instance_mut().take_last_error()
84    }
85}
86
87/// A SIM graph [`Processor`] presented as an LV2-shaped [`PluginInstance`].
88///
89/// Wraps the shared `ProcessorPlugin` from `sim-lib-plugin-core`, pairing a
90/// [`PluginDescriptor`] with the inner processor so a native SIM processor can
91/// be exported and hosted as if it were an LV2 plugin.
92#[derive(Clone, Debug)]
93pub struct Lv2ExportedProcessor<P> {
94    inner: ProcessorPlugin<P>,
95}
96
97impl<P> Lv2ExportedProcessor<P> {
98    /// Pairs `processor` with `descriptor` to form an exported plugin instance.
99    pub fn new(descriptor: PluginDescriptor, processor: P) -> Self {
100        Self {
101            inner: ProcessorPlugin::new(descriptor, processor),
102        }
103    }
104}
105
106sim_lib_plugin_core::forward_plugin_instance!(Lv2ExportedProcessor);
107
108/// Exports `processor` as an LV2-shaped plugin instance under `descriptor`.
109pub fn export_processor_as_lv2<P: Processor>(
110    descriptor: PluginDescriptor,
111    processor: P,
112) -> Lv2ExportedProcessor<P> {
113    Lv2ExportedProcessor::new(descriptor, processor)
114}
115
116/// Exports the built-in gain processor as an LV2-shaped plugin instance.
117///
118/// `gain` is the linear gain multiplier; the instance carries the standard
119/// [`lv2_gain_descriptor`](crate::lv2_gain_descriptor) metadata.
120pub fn export_gain_as_lv2(gain: f32) -> Result<Lv2ExportedProcessor<Gain>> {
121    Ok(export_processor_as_lv2(
122        lv2_gain_descriptor()?,
123        Gain::new(gain),
124    ))
125}