Update clap-sys with optional function pointers
None of these function pointers are allowed to be null, yet even the official `clap-helpers` do this. This new `clap_call!()` macro asserts that a pointer is non-null before calling it.
This commit is contained in:
parent
24d499e716
commit
5cbd8827e9
5
Cargo.lock
generated
5
Cargo.lock
generated
|
@ -502,9 +502,8 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap-sys"
|
name = "clap-sys"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/glowcoil/clap-sys.git?rev=efc0940651c3a57a3f9402bf3798cda9a7f7fc87#efc0940651c3a57a3f9402bf3798cda9a7f7fc87"
|
||||||
checksum = "4a8aa914ef6a42441b5ef7884eef20c6d38bd5b24c3c9eba865b08bf3353bc11"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_derive"
|
name = "clap_derive"
|
||||||
|
|
|
@ -67,7 +67,8 @@ atomic_refcell = "0.1"
|
||||||
backtrace = "0.3.65"
|
backtrace = "0.3.65"
|
||||||
bitflags = "1.3"
|
bitflags = "1.3"
|
||||||
cfg-if = "1.0"
|
cfg-if = "1.0"
|
||||||
clap-sys = "0.1"
|
# TODO: Switch back to the crates.rs version once the debug prints are in a released version
|
||||||
|
clap-sys = { git = "https://github.com/glowcoil/clap-sys.git", rev = "efc0940651c3a57a3f9402bf3798cda9a7f7fc87" }
|
||||||
crossbeam = "0.8"
|
crossbeam = "0.8"
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
log = { version = "0.4", features = ["std", "release_max_level_info"] }
|
log = { version = "0.4", features = ["std", "release_max_level_info"] }
|
||||||
|
|
|
@ -42,11 +42,7 @@ macro_rules! nih_export_clap {
|
||||||
) -> *const ::std::ffi::c_void {
|
) -> *const ::std::ffi::c_void {
|
||||||
if !factory_id.is_null()
|
if !factory_id.is_null()
|
||||||
&& unsafe { ::std::ffi::CStr::from_ptr(factory_id) }
|
&& unsafe { ::std::ffi::CStr::from_ptr(factory_id) }
|
||||||
== unsafe {
|
== ::nih_plug::wrapper::clap::CLAP_PLUGIN_FACTORY_ID
|
||||||
::std::ffi::CStr::from_ptr(
|
|
||||||
::nih_plug::wrapper::clap::CLAP_PLUGIN_FACTORY_ID,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
&(*FACTORY).clap_plugin_factory as *const _ as *const ::std::ffi::c_void
|
&(*FACTORY).clap_plugin_factory as *const _ as *const ::std::ffi::c_void
|
||||||
} else {
|
} else {
|
||||||
|
@ -60,9 +56,9 @@ macro_rules! nih_export_clap {
|
||||||
pub static clap_entry: ::nih_plug::wrapper::clap::clap_plugin_entry =
|
pub static clap_entry: ::nih_plug::wrapper::clap::clap_plugin_entry =
|
||||||
::nih_plug::wrapper::clap::clap_plugin_entry {
|
::nih_plug::wrapper::clap::clap_plugin_entry {
|
||||||
clap_version: ::nih_plug::wrapper::clap::CLAP_VERSION,
|
clap_version: ::nih_plug::wrapper::clap::CLAP_VERSION,
|
||||||
init: self::clap::init,
|
init: Some(self::clap::init),
|
||||||
deinit: self::clap::deinit,
|
deinit: Some(self::clap::deinit),
|
||||||
get_factory: self::clap::get_factory,
|
get_factory: Some(self::clap::get_factory),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,9 +25,9 @@ impl<P: ClapPlugin> Default for Factory<P> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
clap_plugin_factory: clap_plugin_factory {
|
clap_plugin_factory: clap_plugin_factory {
|
||||||
get_plugin_count: Self::get_plugin_count,
|
get_plugin_count: Some(Self::get_plugin_count),
|
||||||
get_plugin_descriptor: Self::get_plugin_descriptor,
|
get_plugin_descriptor: Some(Self::get_plugin_descriptor),
|
||||||
create_plugin: Self::create_plugin,
|
create_plugin: Some(Self::create_plugin),
|
||||||
},
|
},
|
||||||
plugin_descriptor: PluginDescriptor::default(),
|
plugin_descriptor: PluginDescriptor::default(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::os::raw::c_void;
|
||||||
/// null.
|
/// null.
|
||||||
macro_rules! check_null_ptr {
|
macro_rules! check_null_ptr {
|
||||||
($ret:expr, $ptr:expr $(, $ptrs:expr)* $(, )?) => {
|
($ret:expr, $ptr:expr $(, $ptrs:expr)* $(, )?) => {
|
||||||
check_null_ptr_msg!("Null pointer passed to function", $ret, $ptr $(, $ptrs)*)
|
$crate::wrapper::clap::util::check_null_ptr_msg!("Null pointer passed to function", $ret, $ptr $(, $ptrs)*)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,40 @@ macro_rules! check_null_ptr_msg {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Call a CLAP function. This is needed because even though none of CLAP's functions are allowed to
|
||||||
|
/// be null pointers, people will still use null pointers for some of the function arguments. This
|
||||||
|
/// also happens in the official `clap-helpers`. As such, these functions are now `Option<fn(...)>`
|
||||||
|
/// optional function pointers in `clap-sys`. This macro asserts that the pointer is not null, and
|
||||||
|
/// prints a nicely formatted error message containing the struct and funciton name if it is. It
|
||||||
|
/// also emulates C's syntax for accessing fields struct through a pointer. Except that it uses `=>`
|
||||||
|
/// instead of `->`. Because that sounds like it would be hilarious.
|
||||||
|
macro_rules! clap_call {
|
||||||
|
{ $obj_ptr:expr=>$function_name:ident($($args:expr),* $(, )?) } => {
|
||||||
|
match (*$obj_ptr).$function_name {
|
||||||
|
Some(function_ptr) => function_ptr($($args),*),
|
||||||
|
None => panic!("'{}::{}' is a null pointer, but this is not allowed", $crate::wrapper::clap::util::type_name_of_ptr($obj_ptr), stringify!($function_name)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// [`clap_call!()`], wrapped in an unsafe block.
|
||||||
|
macro_rules! unsafe_clap_call {
|
||||||
|
{ $($args:tt)* } => {
|
||||||
|
unsafe { $crate::wrapper::clap::util::clap_call! { $($args)* } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Similar to, [`std::any::type_name_of_val()`], but on stable Rust, and stripping away the pointer
|
||||||
|
/// part.
|
||||||
|
#[must_use]
|
||||||
|
pub fn type_name_of_ptr<T: ?Sized>(_ptr: *const T) -> &'static str {
|
||||||
|
std::any::type_name::<T>()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) use check_null_ptr_msg;
|
||||||
|
pub(crate) use clap_call;
|
||||||
|
pub(crate) use unsafe_clap_call;
|
||||||
|
|
||||||
/// Send+Sync wrapper around CLAP host extension pointers.
|
/// Send+Sync wrapper around CLAP host extension pointers.
|
||||||
pub struct ClapPtr<T> {
|
pub struct ClapPtr<T> {
|
||||||
inner: *const T,
|
inner: *const T,
|
||||||
|
@ -92,8 +126,8 @@ unsafe impl ByteReadBuffer for &mut [MaybeUninit<u8>] {
|
||||||
pub fn read_stream(stream: &clap_istream, mut slice: impl ByteReadBuffer) -> bool {
|
pub fn read_stream(stream: &clap_istream, mut slice: impl ByteReadBuffer) -> bool {
|
||||||
let mut read_pos = 0;
|
let mut read_pos = 0;
|
||||||
while read_pos < slice.len() {
|
while read_pos < slice.len() {
|
||||||
let bytes_read = unsafe {
|
let bytes_read = unsafe_clap_call! {
|
||||||
(stream.read)(
|
stream=>read(
|
||||||
stream,
|
stream,
|
||||||
slice.as_mut_ptr().add(read_pos) as *mut c_void,
|
slice.as_mut_ptr().add(read_pos) as *mut c_void,
|
||||||
(slice.len() - read_pos) as u64,
|
(slice.len() - read_pos) as u64,
|
||||||
|
@ -115,8 +149,8 @@ pub fn read_stream(stream: &clap_istream, mut slice: impl ByteReadBuffer) -> boo
|
||||||
pub fn write_stream(stream: &clap_ostream, slice: &[u8]) -> bool {
|
pub fn write_stream(stream: &clap_ostream, slice: &[u8]) -> bool {
|
||||||
let mut write_pos = 0;
|
let mut write_pos = 0;
|
||||||
while write_pos < slice.len() {
|
while write_pos < slice.len() {
|
||||||
let bytes_written = unsafe {
|
let bytes_written = unsafe_clap_call! {
|
||||||
(stream.write)(
|
stream=>write(
|
||||||
stream,
|
stream,
|
||||||
slice.as_ptr().add(write_pos) as *const c_void,
|
slice.as_ptr().add(write_pos) as *const c_void,
|
||||||
(slice.len() - write_pos) as u64,
|
(slice.len() - write_pos) as u64,
|
||||||
|
|
|
@ -305,7 +305,7 @@ impl<P: ClapPlugin> EventLoop<Task, Wrapper<P>> for Wrapper<P> {
|
||||||
if success {
|
if success {
|
||||||
// CLAP lets us use the host's event loop instead of having to implement our own
|
// CLAP lets us use the host's event loop instead of having to implement our own
|
||||||
let host = &self.host_callback;
|
let host = &self.host_callback;
|
||||||
unsafe { (host.request_callback)(&**host) };
|
unsafe_clap_call! { host=>request_callback(&**host) };
|
||||||
}
|
}
|
||||||
|
|
||||||
success
|
success
|
||||||
|
@ -316,7 +316,9 @@ impl<P: ClapPlugin> EventLoop<Task, Wrapper<P>> for Wrapper<P> {
|
||||||
// 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.borrow() {
|
match &*self.host_thread_check.borrow() {
|
||||||
Some(thread_check) => unsafe { (thread_check.is_main_thread)(&*self.host_callback) },
|
Some(thread_check) => {
|
||||||
|
unsafe_clap_call! { thread_check=>is_main_thread(&*self.host_callback) }
|
||||||
|
}
|
||||||
// FIXME: `thread::current()` may allocate the first time it's called, is there a safe
|
// FIXME: `thread::current()` may allocate the first time it's called, is there a safe
|
||||||
// nonallocating version of this without using huge OS-specific libraries?
|
// nonallocating version of this without using huge OS-specific libraries?
|
||||||
None => permit_alloc(|| thread::current().id() == self.main_thread_id),
|
None => permit_alloc(|| thread::current().id() == self.main_thread_id),
|
||||||
|
@ -335,16 +337,16 @@ impl<P: ClapPlugin> MainThreadExecutor<Task> for Wrapper<P> {
|
||||||
// is processing, but we'll treat it as the same thing). In practice just
|
// is processing, but we'll treat it as the same thing). In practice just
|
||||||
// calling the latency changed function also seems to work just fine.
|
// calling the latency changed function also seems to work just fine.
|
||||||
if self.is_processing.load(Ordering::SeqCst) {
|
if self.is_processing.load(Ordering::SeqCst) {
|
||||||
(self.host_callback.request_restart)(&*self.host_callback)
|
clap_call! { &*self.host_callback=>request_restart(&*self.host_callback) };
|
||||||
} else {
|
} else {
|
||||||
(host_latency.changed)(&*self.host_callback)
|
clap_call! { 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"),
|
||||||
},
|
},
|
||||||
Task::RescanParamValues => match &*self.host_params.borrow() {
|
Task::RescanParamValues => match &*self.host_params.borrow() {
|
||||||
Some(host_params) => {
|
Some(host_params) => {
|
||||||
(host_params.rescan)(&*self.host_callback, CLAP_PARAM_RESCAN_VALUES);
|
clap_call! { host_params=>rescan(&*self.host_callback, CLAP_PARAM_RESCAN_VALUES) };
|
||||||
}
|
}
|
||||||
None => nih_debug_assert_failure!("The host does not support parameters? What?"),
|
None => nih_debug_assert_failure!("The host does not support parameters? What?"),
|
||||||
},
|
},
|
||||||
|
@ -487,16 +489,16 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
// We already need to use pointer casts in the factory, so might as well continue
|
// We already need to use pointer casts in the factory, so might as well continue
|
||||||
// doing that here
|
// doing that here
|
||||||
plugin_data: ptr::null_mut(),
|
plugin_data: ptr::null_mut(),
|
||||||
init: Self::init,
|
init: Some(Self::init),
|
||||||
destroy: Self::destroy,
|
destroy: Some(Self::destroy),
|
||||||
activate: Self::activate,
|
activate: Some(Self::activate),
|
||||||
deactivate: Self::deactivate,
|
deactivate: Some(Self::deactivate),
|
||||||
start_processing: Self::start_processing,
|
start_processing: Some(Self::start_processing),
|
||||||
stop_processing: Self::stop_processing,
|
stop_processing: Some(Self::stop_processing),
|
||||||
reset: Self::reset,
|
reset: Some(Self::reset),
|
||||||
process: Self::process,
|
process: Some(Self::process),
|
||||||
get_extension: Self::get_extension,
|
get_extension: Some(Self::get_extension),
|
||||||
on_main_thread: Self::on_main_thread,
|
on_main_thread: Some(Self::on_main_thread),
|
||||||
},
|
},
|
||||||
|
|
||||||
this: AtomicRefCell::new(Weak::new()),
|
this: AtomicRefCell::new(Weak::new()),
|
||||||
|
@ -532,53 +534,53 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
host_callback,
|
host_callback,
|
||||||
|
|
||||||
clap_plugin_audio_ports_config: clap_plugin_audio_ports_config {
|
clap_plugin_audio_ports_config: clap_plugin_audio_ports_config {
|
||||||
count: Self::ext_audio_ports_config_count,
|
count: Some(Self::ext_audio_ports_config_count),
|
||||||
get: Self::ext_audio_ports_config_get,
|
get: Some(Self::ext_audio_ports_config_get),
|
||||||
select: Self::ext_audio_ports_config_select,
|
select: Some(Self::ext_audio_ports_config_select),
|
||||||
},
|
},
|
||||||
supported_bus_configs,
|
supported_bus_configs,
|
||||||
|
|
||||||
clap_plugin_audio_ports: clap_plugin_audio_ports {
|
clap_plugin_audio_ports: clap_plugin_audio_ports {
|
||||||
count: Self::ext_audio_ports_count,
|
count: Some(Self::ext_audio_ports_count),
|
||||||
get: Self::ext_audio_ports_get,
|
get: Some(Self::ext_audio_ports_get),
|
||||||
},
|
},
|
||||||
|
|
||||||
clap_plugin_gui: clap_plugin_gui {
|
clap_plugin_gui: clap_plugin_gui {
|
||||||
is_api_supported: Self::ext_gui_is_api_supported,
|
is_api_supported: Some(Self::ext_gui_is_api_supported),
|
||||||
get_preferred_api: Self::ext_gui_get_preferred_api,
|
get_preferred_api: Some(Self::ext_gui_get_preferred_api),
|
||||||
create: Self::ext_gui_create,
|
create: Some(Self::ext_gui_create),
|
||||||
destroy: Self::ext_gui_destroy,
|
destroy: Some(Self::ext_gui_destroy),
|
||||||
set_scale: Self::ext_gui_set_scale,
|
set_scale: Some(Self::ext_gui_set_scale),
|
||||||
get_size: Self::ext_gui_get_size,
|
get_size: Some(Self::ext_gui_get_size),
|
||||||
can_resize: Self::ext_gui_can_resize,
|
can_resize: Some(Self::ext_gui_can_resize),
|
||||||
get_resize_hints: Self::ext_gui_get_resize_hints,
|
get_resize_hints: Some(Self::ext_gui_get_resize_hints),
|
||||||
adjust_size: Self::ext_gui_adjust_size,
|
adjust_size: Some(Self::ext_gui_adjust_size),
|
||||||
set_size: Self::ext_gui_set_size,
|
set_size: Some(Self::ext_gui_set_size),
|
||||||
set_parent: Self::ext_gui_set_parent,
|
set_parent: Some(Self::ext_gui_set_parent),
|
||||||
set_transient: Self::ext_gui_set_transient,
|
set_transient: Some(Self::ext_gui_set_transient),
|
||||||
suggest_title: Self::ext_gui_suggest_title,
|
suggest_title: Some(Self::ext_gui_suggest_title),
|
||||||
show: Self::ext_gui_show,
|
show: Some(Self::ext_gui_show),
|
||||||
hide: Self::ext_gui_hide,
|
hide: Some(Self::ext_gui_hide),
|
||||||
},
|
},
|
||||||
host_gui: AtomicRefCell::new(None),
|
host_gui: AtomicRefCell::new(None),
|
||||||
|
|
||||||
clap_plugin_latency: clap_plugin_latency {
|
clap_plugin_latency: clap_plugin_latency {
|
||||||
get: Self::ext_latency_get,
|
get: Some(Self::ext_latency_get),
|
||||||
},
|
},
|
||||||
host_latency: AtomicRefCell::new(None),
|
host_latency: AtomicRefCell::new(None),
|
||||||
|
|
||||||
clap_plugin_note_ports: clap_plugin_note_ports {
|
clap_plugin_note_ports: clap_plugin_note_ports {
|
||||||
count: Self::ext_note_ports_count,
|
count: Some(Self::ext_note_ports_count),
|
||||||
get: Self::ext_note_ports_get,
|
get: Some(Self::ext_note_ports_get),
|
||||||
},
|
},
|
||||||
|
|
||||||
clap_plugin_params: clap_plugin_params {
|
clap_plugin_params: clap_plugin_params {
|
||||||
count: Self::ext_params_count,
|
count: Some(Self::ext_params_count),
|
||||||
get_info: Self::ext_params_get_info,
|
get_info: Some(Self::ext_params_get_info),
|
||||||
get_value: Self::ext_params_get_value,
|
get_value: Some(Self::ext_params_get_value),
|
||||||
value_to_text: Self::ext_params_value_to_text,
|
value_to_text: Some(Self::ext_params_value_to_text),
|
||||||
text_to_value: Self::ext_params_text_to_value,
|
text_to_value: Some(Self::ext_params_text_to_value),
|
||||||
flush: Self::ext_params_flush,
|
flush: Some(Self::ext_params_flush),
|
||||||
},
|
},
|
||||||
host_params: AtomicRefCell::new(None),
|
host_params: AtomicRefCell::new(None),
|
||||||
param_hashes,
|
param_hashes,
|
||||||
|
@ -591,17 +593,17 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
host_thread_check: AtomicRefCell::new(None),
|
host_thread_check: AtomicRefCell::new(None),
|
||||||
|
|
||||||
clap_plugin_render: clap_plugin_render {
|
clap_plugin_render: clap_plugin_render {
|
||||||
has_hard_realtime_requirement: Self::ext_render_has_hard_realtime_requirement,
|
has_hard_realtime_requirement: Some(Self::ext_render_has_hard_realtime_requirement),
|
||||||
set: Self::ext_render_set,
|
set: Some(Self::ext_render_set),
|
||||||
},
|
},
|
||||||
|
|
||||||
clap_plugin_state: clap_plugin_state {
|
clap_plugin_state: clap_plugin_state {
|
||||||
save: Self::ext_state_save,
|
save: Some(Self::ext_state_save),
|
||||||
load: Self::ext_state_load,
|
load: Some(Self::ext_state_load),
|
||||||
},
|
},
|
||||||
|
|
||||||
clap_plugin_tail: clap_plugin_tail {
|
clap_plugin_tail: clap_plugin_tail {
|
||||||
get: Self::ext_tail_get,
|
get: Some(Self::ext_tail_get),
|
||||||
},
|
},
|
||||||
|
|
||||||
tasks: ArrayQueue::new(TASK_QUEUE_CAPACITY),
|
tasks: ArrayQueue::new(TASK_QUEUE_CAPACITY),
|
||||||
|
@ -645,7 +647,9 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
|
|
||||||
// Requesting a flush is fine even during audio processing. This avoids a race condition.
|
// Requesting a flush is fine even during audio processing. This avoids a race condition.
|
||||||
match &*self.host_params.borrow() {
|
match &*self.host_params.borrow() {
|
||||||
Some(host_params) => unsafe { (host_params.request_flush)(&*self.host_callback) },
|
Some(host_params) => {
|
||||||
|
unsafe_clap_call! { host_params=>request_flush(&*self.host_callback) }
|
||||||
|
}
|
||||||
None => nih_debug_assert_failure!("The host does not support parameters? What?"),
|
None => nih_debug_assert_failure!("The host does not support parameters? What?"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -670,8 +674,8 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
let (unscaled_width, unscaled_height) = editor.size();
|
let (unscaled_width, unscaled_height) = editor.size();
|
||||||
let scaling_factor = self.editor_scaling_factor.load(Ordering::Relaxed);
|
let scaling_factor = self.editor_scaling_factor.load(Ordering::Relaxed);
|
||||||
|
|
||||||
unsafe {
|
unsafe_clap_call! {
|
||||||
(host_gui.request_resize)(
|
host_gui=>request_resize(
|
||||||
&*self.host_callback,
|
&*self.host_callback,
|
||||||
(unscaled_width as f32 * scaling_factor).round() as u32,
|
(unscaled_width as f32 * scaling_factor).round() as u32,
|
||||||
(unscaled_height as f32 * scaling_factor).round() as u32,
|
(unscaled_height as f32 * scaling_factor).round() as u32,
|
||||||
|
@ -738,10 +742,10 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
let mut input_events = self.input_events.borrow_mut();
|
let mut input_events = self.input_events.borrow_mut();
|
||||||
input_events.clear();
|
input_events.clear();
|
||||||
|
|
||||||
let num_events = ((*in_).size)(in_);
|
let num_events = clap_call! { in_=>size(in_) };
|
||||||
let mut parameter_values_changed = false;
|
let mut parameter_values_changed = false;
|
||||||
for event_idx in 0..num_events {
|
for event_idx in 0..num_events {
|
||||||
let event = ((*in_).get)(in_, event_idx);
|
let event = clap_call! { in_=>get(in_, event_idx) };
|
||||||
parameter_values_changed |=
|
parameter_values_changed |=
|
||||||
self.handle_in_event(event, &mut input_events, None, current_sample_idx);
|
self.handle_in_event(event, &mut input_events, None, current_sample_idx);
|
||||||
}
|
}
|
||||||
|
@ -773,13 +777,13 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
input_events.clear();
|
input_events.clear();
|
||||||
|
|
||||||
// To achive this, we'll always read one event ahead
|
// To achive this, we'll always read one event ahead
|
||||||
let num_events = ((*in_).size)(in_);
|
let num_events = clap_call! { in_=>size(in_) };
|
||||||
if num_events == 0 {
|
if num_events == 0 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let start_idx = resume_from_event_idx as u32;
|
let start_idx = resume_from_event_idx as u32;
|
||||||
let mut event: *const clap_event_header = ((*in_).get)(in_, start_idx);
|
let mut event: *const clap_event_header = clap_call! { in_=>get(in_, start_idx) };
|
||||||
let mut parameter_values_changed = false;
|
let mut parameter_values_changed = false;
|
||||||
for next_event_idx in (start_idx + 1)..num_events {
|
for next_event_idx in (start_idx + 1)..num_events {
|
||||||
parameter_values_changed |= self.handle_in_event(
|
parameter_values_changed |= self.handle_in_event(
|
||||||
|
@ -791,7 +795,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
|
|
||||||
// Stop just before the next parameter change or transport information event at a sample
|
// Stop just before the next parameter change or transport information event at a sample
|
||||||
// after the current sample
|
// after the current sample
|
||||||
let next_event: *const clap_event_header = ((*in_).get)(in_, next_event_idx);
|
let next_event: *const clap_event_header = clap_call! { in_=>get(in_, next_event_idx) };
|
||||||
if (*next_event).time > current_sample_idx as u32 && stop_predicate(next_event) {
|
if (*next_event).time > current_sample_idx as u32 && stop_predicate(next_event) {
|
||||||
return Some(((*next_event).time as usize, next_event_idx as usize));
|
return Some(((*next_event).time as usize, next_event_idx as usize));
|
||||||
}
|
}
|
||||||
|
@ -840,7 +844,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
param_id: param_hash,
|
param_id: param_hash,
|
||||||
};
|
};
|
||||||
|
|
||||||
(out.try_push)(out, &event.header)
|
clap_call! { out=>try_push(out, &event.header) }
|
||||||
}
|
}
|
||||||
OutputParamEvent::SetValue {
|
OutputParamEvent::SetValue {
|
||||||
param_hash,
|
param_hash,
|
||||||
|
@ -870,7 +874,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
value: clap_plain_value,
|
value: clap_plain_value,
|
||||||
};
|
};
|
||||||
|
|
||||||
(out.try_push)(out, &event.header)
|
clap_call! { out=>try_push(out, &event.header) }
|
||||||
}
|
}
|
||||||
OutputParamEvent::EndGesture { param_hash } => {
|
OutputParamEvent::EndGesture { param_hash } => {
|
||||||
let event = clap_event_param_gesture {
|
let event = clap_event_param_gesture {
|
||||||
|
@ -884,7 +888,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
param_id: param_hash,
|
param_id: param_hash,
|
||||||
};
|
};
|
||||||
|
|
||||||
(out.try_push)(out, &event.header)
|
clap_call! { out=>try_push(out, &event.header) }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -925,7 +929,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
velocity: velocity as f64,
|
velocity: velocity as f64,
|
||||||
};
|
};
|
||||||
|
|
||||||
(out.try_push)(out, &event.header)
|
clap_call! { out=>try_push(out, &event.header) }
|
||||||
}
|
}
|
||||||
NoteEvent::NoteOff {
|
NoteEvent::NoteOff {
|
||||||
timing: _,
|
timing: _,
|
||||||
|
@ -948,7 +952,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
velocity: velocity as f64,
|
velocity: velocity as f64,
|
||||||
};
|
};
|
||||||
|
|
||||||
(out.try_push)(out, &event.header)
|
clap_call! { out=>try_push(out, &event.header) }
|
||||||
}
|
}
|
||||||
NoteEvent::PolyPressure {
|
NoteEvent::PolyPressure {
|
||||||
timing: _,
|
timing: _,
|
||||||
|
@ -972,7 +976,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
value: pressure as f64,
|
value: pressure as f64,
|
||||||
};
|
};
|
||||||
|
|
||||||
(out.try_push)(out, &event.header)
|
clap_call! { out=>try_push(out, &event.header) }
|
||||||
}
|
}
|
||||||
NoteEvent::PolyVolume {
|
NoteEvent::PolyVolume {
|
||||||
timing: _,
|
timing: _,
|
||||||
|
@ -996,7 +1000,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
value: gain as f64,
|
value: gain as f64,
|
||||||
};
|
};
|
||||||
|
|
||||||
(out.try_push)(out, &event.header)
|
clap_call! { out=>try_push(out, &event.header) }
|
||||||
}
|
}
|
||||||
NoteEvent::PolyPan {
|
NoteEvent::PolyPan {
|
||||||
timing: _,
|
timing: _,
|
||||||
|
@ -1020,7 +1024,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
value: (pan as f64 + 1.0) / 2.0,
|
value: (pan as f64 + 1.0) / 2.0,
|
||||||
};
|
};
|
||||||
|
|
||||||
(out.try_push)(out, &event.header)
|
clap_call! { out=>try_push(out, &event.header) }
|
||||||
}
|
}
|
||||||
NoteEvent::PolyTuning {
|
NoteEvent::PolyTuning {
|
||||||
timing: _,
|
timing: _,
|
||||||
|
@ -1044,7 +1048,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
value: tuning as f64,
|
value: tuning as f64,
|
||||||
};
|
};
|
||||||
|
|
||||||
(out.try_push)(out, &event.header)
|
clap_call! { out=>try_push(out, &event.header) }
|
||||||
}
|
}
|
||||||
NoteEvent::PolyVibrato {
|
NoteEvent::PolyVibrato {
|
||||||
timing: _,
|
timing: _,
|
||||||
|
@ -1068,7 +1072,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
value: vibrato as f64,
|
value: vibrato as f64,
|
||||||
};
|
};
|
||||||
|
|
||||||
(out.try_push)(out, &event.header)
|
clap_call! { out=>try_push(out, &event.header) }
|
||||||
}
|
}
|
||||||
NoteEvent::PolyExpression {
|
NoteEvent::PolyExpression {
|
||||||
timing: _,
|
timing: _,
|
||||||
|
@ -1092,7 +1096,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
value: expression as f64,
|
value: expression as f64,
|
||||||
};
|
};
|
||||||
|
|
||||||
(out.try_push)(out, &event.header)
|
clap_call! { out=>try_push(out, &event.header) }
|
||||||
}
|
}
|
||||||
NoteEvent::PolyBrightness {
|
NoteEvent::PolyBrightness {
|
||||||
timing: _,
|
timing: _,
|
||||||
|
@ -1116,7 +1120,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
value: brightness as f64,
|
value: brightness as f64,
|
||||||
};
|
};
|
||||||
|
|
||||||
(out.try_push)(out, &event.header)
|
clap_call! { out=>try_push(out, &event.header) }
|
||||||
}
|
}
|
||||||
NoteEvent::MidiChannelPressure {
|
NoteEvent::MidiChannelPressure {
|
||||||
timing: _,
|
timing: _,
|
||||||
|
@ -1139,7 +1143,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
(out.try_push)(out, &event.header)
|
clap_call! { out=>try_push(out, &event.header) }
|
||||||
}
|
}
|
||||||
NoteEvent::MidiPitchBend {
|
NoteEvent::MidiPitchBend {
|
||||||
timing: _,
|
timing: _,
|
||||||
|
@ -1164,7 +1168,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
(out.try_push)(out, &event.header)
|
clap_call! { out=>try_push(out, &event.header) }
|
||||||
}
|
}
|
||||||
NoteEvent::MidiCC {
|
NoteEvent::MidiCC {
|
||||||
timing: _,
|
timing: _,
|
||||||
|
@ -1188,7 +1192,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
(out.try_push)(out, &event.header)
|
clap_call! { out=>try_push(out, &event.header) }
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
nih_debug_assert_failure!(
|
nih_debug_assert_failure!(
|
||||||
|
@ -2081,24 +2085,24 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
|
|
||||||
let id = CStr::from_ptr(id);
|
let id = CStr::from_ptr(id);
|
||||||
|
|
||||||
if id == CStr::from_ptr(CLAP_EXT_AUDIO_PORTS_CONFIG) {
|
if id == CLAP_EXT_AUDIO_PORTS_CONFIG {
|
||||||
&wrapper.clap_plugin_audio_ports_config as *const _ as *const c_void
|
&wrapper.clap_plugin_audio_ports_config as *const _ as *const c_void
|
||||||
} else if id == CStr::from_ptr(CLAP_EXT_AUDIO_PORTS) {
|
} else if id == CLAP_EXT_AUDIO_PORTS {
|
||||||
&wrapper.clap_plugin_audio_ports as *const _ as *const c_void
|
&wrapper.clap_plugin_audio_ports as *const _ as *const c_void
|
||||||
} else if id == CStr::from_ptr(CLAP_EXT_GUI) && wrapper.editor.is_some() {
|
} else if id == CLAP_EXT_GUI && wrapper.editor.is_some() {
|
||||||
// Only report that we support this extension if the plugin has an editor
|
// Only report that we support this extension if the plugin has an editor
|
||||||
&wrapper.clap_plugin_gui as *const _ as *const c_void
|
&wrapper.clap_plugin_gui as *const _ as *const c_void
|
||||||
} else if id == CStr::from_ptr(CLAP_EXT_LATENCY) {
|
} else if id == CLAP_EXT_LATENCY {
|
||||||
&wrapper.clap_plugin_latency as *const _ as *const c_void
|
&wrapper.clap_plugin_latency as *const _ as *const c_void
|
||||||
} else if id == CStr::from_ptr(CLAP_EXT_NOTE_PORTS)
|
} else if id == CLAP_EXT_NOTE_PORTS
|
||||||
&& (P::MIDI_INPUT >= MidiConfig::Basic || P::MIDI_OUTPUT >= MidiConfig::Basic)
|
&& (P::MIDI_INPUT >= MidiConfig::Basic || P::MIDI_OUTPUT >= MidiConfig::Basic)
|
||||||
{
|
{
|
||||||
&wrapper.clap_plugin_note_ports as *const _ as *const c_void
|
&wrapper.clap_plugin_note_ports as *const _ as *const c_void
|
||||||
} else if id == CStr::from_ptr(CLAP_EXT_PARAMS) {
|
} else if id == CLAP_EXT_PARAMS {
|
||||||
&wrapper.clap_plugin_params as *const _ as *const c_void
|
&wrapper.clap_plugin_params as *const _ as *const c_void
|
||||||
} else if id == CStr::from_ptr(CLAP_EXT_STATE) {
|
} else if id == CLAP_EXT_STATE {
|
||||||
&wrapper.clap_plugin_state as *const _ as *const c_void
|
&wrapper.clap_plugin_state as *const _ as *const c_void
|
||||||
} else if id == CStr::from_ptr(CLAP_EXT_TAIL) {
|
} else if id == CLAP_EXT_TAIL {
|
||||||
&wrapper.clap_plugin_tail as *const _ as *const c_void
|
&wrapper.clap_plugin_tail as *const _ as *const c_void
|
||||||
} else {
|
} else {
|
||||||
nih_trace!("Host tried to query unknown extension {:?}", id);
|
nih_trace!("Host tried to query unknown extension {:?}", id);
|
||||||
|
@ -2154,13 +2158,13 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
} => format!("{num_input_channels} inputs, {num_output_channels} outputs"),
|
} => format!("{num_input_channels} inputs, {num_output_channels} outputs"),
|
||||||
};
|
};
|
||||||
let input_port_type = match bus_config.num_input_channels {
|
let input_port_type = match bus_config.num_input_channels {
|
||||||
1 => CLAP_PORT_MONO,
|
1 => CLAP_PORT_MONO.as_ptr(),
|
||||||
2 => CLAP_PORT_STEREO,
|
2 => CLAP_PORT_STEREO.as_ptr(),
|
||||||
_ => ptr::null(),
|
_ => ptr::null(),
|
||||||
};
|
};
|
||||||
let output_port_type = match bus_config.num_output_channels {
|
let output_port_type = match bus_config.num_output_channels {
|
||||||
1 => CLAP_PORT_MONO,
|
1 => CLAP_PORT_MONO.as_ptr(),
|
||||||
2 => CLAP_PORT_STEREO,
|
2 => CLAP_PORT_STEREO.as_ptr(),
|
||||||
_ => ptr::null(),
|
_ => ptr::null(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2302,8 +2306,8 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let port_type = match channel_count {
|
let port_type = match channel_count {
|
||||||
1 => CLAP_PORT_MONO,
|
1 => CLAP_PORT_MONO.as_ptr(),
|
||||||
2 => CLAP_PORT_STEREO,
|
2 => CLAP_PORT_STEREO.as_ptr(),
|
||||||
_ => ptr::null(),
|
_ => ptr::null(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2377,15 +2381,15 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(target_family = "unix", not(target_os = "macos")))]
|
#[cfg(all(target_family = "unix", not(target_os = "macos")))]
|
||||||
if CStr::from_ptr(api) == CStr::from_ptr(CLAP_WINDOW_API_X11) {
|
if CStr::from_ptr(api) == CLAP_WINDOW_API_X11 {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
if CStr::from_ptr(api) == CStr::from_ptr(CLAP_WINDOW_API_COCOA) {
|
if CStr::from_ptr(api) == CLAP_WINDOW_API_COCOA {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
if CStr::from_ptr(api) == CStr::from_ptr(CLAP_WINDOW_API_WIN32) {
|
if CStr::from_ptr(api) == CLAP_WINDOW_API_WIN32 {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2401,15 +2405,15 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
|
|
||||||
#[cfg(all(target_family = "unix", not(target_os = "macos")))]
|
#[cfg(all(target_family = "unix", not(target_os = "macos")))]
|
||||||
{
|
{
|
||||||
*api = CLAP_WINDOW_API_X11;
|
*api = CLAP_WINDOW_API_X11.as_ptr();
|
||||||
}
|
}
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
{
|
{
|
||||||
*api = CLAP_WINDOW_API_COCOA;
|
*api = CLAP_WINDOW_API_COCOA.as_ptr();
|
||||||
}
|
}
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
{
|
{
|
||||||
*api = CLAP_WINDOW_API_WIN32;
|
*api = CLAP_WINDOW_API_WIN32.as_ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't do standalone floating windows yet
|
// We don't do standalone floating windows yet
|
||||||
|
@ -2555,15 +2559,15 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
let mut editor_handle = wrapper.editor_handle.write();
|
let mut editor_handle = wrapper.editor_handle.write();
|
||||||
if editor_handle.is_none() {
|
if editor_handle.is_none() {
|
||||||
let api = CStr::from_ptr(window.api);
|
let api = CStr::from_ptr(window.api);
|
||||||
let handle = if api == CStr::from_ptr(CLAP_WINDOW_API_X11) {
|
let handle = if api == CLAP_WINDOW_API_X11 {
|
||||||
let mut handle = raw_window_handle::XcbHandle::empty();
|
let mut handle = raw_window_handle::XcbHandle::empty();
|
||||||
handle.window = window.specific.x11 as u32;
|
handle.window = window.specific.x11 as u32;
|
||||||
RawWindowHandle::Xcb(handle)
|
RawWindowHandle::Xcb(handle)
|
||||||
} else if api == CStr::from_ptr(CLAP_WINDOW_API_COCOA) {
|
} else if api == CLAP_WINDOW_API_COCOA {
|
||||||
let mut handle = raw_window_handle::AppKitHandle::empty();
|
let mut handle = raw_window_handle::AppKitHandle::empty();
|
||||||
handle.ns_view = window.specific.cocoa;
|
handle.ns_view = window.specific.cocoa;
|
||||||
RawWindowHandle::AppKit(handle)
|
RawWindowHandle::AppKit(handle)
|
||||||
} else if api == CStr::from_ptr(CLAP_WINDOW_API_WIN32) {
|
} else if api == CLAP_WINDOW_API_WIN32 {
|
||||||
let mut handle = raw_window_handle::Win32Handle::empty();
|
let mut handle = raw_window_handle::Win32Handle::empty();
|
||||||
handle.hwnd = window.specific.win32;
|
handle.hwnd = window.specific.win32;
|
||||||
RawWindowHandle::Win32(handle)
|
RawWindowHandle::Win32(handle)
|
||||||
|
@ -2971,9 +2975,10 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
/// The extension type `T` must match the extension's name `name`.
|
/// The extension type `T` must match the extension's name `name`.
|
||||||
unsafe fn query_host_extension<T>(
|
unsafe fn query_host_extension<T>(
|
||||||
host_callback: &ClapPtr<clap_host>,
|
host_callback: &ClapPtr<clap_host>,
|
||||||
name: *const c_char,
|
name: &CStr,
|
||||||
) -> Option<ClapPtr<T>> {
|
) -> Option<ClapPtr<T>> {
|
||||||
let extension_ptr = (host_callback.get_extension)(&**host_callback, name);
|
let extension_ptr =
|
||||||
|
clap_call! { host_callback=>get_extension(&**host_callback, name.as_ptr()) };
|
||||||
if !extension_ptr.is_null() {
|
if !extension_ptr.is_null() {
|
||||||
Some(ClapPtr::new(extension_ptr as *const T))
|
Some(ClapPtr::new(extension_ptr as *const T))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -74,6 +74,7 @@ impl<P: Vst3Plugin> GuiContext for WrapperGuiContext<P> {
|
||||||
// FIXME: So this doesn't work for REAPER, because they just silently stop
|
// FIXME: So this doesn't work for REAPER, because they just silently stop
|
||||||
// processing audio when you bypass the plugin. Great. We can add a time
|
// processing audio when you bypass the plugin. Great. We can add a time
|
||||||
// based heuristic to work aorund this in the meantime.
|
// based heuristic to work aorund this in the meantime.
|
||||||
|
concat!("asfd", "dsaf", stringify!(34));
|
||||||
if !self.inner.is_processing.load(Ordering::SeqCst) {
|
if !self.inner.is_processing.load(Ordering::SeqCst) {
|
||||||
self.inner.set_normalized_value_by_hash(
|
self.inner.set_normalized_value_by_hash(
|
||||||
*hash,
|
*hash,
|
||||||
|
|
Loading…
Reference in a new issue