macro_rules! ae_acquire_suite_ptr {
($pica:expr, $type:ident, $name:ident, $version:ident) => {{
unsafe {
let mut suite_ptr = std::mem::MaybeUninit::<*const after_effects_sys::$type>::uninit();
let aquire_suite_func = (*($pica)).AcquireSuite.unwrap_or_else(|| unreachable!());
match aquire_suite_func(
after_effects_sys::$name.as_ptr() as *const i8,
after_effects_sys::$version as i32,
suite_ptr.as_mut_ptr() as *mut *const _ as _,
) as u32
{
after_effects_sys::kSPNoError => Ok(suite_ptr.assume_init()),
_ => {
log::error!("Suite not found: {} {} {}", stringify!($type), stringify!($name), stringify!($version));
Err($crate::Error::MissingSuite)
},
}
}
}};
}
macro_rules! ae_release_suite_ptr {
($pica:expr, $name:ident, $version:ident) => {{
unsafe {
let release_suite_func = (*($pica)).ReleaseSuite.unwrap_or_else(|| unreachable!());
release_suite_func(
after_effects_sys::$name.as_ptr() as *const i8,
after_effects_sys::$version as i32,
);
}
}};
}
macro_rules! ae_get_suite_fn {
($suite_ptr:expr, $function:ident ) => {{
(*($suite_ptr)).$function.unwrap_or_else(|| unreachable!())
}};
}
macro_rules! call_suite_fn {
($self:expr, $function:ident, $($arg:tt)* ) => {{
let err = unsafe { ae_get_suite_fn!(($self.suite_ptr), $function)($($arg)*) };
match err {
0 => Ok(()),
_ => Err(Error::from(err))
}
}};
}
macro_rules! call_suite_fn_single {
($self:expr, $function:ident -> $typ:ty, $($arg:tt)* ) => {{
let mut val: $typ = unsafe { std::mem::zeroed() };
let err = unsafe { ae_get_suite_fn!($self.suite_ptr, $function)($($arg)*, &mut val) };
match err {
0 => Ok(val),
_ => Err(Error::from(err))
}
}};
($self:expr, $function:ident -> $typ:ty) => {{
let mut val: $typ = unsafe { std::mem::zeroed() };
let err = unsafe { ae_get_suite_fn!($self.suite_ptr, $function)(&mut val) };
match err {
0 => Ok(val),
_ => Err(Error::from(err))
}
}};
}
macro_rules! call_suite_fn_double {
($self:expr, $function:ident -> $typ1:ty, $typ2:ty, $($arg:tt)* ) => {{
let mut v1: $typ1 = unsafe { std::mem::zeroed() };
let mut v2: $typ2 = unsafe { std::mem::zeroed() };
let err = unsafe { ae_get_suite_fn!($self.suite_ptr, $function)($($arg)*, &mut v1, &mut v2) };
match err {
0 => Ok((v1, v2)),
_ => Err(Error::from(err))
}
}};
($self:expr, $function:ident -> $typ1:ty, $typ2:ty) => {{
let mut v1: $typ1 = unsafe { std::mem::zeroed() };
let mut v2: $typ2 = unsafe { std::mem::zeroed() };
let err = unsafe { ae_get_suite_fn!($self.suite_ptr, $function)(&mut v1, &mut v2) };
match err {
0 => Ok((v1, v2)),
_ => Err(Error::from(err))
}
}};
}
macro_rules! call_suite_fn_no_err {
($self:expr, $function:ident, $($arg:tt)* ) => {{
unsafe {
ae_get_suite_fn!(($self.suite_ptr), $function)($($arg)*)
}
}};
}
macro_rules! register_handle {
($data_type:ident) => {
impl AsPtr<after_effects_sys::$data_type> for after_effects_sys::$data_type {
fn as_ptr(&self) -> after_effects_sys::$data_type {
*self
}
}
};
}
macro_rules! define_handle_wrapper {
($wrapper_pretty_name:ident, $data_type:ident) => {
#[derive(Copy, Clone, Debug, Hash)]
pub struct $wrapper_pretty_name(pub(crate) after_effects_sys::$data_type);
impl $wrapper_pretty_name {
pub fn from_raw(raw_handle: after_effects_sys::$data_type) -> Self {
Self(raw_handle)
}
pub fn is_null(&self) -> bool {
self.0.is_null()
}
}
impl From<$wrapper_pretty_name> for after_effects_sys::$data_type {
fn from(handle_wrapper: $wrapper_pretty_name) -> Self {
handle_wrapper.as_ptr()
}
}
impl AsRef<after_effects_sys::$data_type> for $wrapper_pretty_name {
fn as_ref(&self) -> &after_effects_sys::$data_type {
&self.0
}
}
impl AsPtr<after_effects_sys::$data_type> for $wrapper_pretty_name {
fn as_ptr(&self) -> after_effects_sys::$data_type {
self.0
}
}
impl AsPtr<after_effects_sys::$data_type> for &$wrapper_pretty_name {
fn as_ptr(&self) -> after_effects_sys::$data_type {
self.0
}
}
};
}
macro_rules! define_struct_wrapper {
($wrapper_pretty_name:ident, $data_type:ident) => {
#[derive(Copy, Clone)]
pub struct $wrapper_pretty_name(*mut after_effects_sys::$data_type);
impl $wrapper_pretty_name {
pub fn from_raw(ae_struct: *mut after_effects_sys::$data_type) -> Self {
assert!(!ae_struct.is_null());
Self(ae_struct)
}
}
impl AsRef<after_effects_sys::$data_type> for $wrapper_pretty_name {
fn as_ref(&self) -> &after_effects_sys::$data_type {
unsafe { &*self.0 }
}
}
impl AsMut<after_effects_sys::$data_type> for $wrapper_pretty_name {
fn as_mut(&mut self) -> &mut after_effects_sys::$data_type {
unsafe { &mut *self.0 }
}
}
impl AsPtr<*mut after_effects_sys::$data_type> for $wrapper_pretty_name {
fn as_ptr(&self) -> *mut after_effects_sys::$data_type {
self.0
}
}
impl AsPtr<*mut after_effects_sys::$data_type> for &$wrapper_pretty_name {
fn as_ptr(&self) -> *mut after_effects_sys::$data_type {
self.0
}
}
};
}
macro_rules! define_owned_handle_wrapper {
($wrapper_pretty_name:ident, $data_type:ident) => {
#[derive(Debug, Hash)]
pub struct $wrapper_pretty_name(after_effects_sys::$data_type, bool);
impl $wrapper_pretty_name {
pub fn from_raw(raw_handle: after_effects_sys::$data_type) -> Self {
Self(raw_handle, false)
}
pub fn from_raw_owned(raw_handle: after_effects_sys::$data_type) -> Self {
Self(raw_handle, true)
}
pub fn as_ptr(&self) -> after_effects_sys::$data_type {
self.0
}
pub fn set_owned(&mut self, is_owned: bool) {
self.1 = is_owned;
}
pub fn is_owned(&self) -> bool {
self.1
}
}
impl From<$wrapper_pretty_name> for after_effects_sys::$data_type {
fn from(handle_wrapper: $wrapper_pretty_name) -> Self {
handle_wrapper.as_ptr()
}
}
impl AsRef<after_effects_sys::$data_type> for $wrapper_pretty_name {
fn as_ref(&self) -> &after_effects_sys::$data_type {
&self.0
}
}
impl AsPtr<after_effects_sys::$data_type> for $wrapper_pretty_name {
fn as_ptr(&self) -> after_effects_sys::$data_type {
self.0
}
}
impl AsPtr<after_effects_sys::$data_type> for &$wrapper_pretty_name {
fn as_ptr(&self) -> after_effects_sys::$data_type {
self.0
}
}
};
}
macro_rules! define_param_wrapper {
($sys_enum:ident, $sys_type:ident, $sys_field:ident, $param_enum:path, $(#[$attr:meta])* $name:ident {
$($field_name:ident: $field_type:ty, )*
},
$(impl $impl_name:tt: $impl_type:tt, )*
$(fn init($self_name:ident) $init_fn:block)? ) => {
$(#[$attr])*
pub struct $name<'parent> {
pub(crate) def: Ownership<'parent, ae_sys::$sys_type>,
pub(crate) _parent_ptr: Option<*const ae_sys::PF_ParamDef>,
pub(crate) _in_data: *const ae_sys::PF_InData,
$($field_name: $field_type, )*
}
impl<'parent> $name<'parent> {
pub fn new() -> Self {
#[allow(unused_mut)]
let mut param = Self {
def: Ownership::Rust(unsafe { std::mem::zeroed() }),
_in_data: std::ptr::null(),
_parent_ptr: None,
$($field_name: Default::default(), )*
};
$( let $self_name = &mut param; $init_fn; )?
param
}
pub fn setup<F: FnOnce(&mut Self)>(cb: F) -> Self {
let mut ret = Self::new();
cb(&mut ret);
ret
}
pub fn from_mut(def: &'parent mut ae_sys::$sys_type, in_data: *const ae_sys::PF_InData, parent_ptr: *const ae_sys::PF_ParamDef) -> Self {
Self {
def: Ownership::AfterEffectsMut(def),
_parent_ptr: Some(parent_ptr),
_in_data: in_data,
$($field_name: Default::default(), )*
}
}
pub fn from_ref(def: &'parent ae_sys::$sys_type, in_data: *const ae_sys::PF_InData, parent_ptr: *const ae_sys::PF_ParamDef) -> Self {
Self {
def: Ownership::AfterEffects(def),
_parent_ptr: Some(parent_ptr),
_in_data: in_data,
$($field_name: Default::default(), )*
}
}
pub fn from_owned(def: ae_sys::$sys_type) -> Self {
Self {
def: Ownership::Rust(def),
_parent_ptr: None,
_in_data: std::ptr::null(),
$($field_name: Default::default(), )*
}
}
pub fn set_value_changed(&mut self) {
if let Some(parent_ptr) = self._parent_ptr {
let parent_ptr = parent_ptr as *mut ae_sys::PF_ParamDef;
let parent = unsafe { &mut *parent_ptr };
if (parent.ui_flags & (ae_sys::PF_PUI_STD_CONTROL_ONLY as ae_sys::PF_ParamUIFlags)) == 0 {
parent.uu.change_flags = ChangeFlag::CHANGED_VALUE.bits();
}
}
}
$(
define_param_wrapper!(impl $impl_type, $impl_name);
)*
}
impl<'p> Into<Param<'p>> for $name<'p> {
fn into(self) -> Param<'p> {
$param_enum(self)
}
}
};
(impl String, $name:ident) => {
paste::item! {
pub fn [<set_ $name>](&mut self, v: &str) -> &mut Self {
self.$name = CString::new(v).unwrap();
{ self.def.u.namesptr = self.$name.as_ptr(); }
self
}
}
pub fn $name(&self) -> &str {
unsafe { CStr::from_ptr(self.def.u.namesptr).to_str().unwrap() }
}
};
(impl ShortString, $name:ident) => {
paste::item! {
pub fn [<set_ $name>](&mut self, v: &str) -> &mut Self {
assert!(v.len() < 32);
let cstr = CString::new(v).unwrap();
let slice = cstr.to_bytes_with_nul();
self.def.$name[0..slice.len()].copy_from_slice(unsafe { std::mem::transmute(slice) });
self
}
}
pub fn $name(&self) -> &str {
let ptr = self.def.$name;
let u8_slice: &[u8] = unsafe { std::slice::from_raw_parts(ptr.as_ptr() as *const u8, ptr.len()) };
CStr::from_bytes_until_nul(u8_slice).unwrap().to_str().unwrap()
}
};
(impl bool, $name:ident) => {
paste::item! {
pub fn [<set_ $name>](&mut self, v: bool) -> &mut Self {
self.def.$name = if v { 1 } else { 0 };
self.set_value_changed();
self
}
}
pub fn $name(&self) -> bool {
self.def.$name != 0
}
};
(impl Fixed, $name:ident) => {
paste::item! {
pub fn [<set_ $name>](&mut self, v: f32) -> &mut Self {
self.def.$name = Fixed::from(v).as_fixed();
self.set_value_changed();
self
}
}
pub fn $name(&self) -> f32 {
Fixed::from_fixed(self.def.$name).into()
}
};
(impl $typ:ty, default) => {
pub fn set_default(&mut self, v: $typ) -> &mut Self {
self.def.dephault = v as _;
self
}
pub fn default(&self) -> $typ {
self.def.dephault as _
}
};
(impl $typ:ty, $name:ident) => {
paste::item! {
pub fn [<set_ $name>](&mut self, v: $typ) -> &mut Self {
self.def.$name = v.into();
self.set_value_changed();
self
}
}
pub fn $name(&self) -> $typ {
self.def.$name.into()
}
};
}
macro_rules! define_struct {
($raw_type:path, $(#[$attr:meta])* $name:ident { $( $(#[$fattr:meta])* $field:ident: $type:ty ),*, }) => {
#[derive(Debug, Copy, Clone, PartialEq)]
$(#[$attr])*
pub struct $name {
$(
$(#[$fattr])*
pub $field: $type,
)*
}
impl From<$name> for $raw_type {
fn from(v: $name) -> Self {
Self {
$( $field: v.$field as _, )*
}
}
}
impl From<$raw_type> for $name {
fn from(v: $raw_type) -> Self {
Self {
$( $field: v.$field as _, )*
}
}
}
};
}
macro_rules! define_struct_conv {
($raw_type:path, $name:ident { $( $field:ident ),* }) => {
impl From<$name> for $raw_type {
fn from(v: $name) -> Self {
Self {
$( $field: v.$field as _, )*
}
}
}
impl From<$raw_type> for $name {
fn from(v: $raw_type) -> Self {
Self {
$( $field: v.$field as _, )*
}
}
}
};
}
macro_rules! define_enum {
($raw_type:ty, $(#[$topattr:meta])* $name:ident { $( $(#[$attr:meta])* $variant:ident = $value:path ),*, }) => {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(i32)]
$(#[$topattr])*
pub enum $name {
$(
$(#[$attr])*
$variant = $value as _,
)*
}
impl From<$name> for $raw_type {
fn from(v: $name) -> Self {
match v {
$(
$name::$variant => $value as _,
)*
}
}
}
impl From<$raw_type> for $name {
fn from(v: $raw_type) -> Self {
match v as _ {
$(
$value => Self::$variant,
)*
_ => {
panic!("Unknown enum value {}: {v}", stringify!($name));
}
}
}
}
};
}
macro_rules! define_suite {
($(#[$attr:meta])* $suite_pretty_name:ident, $suite_name:ident, $suite_name_string:ident, $suite_version:ident) => {
#[derive(Debug, Hash)]
$(#[$attr])*
pub struct $suite_pretty_name {
pica_basic_suite_ptr: *const after_effects_sys::SPBasicSuite,
suite_ptr: *const after_effects_sys::$suite_name,
}
impl Suite for $suite_pretty_name {
fn new() -> Result<Self, Error> {
let pica_basic_suite_ptr = borrow_pica_basic_as_ptr();
match ae_acquire_suite_ptr!(
pica_basic_suite_ptr,
$suite_name,
$suite_name_string,
$suite_version
) {
Ok(suite_ptr) => Ok(Self {
pica_basic_suite_ptr,
suite_ptr,
}),
Err(e) => Err(e),
}
}
}
impl Clone for $suite_pretty_name {
fn clone(&self) -> Self {
Suite::new().unwrap()
}
}
impl Drop for $suite_pretty_name {
fn drop(&mut self) {
ae_release_suite_ptr!(
self.pica_basic_suite_ptr,
$suite_name_string,
$suite_version
);
}
}
};
}
macro_rules! define_suite_item_wrapper {
($raw_handle_type:ty, $handle_type:ty, $( $suite_ident:ident: $suite_type:ty ),*, $(#[$type_attr:meta])+ $name:ident {
dispose: $( $dispose_suite_fn_ident:ident.$dispose_fun:ident )?;
$( $(#[$attr:meta])* $fn_name:ident($($arg:ident: $argt:ty),*) -> $ret:ty => $suite_fn_ident:ident.$suite_fn:ident ),*,
}) => {
$(#[$type_attr])+
pub struct $name {
handle: $handle_type,
$( $suite_ident: once_cell::sync::Lazy<Result<$suite_type, crate::Error>>, )*
#[allow(dead_code)]
is_owned: bool,
}
impl $name {
pub fn from_handle(handle: $handle_type, owned: bool) -> Self {
Self {
handle,
$( $suite_ident: once_cell::sync::Lazy::new(|| <$suite_type>::new()), )*
is_owned: owned,
}
}
pub fn from_raw(raw_handle: $raw_handle_type) -> Self {
Self::from_handle(<$handle_type>::from_raw(raw_handle), false)
}
pub fn handle(&self) -> &$handle_type {
&self.handle
}
pub fn into_raw(item: Self) -> $raw_handle_type {
item.handle.into()
}
pub fn as_ptr(&self) -> $raw_handle_type {
self.handle.as_ptr()
}
$(
$(#[$attr])*
pub fn $fn_name(&self, $($arg: $argt, )*) -> Result<$ret, crate::Error> {
if let Ok(ref suite) = *self.$suite_fn_ident {
suite.$suite_fn(self.handle.as_ptr(), $($arg, )*).map(Into::into)
} else {
Err(crate::Error::MissingSuite)
}
}
)*
}
impl AsRef<$handle_type> for $name {
fn as_ref(&self) -> &$handle_type {
&self.handle
}
}
impl From<$handle_type> for $name {
fn from(handle: $handle_type) -> Self {
Self::from_handle(handle, false)
}
}
impl crate::AsPtr<$raw_handle_type> for $name {
fn as_ptr(&self) -> $raw_handle_type {
self.handle.as_ptr()
}
}
$(
impl Drop for $name {
fn drop(&mut self) {
if self.is_owned {
if let Ok(ref suite) = *self.$dispose_suite_fn_ident {
suite.$dispose_fun(self.handle).expect(concat!("Failed to dispose the ", stringify!($name), " handle."));
}
}
}
}
)?
};
}
#[cfg(feature = "artisan-2-api")]
macro_rules! define_ptr_wrapper {
($wrapper_pretty_name:ident, $data_type:ident) => {
#[derive(Copy, Clone, Debug, Hash)]
pub struct $wrapper_pretty_name(pub(crate) *const after_effects_sys::$data_type);
impl $wrapper_pretty_name {
pub fn from_raw(raw_ptr: *const after_effects_sys::$data_type) -> Self {
Self(raw_ptr)
}
pub fn as_ptr(&self) -> *const after_effects_sys::$data_type {
self.0
}
pub fn is_null(&self) -> bool {
self.0.is_null()
}
}
impl From<$wrapper_pretty_name> for *const after_effects_sys::$data_type {
fn from(ptr_wrapper: $wrapper_pretty_name) -> Self {
ptr_wrapper.as_ptr()
}
}
};
}