Skip to content

Commit bb6e072

Browse files
committed
clap: implement param gestures
1 parent e4509c1 commit bb6e072

File tree

2 files changed

+184
-12
lines changed

2 files changed

+184
-12
lines changed

src/format/clap/gui.rs

+40-7
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,48 @@
1+
use std::collections::HashMap;
12
use std::ffi::{c_char, CStr};
23
use std::rc::Rc;
4+
use std::sync::Arc;
35

4-
use clap_sys::ext::gui::*;
5-
use clap_sys::plugin::*;
6+
use clap_sys::ext::{gui::*, params::*};
7+
use clap_sys::{host::*, plugin::*};
68

79
use super::instance::Instance;
810
use crate::editor::{Editor, EditorHost, EditorHostInner, ParentWindow, RawParent};
911
use crate::params::{ParamId, ParamValue};
1012
use crate::plugin::Plugin;
13+
use crate::sync::param_gestures::ParamGestures;
1114

12-
struct ClapEditorHost {}
15+
struct ClapEditorHost {
16+
host: *const clap_host,
17+
host_params: Option<*const clap_host_params>,
18+
param_map: Arc<HashMap<ParamId, usize>>,
19+
param_gestures: Arc<ParamGestures>,
20+
}
1321

1422
impl EditorHostInner for ClapEditorHost {
15-
fn begin_gesture(&self, _id: ParamId) {}
16-
fn end_gesture(&self, _id: ParamId) {}
17-
fn set_param(&self, _id: ParamId, _value: ParamValue) {}
23+
fn begin_gesture(&self, id: ParamId) {
24+
self.param_gestures.begin_gesture(self.param_map[&id]);
25+
26+
if let Some(host_params) = self.host_params {
27+
unsafe { (*host_params).request_flush.unwrap()(self.host) };
28+
}
29+
}
30+
31+
fn end_gesture(&self, id: ParamId) {
32+
self.param_gestures.end_gesture(self.param_map[&id]);
33+
34+
if let Some(host_params) = self.host_params {
35+
unsafe { (*host_params).request_flush.unwrap()(self.host) };
36+
}
37+
}
38+
39+
fn set_param(&self, id: ParamId, value: ParamValue) {
40+
self.param_gestures.set_value(self.param_map[&id], value);
41+
42+
if let Some(host_params) = self.host_params {
43+
unsafe { (*host_params).request_flush.unwrap()(self.host) };
44+
}
45+
}
1846
}
1947

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

164-
let host = EditorHost::from_inner(Rc::new(ClapEditorHost {}));
192+
let host = EditorHost::from_inner(Rc::new(ClapEditorHost {
193+
host: instance.host,
194+
host_params: main_thread_state.host_params,
195+
param_map: Arc::clone(&instance.param_map),
196+
param_gestures: Arc::clone(&instance.param_gestures),
197+
}));
165198
let parent = ParentWindow::from_raw(raw_parent);
166199
let editor = main_thread_state.plugin.editor(host, &parent);
167200
main_thread_state.editor = Some(editor);

src/format/clap/instance.rs

+144-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::ffi::{c_char, c_void, CStr};
44
use std::iter::zip;
55
use std::ptr::NonNull;
66
use std::sync::Arc;
7-
use std::{io, ptr, slice};
7+
use std::{io, mem, ptr, slice};
88

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

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

4748
pub struct MainThreadState<P: Plugin> {
49+
pub host_params: Option<*const clap_host_params>,
4850
pub layout_index: usize,
4951
pub plugin: P,
5052
pub editor: Option<P::Editor>,
5153
}
5254

5355
pub struct ProcessState<P: Plugin> {
56+
gesture_states: GestureStates,
5457
buffer_data: Vec<BufferData>,
5558
buffer_ptrs: Vec<*mut f32>,
5659
events: Vec<Event>,
@@ -65,11 +68,12 @@ pub struct Instance<P: Plugin> {
6568
pub info: Arc<PluginInfo>,
6669
pub input_bus_map: Vec<usize>,
6770
pub output_bus_map: Vec<usize>,
68-
pub param_map: HashMap<ParamId, usize>,
71+
pub param_map: Arc<HashMap<ParamId, usize>>,
6972
// Processor -> plugin parameter changes
7073
pub plugin_params: ParamValues,
7174
// Plugin -> processor parameter changes
7275
pub processor_params: ParamValues,
76+
pub param_gestures: Arc<ParamGestures>,
7377
pub main_thread_state: UnsafeCell<MainThreadState<P>>,
7478
pub process_state: UnsafeCell<ProcessState<P>>,
7579
}
@@ -119,15 +123,18 @@ impl<P: Plugin> Instance<P> {
119123
info: info.clone(),
120124
input_bus_map,
121125
output_bus_map,
122-
param_map,
126+
param_map: Arc::new(param_map),
123127
plugin_params: ParamValues::with_count(info.params.len()),
124128
processor_params: ParamValues::with_count(info.params.len()),
129+
param_gestures: Arc::new(ParamGestures::with_count(info.params.len())),
125130
main_thread_state: UnsafeCell::new(MainThreadState {
131+
host_params: None,
126132
layout_index: 0,
127133
plugin: P::new(Host::from_inner(Arc::new(ClapHost {}))),
128134
editor: None,
129135
}),
130136
process_state: UnsafeCell::new(ProcessState {
137+
gesture_states: GestureStates::with_count(info.params.len()),
131138
buffer_data: Vec::new(),
132139
buffer_ptrs: Vec::new(),
133140
events: Vec::with_capacity(4096),
@@ -197,10 +204,114 @@ impl<P: Plugin> Instance<P> {
197204
(*self.host).request_callback.unwrap()(self.host);
198205
}
199206
}
207+
208+
unsafe fn process_gestures(
209+
&self,
210+
gesture_states: &mut GestureStates,
211+
events: &mut Vec<Event>,
212+
out_events: *const clap_output_events,
213+
time: u32,
214+
) {
215+
for update in self.param_gestures.poll(gesture_states) {
216+
let param = &self.info.params[update.index];
217+
218+
if let Some(value) = update.set_value {
219+
events.push(Event {
220+
time: time as i64,
221+
data: Data::ParamChange {
222+
id: param.id,
223+
value,
224+
},
225+
});
226+
227+
self.plugin_params.set(update.index, value);
228+
}
229+
230+
self.send_gesture_events(&update, out_events, time);
231+
}
232+
}
233+
234+
unsafe fn send_gesture_events(
235+
&self,
236+
update: &GestureUpdate,
237+
out_events: *const clap_output_events,
238+
time: u32,
239+
) {
240+
let param = &self.info.params[update.index];
241+
242+
if update.begin_gesture {
243+
let event = clap_event_param_gesture {
244+
header: clap_event_header {
245+
size: mem::size_of::<clap_event_param_gesture>() as u32,
246+
time,
247+
space_id: CLAP_CORE_EVENT_SPACE_ID,
248+
type_: CLAP_EVENT_PARAM_GESTURE_BEGIN,
249+
flags: CLAP_EVENT_IS_LIVE,
250+
},
251+
param_id: param.id,
252+
};
253+
254+
(*out_events).try_push.unwrap()(
255+
out_events,
256+
&event as *const clap_event_param_gesture as *const clap_event_header,
257+
);
258+
}
259+
260+
if let Some(value) = update.set_value {
261+
let event = clap_event_param_value {
262+
header: clap_event_header {
263+
size: mem::size_of::<clap_event_param_value>() as u32,
264+
time,
265+
space_id: CLAP_CORE_EVENT_SPACE_ID,
266+
type_: CLAP_EVENT_PARAM_VALUE,
267+
flags: CLAP_EVENT_IS_LIVE,
268+
},
269+
param_id: param.id,
270+
cookie: ptr::null_mut(),
271+
note_id: -1,
272+
port_index: -1,
273+
channel: -1,
274+
key: -1,
275+
value: map_param_out(param, value),
276+
};
277+
278+
(*out_events).try_push.unwrap()(
279+
out_events,
280+
&event as *const clap_event_param_value as *const clap_event_header,
281+
);
282+
}
283+
284+
if update.end_gesture {
285+
let event = clap_event_param_gesture {
286+
header: clap_event_header {
287+
size: mem::size_of::<clap_event_param_gesture>() as u32,
288+
time,
289+
space_id: CLAP_CORE_EVENT_SPACE_ID,
290+
type_: CLAP_EVENT_PARAM_GESTURE_END,
291+
flags: CLAP_EVENT_IS_LIVE,
292+
},
293+
param_id: param.id,
294+
};
295+
296+
(*out_events).try_push.unwrap()(
297+
out_events,
298+
&event as *const clap_event_param_gesture as *const clap_event_header,
299+
);
300+
}
301+
}
200302
}
201303

202304
impl<P: Plugin> Instance<P> {
203-
unsafe extern "C" fn init(_plugin: *const clap_plugin) -> bool {
305+
unsafe extern "C" fn init(plugin: *const clap_plugin) -> bool {
306+
let instance = &*(plugin as *const Self);
307+
let main_thread_state = &mut *instance.main_thread_state.get();
308+
309+
let host_params =
310+
(*instance.host).get_extension.unwrap()(instance.host, CLAP_EXT_PARAMS.as_ptr());
311+
if !host_params.is_null() {
312+
main_thread_state.host_params = Some(host_params as *const clap_host_params);
313+
}
314+
204315
true
205316
}
206317

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

486+
let last_sample = process.frames_count.saturating_sub(1);
487+
instance.process_gestures(
488+
&mut process_state.gesture_states,
489+
&mut process_state.events,
490+
process.out_events,
491+
last_sample,
492+
);
493+
375494
processor.process(
376495
Buffers::from_raw_parts(
377496
&process_state.buffer_data,
@@ -684,7 +803,7 @@ impl<P: Plugin> Instance<P> {
684803
unsafe extern "C" fn params_flush(
685804
plugin: *const clap_plugin,
686805
in_: *const clap_input_events,
687-
_out: *const clap_output_events,
806+
out: *const clap_output_events,
688807
) {
689808
let instance = &*(plugin as *const Self);
690809
let process_state = &mut *instance.process_state.get();
@@ -696,6 +815,12 @@ impl<P: Plugin> Instance<P> {
696815
process_state.events.clear();
697816
instance.sync_processor(&mut process_state.events);
698817
instance.process_param_events(in_, &mut process_state.events);
818+
instance.process_gestures(
819+
&mut process_state.gesture_states,
820+
&mut process_state.events,
821+
out,
822+
0,
823+
);
699824

700825
processor.process(
701826
Buffers::from_raw_parts(
@@ -730,6 +855,20 @@ impl<P: Plugin> Instance<P> {
730855
}
731856
}
732857
}
858+
859+
for update in instance.param_gestures.poll(&mut process_state.gesture_states) {
860+
let param = &instance.info.params[update.index];
861+
862+
if let Some(value) = update.set_value {
863+
main_thread_state.plugin.set_param(param.id, value);
864+
865+
if let Some(editor) = &mut main_thread_state.editor {
866+
editor.param_changed(param.id, value);
867+
}
868+
}
869+
870+
instance.send_gesture_events(&update, out, 0);
871+
}
733872
}
734873
}
735874
}

0 commit comments

Comments
 (0)