Patch

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::*, log::*};

#[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,
        events: &mut ProcEvents,
        _logger: &mut RealtimeLogger,
    ) -> ProcessStatus {
        // Synchronize `params` from the event list.
        for patch in events.drain_patches::<MyParams>() {
            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,
        events: &mut ProcEvents,
        _logger: &mut RealtimeLogger,
    ) -> ProcessStatus {
        for mut patch in events.drain_patches::<MyParams>() {
            // 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();

for event in event_list.drain() {
    match event {
        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 drain_patches.

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

let mut filter_params = FilterParams::default();
for patch in event_list.drain_patches::<FilterParams>() { 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 Option<EventInstant>

Source§

type Patch = Option<EventInstant>

Source§

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

Source§

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

Source§

impl Patch for Option<Volume>

Source§

type Patch = Option<Volume>

Source§

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

Source§

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

Source§

impl Patch for Option<bool>

Source§

type Patch = Option<bool>

Source§

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

Source§

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

Source§

impl Patch for Option<f32>

Source§

type Patch = Option<f32>

Source§

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

Source§

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

Source§

impl Patch for Option<f64>

Source§

type Patch = Option<f64>

Source§

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

Source§

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

Source§

impl Patch for Option<i8>

Source§

type Patch = Option<i8>

Source§

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

Source§

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

Source§

impl Patch for Option<i16>

Source§

type Patch = Option<i16>

Source§

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

Source§

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

Source§

impl Patch for Option<i32>

Source§

type Patch = Option<i32>

Source§

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

Source§

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

Source§

impl Patch for Option<i64>

Source§

type Patch = Option<i64>

Source§

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

Source§

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

Source§

impl Patch for Option<u8>

Source§

type Patch = Option<u8>

Source§

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

Source§

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

Source§

impl Patch for Option<u16>

Source§

type Patch = Option<u16>

Source§

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

Source§

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

Source§

impl Patch for Option<u32>

Source§

type Patch = Option<u32>

Source§

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

Source§

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

Source§

impl Patch for Option<u64>

Source§

type Patch = Option<u64>

Source§

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

Source§

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

Source§

impl Patch for Option<DurationMusical>

Source§

type Patch = Option<DurationMusical>

Source§

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

Source§

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

Source§

impl Patch for Option<DurationSamples>

Source§

type Patch = Option<DurationSamples>

Source§

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

Source§

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

Source§

impl Patch for Option<DurationSeconds>

Source§

type Patch = Option<DurationSeconds>

Source§

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

Source§

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

Source§

impl Patch for Option<InstantMusical>

Source§

type Patch = Option<InstantMusical>

Source§

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

Source§

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

Source§

impl Patch for Option<InstantSamples>

Source§

type Patch = Option<InstantSamples>

Source§

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

Source§

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

Source§

impl Patch for Option<InstantSeconds>

Source§

type Patch = Option<InstantSeconds>

Source§

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

Source§

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

Source§

impl Patch for Option<Vec2>

Source§

type Patch = Option<Vec2>

Source§

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

Source§

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

Source§

impl Patch for Option<Vec3>

Source§

type Patch = Option<Vec3>

Source§

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

Source§

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

Source§

impl Patch for Option<Vec2>

Source§

type Patch = Option<Vec2>

Source§

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

Source§

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

Source§

impl Patch for Option<Vec3>

Source§

type Patch = Option<Vec3>

Source§

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

Source§

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

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 Patch for Vec2

Source§

type Patch = Vec2

Source§

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

Source§

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

Source§

impl Patch for Vec3

Source§

type Patch = Vec3

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 + RealtimeClone + 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 EventInstant

Source§

impl Patch for DistanceModel

Source§

impl Patch for PanLaw

Source§

impl Patch for Volume

Source§

impl Patch for DurationMusical

Source§

impl Patch for DurationSamples

Source§

impl Patch for DurationSeconds

Source§

impl Patch for InstantMusical

Source§

impl Patch for InstantSamples

Source§

impl Patch for InstantSeconds

Source§

impl Patch for DistanceAttenuation

Source§

impl Patch for firewheel_core::vector::Vec2

Source§

impl Patch for firewheel_core::vector::Vec3

Source§

impl Patch for Notify<Volume>

Source§

impl Patch for Notify<bool>

Source§

impl Patch for Notify<f32>

Source§

impl Patch for Notify<f64>

Source§

impl Patch for Notify<i8>

Source§

impl Patch for Notify<i16>

Source§

impl Patch for Notify<i32>

Source§

impl Patch for Notify<i64>

Source§

impl Patch for Notify<u8>

Source§

impl Patch for Notify<u16>

Source§

impl Patch for Notify<u32>

Source§

impl Patch for Notify<u64>

Source§

impl Patch for Notify<()>

Source§

impl Patch for Notify<DurationMusical>

Source§

impl Patch for Notify<DurationSamples>

Source§

impl Patch for Notify<DurationSeconds>

Source§

impl Patch for Notify<InstantMusical>

Source§

impl Patch for Notify<InstantSamples>

Source§

impl Patch for Notify<InstantSeconds>

Source§

impl Patch for Notify<Vec2>

Source§

impl Patch for Notify<Vec3>

Source§

impl Patch for Notify<Vec2>

Source§

impl Patch for Notify<Vec3>

Source§

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

Source§

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