Skip to content

Commit 0db4d62

Browse files
committed
switch from vst3-sys to vst3
1 parent 28b149e commit 0db4d62

File tree

11 files changed

+536
-612
lines changed

11 files changed

+536
-612
lines changed

Cargo.lock

Lines changed: 12 additions & 34 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ standalone = ["dep:baseview", "dep:clap", "dep:cpal", "dep:jack", "dep:midir", "
6262
# exists mostly for GPL-compliance reasons, since even if you don't use the VST3
6363
# wrapper you might otherwise still include a couple (unused) symbols from the
6464
# `vst3-sys` crate.
65-
vst3 = ["dep:vst3-sys"]
65+
vst3 = ["dep:vst3"]
6666
# Add adapters to the Buffer object for reading the channel data to and from
6767
# `std::simd` vectors. Requires a nightly compiler.
6868
simd = []
@@ -112,7 +112,7 @@ midir = { version = "0.9.1", optional = true }
112112
rtrb = { version = "0.2.2", optional = true }
113113

114114
# Used for the `vst3` feature
115-
vst3-sys = { git = "https://github.com/robbert-vdh/vst3-sys.git", branch = "fix/drop-box-from-raw", optional = true }
115+
vst3 = { version = "0.3.0", optional = true }
116116

117117
# Used for the `zstd` feature
118118
zstd = { version = "0.12.3", optional = true }

src/wrapper/vst3.rs

Lines changed: 40 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ mod wrapper;
1212

1313
/// Re-export for the wrapper.
1414
pub use factory::PluginInfo;
15-
pub use vst3_sys;
15+
pub use vst3;
1616
pub 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

src/wrapper/vst3/context.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::cell::Cell;
33
use std::collections::VecDeque;
44
use std::sync::atomic::Ordering;
55
use std::sync::Arc;
6-
use vst3_sys::vst::IComponentHandler;
6+
use vst3::Steinberg::Vst::IComponentHandlerTrait;
77

88
use crate::prelude::{
99
GuiContext, InitContext, ParamPtr, PluginApi, PluginNoteEvent, PluginState, ProcessContext,
@@ -44,6 +44,9 @@ pub(crate) struct WrapperProcessContext<'a, P: Vst3Plugin> {
4444
pub(super) transport: Transport,
4545
}
4646

47+
unsafe impl<P: Vst3Plugin> Send for WrapperGuiContext<P> {}
48+
unsafe impl<P: Vst3Plugin> Sync for WrapperGuiContext<P> {}
49+
4750
/// A [`GuiContext`] implementation for the wrapper. This is passed to the plugin in
4851
/// [`Editor::spawn()`][crate::prelude::Editor::spawn()] so it can interact with the rest of the plugin and
4952
/// with the host for things like setting parameters.
@@ -118,7 +121,7 @@ impl<P: Vst3Plugin> ProcessContext<P> for WrapperProcessContext<'_, P> {
118121
}
119122
}
120123

121-
impl<P: Vst3Plugin> GuiContext for WrapperGuiContext<P> {
124+
impl<P: Vst3Plugin + Send> GuiContext for WrapperGuiContext<P> {
122125
fn plugin_api(&self) -> PluginApi {
123126
PluginApi::Vst3
124127
}
@@ -138,7 +141,7 @@ impl<P: Vst3Plugin> GuiContext for WrapperGuiContext<P> {
138141
match &*self.inner.component_handler.borrow() {
139142
Some(handler) => match self.inner.param_ptr_to_hash.get(&param) {
140143
Some(hash) => {
141-
handler.begin_edit(*hash);
144+
handler.beginEdit(*hash);
142145
}
143146
None => nih_debug_assert_failure!("Unknown parameter: {:?}", param),
144147
},
@@ -179,7 +182,7 @@ impl<P: Vst3Plugin> GuiContext for WrapperGuiContext<P> {
179182
);
180183
}
181184

182-
handler.perform_edit(*hash, normalized as f64);
185+
handler.performEdit(*hash, normalized as f64);
183186
}
184187
None => nih_debug_assert_failure!("Unknown parameter: {:?}", param),
185188
},
@@ -202,7 +205,7 @@ impl<P: Vst3Plugin> GuiContext for WrapperGuiContext<P> {
202205
match &*self.inner.component_handler.borrow() {
203206
Some(handler) => match self.inner.param_ptr_to_hash.get(&param) {
204207
Some(hash) => {
205-
handler.end_edit(*hash);
208+
handler.endEdit(*hash);
206209
}
207210
None => nih_debug_assert_failure!("Unknown parameter: {:?}", param),
208211
},

0 commit comments

Comments
 (0)