frei0r_rs/lib.rs
1#![allow(clippy::too_many_arguments)]
2
3//! Rust binding for the implementation of fri0r plugin API <https://frei0r.dyne.org/>.
4//!
5//! See example for API usage.
6
7#[doc(hidden)]
8pub mod ffi;
9
10use std::ffi::CStr;
11use std::ffi::CString;
12
13/// Color parameter.
14///
15/// All components are in the range [0, 1].
16#[derive(Debug, Clone, Copy)]
17pub struct Color {
18 /// Red component.
19 pub r : f32,
20 /// Green component.
21 pub g : f32,
22 /// Blue component.
23 pub b : f32,
24}
25
26/// Position parameter.
27///
28/// All coordinates are in the range [0, 1].
29#[derive(Debug, Clone, Copy)]
30pub struct Position {
31 pub x : f64,
32 pub y : f64,
33}
34
35/// Type of a parameter.
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37pub enum ParamKind {
38 Bool,
39 Double,
40 Color,
41 Position,
42 String,
43}
44
45/// Information of a parameter.
46#[derive(Debug, Clone, Copy)]
47pub struct ParamInfo {
48 pub name : &'static CStr,
49 pub kind : ParamKind,
50 pub explanation : &'static CStr,
51}
52
53/// Reference to a parameter.
54#[derive(Debug, Clone, Copy)]
55pub enum ParamRef<'a> {
56 Bool(&'a bool),
57 Double(&'a f64),
58 Color(&'a Color),
59 Position(&'a Position),
60 String(&'a CString),
61}
62
63/// Mutable reference to a parameter.
64#[derive(Debug)]
65pub enum ParamMut<'a> {
66 Bool(&'a mut bool),
67 Double(&'a mut f64),
68 Color(&'a mut Color),
69 Position(&'a mut Position),
70 String(&'a mut CString),
71}
72
73/// Base trait of [Plugin] which is responsible for setting/getting of plugin parameters.
74///
75/// **AVOID** implementing it directly. Use the derive macro [PluginBase](frei0r_macros::PluginBase) instead.
76///
77/// # Safety
78///
79/// Implementers must verify that the parameter type returned by [PluginBase::param_info],
80/// [PluginBase::param_ref] and [PluginBase::param_mut] agrees with each other.
81pub unsafe trait PluginBase {
82 fn param_count() -> usize;
83 fn param_info(index : usize) -> ParamInfo;
84
85 fn param_ref(&self, param_index : usize) -> ParamRef<'_>;
86 fn param_mut(&mut self, param_index : usize) -> ParamMut<'_>;
87}
88
89/// Type of the plugin.
90///
91/// These defines determine whether the plugin is a source, a filter or one of the two mixer types.
92#[derive(Debug, Clone, Copy, PartialEq, Eq)]
93pub enum PluginType {
94 /// One input and one output
95 Filter,
96 /// Just one output
97 Source,
98 /// Two inputs and one output
99 Mixer2,
100 /// Three inputs and one output
101 Mixer3,
102}
103
104/// List of supported color models.
105///
106/// Note: the color models are endian independent, because the color components are defined by
107/// their positon in memory, not by their significance in an uint32_t value.
108///
109/// For effects that work on the color components, RGBA8888 is the recommended color model for
110/// frei0r-1.2 effects. For effects that only work on pixels, PACKED32 is the recommended color
111/// model since it helps the application to avoid unnecessary color conversions.
112///
113/// Effects can choose an appropriate color model, applications must support all color models and
114/// do conversions if necessary. Source effects must not use the PACKED32 color model because the
115/// application must know in which color model the created framebuffers are represented.
116///
117/// For each color model, a frame consists of width*height pixels which are stored row-wise and
118/// consecutively in memory. The size of a pixel is
119/// 4 bytes. There is no extra pitch parameter (i.e. the pitch is simply width*4).
120///
121/// The following additional constraints must be honored: - The top-most line of a frame is stored
122/// first in memory. - A frame must be aligned to a 16 byte border in memory. - The width and
123/// height of a frame must be positive - The width and height of a frame must be integer multiples
124/// of 8
125///
126/// These constraints make sure that each line is stored at an address aligned to 16 byte.
127#[derive(Debug, Clone, Copy, PartialEq, Eq)]
128pub enum ColorModel {
129 /// In BGRA8888, each pixel is represented by 4 consecutive unsigned bytes, where the first
130 /// byte value represents the blue, the second the green, and the third the red color component
131 /// of the pixel. The last value represents the alpha value.
132 BGRA8888,
133
134 /// In RGBA8888, each pixel is represented by 4 consecutive unsigned bytes, where the first
135 /// byte value represents the red, the second the green, and the third the blue color component
136 /// of the pixel. The last value represents the alpha value.
137 RGBA8888,
138
139 /// In PACKED32, each pixel is represented by 4 consecutive bytes, but it is not defined how
140 /// the color componets are stored. The true color format could be RGBA8888, BGRA8888, a packed
141 /// 32 bit YUV format, or any other color format that stores pixels in 32 bit.
142 ///
143 /// This is useful for effects that don't work on color but only on pixels (for example a
144 /// mirror effect).
145 ///
146 /// Note that source effects must not use this color model.
147 PACKED32,
148}
149
150/// The type returned by the plugin to tell the application about its name, type, number of
151/// parameters, and version.
152#[derive(Debug, Clone, Copy)]
153pub struct PluginInfo {
154 /// The (short) name of the plugin
155 pub name : &'static CStr,
156 /// The plugin author
157 pub author : &'static CStr,
158 /// The plugin type
159 pub plugin_type : PluginType,
160 /// The color model used
161 pub color_model : ColorModel,
162 /// The major version of the plugin
163 pub major_version : i32,
164 /// The minor version of the plugin
165 pub minor_version : i32,
166 /// An optional explanation string
167 pub explanation : &'static CStr,
168}
169
170/// The plugin type.
171pub trait Plugin: PluginBase {
172 /// Called by the application to query plugin information.
173 fn info() -> PluginInfo;
174
175 /// Constructor for effect instances.
176 ///
177 /// The resolution must be an integer multiple of 8, must be greater than 0 and be at most 2048
178 /// in both dimensions.
179 ///
180 /// The plugin must set default values for all parameters in this function.
181 fn new(width : usize, height : usize) -> Self;
182
183 /// This is where the core effect processing happens. The application calls it after it has
184 /// set the necessary parameter values.
185 ///
186 /// The function is responsible to restore the fpu state (e.g. rounding mode) and mmx state if
187 /// applicable before it returns to the caller.
188 ///
189 /// This is never called for effect of type [PluginType::Mixer2] and [PluginType::Mixer3].
190 fn update(&self, time : f64, width : usize, height : usize, inframe : &[u32], outframe : &mut [u32]);
191
192 /// For effect of type [PluginType::Mixer2] and [PluginType::Mixer3].
193 fn update2(&self, time : f64, width : usize, height : usize, inframe1 : &[u32], inframe2 : &[u32], inframe3 : &[u32], outframe : &mut [u32]);
194}
195
196pub use frei0r_macros::PluginBase;
197
198/// Helper trait used in the implmenetation of derive macro [PluginBase](frei0r_macros::PluginBase). **DO NOT** use directly.
199///
200/// # Safety
201///
202/// Implementers must verify that the parameter type returned by [Param::kind], [Param::as_ref] and
203/// [Param::as_mut] agrees with each other.
204pub unsafe trait Param {
205 fn kind() -> ParamKind;
206 fn as_ref(&self) -> ParamRef<'_>;
207 fn as_mut(&mut self) -> ParamMut<'_>;
208}
209
210unsafe impl Param for bool {
211 fn kind() -> ParamKind { ParamKind::Bool }
212 fn as_ref(&self) -> ParamRef<'_> { ParamRef::Bool(self) }
213 fn as_mut(&mut self) -> ParamMut<'_> { ParamMut::Bool(self) }
214}
215
216unsafe impl Param for f64 {
217 fn kind() -> ParamKind { ParamKind::Double }
218 fn as_ref(&self) -> ParamRef<'_> { ParamRef::Double(self) }
219 fn as_mut(&mut self) -> ParamMut<'_> { ParamMut::Double(self) }
220}
221
222unsafe impl Param for Color {
223 fn kind() -> ParamKind { ParamKind::Color }
224 fn as_ref(&self) -> ParamRef<'_> { ParamRef::Color(self) }
225 fn as_mut(&mut self) -> ParamMut<'_> { ParamMut::Color(self) }
226}
227
228unsafe impl Param for Position {
229 fn kind() -> ParamKind { ParamKind::Position }
230 fn as_ref(&self) -> ParamRef<'_> { ParamRef::Position(self) }
231 fn as_mut(&mut self) -> ParamMut<'_> { ParamMut::Position(self) }
232}
233
234unsafe impl Param for CString {
235 fn kind() -> ParamKind { ParamKind::String }
236 fn as_ref(&self) -> ParamRef<'_> { ParamRef::String(self) }
237 fn as_mut(&mut self) -> ParamMut<'_> { ParamMut::String(self) }
238}
239
240/// Export necessary C bindings for frei0r plugin.
241#[macro_export]
242macro_rules! plugin {
243 ($type:ty) => {
244 use frei0r_rs::ffi;
245
246 #[no_mangle] pub unsafe extern "C" fn f0r_init() -> ffi::c_int { ffi::f0r_init() }
247 #[no_mangle] pub unsafe extern "C" fn f0r_deinit() { ffi::f0r_deinit() }
248 #[no_mangle] pub unsafe extern "C" fn f0r_get_plugin_info(info: *mut ffi::f0r_plugin_info_t) { ffi::f0r_get_plugin_info::<$type>(info) }
249 #[no_mangle] pub unsafe extern "C" fn f0r_get_param_info(info: *mut ffi::f0r_param_info_t, param_index: ffi::c_int) { ffi::f0r_get_param_info::<$type>(info, param_index) }
250 #[no_mangle] pub unsafe extern "C" fn f0r_construct(width : ffi::c_uint, height: ffi::c_uint) -> ffi::f0r_instance_t { ffi::f0r_construct::<$type>(width, height) }
251 #[no_mangle] pub unsafe extern "C" fn f0r_destruct(instance : ffi::f0r_instance_t) { ffi::f0r_destruct::<$type>(instance) }
252 #[no_mangle] pub unsafe extern "C" fn f0r_set_param_value(instance: ffi::f0r_instance_t, param: ffi::f0r_param_t, param_index: ffi::c_int) { ffi::f0r_set_param_value::<$type>(instance, param, param_index) }
253 #[no_mangle] pub unsafe extern "C" fn f0r_get_param_value(instance: ffi::f0r_instance_t, param: ffi::f0r_param_t, param_index: ffi::c_int) { ffi::f0r_get_param_value::<$type>(instance, param, param_index) }
254 #[no_mangle] pub unsafe extern "C" fn f0r_update(instance: ffi::f0r_instance_t, time: f64, inframe: *const u32, outframe: *mut u32) { ffi::f0r_update::<$type>(instance, time, inframe, outframe) }
255 #[no_mangle] pub unsafe extern "C" fn f0r_update2(instance: ffi::f0r_instance_t, time: f64, inframe1: *const u32, inframe2: *const u32, inframe3: *const u32, outframe: *mut u32) { ffi::f0r_update2::<$type>(instance, time, inframe1, inframe2, inframe3, outframe) }
256 }
257}
258