Skip to main content

truce_core/
process.rs

1use crate::events::{EventList, TransportInfo};
2
3/// Per-block context handed to `process()`. Construct via
4/// [`Self::new`] + the `with_*` builders. Marked `#[non_exhaustive]`
5/// so adding host-populated fields in future (e.g. `host_latency`,
6/// `bus_routing`) isn't a `SemVer` break for downstream pre-1.0 callers.
7#[non_exhaustive]
8pub struct ProcessContext<'a> {
9    pub transport: &'a TransportInfo,
10    pub sample_rate: f64,
11    pub block_size: usize,
12    pub output_events: &'a mut EventList,
13    params_fn: Option<&'a dyn Fn(u32) -> f64>,
14    meters_fn: Option<&'a dyn Fn(u32, f32)>,
15}
16
17impl<'a> ProcessContext<'a> {
18    pub fn new(
19        transport: &'a TransportInfo,
20        sample_rate: f64,
21        block_size: usize,
22        output_events: &'a mut EventList,
23    ) -> Self {
24        Self {
25            transport,
26            sample_rate,
27            block_size,
28            output_events,
29            params_fn: None,
30            meters_fn: None,
31        }
32    }
33
34    /// Set the parameter lookup callback.
35    #[must_use]
36    pub fn with_params(mut self, f: &'a dyn Fn(u32) -> f64) -> Self {
37        self.params_fn = Some(f);
38        self
39    }
40
41    /// Set the meter reporting callback.
42    #[must_use]
43    pub fn with_meters(mut self, f: &'a dyn Fn(u32, f32)) -> Self {
44        self.meters_fn = Some(f);
45        self
46    }
47
48    /// Read a parameter's plain value by ID.
49    ///
50    /// Returns `None` when no params callback is wired up (e.g. when a
51    /// plugin runs under the bare test driver without a `with_params`
52    /// closure). Callers that always run inside a real format wrapper
53    /// can `.unwrap_or_default()`. Distinguishing "no callback" from
54    /// "value is zero" lets test harnesses notice when they forgot to
55    /// wire up params rather than masking the misconfiguration as
56    /// "host set the value to zero".
57    #[must_use]
58    pub fn param(&self, id: u32) -> Option<f64> {
59        self.params_fn.map(|f| f(id))
60    }
61
62    /// Report a meter value (0.0 to 1.0).
63    pub fn set_meter(&self, id: impl Into<u32>, value: f32) {
64        let id = id.into();
65        if let Some(f) = self.meters_fn {
66            f(id, value);
67        }
68    }
69}
70
71#[derive(Clone, Copy, Debug, PartialEq)]
72pub enum ProcessStatus {
73    /// Plugin produced meaningful output.
74    Normal,
75    /// Plugin is producing tail. Value = remaining tail samples.
76    Tail(u32),
77    /// Keep alive even if input is silent.
78    KeepAlive,
79}