use super::*;
use crate::host::HostInfo;
use crate::plugin::{PluginDescriptor, PluginInstance};
use clack_common::factory::plugin::PluginFactory;
use clap_sys::factory::plugin_factory::clap_plugin_factory;
use clap_sys::host::clap_host;
use clap_sys::plugin::{clap_plugin, clap_plugin_descriptor};
use std::ffi::CStr;
use std::ptr::NonNull;
pub struct PluginFactoryWrapper<F> {
inner: FactoryWrapper<clap_plugin_factory, F>,
}
impl<F: PluginFactoryImpl> PluginFactoryWrapper<F> {
const RAW: clap_plugin_factory = clap_plugin_factory {
get_plugin_count: Some(Self::get_plugin_count),
get_plugin_descriptor: Some(Self::get_plugin_descriptor),
create_plugin: Some(Self::create_plugin),
};
pub const fn new(factory: F) -> Self {
Self {
inner: FactoryWrapper::new(Self::RAW, factory),
}
}
#[inline]
pub const fn factory(&self) -> &F {
self.inner.factory()
}
#[inline]
pub fn as_raw_ptr(&self) -> *const clap_plugin_factory {
self.inner.as_raw_ptr()
}
#[allow(clippy::missing_safety_doc)]
unsafe extern "C" fn get_plugin_count(factory: *const clap_plugin_factory) -> u32 {
FactoryWrapper::<clap_plugin_factory, F>::handle(factory, |factory| {
Ok(factory.plugin_count())
})
.unwrap_or(0)
}
#[allow(clippy::missing_safety_doc)]
unsafe extern "C" fn get_plugin_descriptor(
factory: *const clap_plugin_factory,
index: u32,
) -> *const clap_plugin_descriptor {
FactoryWrapper::<clap_plugin_factory, F>::handle(factory, |factory| {
match factory.plugin_descriptor(index) {
None => Ok(core::ptr::null()),
Some(d) => Ok(d.as_raw()),
}
})
.unwrap_or(core::ptr::null())
}
#[allow(clippy::missing_safety_doc)]
unsafe extern "C" fn create_plugin(
factory: *const clap_plugin_factory,
clap_host: *const clap_host,
plugin_id: *const std::os::raw::c_char,
) -> *const clap_plugin {
FactoryWrapper::<clap_plugin_factory, F>::handle(factory, |factory| {
let plugin_id = CStr::from_ptr(plugin_id);
let clap_host = NonNull::new(clap_host as *mut _)
.ok_or(FactoryWrapperError::NulPtr("clap_host"))?;
let host_info = HostInfo::from_raw(clap_host);
match factory.create_plugin(host_info, plugin_id) {
None => Ok(core::ptr::null()),
Some(instance) => Ok(instance.into_owned_ptr()),
}
})
.unwrap_or(core::ptr::null())
}
}
unsafe impl<'a, F: PluginFactoryImpl + 'a> FactoryImplementation<'a> for PluginFactoryWrapper<F> {
type Factory = PluginFactory<'a>;
type Wrapped = F;
#[inline]
fn wrapper(&self) -> &FactoryWrapper<clap_plugin_factory, F> {
&self.inner
}
}
pub trait PluginFactoryImpl: Send + Sync {
fn plugin_count(&self) -> u32;
fn plugin_descriptor(&self, index: u32) -> Option<&PluginDescriptor>;
fn create_plugin<'a>(
&'a self,
host_info: HostInfo<'a>,
plugin_id: &CStr,
) -> Option<PluginInstance<'a>>;
}