From 09b611006c5c4721f19270d044a4f054121dbb1b Mon Sep 17 00:00:00 2001 From: Micah Johnston Date: Sun, 15 Oct 2023 23:20:47 -0500 Subject: [PATCH] clap: plugin instantiation --- src/format/clap/factory.rs | 69 +++++++++++++++++++----------- src/format/clap/instance.rs | 84 +++++++++++++++++++++++++++++++++++++ src/format/clap/mod.rs | 1 + 3 files changed, 129 insertions(+), 25 deletions(-) create mode 100644 src/format/clap/instance.rs diff --git a/src/format/clap/factory.rs b/src/format/clap/factory.rs index 70cd44a..8557087 100644 --- a/src/format/clap/factory.rs +++ b/src/format/clap/factory.rs @@ -2,18 +2,25 @@ use std::cell::UnsafeCell; use std::ffi::{c_char, c_void, CStr, CString}; use std::marker::PhantomData; use std::ptr; +use std::sync::Arc; use clap_sys::{host::*, plugin::*, plugin_factory::*, version::*}; +use super::instance::Instance; use super::ClapPlugin; -use crate::Plugin; +use crate::{Plugin, PluginInfo}; + +struct FactoryState { + descriptor: clap_plugin_descriptor, + info: Arc, +} #[doc(hidden)] #[repr(C)] pub struct Factory

{ #[allow(unused)] factory: clap_plugin_factory, - descriptor: UnsafeCell>, + state: UnsafeCell>, _marker: PhantomData

, } @@ -27,16 +34,16 @@ impl Factory

{ get_plugin_descriptor: Some(Self::get_plugin_descriptor), create_plugin: Some(Self::create_plugin), }, - descriptor: UnsafeCell::new(None), + state: UnsafeCell::new(None), _marker: PhantomData, } } pub unsafe fn init(&self) -> bool { + let info = Arc::new(P::info()); let clap_info = P::clap_info(); - let id = CString::new(&*clap_info.id).unwrap().into_raw(); - let info = P::info(); + let id = CString::new(&*clap_info.id).unwrap().into_raw(); let name = CString::new(&*info.name).unwrap().into_raw(); let vendor = CString::new(&*info.vendor).unwrap().into_raw(); let url = CString::new(&*info.url).unwrap().into_raw(); @@ -44,28 +51,31 @@ impl Factory

{ const EMPTY: &'static CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"\0") }; const FEATURES: &'static [*const c_char] = &[ptr::null()]; - *self.descriptor.get() = Some(clap_plugin_descriptor { - clap_version: CLAP_VERSION, - id, - name, - vendor, - url, - manual_url: EMPTY.as_ptr(), - support_url: EMPTY.as_ptr(), - version: EMPTY.as_ptr(), - description: EMPTY.as_ptr(), - features: FEATURES.as_ptr(), + *self.state.get() = Some(FactoryState { + descriptor: clap_plugin_descriptor { + clap_version: CLAP_VERSION, + id, + name, + vendor, + url, + manual_url: EMPTY.as_ptr(), + support_url: EMPTY.as_ptr(), + version: EMPTY.as_ptr(), + description: EMPTY.as_ptr(), + features: FEATURES.as_ptr(), + }, + info, }); true } pub unsafe fn deinit(&self) { - if let Some(descriptor) = (*self.descriptor.get()).take() { - drop(CString::from_raw(descriptor.id as *mut c_char)); - drop(CString::from_raw(descriptor.name as *mut c_char)); - drop(CString::from_raw(descriptor.vendor as *mut c_char)); - drop(CString::from_raw(descriptor.url as *mut c_char)); + if let Some(state) = (*self.state.get()).take() { + drop(CString::from_raw(state.descriptor.id as *mut c_char)); + drop(CString::from_raw(state.descriptor.name as *mut c_char)); + drop(CString::from_raw(state.descriptor.vendor as *mut c_char)); + drop(CString::from_raw(state.descriptor.url as *mut c_char)); } } @@ -88,8 +98,8 @@ impl Factory

{ let factory = &*(factory as *const Self); if index == 0 { - if let Some(descriptor) = &*factory.descriptor.get() { - return descriptor; + if let Some(state) = &*factory.state.get() { + return &state.descriptor; } } @@ -97,10 +107,19 @@ impl Factory

{ } unsafe extern "C" fn create_plugin( - _factory: *const clap_plugin_factory, + factory: *const clap_plugin_factory, _host: *const clap_host, - _plugin_id: *const c_char, + plugin_id: *const c_char, ) -> *const clap_plugin { + let factory = &*(factory as *const Self); + + if let Some(state) = &*factory.state.get() { + if CStr::from_ptr(plugin_id) == CStr::from_ptr(state.descriptor.id) { + let instance = Box::new(Instance::

::new(&state.descriptor, &state.info)); + return Box::into_raw(instance) as *const clap_plugin; + } + } + ptr::null() } } diff --git a/src/format/clap/instance.rs b/src/format/clap/instance.rs new file mode 100644 index 0000000..114b506 --- /dev/null +++ b/src/format/clap/instance.rs @@ -0,0 +1,84 @@ +use std::cell::UnsafeCell; +use std::ffi::{c_char, c_void}; +use std::ptr; +use std::sync::Arc; + +use clap_sys::{plugin::*, process::*}; + +use crate::{Host, Plugin, PluginInfo}; + +#[repr(C)] +pub struct Instance

{ + #[allow(unused)] + clap_plugin: clap_plugin, + info: Arc, + plugin: UnsafeCell

, +} + +unsafe impl

Sync for Instance

{} + +impl Instance

{ + pub fn new(desc: *const clap_plugin_descriptor, info: &Arc) -> Self { + Instance { + clap_plugin: clap_plugin { + desc, + plugin_data: ptr::null_mut(), + init: Some(Self::init), + destroy: Some(Self::destroy), + activate: Some(Self::activate), + deactivate: Some(Self::deactivate), + start_processing: Some(Self::start_processing), + stop_processing: Some(Self::stop_processing), + reset: Some(Self::reset), + process: Some(Self::process), + get_extension: Some(Self::get_extension), + on_main_thread: Some(Self::on_main_thread), + }, + info: info.clone(), + plugin: UnsafeCell::new(P::new(Host {})), + } + } + + unsafe extern "C" fn init(_plugin: *const clap_plugin) -> bool { + true + } + + unsafe extern "C" fn destroy(plugin: *const clap_plugin) { + drop(Box::from_raw(plugin as *mut Self)); + } + + unsafe extern "C" fn activate( + _plugin: *const clap_plugin, + _sample_rate: f64, + _min_frames_count: u32, + _max_frames_count: u32, + ) -> bool { + true + } + + unsafe extern "C" fn deactivate(_plugin: *const clap_plugin) {} + + unsafe extern "C" fn start_processing(_plugin: *const clap_plugin) -> bool { + true + } + + unsafe extern "C" fn stop_processing(_plugin: *const clap_plugin) {} + + unsafe extern "C" fn reset(_plugin: *const clap_plugin) {} + + unsafe extern "C" fn process( + _plugin: *const clap_plugin, + _process: *const clap_process, + ) -> clap_process_status { + CLAP_PROCESS_CONTINUE + } + + unsafe extern "C" fn get_extension( + _plugin: *const clap_plugin, + _id: *const c_char, + ) -> *const c_void { + ptr::null() + } + + unsafe extern "C" fn on_main_thread(_plugin: *const clap_plugin) {} +} diff --git a/src/format/clap/mod.rs b/src/format/clap/mod.rs index 393ccb4..4350823 100644 --- a/src/format/clap/mod.rs +++ b/src/format/clap/mod.rs @@ -3,6 +3,7 @@ use std::ffi::{c_char, c_void}; use clap_sys::{entry::*, version::*}; mod factory; +mod instance; #[doc(hidden)] pub use factory::Factory;