@@ -12,7 +12,7 @@ mod wrapper;
1212
1313/// Re-export for the wrapper.
1414pub use factory:: PluginInfo ;
15- pub use vst3_sys ;
15+ pub use vst3 ;
1616pub use wrapper:: Wrapper ;
1717
1818/// Export one or more VST3 plugins from this library using the provided plugin types. The first
@@ -26,18 +26,16 @@ macro_rules! nih_export_vst3 {
2626 #[ doc( hidden) ]
2727 mod vst3 {
2828 use :: std:: collections:: HashSet ;
29+ use :: std:: ffi:: c_void;
2930
3031 // `vst3_sys` is imported from the VST3 wrapper module
31- use $crate:: wrapper:: vst3:: { vst3_sys , PluginInfo , Wrapper } ;
32- use vst3_sys :: base :: { kInvalidArgument, kResultOk, tresult} ;
33- use vst3_sys :: base :: {
34- FactoryFlags , IPluginFactory , IPluginFactory2 , IPluginFactory3 , IUnknown ,
35- PClassInfo , PClassInfo2 , PClassInfoW , PFactoryInfo ,
32+ use $crate:: wrapper:: vst3:: { PluginInfo , Wrapper } ;
33+ use $crate :: wrapper :: vst3 :: vst3 :: Steinberg :: { kInvalidArgument, kResultOk, tresult, int32 , FIDString , TUID } ;
34+ use $crate :: wrapper :: vst3 :: vst3 :: Steinberg :: {
35+ PFactoryInfo_ :: FactoryFlags_ , IPluginFactory , IPluginFactory2 , IPluginFactory3 , FUnknown ,
36+ PClassInfo , PClassInfo2 , PClassInfoW , PFactoryInfo , IPluginFactoryTrait , IPluginFactory2Trait , IPluginFactory3Trait ,
3637 } ;
37- use vst3_sys:: VST3 ;
38-
39- // This alias is needed for the VST3 attribute macro
40- use vst3_sys as vst3_com;
38+ use $crate:: wrapper:: vst3:: vst3:: { Class , ComWrapper } ;
4139
4240 // Because the `$plugin_ty`s are likely defined in the enclosing scope. This works even
4341 // if the types are not public because this is a child module.
@@ -47,14 +45,17 @@ macro_rules! nih_export_vst3 {
4745 const PLUGIN_COUNT : usize = [ $( stringify!( $plugin_ty) ) ,+] . len( ) ;
4846
4947 #[ doc( hidden) ]
50- #[ VST3 ( implements( IPluginFactory , IPluginFactory2 , IPluginFactory3 ) ) ]
5148 pub struct Factory {
5249 // This is a type erased version of the information stored on the plugin types
5350 plugin_infos: [ PluginInfo ; PLUGIN_COUNT ] ,
5451 }
5552
53+ impl Class for Factory {
54+ type Interfaces = ( IPluginFactory , IPluginFactory2 , IPluginFactory3 ) ;
55+ }
56+
5657 impl Factory {
57- pub fn new( ) -> Box < Self > {
58+ pub fn new( ) -> Self {
5859 let plugin_infos = [ $( PluginInfo :: for_plugin:: <$plugin_ty>( ) ) ,+] ;
5960
6061 if cfg!( debug_assertions) {
@@ -66,12 +67,12 @@ macro_rules! nih_export_vst3 {
6667 ) ;
6768 }
6869
69- Self :: allocate ( plugin_infos)
70+ Factory { plugin_infos }
7071 }
7172 }
7273
73- impl IPluginFactory for Factory {
74- unsafe fn get_factory_info ( & self , info: * mut PFactoryInfo ) -> tresult {
74+ impl IPluginFactoryTrait for Factory {
75+ unsafe fn getFactoryInfo ( & self , info: * mut PFactoryInfo ) -> tresult {
7576 if info. is_null( ) {
7677 return kInvalidArgument;
7778 }
@@ -82,11 +83,11 @@ macro_rules! nih_export_vst3 {
8283 kResultOk
8384 }
8485
85- unsafe fn count_classes ( & self ) -> i32 {
86+ unsafe fn countClasses ( & self ) -> int32 {
8687 self . plugin_infos. len( ) as i32
8788 }
8889
89- unsafe fn get_class_info ( & self , index: i32 , info: * mut PClassInfo ) -> tresult {
90+ unsafe fn getClassInfo ( & self , index: int32 , info: * mut PClassInfo ) -> tresult {
9091 if index < 0 || index >= self . plugin_infos. len( ) as i32 {
9192 return kInvalidArgument;
9293 }
@@ -96,48 +97,31 @@ macro_rules! nih_export_vst3 {
9697 kResultOk
9798 }
9899
99- unsafe fn create_instance (
100+ unsafe fn createInstance (
100101 & self ,
101- cid: * const vst3_sys :: IID ,
102- iid: * const vst3_sys :: IID ,
103- obj: * mut * mut vst3_sys :: c_void,
102+ cid: FIDString ,
103+ iid: FIDString ,
104+ obj: * mut * mut c_void,
104105 ) -> tresult {
105106 // Can't use `check_null_ptr!()` here without polluting NIH-plug's general
106107 // exports
107108 if cid. is_null( ) || obj. is_null( ) {
108109 return kInvalidArgument;
109110 }
110111
112+ let cid = & * ( cid as * const [ u8 ; 16 ] ) ;
113+
111114 // This is a poor man's way of treating `$plugin_ty` like an indexable array.
112115 // Assuming `self.plugin_infos` is in the same order, we can simply check all of
113116 // the registered plugin CIDs for matches using an unrolled loop.
114117 let mut plugin_idx = 0 ;
115118 $( {
116119 let plugin_info = & self . plugin_infos[ plugin_idx] ;
117- if ( * cid) . data == * plugin_info. cid {
118- let wrapper = Wrapper :: <$plugin_ty>:: new( ) ;
119-
120- // 99.999% of the times `iid` will be that of `IComponent`, but the
121- // caller is technically allowed to create an object for any support
122- // interface. We don't have a way to check whether our plugin supports
123- // the interface without creating it, but since the odds that a caller
124- // will create an object with an interface we don't support are
125- // basically zero this is not a problem.
126- let result = wrapper. query_interface( iid, obj) ;
127- if result == kResultOk {
128- // This is a bit awkward now but if the cast succeeds we need to get
129- // rid of the reference from the `wrapper` binding. The VST3 query
130- // interface always increments the reference count and returns an
131- // owned reference, so we need to explicitly release the reference
132- // from `wrapper` and leak the `Box` so the wrapper doesn't
133- // automatically get deallocated when this function returns (`Box`
134- // is an incorrect choice on vst3-sys' part, it should have used a
135- // `VstPtr` instead).
136- wrapper. release( ) ;
137- Box :: leak( wrapper) ;
138-
139- return kResultOk;
140- }
120+ if cid == plugin_info. cid {
121+ let wrapper = ComWrapper :: new( Wrapper :: <$plugin_ty>:: new( ) ) ;
122+ let unknown = wrapper. as_com_ref:: <FUnknown >( ) . unwrap( ) ;
123+ let ptr = unknown. as_ptr( ) ;
124+ return ( ( * ( * ptr) . vtbl) . queryInterface) ( ptr, iid as * const TUID , obj) ;
141125 }
142126
143127 plugin_idx += 1 ;
@@ -147,8 +131,8 @@ macro_rules! nih_export_vst3 {
147131 }
148132 }
149133
150- impl IPluginFactory2 for Factory {
151- unsafe fn get_class_info2 ( & self , index: i32 , info: * mut PClassInfo2 ) -> tresult {
134+ impl IPluginFactory2Trait for Factory {
135+ unsafe fn getClassInfo2 ( & self , index: int32 , info: * mut PClassInfo2 ) -> tresult {
152136 if index < 0 || index >= self . plugin_infos. len( ) as i32 {
153137 return kInvalidArgument;
154138 }
@@ -159,10 +143,10 @@ macro_rules! nih_export_vst3 {
159143 }
160144 }
161145
162- impl IPluginFactory3 for Factory {
163- unsafe fn get_class_info_unicode (
146+ impl IPluginFactory3Trait for Factory {
147+ unsafe fn getClassInfoUnicode (
164148 & self ,
165- index: i32 ,
149+ index: int32 ,
166150 info: * mut PClassInfoW ,
167151 ) -> tresult {
168152 if index < 0 || index >= self . plugin_infos. len( ) as i32 {
@@ -174,7 +158,7 @@ macro_rules! nih_export_vst3 {
174158 kResultOk
175159 }
176160
177- unsafe fn set_host_context ( & self , _context: * mut vst3_sys :: c_void ) -> tresult {
161+ unsafe fn setHostContext ( & self , _context: * mut FUnknown ) -> tresult {
178162 // We don't need to do anything with this
179163 kResultOk
180164 }
@@ -184,9 +168,12 @@ macro_rules! nih_export_vst3 {
184168 /// The VST3 plugin factory entry point.
185169 #[ no_mangle]
186170 pub extern "system" fn GetPluginFactory ( ) -> * mut :: std:: ffi:: c_void {
187- let factory = self :: vst3:: Factory :: new ( ) ;
171+ use $crate :: wrapper :: vst3:: vst3 :: { ComWrapper , Steinberg :: IPluginFactory } ;
188172
189- Box :: into_raw( factory) as * mut :: std:: ffi:: c_void
173+ ComWrapper :: new( self :: vst3:: Factory :: new( ) )
174+ . to_com_ptr:: <IPluginFactory >( )
175+ . unwrap( )
176+ . into_raw( ) as * mut :: std:: ffi:: c_void
190177 }
191178
192179 // These two entry points are used on Linux, and they would theoretically also be used on
0 commit comments