vapoursynth4_rs/node/
filter.rs

1use std::{
2    ffi::{CStr, c_void},
3    ptr::null_mut,
4};
5
6use crate::{
7    core::CoreRef,
8    ffi,
9    frame::{Frame, FrameContext},
10    map::MapRef,
11    node::FilterMode,
12};
13
14pub trait Filter
15where
16    Self: Sized + std::panic::RefUnwindSafe,
17{
18    const FILTER_MODE: FilterMode = FilterMode::Parallel;
19    /// Filter error that can turned into a [`&CStr`](std::ffi::CStr)
20    type Error: AsRef<CStr>;
21    type FrameType: Frame;
22    type FilterData; // TODO: Ensure Send + Sync when FILTER_MODE is Parallel
23
24    const NAME: &'static CStr;
25    const ARGS: &'static CStr;
26    const RETURN_TYPE: &'static CStr;
27
28    /// # Errors
29    ///
30    /// Return [`Self::Error`] if anything happens during the filter creation.
31    /// The error message will be passed to `VapourSynth`.
32    fn create(
33        input: MapRef,
34        output: MapRef,
35        data: Option<Box<Self::FilterData>>,
36        core: CoreRef,
37    ) -> Result<(), Self::Error>;
38
39    /// # Errors
40    ///
41    /// Return [`Self::Error`] if anything happens during the filter creation.
42    /// The error message will be passed to `VapourSynth`.
43    fn get_frame(
44        &self,
45        n: i32,
46        activation_reason: ffi::VSActivationReason,
47        frame_data: *mut *mut c_void,
48        frame_ctx: FrameContext,
49        core: CoreRef,
50    ) -> Result<Option<Self::FrameType>, Self::Error>;
51    /// Free the filter
52    fn free(self, core: CoreRef) {
53        let _ = core;
54    }
55}
56
57pub struct FilterRegister<F: Filter> {
58    data: Option<F::FilterData>,
59}
60
61impl<F: Filter> FilterRegister<F> {
62    pub fn new(data: Option<F::FilterData>) -> Self {
63        Self { data }
64    }
65
66    /// # Safety
67    pub unsafe fn register(self, plugin: *mut ffi::VSPlugin, vspapi: *const ffi::VSPLUGINAPI) {
68        use super::internal::FilterExtern;
69
70        unsafe {
71            ((*vspapi).registerFunction)(
72                F::NAME.as_ptr(),
73                F::ARGS.as_ptr(),
74                F::RETURN_TYPE.as_ptr(),
75                F::filter_create,
76                self.data
77                    .map_or(null_mut(), |d| Box::into_raw(Box::new(d)).cast()),
78                plugin,
79            )
80        };
81    }
82}
83
84pub type ActivationReason = ffi::VSActivationReason;