Implement the event loop for CLAP
It cannot yet handle any tasks though.
This commit is contained in:
parent
4ad972ea23
commit
2750b2a6ad
|
@ -2,16 +2,18 @@ use clap_sys::host::clap_host;
|
|||
use clap_sys::plugin::clap_plugin;
|
||||
use clap_sys::process::{clap_process, clap_process_status};
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use crossbeam::queue::ArrayQueue;
|
||||
use parking_lot::RwLock;
|
||||
use std::collections::VecDeque;
|
||||
use std::ffi::c_void;
|
||||
use std::os::raw::c_char;
|
||||
use std::ptr;
|
||||
use std::sync::atomic::AtomicU32;
|
||||
use std::thread::{self, ThreadId};
|
||||
|
||||
use super::context::WrapperProcessContext;
|
||||
use super::descriptor::PluginDescriptor;
|
||||
use crate::event_loop::{EventLoop, MainThreadExecutor};
|
||||
use crate::event_loop::{EventLoop, MainThreadExecutor, TASK_QUEUE_CAPACITY};
|
||||
use crate::plugin::{BufferConfig, BusConfig, ClapPlugin};
|
||||
use crate::NoteEvent;
|
||||
|
||||
|
@ -45,6 +47,18 @@ pub struct Plugin<P: ClapPlugin> {
|
|||
/// Needs to be boxed because the plugin object is supposed to contain a static reference to
|
||||
/// this.
|
||||
plugin_descriptor: Box<PluginDescriptor<P>>,
|
||||
|
||||
/// A queue of tasks that still need to be performed. Because CLAP lets the plugin request a
|
||||
/// host callback directly, we don't need to use the OsEventLoop we use in our other plugin
|
||||
/// implementations. Instead, we'll post tasks to this queue, ask the host to call
|
||||
/// [Self::on_main_thread] on the main thread, and then continue to pop tasks off this queue
|
||||
/// there until it is empty.
|
||||
tasks: ArrayQueue<Task>,
|
||||
/// The ID of the main thread. In practice this is the ID of the thread that created this
|
||||
/// object.
|
||||
///
|
||||
/// TODO: If the host supports the ThreadCheck extension, we should use that instead.
|
||||
main_thread_id: ThreadId,
|
||||
}
|
||||
|
||||
/// Send+Sync wrapper around clap_host.
|
||||
|
@ -62,22 +76,35 @@ pub enum Task {
|
|||
/// Because CLAP has this [clap_host::request_host_callback()] function, we don't need to use
|
||||
/// `OsEventLoop` and can instead just request a main thread callback directly.
|
||||
impl<P: ClapPlugin> EventLoop<Task, Plugin<P>> for Plugin<P> {
|
||||
fn new_and_spawn(executor: std::sync::Weak<Self>) -> Self {
|
||||
fn new_and_spawn(_executor: std::sync::Weak<Self>) -> Self {
|
||||
panic!("What are you doing");
|
||||
}
|
||||
|
||||
fn do_maybe_async(&self, task: Task) -> bool {
|
||||
todo!()
|
||||
if self.is_main_thread() {
|
||||
unsafe { self.execute(task) };
|
||||
true
|
||||
} else {
|
||||
let success = self.tasks.push(task).is_ok();
|
||||
if success {
|
||||
// CLAP lets us use the host's event loop instead of having to implement our own
|
||||
let host = self.host_callback.0;
|
||||
unsafe { ((*host).request_callback)(host) };
|
||||
}
|
||||
|
||||
success
|
||||
}
|
||||
}
|
||||
|
||||
fn is_main_thread(&self) -> bool {
|
||||
todo!()
|
||||
// TODO: Use the `thread_check::is_main_thread` extension method if that's available
|
||||
thread::current().id() == self.main_thread_id
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: ClapPlugin> MainThreadExecutor<Task> for Plugin<P> {
|
||||
unsafe fn execute(&self, task: Task) {
|
||||
todo!()
|
||||
todo!("Implement latency changes for CLAP")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,6 +147,9 @@ impl<P: ClapPlugin> Plugin<P> {
|
|||
|
||||
host_callback: HostCallback(host_callback),
|
||||
plugin_descriptor,
|
||||
|
||||
tasks: ArrayQueue::new(TASK_QUEUE_CAPACITY),
|
||||
main_thread_id: thread::current().id(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,7 +172,7 @@ impl<P: ClapPlugin> Plugin<P> {
|
|||
unsafe extern "C" fn activate(
|
||||
plugin: *const clap_plugin,
|
||||
sample_rate: f64,
|
||||
min_frames_count: u32,
|
||||
_min_frames_count: u32,
|
||||
max_frames_count: u32,
|
||||
) -> bool {
|
||||
let plugin = &*(plugin as *const Self);
|
||||
|
@ -199,6 +229,12 @@ impl<P: ClapPlugin> Plugin<P> {
|
|||
}
|
||||
|
||||
unsafe extern "C" fn on_main_thread(plugin: *const clap_plugin) {
|
||||
todo!();
|
||||
let plugin = &*(plugin as *const Self);
|
||||
|
||||
// [Self::do_maybe_async] posts a task to the queue and asks the host to call this function
|
||||
// on the main thread, so once that's done we can just handle all requests here
|
||||
while let Some(task) = plugin.tasks.pop() {
|
||||
plugin.execute(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue