1
0
Fork 0

Handle MIDI events for CLAP

This commit is contained in:
Robbert van der Helm 2022-03-02 00:29:50 +01:00
parent 0d359c344a
commit 69a085ddad

View file

@ -1,6 +1,8 @@
use clap_sys::events::{
clap_event_header, clap_event_param_mod, clap_event_param_value, clap_input_events,
clap_output_events, CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_PARAM_MOD, CLAP_EVENT_PARAM_VALUE,
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,
};
use clap_sys::ext::params::{
clap_param_info, clap_plugin_params, CLAP_EXT_PARAMS, CLAP_PARAM_IS_BYPASS,
@ -17,7 +19,7 @@ use clap_sys::process::{
use crossbeam::atomic::AtomicCell;
use crossbeam::queue::ArrayQueue;
use lazy_static::lazy_static;
use parking_lot::RwLock;
use parking_lot::{RwLock, RwLockWriteGuard};
use std::cmp;
use std::collections::{HashMap, VecDeque};
use std::ffi::{c_void, CStr};
@ -64,7 +66,6 @@ pub struct Wrapper<P: ClapPlugin> {
///
/// TODO: Maybe load these lazily at some point instead of needing to spool them all to this
/// queue first
/// TODO: Read these in the process call.
input_events: RwLock<VecDeque<NoteEvent>>,
/// The current latency in samples, as set by the plugin through the [ProcessContext]. uses the
/// latency extnesion
@ -347,7 +348,14 @@ impl<P: ClapPlugin> Wrapper<P> {
/// Handle an incoming CLAP event. You must clear [Self::input_events] first before calling this
/// from the process function.
pub unsafe fn handle_event(&self, event: *const clap_event_header) {
///
/// To save on mutex operations when handing MIDI events, the lock guard for the input events
/// need to be passed into this function.
pub unsafe fn handle_event(
&self,
event: *const clap_event_header,
input_events: &mut RwLockWriteGuard<VecDeque<NoteEvent>>,
) {
let raw_event = &*event;
match (raw_event.space_id, raw_event.type_) {
// TODO: Implement the event filter
@ -369,7 +377,38 @@ impl<P: ClapPlugin> Wrapper<P> {
self.current_buffer_config.load().map(|c| c.sample_rate),
);
}
// TODO: Handle MIDI if `P::ACCEPTS_MIDI` is true
(CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_NOTE_ON) => {
if P::ACCEPTS_MIDI {
let event = &*(event as *const clap_event_note);
input_events.push_back(NoteEvent::NoteOn {
timing: raw_event.time,
channel: event.channel as u8,
note: event.key as u8,
velocity: (event.velocity * 127.0).round() as u8,
});
}
}
(CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_NOTE_OFF) => {
if P::ACCEPTS_MIDI {
let event = &*(event as *const clap_event_note);
input_events.push_back(NoteEvent::NoteOff {
timing: raw_event.time,
channel: event.channel as u8,
note: event.key as u8,
velocity: (event.velocity * 127.0).round() as u8,
});
}
}
(CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_NOTE_EXPRESSION) => {
if P::ACCEPTS_MIDI {
// TODO: Implement pressure and other expressions along with MIDI CCs
}
}
(CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_MIDI) => {
if P::ACCEPTS_MIDI {
// TODO: Implement raw MIDI handling once we add CCs
}
}
// TODO: Make sure this only gets logged in debug mode
_ => nih_log!(
"Unhandled CLAP event type {} for namespace {}",
@ -455,13 +494,15 @@ impl<P: ClapPlugin> Wrapper<P> {
process_wrapper(|| {
// We need to handle incoming automation and MIDI events. Since we don't support sample
// accuration automation yet and there's no way to get the last event for a parameter,
// we'll process every incomingevent.
// we'll process every incoming event.
let process = &*process;
if !process.in_events.is_null() {
let mut input_events_guard = wrapper.input_events.write();
let num_events = ((*process.in_events).size)(&*process.in_events);
for event_idx in 0..num_events {
let event = ((*process.in_events).get)(&*process.in_events, event_idx);
wrapper.handle_event(event);
wrapper.handle_event(event, &mut input_events_guard);
}
}
@ -761,10 +802,12 @@ impl<P: ClapPlugin> Wrapper<P> {
let wrapper = &*(plugin as *const Self);
if !in_.is_null() {
let mut input_events_guard = wrapper.input_events.write();
let num_events = ((*in_).size)(&*in_);
for event_idx in 0..num_events {
let event = ((*in_).get)(&*in_, event_idx);
wrapper.handle_event(event);
wrapper.handle_event(event, &mut input_events_guard);
}
}