Trait Patch

Source
pub trait Patch {
    type Patch;

    // Required methods
    fn patch(data: &ParamData, path: &[u32]) -> Result<Self::Patch, PatchError>;
    fn apply(&mut self, patch: Self::Patch);

    // Provided method
    fn patch_event(event: &NodeEventType) -> Option<Self::Patch> { ... }
}
Expand description

Fine-grained parameter patching.

This trait allows a type to perform patching on itself, applying changes generated from another instance.

For more information, see the module docs.

§Examples

Like with Diff, the typical Patch usage is simple.

use firewheel_core::{diff::Patch, event::*, node::*};

#[derive(Patch)]
struct MyParams {
    a: f32,
    b: f32,
}

struct MyProcessor {
    params: MyParams,
}

impl AudioNodeProcessor for MyProcessor {
    fn process(
        &mut self,
        buffers: ProcBuffers,
        proc_info: &ProcInfo,
        mut events: NodeEventList,
    ) -> ProcessStatus {
        // Synchronize `params` from the event list.
        events.for_each_patch::<MyParams>(|patch| self.params.apply(patch));

        // ...

        ProcessStatus::outputs_not_silent()
    }
}

If you need fine access to each patch, you can match on the patch type.

impl AudioNodeProcessor for MyProcessor {
    fn process(
        &mut self,
        buffers: ProcBuffers,
        proc_info: &ProcInfo,
        mut events: NodeEventList,
    ) -> ProcessStatus {
        events.for_each_patch::<MyParams>(|mut patch| {
            // When you derive `Patch`, it creates an enum with variants
            // for each field.
            match &mut patch {
                MyParamsPatch::A(a) => {
                    // You can mutate the patch itself if you want
                    // to constrain or modify values.
                    *a = a.clamp(0.0, 1.0);
                }
                MyParamsPatch::B(b) => {}
            }

            // And / or apply it directly.
            self.params.apply(patch);
        });

        // ...

        ProcessStatus::outputs_not_silent()
    }
}

§Manual implementation

Like with Diff, types like parameters should prefer the Patch derive macro. Nonetheless, Firewheel provides a few tools to make manual implementations straightforward.

use firewheel_core::{diff::{Patch, PatchError}, event::ParamData};

struct MyParams {
    a: f32,
    b: bool,
}

// To follow the derive macro convention, create an
// enum with variants for each field.
enum MyParamsPatch {
    A(f32),
    B(bool),
}

impl Patch for MyParams {
    type Patch = MyParamsPatch;

    fn patch(data: &ParamData, path: &[u32]) -> Result<Self::Patch, PatchError> {
        match path {
            [0] => {
                // Types that exist in `ParamData`'s variants can use
                // `try_into`.
                let a = data.try_into()?;
                Ok(MyParamsPatch::A(a))
            }
            [1] => {
                let b = data.try_into()?;
                Ok(MyParamsPatch::B(b))
            }
            _ => Err(PatchError::InvalidPath)
        }
    }

    fn apply(&mut self, patch: Self::Patch) {
        match patch {
            MyParamsPatch::A(a) => self.a = a,
            MyParamsPatch::B(b) => self.b = b,
        }
    }
}

Required Associated Types§

Source

type Patch

A type’s patch.

This is a value that enumerates all the ways a type can be changed. For leaf types (values that represent the smallest diffable unit) like f32, this is just the type itself. For aggregate types like structs, this should be an enum over each field.

struct FilterParams {
    frequency: f32,
    quality: f32,
}

enum FilterParamsPatch {
    Frequency(f32),
    Quality(f32),
}

This type is converted from NodeEventType::Param in the patch method.

Required Methods§

Source

fn patch(data: &ParamData, path: &[u32]) -> Result<Self::Patch, PatchError>

Construct a patch from a parameter event.

This converts the intermediate representation in NodeEventType::Param into a concrete value, making it easy to manipulate the event in audio processors.

#[derive(Patch, Default)]
struct FilterParams {
    frequency: f32,
    quality: f32,
}

let mut filter_params = FilterParams::default();

event_list.for_each(|e| {
    match e {
        NodeEventType::Param { data, path } => {
            let Ok(patch) = FilterParams::patch(data, path) else {
                return;
            };

            // You can match on the patch directly
            match &patch {
                FilterParamsPatch::Frequency(f) => {
                    // Handle frequency event...
                }
                FilterParamsPatch::Quality(q) => {
                    // Handle quality event...
                }
            }

            // And/or apply it.
            filter_params.apply(patch);
        }
        _ => {}
    }
});
Source

fn apply(&mut self, patch: Self::Patch)

Apply a patch.

This will generally be called from within the audio thread, so real-time constraints should be respected.

Typically, you’ll call this within for_each_patch.

#[derive(Patch, Default)]
struct FilterParams {
    frequency: f32,
    quality: f32,
}

let mut filter_params = FilterParams::default();
event_list.for_each_patch::<FilterParams>(|patch| filter_params.apply(patch));

Provided Methods§

Source

fn patch_event(event: &NodeEventType) -> Option<Self::Patch>

Construct a patch from a node event.

This is a convenience wrapper around patch, discarding errors and node events besides NodeEventType::Param.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementations on Foreign Types§

Source§

impl Patch for bool

Source§

type Patch = bool

Source§

fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError>

Source§

fn apply(&mut self, value: Self::Patch)

Source§

impl Patch for f32

Source§

type Patch = f32

Source§

fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError>

Source§

fn apply(&mut self, value: Self::Patch)

Source§

impl Patch for f64

Source§

type Patch = f64

Source§

fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError>

Source§

fn apply(&mut self, value: Self::Patch)

Source§

impl Patch for i8

Source§

type Patch = i8

Source§

fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError>

Source§

fn apply(&mut self, value: Self::Patch)

Source§

impl Patch for i16

Source§

type Patch = i16

Source§

fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError>

Source§

fn apply(&mut self, value: Self::Patch)

Source§

impl Patch for i32

Source§

type Patch = i32

Source§

fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError>

Source§

fn apply(&mut self, value: Self::Patch)

Source§

impl Patch for i64

Source§

type Patch = i64

Source§

fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError>

Source§

fn apply(&mut self, value: Self::Patch)

Source§

impl Patch for u8

Source§

type Patch = u8

Source§

fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError>

Source§

fn apply(&mut self, value: Self::Patch)

Source§

impl Patch for u16

Source§

type Patch = u16

Source§

fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError>

Source§

fn apply(&mut self, value: Self::Patch)

Source§

impl Patch for u32

Source§

type Patch = u32

Source§

fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError>

Source§

fn apply(&mut self, value: Self::Patch)

Source§

impl Patch for u64

Source§

type Patch = u64

Source§

fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError>

Source§

fn apply(&mut self, value: Self::Patch)

Source§

impl<A: Patch> Patch for (A,)

Source§

type Patch = Tuple1<A>

Source§

fn patch(data: &ParamData, path: &[u32]) -> Result<Self::Patch, PatchError>

Source§

fn apply(&mut self, patch: Self::Patch)

Source§

impl<A: Patch, B: Patch> Patch for (A, B)

Source§

type Patch = Tuple2<A, B>

Source§

fn patch(data: &ParamData, path: &[u32]) -> Result<Self::Patch, PatchError>

Source§

fn apply(&mut self, patch: Self::Patch)

Source§

impl<A: Patch, B: Patch, C: Patch> Patch for (A, B, C)

Source§

type Patch = Tuple3<A, B, C>

Source§

fn patch(data: &ParamData, path: &[u32]) -> Result<Self::Patch, PatchError>

Source§

fn apply(&mut self, patch: Self::Patch)

Source§

impl<A: Patch, B: Patch, C: Patch, D: Patch> Patch for (A, B, C, D)

Source§

type Patch = Tuple4<A, B, C, D>

Source§

fn patch(data: &ParamData, path: &[u32]) -> Result<Self::Patch, PatchError>

Source§

fn apply(&mut self, patch: Self::Patch)

Source§

impl<A: Patch, B: Patch, C: Patch, D: Patch, E: Patch> Patch for (A, B, C, D, E)

Source§

type Patch = Tuple5<A, B, C, D, E>

Source§

fn patch(data: &ParamData, path: &[u32]) -> Result<Self::Patch, PatchError>

Source§

fn apply(&mut self, patch: Self::Patch)

Source§

impl<A: Patch, B: Patch, C: Patch, D: Patch, E: Patch, F: Patch> Patch for (A, B, C, D, E, F)

Source§

type Patch = Tuple6<A, B, C, D, E, F>

Source§

fn patch(data: &ParamData, path: &[u32]) -> Result<Self::Patch, PatchError>

Source§

fn apply(&mut self, patch: Self::Patch)

Source§

impl<A: Patch, B: Patch, C: Patch, D: Patch, E: Patch, F: Patch, G: Patch> Patch for (A, B, C, D, E, F, G)

Source§

type Patch = Tuple7<A, B, C, D, E, F, G>

Source§

fn patch(data: &ParamData, path: &[u32]) -> Result<Self::Patch, PatchError>

Source§

fn apply(&mut self, patch: Self::Patch)

Source§

impl<A: Patch, B: Patch, C: Patch, D: Patch, E: Patch, F: Patch, G: Patch, H: Patch> Patch for (A, B, C, D, E, F, G, H)

Source§

type Patch = Tuple8<A, B, C, D, E, F, G, H>

Source§

fn patch(data: &ParamData, path: &[u32]) -> Result<Self::Patch, PatchError>

Source§

fn apply(&mut self, patch: Self::Patch)

Source§

impl<T: Send + Sync + Clone + PartialEq + 'static> Patch for Option<T>

Source§

type Patch = Option<T>

Source§

fn patch(data: &ParamData, _: &[u32]) -> Result<Self::Patch, PatchError>

Source§

fn apply(&mut self, patch: Self::Patch)

Source§

impl<T: Patch> Patch for [T]

Source§

type Patch = (usize, <T as Patch>::Patch)

Source§

fn patch(data: &ParamData, path: &[u32]) -> Result<Self::Patch, PatchError>

Source§

fn apply(&mut self, patch: Self::Patch)

Source§

impl<T: Patch> Patch for Box<[T]>

Source§

type Patch = (usize, <T as Patch>::Patch)

Source§

fn patch(data: &ParamData, path: &[u32]) -> Result<Self::Patch, PatchError>

Source§

fn apply(&mut self, patch: Self::Patch)

Source§

impl<T: Patch> Patch for Vec<T>

Source§

type Patch = (usize, <T as Patch>::Patch)

Source§

fn patch(data: &ParamData, path: &[u32]) -> Result<Self::Patch, PatchError>

Source§

fn apply(&mut self, patch: Self::Patch)

Source§

impl<T: Patch, const LEN: usize> Patch for [T; LEN]

Source§

type Patch = (usize, <T as Patch>::Patch)

Source§

fn patch(data: &ParamData, path: &[u32]) -> Result<Self::Patch, PatchError>

Source§

fn apply(&mut self, patch: Self::Patch)

Implementors§

Source§

impl Patch for PanLaw

Source§

impl Patch for Volume

Source§

impl Patch for Vec2

Source§

impl Patch for Vec3

Source§

impl<A: ?Sized + Send + Sync + 'static> Patch for ArcGc<A>

Source§

impl<T: Clone + Send + Sync + 'static> Patch for Notify<T>