1
0
Fork 0

Delay CLAP host extension query to init()

Or the CLAP example host will get very mad at us.
This commit is contained in:
Robbert van der Helm 2022-03-03 21:09:12 +01:00
parent e4ca8ba75a
commit 184355a886

View file

@ -2,6 +2,7 @@
// explicitly pattern match on that unit // explicitly pattern match on that unit
#![allow(clippy::unused_unit)] #![allow(clippy::unused_unit)]
use atomic_refcell::AtomicRefCell;
use clap_sys::events::{ use clap_sys::events::{
clap_event_header, clap_event_note, clap_event_param_mod, clap_event_param_value, clap_event_header, clap_event_note, clap_event_param_mod, clap_event_param_value,
clap_input_events, clap_output_events, CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_MIDI, clap_input_events, clap_output_events, CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_MIDI,
@ -151,10 +152,10 @@ pub struct Wrapper<P: ClapPlugin> {
clap_plugin_gui_win32: clap_plugin_gui_win32, clap_plugin_gui_win32: clap_plugin_gui_win32,
clap_plugin_latency: clap_plugin_latency, clap_plugin_latency: clap_plugin_latency,
host_latency: Option<ClapPtr<clap_host_latency>>, host_latency: AtomicRefCell<Option<ClapPtr<clap_host_latency>>>,
clap_plugin_params: clap_plugin_params, clap_plugin_params: clap_plugin_params,
host_params: Option<ClapPtr<clap_host_params>>, host_params: AtomicRefCell<Option<ClapPtr<clap_host_params>>>,
// These fiels are exactly the same as their VST3 wrapper counterparts. // These fiels are exactly the same as their VST3 wrapper counterparts.
// //
/// The keys from `param_map` in a stable order. /// The keys from `param_map` in a stable order.
@ -182,7 +183,7 @@ pub struct Wrapper<P: ClapPlugin> {
/// in the same order, right? /// in the same order, right?
output_parameter_changes: ArrayQueue<OutputParamChange>, output_parameter_changes: ArrayQueue<OutputParamChange>,
host_thread_check: Option<ClapPtr<clap_host_thread_check>>, host_thread_check: AtomicRefCell<Option<ClapPtr<clap_host_thread_check>>>,
clap_plugin_state: clap_plugin_state, clap_plugin_state: clap_plugin_state,
@ -252,7 +253,7 @@ impl<P: ClapPlugin> EventLoop<Task, Wrapper<P>> for Wrapper<P> {
fn is_main_thread(&self) -> bool { fn is_main_thread(&self) -> bool {
// If the host supports the thread check interface then we'll use that, otherwise we'll // If the host supports the thread check interface then we'll use that, otherwise we'll
// check if this is the same thread as the one that created the plugin instance. // check if this is the same thread as the one that created the plugin instance.
match &self.host_thread_check { match &*self.host_thread_check.borrow() {
Some(thread_check) => unsafe { (thread_check.is_main_thread)(&*self.host_callback) }, Some(thread_check) => unsafe { (thread_check.is_main_thread)(&*self.host_callback) },
None => thread::current().id() == self.main_thread_id, None => thread::current().id() == self.main_thread_id,
} }
@ -263,7 +264,7 @@ impl<P: ClapPlugin> MainThreadExecutor<Task> for Wrapper<P> {
unsafe fn execute(&self, task: Task) { unsafe fn execute(&self, task: Task) {
// This function is always called from the main thread, from [Self::on_main_thread]. // This function is always called from the main thread, from [Self::on_main_thread].
match task { match task {
Task::LatencyChanged => match &self.host_latency { Task::LatencyChanged => match &*self.host_latency.borrow() {
Some(host_latency) => (host_latency.changed)(&*self.host_callback), Some(host_latency) => (host_latency.changed)(&*self.host_callback),
None => nih_debug_assert_failure!("Host does not support the latency extension"), None => nih_debug_assert_failure!("Host does not support the latency extension"),
}, },
@ -278,15 +279,10 @@ impl<P: ClapPlugin> Wrapper<P> {
let plugin_descriptor = Box::new(PluginDescriptor::default()); let plugin_descriptor = Box::new(PluginDescriptor::default());
// We're not allowed to query any extensions until the init function has been called, so we
// need a bunch of AtomicRefCells instead
assert!(!host_callback.is_null()); assert!(!host_callback.is_null());
let host_callback = unsafe { ClapPtr::new(host_callback) }; let host_callback = unsafe { ClapPtr::new(host_callback) };
let host_latency =
unsafe { query_host_extension::<clap_host_latency>(&host_callback, CLAP_EXT_LATENCY) };
let host_params =
unsafe { query_host_extension::<clap_host_params>(&host_callback, CLAP_EXT_PARAMS) };
let host_thread_check = unsafe {
query_host_extension::<clap_host_thread_check>(&host_callback, CLAP_EXT_THREAD_CHECK)
};
let mut wrapper = Self { let mut wrapper = Self {
clap_plugin: clap_plugin { clap_plugin: clap_plugin {
@ -370,7 +366,7 @@ impl<P: ClapPlugin> Wrapper<P> {
clap_plugin_latency: clap_plugin_latency { clap_plugin_latency: clap_plugin_latency {
get: Self::ext_latency_get, get: Self::ext_latency_get,
}, },
host_latency, host_latency: AtomicRefCell::new(None),
clap_plugin_params: clap_plugin_params { clap_plugin_params: clap_plugin_params {
count: Self::ext_params_count, count: Self::ext_params_count,
@ -380,7 +376,7 @@ impl<P: ClapPlugin> Wrapper<P> {
text_to_value: Self::ext_params_text_to_value, text_to_value: Self::ext_params_text_to_value,
flush: Self::ext_params_flush, flush: Self::ext_params_flush,
}, },
host_params, host_params: AtomicRefCell::new(None),
param_hashes: Vec::new(), param_hashes: Vec::new(),
param_by_hash: HashMap::new(), param_by_hash: HashMap::new(),
param_defaults_normalized: HashMap::new(), param_defaults_normalized: HashMap::new(),
@ -388,7 +384,7 @@ impl<P: ClapPlugin> Wrapper<P> {
param_ptr_to_hash: HashMap::new(), param_ptr_to_hash: HashMap::new(),
output_parameter_changes: ArrayQueue::new(OUTPUT_EVENT_QUEUE_CAPACITY), output_parameter_changes: ArrayQueue::new(OUTPUT_EVENT_QUEUE_CAPACITY),
host_thread_check, host_thread_check: AtomicRefCell::new(None),
clap_plugin_state: clap_plugin_state { clap_plugin_state: clap_plugin_state {
save: Self::ext_state_save, save: Self::ext_state_save,
@ -495,7 +491,7 @@ impl<P: ClapPlugin> Wrapper<P> {
/// host (it will still be set on the plugin either way). /// host (it will still be set on the plugin either way).
pub fn queue_parameter_change(&self, change: OutputParamChange) -> bool { pub fn queue_parameter_change(&self, change: OutputParamChange) -> bool {
let result = self.output_parameter_changes.push(change).is_ok(); let result = self.output_parameter_changes.push(change).is_ok();
match &self.host_params { match &*self.host_params.borrow() {
Some(host_params) if !self.is_processing.load(Ordering::SeqCst) => { Some(host_params) if !self.is_processing.load(Ordering::SeqCst) => {
unsafe { (host_params.request_flush)(&*self.host_callback) }; unsafe { (host_params.request_flush)(&*self.host_callback) };
} }
@ -679,8 +675,20 @@ impl<P: ClapPlugin> Wrapper<P> {
} }
} }
unsafe extern "C" fn init(_plugin: *const clap_plugin) -> bool { unsafe extern "C" fn init(plugin: *const clap_plugin) -> bool {
// We don't need any special initialization check_null_ptr!(false, plugin);
let wrapper = &*(plugin as *const Self);
// We weren't allowed to query these in the constructor, so we need to do it now intead.
*wrapper.host_latency.borrow_mut() =
query_host_extension::<clap_host_latency>(&wrapper.host_callback, CLAP_EXT_LATENCY);
*wrapper.host_params.borrow_mut() =
query_host_extension::<clap_host_params>(&wrapper.host_callback, CLAP_EXT_PARAMS);
*wrapper.host_thread_check.borrow_mut() = query_host_extension::<clap_host_thread_check>(
&wrapper.host_callback,
CLAP_EXT_THREAD_CHECK,
);
true true
} }