1
0
Fork 0

Update for CLAP 0.20

This commit is contained in:
Robbert van der Helm 2022-03-08 00:21:51 +01:00
parent fedfa47b43
commit 8ee380864c
3 changed files with 120 additions and 165 deletions

16
Cargo.lock generated
View file

@ -4,9 +4,9 @@ version = 3
[[package]]
name = "ab_glyph"
version = "0.2.14"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d54a65e0d4f66f8536c98cb3ca81ca33b7e2ca43442465507a3a62291ec0d9e4"
checksum = "24606928a235e73cdef55a0c909719cadd72fce573e5713d58cb2952d8f5794c"
dependencies = [
"ab_glyph_rasterizer",
"owned_ttf_parser",
@ -46,9 +46,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.55"
version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "159bb86af3a200e19a068f4224eae4c8bb2d0fa054c7e5d1cacd5cef95e684cd"
checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27"
[[package]]
name = "assert_no_alloc"
@ -77,7 +77,7 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "baseview"
version = "0.1.0"
source = "git+https://github.com/robbert-vdh/baseview.git?branch=feature/mouse-event-modifiers#a8ef4ddc1c53e48a2c2ca7379f89e6573a250407"
source = "git+https://github.com/robbert-vdh/baseview.git?branch=feature/mouse-event-modifiers#8e7f854c537712a30ba388bdce8764f10b466652"
dependencies = [
"cocoa",
"core-foundation",
@ -169,7 +169,7 @@ dependencies = [
[[package]]
name = "clap-sys"
version = "0.1.0"
source = "git+https://github.com/glowcoil/clap-sys?rev=3ef7048e1d3b426a7c6b02b5d3ae18f14874d4e5#3ef7048e1d3b426a7c6b02b5d3ae18f14874d4e5"
source = "git+https://github.com/robbert-vdh/clap-sys?branch=update/clap-0.20#d795c86022e0229cb219d68675329dadf1778a86"
[[package]]
name = "clipboard-win"
@ -887,9 +887,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.9.0"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
[[package]]
name = "owned_ttf_parser"

View file

@ -42,8 +42,8 @@ nih_plug_derive = { path = "nih_plug_derive" }
atomic_float = "0.1"
atomic_refcell = "0.1"
cfg-if = "1.0"
# For CLAP 0.18
clap-sys = { git = "https://github.com/glowcoil/clap-sys", rev = "3ef7048e1d3b426a7c6b02b5d3ae18f14874d4e5" }
# For CLAP 0.20
clap-sys = { git = "https://github.com/robbert-vdh/clap-sys", branch = "update/clap-0.20" }
crossbeam = "0.8"
lazy_static = "1.4"
parking_lot = "0.12"

View file

@ -20,11 +20,14 @@ use clap_sys::ext::audio_ports::{
use clap_sys::ext::audio_ports_config::{
clap_audio_ports_config, clap_plugin_audio_ports_config, CLAP_EXT_AUDIO_PORTS_CONFIG,
};
use clap_sys::ext::gui::{clap_plugin_gui, CLAP_EXT_GUI};
use clap_sys::ext::gui::{
clap_plugin_gui, clap_window, CLAP_EXT_GUI, CLAP_WINDOW_API_COCOA, CLAP_WINDOW_API_WIN32,
CLAP_WINDOW_API_X11,
};
use clap_sys::ext::latency::{clap_host_latency, clap_plugin_latency, CLAP_EXT_LATENCY};
use clap_sys::ext::params::{
clap_host_params, clap_param_info, clap_plugin_params, CLAP_EXT_PARAMS, CLAP_PARAM_IS_BYPASS,
CLAP_PARAM_IS_STEPPED,
clap_host_params, clap_param_info, clap_plugin_params, CLAP_EXT_PARAMS,
CLAP_PARAM_IS_AUTOMATABLE, CLAP_PARAM_IS_BYPASS, CLAP_PARAM_IS_STEPPED,
};
use clap_sys::ext::state::{clap_plugin_state, CLAP_EXT_STATE};
use clap_sys::ext::thread_check::{clap_host_thread_check, CLAP_EXT_THREAD_CHECK};
@ -47,19 +50,12 @@ use std::cmp;
use std::collections::{HashMap, VecDeque};
use std::ffi::{c_void, CStr};
use std::mem;
use std::os::raw::{c_char, c_ulong};
use std::os::raw::c_char;
use std::ptr;
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
use std::sync::{Arc, Weak};
use std::thread::{self, ThreadId};
#[cfg(target_os = "macos")]
use clap_sys::ext::gui_cocoa::{clap_plugin_gui_cocoa, CLAP_EXT_GUI_COCOA};
#[cfg(target_os = "windows")]
use clap_sys::ext::gui_win32::{clap_hwnd, clap_plugin_gui_win32, CLAP_EXT_GUI_WIN32};
#[cfg(all(target_family = "unix", not(target_os = "macos")))]
use clap_sys::ext::gui_x11::{clap_plugin_gui_x11, CLAP_EXT_GUI_X11};
use super::context::{WrapperGuiContext, WrapperProcessContext};
use super::descriptor::PluginDescriptor;
use super::util::ClapPtr;
@ -153,15 +149,6 @@ pub struct Wrapper<P: ClapPlugin> {
clap_plugin_gui: clap_plugin_gui,
// These are now platform specific, but after CLAP 0.19 this will all be merged into the regular
// GUI extension
#[cfg(all(target_family = "unix", not(target_os = "macos")))]
clap_plugin_gui_x11: clap_plugin_gui_x11,
#[cfg(target_os = "macos")]
clap_plugin_gui_cocoa: clap_plugin_gui_cocoa,
#[cfg(target_os = "windows")]
clap_plugin_gui_win32: clap_plugin_gui_win32,
clap_plugin_latency: clap_plugin_latency,
host_latency: AtomicRefCell<Option<ClapPtr<clap_host_latency>>>,
@ -323,6 +310,7 @@ impl<P: ClapPlugin> Wrapper<P> {
deactivate: Self::deactivate,
start_processing: Self::start_processing,
stop_processing: Self::stop_processing,
reset: Self::reset,
process: Self::process,
get_extension: Self::get_extension,
on_main_thread: Self::on_main_thread,
@ -363,30 +351,21 @@ impl<P: ClapPlugin> Wrapper<P> {
},
clap_plugin_gui: clap_plugin_gui {
is_api_supported: Self::ext_gui_is_api_supported,
create: Self::ext_gui_create,
destroy: Self::ext_gui_destroy,
set_scale: Self::ext_gui_set_scale,
get_size: Self::ext_gui_get_size,
can_resize: Self::ext_gui_can_resize,
round_size: Self::ext_gui_round_size,
adjust_size: Self::ext_gui_adjust_size,
set_size: Self::ext_gui_set_size,
set_parent: Self::ext_gui_set_parent,
set_transient: Self::ext_gui_set_transient,
suggest_title: Self::ext_gui_suggest_title,
show: Self::ext_gui_show,
hide: Self::ext_gui_hide,
},
#[cfg(all(target_family = "unix", not(target_os = "macos")))]
clap_plugin_gui_x11: clap_plugin_gui_x11 {
attach: Self::ext_gui_x11_attach,
},
#[cfg(target_os = "macos")]
clap_plugin_gui_cocoa: clap_plugin_gui_cocoa {
attach: Self::ext_gui_cocoa_attach,
},
#[cfg(target_os = "windows")]
clap_plugin_gui_win32: clap_plugin_gui_win32 {
attach: Self::ext_gui_win32_attach,
},
clap_plugin_latency: clap_plugin_latency {
get: Self::ext_latency_get,
},
@ -624,7 +603,8 @@ impl<P: ClapPlugin> Wrapper<P> {
value: change.clap_plain_value,
};
(out.push_back)(out, &event.header);
let push_succesful = (out.try_push)(out, &event.header);
nih_debug_assert!(push_succesful);
}
}
@ -786,6 +766,10 @@ impl<P: ClapPlugin> Wrapper<P> {
wrapper.is_processing.store(false, Ordering::SeqCst);
}
unsafe extern "C" fn reset(_plugin: *const clap_plugin) {
// TODO: Split `Plugin::intialize()` into an initialize and a reset function
}
unsafe extern "C" fn process(
plugin: *const clap_plugin,
process: *const clap_process,
@ -963,21 +947,9 @@ impl<P: ClapPlugin> Wrapper<P> {
let id = CStr::from_ptr(id);
// These extensions are only relevant on the respective platforms and they will be removed
// entirely in CLAP 0.19
#[cfg(all(target_family = "unix", not(target_os = "macos")))]
if id == CStr::from_ptr(CLAP_EXT_GUI_X11) && wrapper.editor.is_some() {
return &wrapper.clap_plugin_gui_x11 as *const _ as *const c_void;
}
#[cfg(target_os = "macos")]
if id == CStr::from_ptr(CLAP_EXT_GUI_COCOA) && wrapper.editor.is_some() {
return &wrapper.clap_plugin_gui_cocoa as *const _ as *const c_void;
}
#[cfg(target_os = "windows")]
if id == CStr::from_ptr(CLAP_EXT_GUI_WIN32) && wrapper.editor.is_some() {
return &wrapper.clap_plugin_gui_win32 as *const _ as *const c_void;
}
// TODO: Implement:
// - event_filter
// - tail
if id == CStr::from_ptr(CLAP_EXT_AUDIO_PORTS_CONFIG) {
&wrapper.clap_plugin_audio_ports_config as *const _ as *const c_void
} else if id == CStr::from_ptr(CLAP_EXT_AUDIO_PORTS) {
@ -1184,10 +1156,45 @@ impl<P: ClapPlugin> Wrapper<P> {
}
}
unsafe extern "C" fn ext_gui_create(plugin: *const clap_plugin) -> bool {
// This is a bit weird, because in CLAP 0.18 creating the editor window and embedding it in
// another window are separate, and those things are one and the same in our framework. So
// we'll just pretend we did something here.
unsafe extern "C" fn ext_gui_is_api_supported(
_plugin: *const clap_plugin,
api: *const c_char,
is_floating: bool,
) -> bool {
// We don't do standalone floating windows
if is_floating {
return false;
}
#[cfg(all(target_family = "unix", not(target_os = "macos")))]
if CStr::from_ptr(api) == CStr::from_ptr(CLAP_WINDOW_API_X11) {
return true;
}
#[cfg(target_os = "macos")]
if CStr::from_ptr(api) == CStr::from_ptr(CLAP_WINDOW_API_COCOA) {
return true;
}
#[cfg(target_os = "windows")]
if CStr::from_ptr(api) == CStr::from_ptr(CLAP_WINDOW_API_WIN32) {
return true;
}
false
}
unsafe extern "C" fn ext_gui_create(
plugin: *const clap_plugin,
api: *const c_char,
is_floating: bool,
) -> bool {
// Double check this in case the host didn't
if !Self::ext_gui_is_api_supported(plugin, api, is_floating) {
return false;
}
// In CLAP creating the editor window and embedding it in another window are separate, and
// those things are one and the same in our framework. So we'll just pretend we did
// something here.
check_null_ptr!(false, plugin);
let wrapper = &*(plugin as *const Self);
@ -1245,6 +1252,7 @@ impl<P: ClapPlugin> Wrapper<P> {
check_null_ptr!(false, plugin, width, height);
let wrapper = &*(plugin as *const Self);
// For macOS the scaling factor is always 1
let (unscaled_width, unscaled_height) = wrapper.editor.as_ref().unwrap().size();
let scaling_factor = wrapper.editor_scaling_factor.load(Ordering::Relaxed);
(*width, *height) = (
@ -1260,12 +1268,13 @@ impl<P: ClapPlugin> Wrapper<P> {
false
}
unsafe extern "C" fn ext_gui_round_size(
unsafe extern "C" fn ext_gui_adjust_size(
_plugin: *const clap_plugin,
_width: *mut u32,
_height: *mut u32,
) {
) -> bool {
// TODO: Implement GUI resizing
false
}
unsafe extern "C" fn ext_gui_set_size(
@ -1287,113 +1296,35 @@ impl<P: ClapPlugin> Wrapper<P> {
width == editor_width && height == editor_height
}
unsafe extern "C" fn ext_gui_show(_plugin: *const clap_plugin) {
// TODO: Does this get used? Is this only for the free-standing window extension? (which we
// don't implement) This wouldn't make any sense for embedded editors.
}
unsafe extern "C" fn ext_gui_hide(_plugin: *const clap_plugin) {
// TODO: Same as the above
}
#[cfg(all(target_family = "unix", not(target_os = "macos")))]
unsafe extern "C" fn ext_gui_x11_attach(
unsafe extern "C" fn ext_gui_set_parent(
plugin: *const clap_plugin,
// TODO: Should we do anything with the display name?
_display_name: *const c_char,
window: c_ulong,
) -> bool {
check_null_ptr!(false, plugin);
// For this function we need the underlying Arc so we can pass it to the editor
let wrapper = Arc::from_raw(plugin as *const Self);
let result = {
let mut editor_handle = wrapper.editor_handle.write();
if editor_handle.is_none() {
let handle = {
let mut handle = raw_window_handle::XcbHandle::empty();
handle.window = window as u32;
RawWindowHandle::Xcb(handle)
};
// This extension is only exposed when we have an editor
*editor_handle = Some(wrapper.editor.as_ref().unwrap().spawn(
ParentWindowHandle { handle },
wrapper.clone().make_gui_context(),
));
true
} else {
nih_debug_assert_failure!(
"Host tried to attach editor while the editor is already attached"
);
false
}
};
// Leak the Arc again since we only needed a clone to pass to the GuiContext
let _ = Arc::into_raw(wrapper);
result
}
#[cfg(target_os = "macos")]
unsafe extern "C" fn ext_gui_cocoa_attach(
plugin: *const clap_plugin,
ns_view: *mut c_void,
) -> bool {
check_null_ptr!(false, plugin, ns_view);
// For this function we need the underlying Arc so we can pass it to the editor
let wrapper = Arc::from_raw(plugin as *const Self);
let result = {
let mut editor_handle = wrapper.editor_handle.write();
if editor_handle.is_none() {
let handle = {
let mut handle = raw_window_handle::AppKitHandle::empty();
handle.ns_view = ns_view;
RawWindowHandle::AppKit(handle)
};
// This extension is only exposed when we have an editor
*editor_handle = Some(wrapper.editor.as_ref().unwrap().spawn(
ParentWindowHandle { handle },
wrapper.clone().make_gui_context(),
));
true
} else {
nih_debug_assert_failure!(
"Host tried to attach editor while the editor is already attached"
);
false
}
};
// Leak the Arc again since we only needed a clone to pass to the GuiContext
let _ = Arc::into_raw(wrapper);
result
}
#[cfg(target_os = "windows")]
unsafe extern "C" fn ext_gui_win32_attach(
plugin: *const clap_plugin,
window: clap_hwnd,
window: *const clap_window,
) -> bool {
check_null_ptr!(false, plugin, window);
// For this function we need the underlying Arc so we can pass it to the editor
let wrapper = Arc::from_raw(plugin as *const Self);
let window = &*window;
let result = {
let mut editor_handle = wrapper.editor_handle.write();
if editor_handle.is_none() {
let handle = {
let api = CStr::from_ptr(window.api);
let handle = if api == CStr::from_ptr(CLAP_WINDOW_API_X11) {
let mut handle = raw_window_handle::XcbHandle::empty();
handle.window = window.specific.x11 as u32;
RawWindowHandle::Xcb(handle)
} else if api == CStr::from_ptr(CLAP_WINDOW_API_COCOA) {
let mut handle = raw_window_handle::AppKitHandle::empty();
handle.ns_view = window.specific.cocoa;
RawWindowHandle::AppKit(handle)
} else if api == CStr::from_ptr(CLAP_WINDOW_API_WIN32) {
let mut handle = raw_window_handle::Win32Handle::empty();
handle.hwnd = window;
handle.hwnd = window.specific.win32;
RawWindowHandle::Win32(handle)
} else {
nih_debug_assert_failure!("Host passed an invalid API");
return false;
};
// This extension is only exposed when we have an editor
@ -1418,6 +1349,29 @@ impl<P: ClapPlugin> Wrapper<P> {
result
}
unsafe extern "C" fn ext_gui_set_transient(
_plugin: *const clap_plugin,
_window: *const clap_window,
) -> bool {
// This is only relevant for floating windows
false
}
unsafe extern "C" fn ext_gui_suggest_title(_plugin: *const clap_plugin, _title: *const c_char) {
// This is only relevant for floating windows
}
unsafe extern "C" fn ext_gui_show(_plugin: *const clap_plugin) -> bool {
// TODO: Does this get used? Is this only for the free-standing window extension? (which we
// don't implement) This wouldn't make any sense for embedded editors.
false
}
unsafe extern "C" fn ext_gui_hide(_plugin: *const clap_plugin) -> bool {
// TODO: Same as the above
false
}
unsafe extern "C" fn ext_latency_get(plugin: *const clap_plugin) -> u32 {
check_null_ptr!(0, plugin);
let wrapper = &*(plugin as *const Self);
@ -1454,7 +1408,8 @@ impl<P: ClapPlugin> Wrapper<P> {
let param_info = &mut *param_info;
if param_index == wrapper.param_hashes.len() as i32 {
param_info.id = *BYPASS_PARAM_HASH;
param_info.flags = CLAP_PARAM_IS_STEPPED | CLAP_PARAM_IS_BYPASS;
param_info.flags =
CLAP_PARAM_IS_STEPPED | CLAP_PARAM_IS_BYPASS | CLAP_PARAM_IS_AUTOMATABLE;
param_info.cookie = ptr::null_mut();
strlcpy(&mut param_info.name, "Bypass");
strlcpy(&mut param_info.module, "");
@ -1469,9 +1424,9 @@ impl<P: ClapPlugin> Wrapper<P> {
param_info.id = *param_hash;
param_info.flags = if step_count.is_some() {
CLAP_PARAM_IS_STEPPED
CLAP_PARAM_IS_STEPPED | CLAP_PARAM_IS_AUTOMATABLE
} else {
0
CLAP_PARAM_IS_AUTOMATABLE
};
param_info.cookie = ptr::null_mut();
strlcpy(&mut param_info.name, param_ptr.name());