From a97c8ea554617c6a8e88e00375a51ef4c0e570b8 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Fri, 3 Mar 2023 00:08:12 +0100 Subject: [PATCH] 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. --- src/wrapper/vst3/factory.rs | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/wrapper/vst3/factory.rs b/src/wrapper/vst3/factory.rs index be4c1601..8b1ae8ab 100644 --- a/src/wrapper/vst3/factory.rs +++ b/src/wrapper/vst3/factory.rs @@ -1,8 +1,8 @@ use std::ffi::c_void; use std::marker::PhantomData; use std::mem; -use vst3_sys::base::{kInvalidArgument, kNoInterface, kResultOk, tresult}; -use vst3_sys::base::{IPluginFactory, IPluginFactory2, IPluginFactory3}; +use vst3_sys::base::{kInvalidArgument, kResultOk, tresult}; +use vst3_sys::base::{IPluginFactory, IPluginFactory2, IPluginFactory3, IUnknown}; use vst3_sys::VST3; // Alias needed for the VST3 attribute macro @@ -70,18 +70,35 @@ impl IPluginFactory for Factory

{ unsafe fn create_instance( &self, cid: *const vst3_sys::IID, - _iid: *const vst3_sys::IID, + iid: *const vst3_sys::IID, obj: *mut *mut vst3_sys::c_void, ) -> tresult { check_null_ptr!(cid, obj); if (*cid).data != P::PLATFORM_VST3_CLASS_ID { - return kNoInterface; + return kInvalidArgument; } - *obj = Box::into_raw(Wrapper::

::new()) as *mut vst3_sys::c_void; + let wrapper = Wrapper::

::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 } }