use std::ops::Deref;
use std::sync::Arc;
use truce_params::Params;
use truce_params::sample::Float;
use crate::events::TransportInfo;
pub struct SendPtr<T>(*const T);
impl<T> SendPtr<T> {
pub unsafe fn new(ptr: *const T) -> Self {
Self(ptr)
}
#[must_use]
pub unsafe fn get(&self) -> &T {
unsafe { &*self.0 }
}
#[must_use]
pub fn as_ptr(&self) -> *const T {
self.0
}
}
impl<T> Clone for SendPtr<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for SendPtr<T> {}
unsafe impl<T> Send for SendPtr<T> {}
unsafe impl<T> Sync for SendPtr<T> {}
#[derive(Clone, Copy, Debug)]
pub enum RawWindowHandle {
AppKit(*mut std::ffi::c_void), UiKit(*mut std::ffi::c_void), Win32(*mut std::ffi::c_void), X11(u64), }
pub trait Editor: Send {
fn size(&self) -> (u32, u32);
fn open(&mut self, parent: RawWindowHandle, context: PluginContext);
fn close(&mut self);
fn idle(&mut self) {}
fn set_size(&mut self, _width: u32, _height: u32) -> bool {
false
}
fn can_resize(&self) -> bool {
false
}
fn set_scale_factor(&mut self, _factor: f64) {}
fn state_changed(&mut self) {}
fn screenshot(&mut self, params: Arc<dyn truce_params::Params>) -> Option<(Vec<u8>, u32, u32)> {
let _ = params;
None
}
}
pub trait IntoEditor {
fn into_editor(self) -> Box<dyn Editor>;
}
impl<E: Editor + 'static> IntoEditor for E {
fn into_editor(self) -> Box<dyn Editor> {
Box::new(self)
}
}
pub trait EditorBridge: Send + Sync {
fn begin_edit(&self, id: u32);
fn set_param(&self, id: u32, normalized: f64);
fn end_edit(&self, id: u32);
fn request_resize(&self, w: u32, h: u32) -> bool;
fn get_param(&self, id: u32) -> f64;
fn get_param_plain(&self, id: u32) -> f64;
fn format_param(&self, id: u32) -> String;
fn format_param_into(&self, id: u32, out: &mut String) {
out.clear();
out.push_str(&self.format_param(id));
}
fn get_meter(&self, id: u32) -> f32;
fn get_state(&self) -> Vec<u8>;
fn set_state(&self, data: Vec<u8>);
fn transport(&self) -> Option<TransportInfo>;
}
pub struct ClosureBridge {
pub begin_edit: Box<dyn Fn(u32) + Send + Sync>,
pub set_param: Box<dyn Fn(u32, f64) + Send + Sync>,
pub end_edit: Box<dyn Fn(u32) + Send + Sync>,
pub request_resize: Box<dyn Fn(u32, u32) -> bool + Send + Sync>,
pub get_param: Box<dyn Fn(u32) -> f64 + Send + Sync>,
pub get_param_plain: Box<dyn Fn(u32) -> f64 + Send + Sync>,
pub format_param: Box<dyn Fn(u32) -> String + Send + Sync>,
pub get_meter: Box<dyn Fn(u32) -> f32 + Send + Sync>,
pub get_state: Box<dyn Fn() -> Vec<u8> + Send + Sync>,
pub set_state: Box<dyn Fn(Vec<u8>) + Send + Sync>,
pub transport: Box<dyn Fn() -> Option<TransportInfo> + Send + Sync>,
}
impl EditorBridge for ClosureBridge {
fn begin_edit(&self, id: u32) {
(self.begin_edit)(id);
}
fn set_param(&self, id: u32, normalized: f64) {
(self.set_param)(id, normalized);
}
fn end_edit(&self, id: u32) {
(self.end_edit)(id);
}
fn request_resize(&self, w: u32, h: u32) -> bool {
(self.request_resize)(w, h)
}
fn get_param(&self, id: u32) -> f64 {
(self.get_param)(id)
}
fn get_param_plain(&self, id: u32) -> f64 {
(self.get_param_plain)(id)
}
fn format_param(&self, id: u32) -> String {
(self.format_param)(id)
}
fn get_meter(&self, id: u32) -> f32 {
(self.get_meter)(id)
}
fn get_state(&self) -> Vec<u8> {
(self.get_state)()
}
fn set_state(&self, data: Vec<u8>) {
(self.set_state)(data);
}
fn transport(&self) -> Option<TransportInfo> {
(self.transport)()
}
}
pub struct PluginContext<P: ?Sized = dyn Params> {
bridge: Arc<dyn EditorBridge>,
params: Arc<P>,
}
impl<P: ?Sized> Clone for PluginContext<P> {
fn clone(&self) -> Self {
Self {
bridge: Arc::clone(&self.bridge),
params: Arc::clone(&self.params),
}
}
}
impl<P: ?Sized> PluginContext<P> {
pub fn new(bridge: Arc<dyn EditorBridge>, params: Arc<P>) -> Self {
Self { bridge, params }
}
#[must_use]
pub fn bridge(&self) -> &Arc<dyn EditorBridge> {
&self.bridge
}
#[must_use]
pub fn params(&self) -> &Arc<P> {
&self.params
}
pub fn with_params<Q: ?Sized>(&self, params: Arc<Q>) -> PluginContext<Q> {
PluginContext {
bridge: Arc::clone(&self.bridge),
params,
}
}
pub fn begin_edit(&self, id: impl Into<u32>) {
self.bridge.begin_edit(id.into());
}
pub fn set_param(&self, id: impl Into<u32>, normalized: f64) {
self.bridge.set_param(id.into(), normalized);
}
pub fn end_edit(&self, id: impl Into<u32>) {
self.bridge.end_edit(id.into());
}
pub fn automate(&self, id: impl Into<u32>, normalized: f64) {
let id = id.into();
self.bridge.begin_edit(id);
self.bridge.set_param(id, normalized);
self.bridge.end_edit(id);
}
#[must_use]
pub fn request_resize(&self, w: u32, h: u32) -> bool {
self.bridge.request_resize(w, h)
}
pub fn format_param(&self, id: impl Into<u32>) -> String {
self.bridge.format_param(id.into())
}
pub fn format_param_into(&self, id: impl Into<u32>, out: &mut String) {
self.bridge.format_param_into(id.into(), out);
}
pub fn get_meter(&self, id: impl Into<u32>) -> f32 {
self.bridge.get_meter(id.into())
}
#[must_use]
pub fn get_state(&self) -> Vec<u8> {
self.bridge.get_state()
}
pub fn set_state(&self, data: Vec<u8>) {
self.bridge.set_state(data);
}
#[must_use]
pub fn transport(&self) -> Option<TransportInfo> {
self.bridge.transport()
}
}
impl PluginContext<dyn Params> {
pub fn from_closures(bridge: ClosureBridge, params: Arc<dyn Params>) -> Self {
Self {
bridge: Arc::new(bridge),
params,
}
}
}
impl<P: Params + 'static> PluginContext<P> {
#[must_use]
pub fn dyn_erase(self) -> PluginContext<dyn Params> {
PluginContext {
bridge: self.bridge,
params: self.params as Arc<dyn Params>,
}
}
}
impl<P: ?Sized> Deref for PluginContext<P> {
type Target = P;
fn deref(&self) -> &P {
&self.params
}
}
pub fn for_test_params(params: Arc<dyn Params>) -> PluginContext<dyn Params> {
let p_get = Arc::clone(¶ms);
let p_plain = Arc::clone(¶ms);
let p_fmt = Arc::clone(¶ms);
let transport = TransportInfo::for_screenshot();
PluginContext::from_closures(
ClosureBridge {
begin_edit: Box::new(|_| {}),
set_param: Box::new(|_, _| {}),
end_edit: Box::new(|_| {}),
request_resize: Box::new(|_, _| false),
get_param: Box::new(move |id| p_get.get_normalized(id).unwrap_or(0.5)),
get_param_plain: Box::new(move |id| p_plain.get_plain(id).unwrap_or(0.0)),
format_param: Box::new(move |id| {
let plain = p_fmt.get_plain(id).unwrap_or(0.0);
p_fmt
.format_value(id, plain)
.unwrap_or_else(|| format!("{plain:.2}"))
}),
get_meter: Box::new(|_| 0.0),
get_state: Box::new(Vec::new),
set_state: Box::new(|_| {}),
transport: Box::new(move || Some(transport)),
},
params,
)
}
pub trait PluginContextReadF32 {
fn get_param(&self, id: impl Into<u32>) -> f32;
fn get_param_plain(&self, id: impl Into<u32>) -> f32;
}
pub trait PluginContextReadF64 {
fn get_param(&self, id: impl Into<u32>) -> f64;
fn get_param_plain(&self, id: impl Into<u32>) -> f64;
}
impl<P: ?Sized> PluginContextReadF32 for PluginContext<P> {
fn get_param(&self, id: impl Into<u32>) -> f32 {
self.bridge.get_param(id.into()).to_f32()
}
fn get_param_plain(&self, id: impl Into<u32>) -> f32 {
self.bridge.get_param_plain(id.into()).to_f32()
}
}
impl<P: ?Sized> PluginContextReadF64 for PluginContext<P> {
fn get_param(&self, id: impl Into<u32>) -> f64 {
self.bridge.get_param(id.into())
}
fn get_param_plain(&self, id: impl Into<u32>) -> f64 {
self.bridge.get_param_plain(id.into())
}
}