Implement automation gestures for CLAP
This commit is contained in:
parent
5d3527c5c2
commit
246c319bbf
2 changed files with 65 additions and 12 deletions
|
@ -8,6 +8,7 @@ use crate::context::{GuiContext, ProcessContext, Transport};
|
|||
use crate::event_loop::EventLoop;
|
||||
use crate::param::internals::ParamPtr;
|
||||
use crate::plugin::{ClapPlugin, NoteEvent};
|
||||
use crate::wrapper::clap::wrapper::OutputParamChangeType;
|
||||
|
||||
/// A [`GuiContext`] implementation for the wrapper. This is passed to the plugin in
|
||||
/// [`Editor::spawn()`][crate::prelude::Editor::spawn()] so it can interact with the rest of the plugin and
|
||||
|
@ -28,10 +29,23 @@ pub(crate) struct WrapperProcessContext<'a, P: ClapPlugin> {
|
|||
impl<P: ClapPlugin> GuiContext for WrapperGuiContext<P> {
|
||||
// All of these functions are supposed to be called from the main thread, so we'll put some
|
||||
// trust in the caller and assume that this is indeed the case
|
||||
unsafe fn raw_begin_set_parameter(&self, _param: ParamPtr) {
|
||||
// TODO: Parameter event gestures are a bit weird in CLAP right now because they're
|
||||
// implemented as flags on events, and you don't know when a gesture ends before it
|
||||
// has ended. Implement this once that's a bit clearer.
|
||||
unsafe fn raw_begin_set_parameter(&self, param: ParamPtr) {
|
||||
match self.wrapper.param_ptr_to_hash.get(¶m) {
|
||||
Some(hash) => {
|
||||
// Apparently you're supposed to resend old values for the automation begin and end
|
||||
// gestures
|
||||
let clap_plain_value =
|
||||
param.normalized_value() as f64 * param.step_count().unwrap_or(1) as f64;
|
||||
let success = self.wrapper.queue_parameter_change(OutputParamChange {
|
||||
param_hash: *hash,
|
||||
clap_plain_value,
|
||||
change_type: OutputParamChangeType::BeginGesture,
|
||||
});
|
||||
|
||||
nih_debug_assert!(success, "Parameter output queue was full, parameter change will not be sent to the host");
|
||||
}
|
||||
None => nih_debug_assert_failure!("Unknown parameter: {:?}", param),
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn raw_set_parameter_normalized(&self, param: ParamPtr, normalized: f32) {
|
||||
|
@ -46,6 +60,7 @@ impl<P: ClapPlugin> GuiContext for WrapperGuiContext<P> {
|
|||
let success = self.wrapper.queue_parameter_change(OutputParamChange {
|
||||
param_hash: *hash,
|
||||
clap_plain_value,
|
||||
change_type: OutputParamChangeType::Normal,
|
||||
});
|
||||
|
||||
nih_debug_assert!(success, "Parameter output queue was full, parameter change will not be sent to the host");
|
||||
|
@ -54,10 +69,23 @@ impl<P: ClapPlugin> GuiContext for WrapperGuiContext<P> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe fn raw_end_set_parameter(&self, _param: ParamPtr) {
|
||||
// TODO: Parameter event gestures are a bit weird in CLAP right now because they're
|
||||
// implemented as flags on events, and you don't know when a gesture ends before it
|
||||
// has ended. Implement this once that's a bit clearer.
|
||||
unsafe fn raw_end_set_parameter(&self, param: ParamPtr) {
|
||||
match self.wrapper.param_ptr_to_hash.get(¶m) {
|
||||
Some(hash) => {
|
||||
// Apparently you're supposed to resend old values for the automation begin and end
|
||||
// gestures
|
||||
let clap_plain_value =
|
||||
param.normalized_value() as f64 * param.step_count().unwrap_or(1) as f64;
|
||||
let success = self.wrapper.queue_parameter_change(OutputParamChange {
|
||||
param_hash: *hash,
|
||||
clap_plain_value,
|
||||
change_type: OutputParamChangeType::EndGesture,
|
||||
});
|
||||
|
||||
nih_debug_assert!(success, "Parameter output queue was full, parameter change will not be sent to the host");
|
||||
}
|
||||
None => nih_debug_assert_failure!("Unknown parameter: {:?}", param),
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn raw_default_normalized_param_value(&self, param: ParamPtr) -> f32 {
|
||||
|
|
|
@ -6,9 +6,10 @@ use atomic_float::AtomicF32;
|
|||
use atomic_refcell::{AtomicRefCell, AtomicRefMut};
|
||||
use clap_sys::events::{
|
||||
clap_event_header, clap_event_note, clap_event_param_mod, clap_event_param_value,
|
||||
clap_input_events, clap_output_events, CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_MIDI,
|
||||
CLAP_EVENT_NOTE_EXPRESSION, CLAP_EVENT_NOTE_OFF, CLAP_EVENT_NOTE_ON, CLAP_EVENT_PARAM_MOD,
|
||||
CLAP_EVENT_PARAM_VALUE, CLAP_EVENT_SHOULD_RECORD, CLAP_TRANSPORT_HAS_BEATS_TIMELINE,
|
||||
clap_input_events, clap_output_events, CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_BEGIN_ADJUST,
|
||||
CLAP_EVENT_END_ADJUST, CLAP_EVENT_IS_LIVE, CLAP_EVENT_MIDI, CLAP_EVENT_NOTE_EXPRESSION,
|
||||
CLAP_EVENT_NOTE_OFF, CLAP_EVENT_NOTE_ON, CLAP_EVENT_PARAM_MOD, CLAP_EVENT_PARAM_VALUE,
|
||||
CLAP_EVENT_SHOULD_RECORD, CLAP_TRANSPORT_HAS_BEATS_TIMELINE,
|
||||
CLAP_TRANSPORT_HAS_SECONDS_TIMELINE, CLAP_TRANSPORT_HAS_TEMPO,
|
||||
CLAP_TRANSPORT_HAS_TIME_SIGNATURE, CLAP_TRANSPORT_IS_LOOP_ACTIVE, CLAP_TRANSPORT_IS_PLAYING,
|
||||
CLAP_TRANSPORT_IS_RECORDING, CLAP_TRANSPORT_IS_WITHIN_PRE_ROLL,
|
||||
|
@ -226,6 +227,19 @@ pub struct OutputParamChange {
|
|||
/// The 'plain' value as reported to CLAP. This is the normalized value multiplied by
|
||||
/// [`Param::step_size()`][crate::Param::step_size()].
|
||||
pub clap_plain_value: f64,
|
||||
/// The kind of parameter change event, since CLAP wants you to resend an old value to handle
|
||||
/// automation start and end gestures.
|
||||
pub change_type: OutputParamChangeType,
|
||||
}
|
||||
|
||||
/// The type of an [`OutputParamChange`].
|
||||
pub enum OutputParamChangeType {
|
||||
/// A regular parameter change, sending a new value for a parameter.
|
||||
Normal,
|
||||
/// Tell the host that the automation gesture begins. The event may resend an old value.
|
||||
BeginGesture,
|
||||
/// Tell the host that the automation gesture has ended. This event may resend an old value.
|
||||
EndGesture,
|
||||
}
|
||||
|
||||
/// Because CLAP has this [`clap_host::request_host_callback()`] function, we don't need to use
|
||||
|
@ -644,7 +658,18 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
time: current_sample_idx as u32,
|
||||
space_id: CLAP_CORE_EVENT_SPACE_ID,
|
||||
type_: CLAP_EVENT_PARAM_VALUE,
|
||||
flags: CLAP_EVENT_SHOULD_RECORD,
|
||||
flags: match change.change_type {
|
||||
OutputParamChangeType::Normal => {
|
||||
CLAP_EVENT_IS_LIVE | CLAP_EVENT_SHOULD_RECORD
|
||||
}
|
||||
// TODO: Should this include `CLAP_EVENT_SHOULD_RECORD`?
|
||||
OutputParamChangeType::BeginGesture => {
|
||||
CLAP_EVENT_IS_LIVE | CLAP_EVENT_BEGIN_ADJUST
|
||||
}
|
||||
OutputParamChangeType::EndGesture => {
|
||||
CLAP_EVENT_IS_LIVE | CLAP_EVENT_END_ADJUST
|
||||
}
|
||||
},
|
||||
},
|
||||
param_id: change.param_hash,
|
||||
cookie: ptr::null_mut(),
|
||||
|
|
Loading…
Add table
Reference in a new issue