Skip to content

Commit

Permalink
clap: plugin instantiation
Browse files Browse the repository at this point in the history
  • Loading branch information
micahrj committed Oct 16, 2023
1 parent dc12017 commit 09b6110
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 25 deletions.
69 changes: 44 additions & 25 deletions src/format/clap/factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<PluginInfo>,
}

#[doc(hidden)]
#[repr(C)]
pub struct Factory<P> {
#[allow(unused)]
factory: clap_plugin_factory,
descriptor: UnsafeCell<Option<clap_plugin_descriptor>>,
state: UnsafeCell<Option<FactoryState>>,
_marker: PhantomData<P>,
}

Expand All @@ -27,45 +34,48 @@ impl<P: Plugin + ClapPlugin> Factory<P> {
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();

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));
}
}

Expand All @@ -88,19 +98,28 @@ impl<P: Plugin + ClapPlugin> Factory<P> {
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;
}
}

ptr::null()
}

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::<P>::new(&state.descriptor, &state.info));
return Box::into_raw(instance) as *const clap_plugin;
}
}

ptr::null()
}
}
84 changes: 84 additions & 0 deletions src/format/clap/instance.rs
Original file line number Diff line number Diff line change
@@ -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<P> {
#[allow(unused)]
clap_plugin: clap_plugin,
info: Arc<PluginInfo>,
plugin: UnsafeCell<P>,
}

unsafe impl<P> Sync for Instance<P> {}

impl<P: Plugin> Instance<P> {
pub fn new(desc: *const clap_plugin_descriptor, info: &Arc<PluginInfo>) -> 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) {}
}
1 change: 1 addition & 0 deletions src/format/clap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 09b6110

Please sign in to comment.