use lazy_static::lazy_static; use std::ops::Deref; use vst3_sys::{interfaces::IUnknown, ComInterface}; use crate::wrapper::util::hash_param_id; /// Right now the wrapper adds its own bypass parameter. /// /// TODO: Actually use this parameter. pub const BYPASS_PARAM_ID: &str = "bypass"; lazy_static! { pub static ref BYPASS_PARAM_HASH: u32 = hash_param_id(BYPASS_PARAM_ID); } /// Early exit out of a VST3 function when one of the passed pointers is null macro_rules! check_null_ptr { ($ptr:expr $(, $ptrs:expr)* $(, )?) => { check_null_ptr_msg!("Null pointer passed to function", $ptr $(, $ptrs)*) }; } /// The same as [check_null_ptr!], but with a custom message. macro_rules! check_null_ptr_msg { ($msg:expr, $ptr:expr $(, $ptrs:expr)* $(, )?) => { if $ptr.is_null() $(|| $ptrs.is_null())* { nih_debug_assert_failure!($msg); return kInvalidArgument; } }; } /// Send+Sync wrapper for these interface pointers. #[repr(transparent)] pub struct VstPtr { ptr: vst3_sys::VstPtr, } /// The same as [VstPtr] with shared semnatics, but for objects we defined ourself since VstPtr only /// works for interfaces. #[repr(transparent)] pub struct ObjectPtr { ptr: *const T, } impl Deref for VstPtr { type Target = vst3_sys::VstPtr; fn deref(&self) -> &Self::Target { &self.ptr } } impl Deref for ObjectPtr { type Target = T; fn deref(&self) -> &Self::Target { unsafe { &*self.ptr } } } impl From> for VstPtr { fn from(ptr: vst3_sys::VstPtr) -> Self { Self { ptr } } } impl From<&T> for ObjectPtr { /// Create a smart pointer for an existing reference counted object. fn from(obj: &T) -> Self { unsafe { obj.add_ref() }; Self { ptr: obj } } } impl Drop for ObjectPtr { fn drop(&mut self) { unsafe { (*self).release() }; } } /// SAFETY: Sharing these pointers across thread is s safe as they have internal atomic reference /// counting, so as long as a `VstPtr` handle exists the object will stay alive. unsafe impl Send for VstPtr {} unsafe impl Sync for VstPtr {} unsafe impl Send for ObjectPtr {} unsafe impl Sync for ObjectPtr {}