Skip to main content

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