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
83/// A SIM graph [`Processor`] presented as an LV2-shaped [`PluginInstance`].
84///
85/// Wraps the shared `ProcessorPlugin` from `sim-lib-plugin-core`, pairing a
86/// [`PluginDescriptor`] with the inner processor so a native SIM processor can
87/// be exported and hosted as if it were an LV2 plugin.
88#[derive(Clone, Debug)]
89pub struct Lv2ExportedProcessor<P> {
90    inner: ProcessorPlugin<P>,
91}
92
93impl<P> Lv2ExportedProcessor<P> {
94    /// Pairs `processor` with `descriptor` to form an exported plugin instance.
95    pub fn new(descriptor: PluginDescriptor, processor: P) -> Self {
96        Self {
97            inner: ProcessorPlugin::new(descriptor, processor),
98        }
99    }
100}
101
102sim_lib_plugin_core::forward_plugin_instance!(Lv2ExportedProcessor);
103
104/// Exports `processor` as an LV2-shaped plugin instance under `descriptor`.
105pub fn export_processor_as_lv2<P: Processor>(
106    descriptor: PluginDescriptor,
107    processor: P,
108) -> Lv2ExportedProcessor<P> {
109    Lv2ExportedProcessor::new(descriptor, processor)
110}
111
112/// Exports the built-in gain processor as an LV2-shaped plugin instance.
113///
114/// `gain` is the linear gain multiplier; the instance carries the standard
115/// [`lv2_gain_descriptor`](crate::lv2_gain_descriptor) metadata.
116pub fn export_gain_as_lv2(gain: f32) -> Result<Lv2ExportedProcessor<Gain>> {
117    Ok(export_processor_as_lv2(
118        lv2_gain_descriptor()?,
119        Gain::new(gain),
120    ))
121}