1
0
Fork 0

Allow querying other interfaces for VST3 plugins

Not checking `iid` was an oversight, so if the host would create
anything other than `IComponent` this would do the wrong thing. With
this change the host can create an object for any interface we support.

Fixes #58.
This commit is contained in:
Robbert van der Helm 2023-03-03 00:08:12 +01:00
parent 6fe5c7c471
commit a97c8ea554

View file

@ -1,8 +1,8 @@
use std::ffi::c_void; use std::ffi::c_void;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem; use std::mem;
use vst3_sys::base::{kInvalidArgument, kNoInterface, kResultOk, tresult}; use vst3_sys::base::{kInvalidArgument, kResultOk, tresult};
use vst3_sys::base::{IPluginFactory, IPluginFactory2, IPluginFactory3}; use vst3_sys::base::{IPluginFactory, IPluginFactory2, IPluginFactory3, IUnknown};
use vst3_sys::VST3; use vst3_sys::VST3;
// Alias needed for the VST3 attribute macro // Alias needed for the VST3 attribute macro
@ -70,18 +70,35 @@ impl<P: Vst3Plugin> IPluginFactory for Factory<P> {
unsafe fn create_instance( unsafe fn create_instance(
&self, &self,
cid: *const vst3_sys::IID, cid: *const vst3_sys::IID,
_iid: *const vst3_sys::IID, iid: *const vst3_sys::IID,
obj: *mut *mut vst3_sys::c_void, obj: *mut *mut vst3_sys::c_void,
) -> tresult { ) -> tresult {
check_null_ptr!(cid, obj); check_null_ptr!(cid, obj);
if (*cid).data != P::PLATFORM_VST3_CLASS_ID { if (*cid).data != P::PLATFORM_VST3_CLASS_ID {
return kNoInterface; return kInvalidArgument;
} }
*obj = Box::into_raw(Wrapper::<P>::new()) as *mut vst3_sys::c_void; let wrapper = Wrapper::<P>::new();
kResultOk // 99.999% of the times `iid` will be that of `IComponent`, but the caller is technically
// allowed to create an object for any support interface. We don't have a way to check
// whether our plugin supports the interface without creating it, but since the odds that a
// caller will create an object with an interface we don't support are basically zero this
// is not a problem.
let result = wrapper.query_interface(iid, obj);
if result == kResultOk {
// This is a bit awkward now but if the cast succeeds we need to get rid of the
// reference from the `wrapper` binding. The VST3 query interface always increments the
// reference count and returns an owned reference, so we need to explicitly release the
// reference from `wrapper` and leak the `Box` so the wrapper doesn't automatically get
// deallocated when this function returns (`Box` is an incorrect choice on vst3-sys'
// part, it should have used a `VstPtr` instead).
wrapper.release();
Box::leak(wrapper);
}
result
} }
} }