vapoursynth4_rs/
plugin.rs

1pub mod plugin_function;
2pub mod types;
3
4use std::{borrow::Borrow, ffi::CStr, ptr::NonNull};
5
6use crate::{api::Api, core::Core, ffi, map::Map};
7
8pub use plugin_function::*;
9pub use types::*;
10
11#[derive(PartialEq, Eq, Hash, Debug)]
12pub struct Plugin {
13    handle: NonNull<ffi::VSPlugin>,
14    api: Api,
15}
16
17impl Plugin {
18    #[must_use]
19    pub fn new(handle: NonNull<ffi::VSPlugin>, api: Api) -> Self {
20        Self { handle, api }
21    }
22
23    #[must_use]
24    pub fn as_ptr(&self) -> *const ffi::VSPlugin {
25        self.handle.as_ptr()
26    }
27
28    #[must_use]
29    pub fn name(&self) -> &CStr {
30        unsafe {
31            let ptr = (self.api.getPluginName)(self.as_ptr().cast_mut());
32            CStr::from_ptr(ptr)
33        }
34    }
35
36    #[must_use]
37    pub fn id(&self) -> &CStr {
38        unsafe {
39            let ptr = (self.api.getPluginID)(self.as_ptr().cast_mut());
40            CStr::from_ptr(ptr)
41        }
42    }
43
44    #[must_use]
45    pub fn namespace(&self) -> &CStr {
46        unsafe {
47            let ptr = (self.api.getPluginNamespace)(self.as_ptr().cast_mut());
48            CStr::from_ptr(ptr)
49        }
50    }
51
52    #[must_use]
53    pub fn invoke(&self, name: &CStr, args: impl Borrow<Map>) -> Map {
54        unsafe {
55            let ptr = (self.api.invoke)(
56                self.as_ptr().cast_mut(),
57                name.as_ptr(),
58                args.borrow().as_ptr(),
59            );
60            Map::from_ptr(ptr, self.api)
61        }
62    }
63
64    #[must_use]
65    pub fn functions(&self) -> Functions<'_> {
66        Functions::new(self)
67    }
68
69    #[must_use]
70    pub fn get_function_by_name(&self, name: &CStr) -> Option<PluginFunction> {
71        unsafe {
72            NonNull::new((self.api.getPluginFunctionByName)(
73                name.as_ptr(),
74                self.as_ptr().cast_mut(),
75            ))
76        }
77        .map(|handle| PluginFunction::from_ptr(handle, self.api))
78    }
79
80    #[must_use]
81    pub fn path(&self) -> &CStr {
82        unsafe {
83            let ptr = (self.api.getPluginPath)(self.as_ptr().cast_mut());
84            CStr::from_ptr(ptr)
85        }
86    }
87
88    #[must_use]
89    pub fn version(&self) -> i32 {
90        unsafe { (self.api.getPluginVersion)(self.as_ptr().cast_mut()) }
91    }
92}
93
94#[derive(Clone, PartialEq, Eq, Hash, Debug)]
95pub struct Plugins<'c> {
96    cursor: *mut ffi::VSPlugin,
97    core: &'c Core,
98}
99
100impl<'c> Plugins<'c> {
101    pub(crate) fn new(core: &'c Core) -> Plugins<'c> {
102        Self {
103            cursor: std::ptr::null_mut(),
104            core,
105        }
106    }
107}
108
109impl Iterator for Plugins<'_> {
110    type Item = Plugin;
111
112    fn next(&mut self) -> Option<Self::Item> {
113        unsafe {
114            let api = self.core.api();
115            let ptr = (api.getNextPlugin)(self.cursor, self.core.as_ptr());
116            NonNull::new(ptr).map(|p| {
117                self.cursor = ptr;
118                Plugin::new(p, api)
119            })
120        }
121    }
122}
123
124#[macro_export]
125macro_rules! declare_plugin {
126    ($id:literal, $name:literal, $desc:literal,
127        $version:expr,
128        $api_version:expr, $flags:expr
129        $(, ($filter:tt, $data:expr) )*
130    ) => {
131        #[unsafe(no_mangle)]
132        pub unsafe extern "system-unwind" fn VapourSynthPluginInit2(
133            plugin: *mut $crate::ffi::VSPlugin,
134            vspapi: *const $crate::ffi::VSPLUGINAPI,
135        ) {
136            unsafe {
137                ((*vspapi).configPlugin)(
138                    $id.as_ptr(),
139                    $name.as_ptr(),
140                    $desc.as_ptr(),
141                    $crate::utils::make_version($version.0, $version.1),
142                    $crate::VAPOURSYNTH_API_VERSION,
143                    $flags,
144                    plugin,
145                );
146
147                $(
148                    $crate::node::FilterRegister::<$filter>::new($data).register(plugin, vspapi);
149                )*
150            }
151        }
152    };
153}