Move plugin descriptor to its own module
Because we also need this in the clap_plugin implementation.
This commit is contained in:
parent
32a640acf7
commit
2e6faaa324
|
@ -1,3 +1,4 @@
|
||||||
|
mod descriptor;
|
||||||
mod factory;
|
mod factory;
|
||||||
mod plugin;
|
mod plugin;
|
||||||
|
|
||||||
|
|
98
src/wrapper/clap/descriptor.rs
Normal file
98
src/wrapper/clap/descriptor.rs
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
use clap_sys::plugin::clap_plugin_descriptor;
|
||||||
|
use clap_sys::version::CLAP_VERSION;
|
||||||
|
use std::ffi::{CStr, CString};
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use std::mem::MaybeUninit;
|
||||||
|
use std::os::raw::c_char;
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
use crate::plugin::ClapPlugin;
|
||||||
|
|
||||||
|
/// A static descriptor for a plugin. This is used in both the descriptor and on the plugin object
|
||||||
|
/// itself.
|
||||||
|
///
|
||||||
|
/// This cannot be cloned as [Self::clap_features_ptrs] contains pointers to [Self::clap_features].
|
||||||
|
pub struct PluginDescriptor<P: ClapPlugin> {
|
||||||
|
// We need [CString]s for all of `ClapPlugin`'s `&str` fields
|
||||||
|
clap_id: CString,
|
||||||
|
name: CString,
|
||||||
|
vendor: CString,
|
||||||
|
url: CString,
|
||||||
|
clap_manual_url: CString,
|
||||||
|
clap_support_url: CString,
|
||||||
|
version: CString,
|
||||||
|
clap_description: CString,
|
||||||
|
clap_features: Vec<CString>,
|
||||||
|
clap_features_ptrs: MaybeUninit<Vec<*const c_char>>,
|
||||||
|
|
||||||
|
/// We only support a single plugin per descriptor right now, so we'll fill in the plugin
|
||||||
|
/// descriptor upfront. We also need to initialize the `CString` fields above first before we
|
||||||
|
/// can initialize this plugin descriptor.
|
||||||
|
plugin_descriptor: MaybeUninit<clap_plugin_descriptor>,
|
||||||
|
|
||||||
|
/// The plugin's type.
|
||||||
|
_phantom: PhantomData<P>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: ClapPlugin> Default for PluginDescriptor<P> {
|
||||||
|
fn default() -> Self {
|
||||||
|
let mut descriptor = Self {
|
||||||
|
clap_id: CString::new(P::CLAP_ID).expect("`CLAP_ID` contained null bytes"),
|
||||||
|
name: CString::new(P::NAME).expect("`NAME` contained null bytes"),
|
||||||
|
vendor: CString::new(P::VENDOR).expect("`VENDOR` contained null bytes"),
|
||||||
|
url: CString::new(P::URL).expect("`URL` contained null bytes"),
|
||||||
|
clap_manual_url: CString::new(P::CLAP_MANUAL_URL)
|
||||||
|
.expect("`CLAP_MANUAL_URL` contained null bytes"),
|
||||||
|
clap_support_url: CString::new(P::CLAP_SUPPORT_URL)
|
||||||
|
.expect("`CLAP_SUPPORT_URL` contained null bytes"),
|
||||||
|
version: CString::new(P::VERSION).expect("`VERSION` contained null bytes"),
|
||||||
|
clap_description: CString::new(P::CLAP_DESCRIPTION)
|
||||||
|
.expect("`CLAP_DESCRIPTION` contained null bytes"),
|
||||||
|
clap_features: P::CLAP_FEATURES
|
||||||
|
.iter()
|
||||||
|
.map(|s| CString::new(*s).expect("`CLAP_FEATURES` contained null bytes"))
|
||||||
|
.collect(),
|
||||||
|
clap_features_ptrs: MaybeUninit::uninit(),
|
||||||
|
plugin_descriptor: MaybeUninit::uninit(),
|
||||||
|
_phantom: PhantomData,
|
||||||
|
};
|
||||||
|
|
||||||
|
// The keyword list is an environ-like list of char pointers terminated by a null pointer
|
||||||
|
let mut clap_features_ptrs: Vec<*const c_char> = descriptor
|
||||||
|
.clap_features
|
||||||
|
.iter()
|
||||||
|
.map(|feature| feature.as_ptr())
|
||||||
|
.collect();
|
||||||
|
clap_features_ptrs.push(ptr::null());
|
||||||
|
descriptor.clap_features_ptrs.write(clap_features_ptrs);
|
||||||
|
|
||||||
|
// We couldn't initialize this directly because of all the CStrings
|
||||||
|
descriptor.plugin_descriptor.write(clap_plugin_descriptor {
|
||||||
|
clap_version: CLAP_VERSION,
|
||||||
|
id: descriptor.clap_id.as_ptr(),
|
||||||
|
name: descriptor.name.as_ptr(),
|
||||||
|
vendor: descriptor.vendor.as_ptr(),
|
||||||
|
url: descriptor.url.as_ptr(),
|
||||||
|
manual_url: descriptor.clap_manual_url.as_ptr(),
|
||||||
|
support_url: descriptor.clap_support_url.as_ptr(),
|
||||||
|
version: descriptor.version.as_ptr(),
|
||||||
|
description: descriptor.clap_description.as_ptr(),
|
||||||
|
features: unsafe { descriptor.clap_features_ptrs.assume_init_ref() }.as_ptr(),
|
||||||
|
});
|
||||||
|
|
||||||
|
descriptor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<P: ClapPlugin> Send for PluginDescriptor<P> {}
|
||||||
|
unsafe impl<P: ClapPlugin> Sync for PluginDescriptor<P> {}
|
||||||
|
|
||||||
|
impl<P: ClapPlugin> PluginDescriptor<P> {
|
||||||
|
pub fn clap_plugin_descriptor(&self) -> &clap_plugin_descriptor {
|
||||||
|
unsafe { self.plugin_descriptor.assume_init_ref() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clap_id(&self) -> &CStr {
|
||||||
|
self.clap_id.as_c_str()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +1,11 @@
|
||||||
use clap_sys::host::clap_host;
|
use clap_sys::host::clap_host;
|
||||||
use clap_sys::plugin::{clap_plugin, clap_plugin_descriptor};
|
use clap_sys::plugin::{clap_plugin, clap_plugin_descriptor};
|
||||||
use clap_sys::plugin_factory::clap_plugin_factory;
|
use clap_sys::plugin_factory::clap_plugin_factory;
|
||||||
use clap_sys::version::CLAP_VERSION;
|
use std::ffi::CStr;
|
||||||
use std::ffi::{CStr, CString};
|
|
||||||
use std::marker::PhantomData;
|
|
||||||
use std::mem::MaybeUninit;
|
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
|
use super::descriptor::PluginDescriptor;
|
||||||
use super::plugin::Plugin;
|
use super::plugin::Plugin;
|
||||||
use crate::ClapPlugin;
|
use crate::ClapPlugin;
|
||||||
|
|
||||||
|
@ -19,92 +17,22 @@ pub struct Factory<P: ClapPlugin> {
|
||||||
// Keep the vtable as the first field so we can do a simple pointer cast
|
// Keep the vtable as the first field so we can do a simple pointer cast
|
||||||
pub clap_plugin_factory: clap_plugin_factory,
|
pub clap_plugin_factory: clap_plugin_factory,
|
||||||
|
|
||||||
// We need [CString]s for all of `ClapPlugin`'s `&str` fields
|
plugin_descriptor: PluginDescriptor<P>,
|
||||||
clap_id: CString,
|
|
||||||
name: CString,
|
|
||||||
vendor: CString,
|
|
||||||
url: CString,
|
|
||||||
clap_manual_url: CString,
|
|
||||||
clap_support_url: CString,
|
|
||||||
version: CString,
|
|
||||||
clap_description: CString,
|
|
||||||
clap_features: Vec<CString>,
|
|
||||||
clap_features_ptrs: MaybeUninit<CStrPtrs>,
|
|
||||||
|
|
||||||
/// We only support a single plugin per factory right now, so we'll fill in the plugin
|
|
||||||
/// descriptor upfront. We also need to initialize the `CString` fields above first before we
|
|
||||||
/// can initialize this plugin descriptor.
|
|
||||||
plugin_descriptor: MaybeUninit<clap_plugin_descriptor>,
|
|
||||||
|
|
||||||
/// The type will be used for constructing plugin instances later.
|
|
||||||
_phantom: PhantomData<P>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Needed for the Send+Sync implementation for lazy_static.
|
|
||||||
struct CStrPtrs(Vec<*const c_char>);
|
|
||||||
|
|
||||||
impl<P: ClapPlugin> Default for Factory<P> {
|
impl<P: ClapPlugin> Default for Factory<P> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let mut factory = Self {
|
Self {
|
||||||
clap_plugin_factory: clap_plugin_factory {
|
clap_plugin_factory: clap_plugin_factory {
|
||||||
get_plugin_count: Self::get_plugin_count,
|
get_plugin_count: Self::get_plugin_count,
|
||||||
get_plugin_descriptor: Self::get_plugin_descriptor,
|
get_plugin_descriptor: Self::get_plugin_descriptor,
|
||||||
create_plugin: Self::create_plugin,
|
create_plugin: Self::create_plugin,
|
||||||
},
|
},
|
||||||
clap_id: CString::new(P::CLAP_ID).expect("`CLAP_ID` contained null bytes"),
|
plugin_descriptor: PluginDescriptor::default(),
|
||||||
name: CString::new(P::NAME).expect("`NAME` contained null bytes"),
|
}
|
||||||
vendor: CString::new(P::VENDOR).expect("`VENDOR` contained null bytes"),
|
|
||||||
url: CString::new(P::URL).expect("`URL` contained null bytes"),
|
|
||||||
clap_manual_url: CString::new(P::CLAP_MANUAL_URL)
|
|
||||||
.expect("`CLAP_MANUAL_URL` contained null bytes"),
|
|
||||||
clap_support_url: CString::new(P::CLAP_SUPPORT_URL)
|
|
||||||
.expect("`CLAP_SUPPORT_URL` contained null bytes"),
|
|
||||||
version: CString::new(P::VERSION).expect("`VERSION` contained null bytes"),
|
|
||||||
clap_description: CString::new(P::CLAP_DESCRIPTION)
|
|
||||||
.expect("`CLAP_DESCRIPTION` contained null bytes"),
|
|
||||||
clap_features: P::CLAP_FEATURES
|
|
||||||
.iter()
|
|
||||||
.map(|s| CString::new(*s).expect("`CLAP_FEATURES` contained null bytes"))
|
|
||||||
.collect(),
|
|
||||||
clap_features_ptrs: MaybeUninit::uninit(),
|
|
||||||
plugin_descriptor: MaybeUninit::uninit(),
|
|
||||||
_phantom: PhantomData,
|
|
||||||
};
|
|
||||||
|
|
||||||
// The keyword list is an environ-like list of char pointers terminated by a null pointer
|
|
||||||
let mut clap_features_ptrs: Vec<*const c_char> = factory
|
|
||||||
.clap_features
|
|
||||||
.iter()
|
|
||||||
.map(|feature| feature.as_ptr())
|
|
||||||
.collect();
|
|
||||||
clap_features_ptrs.push(ptr::null());
|
|
||||||
factory
|
|
||||||
.clap_features_ptrs
|
|
||||||
.write(CStrPtrs(clap_features_ptrs));
|
|
||||||
|
|
||||||
// We couldn't initialize this directly because of all the CStrings
|
|
||||||
factory.plugin_descriptor.write(clap_plugin_descriptor {
|
|
||||||
clap_version: CLAP_VERSION,
|
|
||||||
id: factory.clap_id.as_ptr(),
|
|
||||||
name: factory.name.as_ptr(),
|
|
||||||
vendor: factory.vendor.as_ptr(),
|
|
||||||
url: factory.url.as_ptr(),
|
|
||||||
manual_url: factory.clap_manual_url.as_ptr(),
|
|
||||||
support_url: factory.clap_support_url.as_ptr(),
|
|
||||||
version: factory.version.as_ptr(),
|
|
||||||
description: factory.clap_description.as_ptr(),
|
|
||||||
features: unsafe { factory.clap_features_ptrs.assume_init_ref() }
|
|
||||||
.0
|
|
||||||
.as_ptr(),
|
|
||||||
});
|
|
||||||
|
|
||||||
factory
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for CStrPtrs {}
|
|
||||||
unsafe impl Sync for CStrPtrs {}
|
|
||||||
|
|
||||||
impl<P: ClapPlugin> Factory<P> {
|
impl<P: ClapPlugin> Factory<P> {
|
||||||
unsafe extern "C" fn get_plugin_count(_factory: *const clap_plugin_factory) -> u32 {
|
unsafe extern "C" fn get_plugin_count(_factory: *const clap_plugin_factory) -> u32 {
|
||||||
1
|
1
|
||||||
|
@ -117,7 +45,7 @@ impl<P: ClapPlugin> Factory<P> {
|
||||||
let factory = &*(factory as *const Self);
|
let factory = &*(factory as *const Self);
|
||||||
|
|
||||||
if index == 0 {
|
if index == 0 {
|
||||||
factory.plugin_descriptor.assume_init_ref()
|
factory.plugin_descriptor.clap_plugin_descriptor()
|
||||||
} else {
|
} else {
|
||||||
ptr::null()
|
ptr::null()
|
||||||
}
|
}
|
||||||
|
@ -130,7 +58,8 @@ impl<P: ClapPlugin> Factory<P> {
|
||||||
) -> *const clap_plugin {
|
) -> *const clap_plugin {
|
||||||
let factory = &*(factory as *const Self);
|
let factory = &*(factory as *const Self);
|
||||||
|
|
||||||
if !plugin_id.is_null() && CStr::from_ptr(plugin_id) == factory.clap_id.as_c_str() {
|
if !plugin_id.is_null() && CStr::from_ptr(plugin_id) == factory.plugin_descriptor.clap_id()
|
||||||
|
{
|
||||||
&Box::leak(Box::new(Plugin::<P>::new(host))).clap_plugin
|
&Box::leak(Box::new(Plugin::<P>::new(host))).clap_plugin
|
||||||
} else {
|
} else {
|
||||||
ptr::null()
|
ptr::null()
|
||||||
|
|
Loading…
Reference in a new issue