1
0
Fork 0
nih-plug/src/wrapper/vst3/factory.rs
2022-02-12 16:04:46 +01:00

143 lines
4.3 KiB
Rust

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::VST3;
// Alias needed for the VST3 attribute macro
use vst3_sys as vst3_com;
use super::wrapper::Wrapper;
use crate::plugin::Vst3Plugin;
use crate::wrapper::util::{strlcpy, u16strlcpy};
/// The VST3 SDK version this is roughtly based on.
const VST3_SDK_VERSION: &str = "VST 3.6.14";
#[doc(hidden)]
#[VST3(implements(IPluginFactory, IPluginFactory2, IPluginFactory3))]
pub struct Factory<P: Vst3Plugin> {
/// The type will be used for constructing plugin instances later.
_phantom: PhantomData<P>,
}
impl<P: Vst3Plugin> Factory<P> {
pub fn new() -> Box<Self> {
Self::allocate(PhantomData::default())
}
}
impl<P: Vst3Plugin> IPluginFactory for Factory<P> {
unsafe fn get_factory_info(&self, info: *mut vst3_sys::base::PFactoryInfo) -> tresult {
*info = mem::zeroed();
let info = &mut *info;
strlcpy(&mut info.vendor, P::VENDOR);
strlcpy(&mut info.url, P::URL);
strlcpy(&mut info.email, P::EMAIL);
info.flags = vst3_sys::base::FactoryFlags::kUnicode as i32;
kResultOk
}
unsafe fn count_classes(&self) -> i32 {
// We don't do shell plugins, and good of an idea having separated components and edit
// controllers in theory is, few software can use it, and doing that would make our simple
// microframework a lot less simple
1
}
unsafe fn get_class_info(&self, index: i32, info: *mut vst3_sys::base::PClassInfo) -> tresult {
if index != 0 {
return kInvalidArgument;
}
*info = mem::zeroed();
let info = &mut *info;
info.cid.data = P::PLATFORM_VST3_CLASS_ID;
info.cardinality = vst3_sys::base::ClassCardinality::kManyInstances as i32;
strlcpy(&mut info.category, "Audio Module Class");
strlcpy(&mut info.name, P::NAME);
kResultOk
}
unsafe fn create_instance(
&self,
cid: *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;
}
*obj = Box::into_raw(Wrapper::<P>::new()) as *mut vst3_sys::c_void;
kResultOk
}
}
impl<P: Vst3Plugin> IPluginFactory2 for Factory<P> {
unsafe fn get_class_info2(
&self,
index: i32,
info: *mut vst3_sys::base::PClassInfo2,
) -> tresult {
if index != 0 {
return kInvalidArgument;
}
*info = mem::zeroed();
let info = &mut *info;
info.cid.data = P::PLATFORM_VST3_CLASS_ID;
info.cardinality = vst3_sys::base::ClassCardinality::kManyInstances as i32;
strlcpy(&mut info.category, "Audio Module Class");
strlcpy(&mut info.name, P::NAME);
info.class_flags = 1 << 1; // kSimpleModeSupported
strlcpy(&mut info.subcategories, P::VST3_CATEGORIES);
strlcpy(&mut info.vendor, P::VENDOR);
strlcpy(&mut info.version, P::VERSION);
strlcpy(&mut info.sdk_version, VST3_SDK_VERSION);
kResultOk
}
}
impl<P: Vst3Plugin> IPluginFactory3 for Factory<P> {
unsafe fn get_class_info_unicode(
&self,
index: i32,
info: *mut vst3_sys::base::PClassInfoW,
) -> tresult {
if index != 0 {
return kInvalidArgument;
}
*info = mem::zeroed();
let info = &mut *info;
info.cid.data = P::PLATFORM_VST3_CLASS_ID;
info.cardinality = vst3_sys::base::ClassCardinality::kManyInstances as i32;
strlcpy(&mut info.category, "Audio Module Class");
u16strlcpy(&mut info.name, P::NAME);
info.class_flags = 1 << 1; // kSimpleModeSupported
strlcpy(&mut info.subcategories, P::VST3_CATEGORIES);
u16strlcpy(&mut info.vendor, P::VENDOR);
u16strlcpy(&mut info.version, P::VERSION);
u16strlcpy(&mut info.sdk_version, VST3_SDK_VERSION);
kResultOk
}
unsafe fn set_host_context(&self, _context: *mut c_void) -> tresult {
// We don't need to do anything with this
kResultOk
}
}