Skip to content

Commit

Permalink
clap: implement param gestures
Browse files Browse the repository at this point in the history
  • Loading branch information
micahrj committed Sep 3, 2024
1 parent e4509c1 commit bb6e072
Show file tree
Hide file tree
Showing 2 changed files with 184 additions and 12 deletions.
47 changes: 40 additions & 7 deletions src/format/clap/gui.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,48 @@
use std::collections::HashMap;
use std::ffi::{c_char, CStr};
use std::rc::Rc;
use std::sync::Arc;

use clap_sys::ext::gui::*;
use clap_sys::plugin::*;
use clap_sys::ext::{gui::*, params::*};
use clap_sys::{host::*, plugin::*};

use super::instance::Instance;
use crate::editor::{Editor, EditorHost, EditorHostInner, ParentWindow, RawParent};
use crate::params::{ParamId, ParamValue};
use crate::plugin::Plugin;
use crate::sync::param_gestures::ParamGestures;

struct ClapEditorHost {}
struct ClapEditorHost {
host: *const clap_host,
host_params: Option<*const clap_host_params>,
param_map: Arc<HashMap<ParamId, usize>>,
param_gestures: Arc<ParamGestures>,
}

impl EditorHostInner for ClapEditorHost {
fn begin_gesture(&self, _id: ParamId) {}
fn end_gesture(&self, _id: ParamId) {}
fn set_param(&self, _id: ParamId, _value: ParamValue) {}
fn begin_gesture(&self, id: ParamId) {
self.param_gestures.begin_gesture(self.param_map[&id]);

if let Some(host_params) = self.host_params {
unsafe { (*host_params).request_flush.unwrap()(self.host) };
}
}

fn end_gesture(&self, id: ParamId) {
self.param_gestures.end_gesture(self.param_map[&id]);

if let Some(host_params) = self.host_params {
unsafe { (*host_params).request_flush.unwrap()(self.host) };
}
}

fn set_param(&self, id: ParamId, value: ParamValue) {
self.param_gestures.set_value(self.param_map[&id], value);

if let Some(host_params) = self.host_params {
unsafe { (*host_params).request_flush.unwrap()(self.host) };
}
}
}

impl<P: Plugin> Instance<P> {
Expand Down Expand Up @@ -161,7 +189,12 @@ impl<P: Plugin> Instance<P> {
let instance = &*(plugin as *const Self);
let main_thread_state = &mut *instance.main_thread_state.get();

let host = EditorHost::from_inner(Rc::new(ClapEditorHost {}));
let host = EditorHost::from_inner(Rc::new(ClapEditorHost {
host: instance.host,
host_params: main_thread_state.host_params,
param_map: Arc::clone(&instance.param_map),
param_gestures: Arc::clone(&instance.param_gestures),
}));
let parent = ParentWindow::from_raw(raw_parent);
let editor = main_thread_state.plugin.editor(host, &parent);
main_thread_state.editor = Some(editor);
Expand Down
149 changes: 144 additions & 5 deletions src/format/clap/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::ffi::{c_char, c_void, CStr};
use std::iter::zip;
use std::ptr::NonNull;
use std::sync::Arc;
use std::{io, ptr, slice};
use std::{io, mem, ptr, slice};

use clap_sys::ext::{audio_ports::*, audio_ports_config::*, gui::*, params::*, state::*};
use clap_sys::{events::*, host::*, id::*, plugin::*, process::*, stream::*};
Expand All @@ -18,6 +18,7 @@ use crate::host::Host;
use crate::params::{ParamId, ParamInfo, ParamValue};
use crate::plugin::{Plugin, PluginInfo};
use crate::process::{Config, Processor};
use crate::sync::param_gestures::{GestureStates, GestureUpdate, ParamGestures};
use crate::sync::params::ParamValues;
use crate::util::{copy_cstring, slice_from_raw_parts_checked, DisplayParam};

Expand Down Expand Up @@ -45,12 +46,14 @@ fn map_param_out(param: &ParamInfo, value: ParamValue) -> f64 {
}

pub struct MainThreadState<P: Plugin> {
pub host_params: Option<*const clap_host_params>,
pub layout_index: usize,
pub plugin: P,
pub editor: Option<P::Editor>,
}

pub struct ProcessState<P: Plugin> {
gesture_states: GestureStates,
buffer_data: Vec<BufferData>,
buffer_ptrs: Vec<*mut f32>,
events: Vec<Event>,
Expand All @@ -65,11 +68,12 @@ pub struct Instance<P: Plugin> {
pub info: Arc<PluginInfo>,
pub input_bus_map: Vec<usize>,
pub output_bus_map: Vec<usize>,
pub param_map: HashMap<ParamId, usize>,
pub param_map: Arc<HashMap<ParamId, usize>>,
// Processor -> plugin parameter changes
pub plugin_params: ParamValues,
// Plugin -> processor parameter changes
pub processor_params: ParamValues,
pub param_gestures: Arc<ParamGestures>,
pub main_thread_state: UnsafeCell<MainThreadState<P>>,
pub process_state: UnsafeCell<ProcessState<P>>,
}
Expand Down Expand Up @@ -119,15 +123,18 @@ impl<P: Plugin> Instance<P> {
info: info.clone(),
input_bus_map,
output_bus_map,
param_map,
param_map: Arc::new(param_map),
plugin_params: ParamValues::with_count(info.params.len()),
processor_params: ParamValues::with_count(info.params.len()),
param_gestures: Arc::new(ParamGestures::with_count(info.params.len())),
main_thread_state: UnsafeCell::new(MainThreadState {
host_params: None,
layout_index: 0,
plugin: P::new(Host::from_inner(Arc::new(ClapHost {}))),
editor: None,
}),
process_state: UnsafeCell::new(ProcessState {
gesture_states: GestureStates::with_count(info.params.len()),
buffer_data: Vec::new(),
buffer_ptrs: Vec::new(),
events: Vec::with_capacity(4096),
Expand Down Expand Up @@ -197,10 +204,114 @@ impl<P: Plugin> Instance<P> {
(*self.host).request_callback.unwrap()(self.host);
}
}

unsafe fn process_gestures(
&self,
gesture_states: &mut GestureStates,
events: &mut Vec<Event>,
out_events: *const clap_output_events,
time: u32,
) {
for update in self.param_gestures.poll(gesture_states) {
let param = &self.info.params[update.index];

if let Some(value) = update.set_value {
events.push(Event {
time: time as i64,
data: Data::ParamChange {
id: param.id,
value,
},
});

self.plugin_params.set(update.index, value);
}

self.send_gesture_events(&update, out_events, time);
}
}

unsafe fn send_gesture_events(
&self,
update: &GestureUpdate,
out_events: *const clap_output_events,
time: u32,
) {
let param = &self.info.params[update.index];

if update.begin_gesture {
let event = clap_event_param_gesture {
header: clap_event_header {
size: mem::size_of::<clap_event_param_gesture>() as u32,
time,
space_id: CLAP_CORE_EVENT_SPACE_ID,
type_: CLAP_EVENT_PARAM_GESTURE_BEGIN,
flags: CLAP_EVENT_IS_LIVE,
},
param_id: param.id,
};

(*out_events).try_push.unwrap()(
out_events,
&event as *const clap_event_param_gesture as *const clap_event_header,
);
}

if let Some(value) = update.set_value {
let event = clap_event_param_value {
header: clap_event_header {
size: mem::size_of::<clap_event_param_value>() as u32,
time,
space_id: CLAP_CORE_EVENT_SPACE_ID,
type_: CLAP_EVENT_PARAM_VALUE,
flags: CLAP_EVENT_IS_LIVE,
},
param_id: param.id,
cookie: ptr::null_mut(),
note_id: -1,
port_index: -1,
channel: -1,
key: -1,
value: map_param_out(param, value),
};

(*out_events).try_push.unwrap()(
out_events,
&event as *const clap_event_param_value as *const clap_event_header,
);
}

if update.end_gesture {
let event = clap_event_param_gesture {
header: clap_event_header {
size: mem::size_of::<clap_event_param_gesture>() as u32,
time,
space_id: CLAP_CORE_EVENT_SPACE_ID,
type_: CLAP_EVENT_PARAM_GESTURE_END,
flags: CLAP_EVENT_IS_LIVE,
},
param_id: param.id,
};

(*out_events).try_push.unwrap()(
out_events,
&event as *const clap_event_param_gesture as *const clap_event_header,
);
}
}
}

impl<P: Plugin> Instance<P> {
unsafe extern "C" fn init(_plugin: *const clap_plugin) -> bool {
unsafe extern "C" fn init(plugin: *const clap_plugin) -> bool {
let instance = &*(plugin as *const Self);
let main_thread_state = &mut *instance.main_thread_state.get();

let host_params =
(*instance.host).get_extension.unwrap()(instance.host, CLAP_EXT_PARAMS.as_ptr());
if !host_params.is_null() {
main_thread_state.host_params = Some(host_params as *const clap_host_params);
}

true
}

Expand Down Expand Up @@ -372,6 +483,14 @@ impl<P: Plugin> Instance<P> {
instance.sync_processor(&mut process_state.events);
instance.process_param_events(process.in_events, &mut process_state.events);

let last_sample = process.frames_count.saturating_sub(1);
instance.process_gestures(
&mut process_state.gesture_states,
&mut process_state.events,
process.out_events,
last_sample,
);

processor.process(
Buffers::from_raw_parts(
&process_state.buffer_data,
Expand Down Expand Up @@ -684,7 +803,7 @@ impl<P: Plugin> Instance<P> {
unsafe extern "C" fn params_flush(
plugin: *const clap_plugin,
in_: *const clap_input_events,
_out: *const clap_output_events,
out: *const clap_output_events,
) {
let instance = &*(plugin as *const Self);
let process_state = &mut *instance.process_state.get();
Expand All @@ -696,6 +815,12 @@ impl<P: Plugin> Instance<P> {
process_state.events.clear();
instance.sync_processor(&mut process_state.events);
instance.process_param_events(in_, &mut process_state.events);
instance.process_gestures(
&mut process_state.gesture_states,
&mut process_state.events,
out,
0,
);

processor.process(
Buffers::from_raw_parts(
Expand Down Expand Up @@ -730,6 +855,20 @@ impl<P: Plugin> Instance<P> {
}
}
}

for update in instance.param_gestures.poll(&mut process_state.gesture_states) {
let param = &instance.info.params[update.index];

if let Some(value) = update.set_value {
main_thread_state.plugin.set_param(param.id, value);

if let Some(editor) = &mut main_thread_state.editor {
editor.param_changed(param.id, value);
}
}

instance.send_gesture_events(&update, out, 0);
}
}
}
}
Expand Down

0 comments on commit bb6e072

Please sign in to comment.