Skip to content

Commit

Permalink
clap: implement gui extension
Browse files Browse the repository at this point in the history
  • Loading branch information
micahrj committed Oct 26, 2023
1 parent e9e677f commit 10f30c2
Show file tree
Hide file tree
Showing 3 changed files with 200 additions and 15 deletions.
176 changes: 176 additions & 0 deletions src/format/clap/gui.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
use std::ffi::{c_char, CStr};

use clap_sys::ext::gui::*;
use clap_sys::plugin::*;

use super::instance::Instance;
use crate::parent::{Parent, RawParent};
use crate::{Editor, Plugin};

impl<P: Plugin> Instance<P> {
pub(super) const GUI: clap_plugin_gui = clap_plugin_gui {
is_api_supported: Some(Self::gui_is_api_supported),
get_preferred_api: Some(Self::gui_get_preferred_api),
create: Some(Self::gui_create),
destroy: Some(Self::gui_destroy),
set_scale: Some(Self::gui_set_scale),
get_size: Some(Self::gui_get_size),
can_resize: Some(Self::gui_can_resize),
get_resize_hints: Some(Self::gui_get_resize_hints),
adjust_size: Some(Self::gui_adjust_size),
set_size: Some(Self::gui_set_size),
set_parent: Some(Self::gui_set_parent),
set_transient: Some(Self::gui_set_transient),
suggest_title: Some(Self::gui_suggest_title),
show: Some(Self::gui_show),
hide: Some(Self::gui_hide),
};

#[cfg(target_os = "windows")]
const API: &CStr = CLAP_WINDOW_API_WIN32;

#[cfg(target_os = "macos")]
const API: &CStr = CLAP_WINDOW_API_COCOA;

#[cfg(target_os = "linux")]
const API: &CStr = CLAP_WINDOW_API_X11;

unsafe extern "C" fn gui_is_api_supported(
_plugin: *const clap_plugin,
api: *const c_char,
is_floating: bool,
) -> bool {
if is_floating {
return false;
}

CStr::from_ptr(api) == Self::API
}

unsafe extern "C" fn gui_get_preferred_api(
_plugin: *const clap_plugin,
api: *mut *const c_char,
is_floating: *mut bool,
) -> bool {
*is_floating = false;

*api = Self::API.as_ptr();

true
}

unsafe extern "C" fn gui_create(
plugin: *const clap_plugin,
api: *const c_char,
is_floating: bool,
) -> bool {
if !Self::gui_is_api_supported(plugin, api, is_floating) {
return false;
}

true
}

unsafe extern "C" fn gui_destroy(plugin: *const clap_plugin) {
let instance = &*(plugin as *const Self);
let main_thread_state = &mut *instance.main_thread_state.get();

main_thread_state.editor = None;
}

unsafe extern "C" fn gui_set_scale(_plugin: *const clap_plugin, _scale: f64) -> bool {
false
}

unsafe extern "C" fn gui_get_size(
plugin: *const clap_plugin,
width: *mut u32,
height: *mut u32,
) -> bool {
let instance = &*(plugin as *const Self);
let main_thread_state = &mut *instance.main_thread_state.get();

if let Some(editor) = &main_thread_state.editor {
let size = editor.size();

*width = size.width.round() as u32;
*height = size.height.round() as u32;

return true;
}

false
}

unsafe extern "C" fn gui_can_resize(_plugin: *const clap_plugin) -> bool {
false
}

unsafe extern "C" fn gui_get_resize_hints(
_plugin: *const clap_plugin,
_hints: *mut clap_gui_resize_hints,
) -> bool {
false
}

unsafe extern "C" fn gui_adjust_size(
_plugin: *const clap_plugin,
_width: *mut u32,
_height: *mut u32,
) -> bool {
false
}

unsafe extern "C" fn gui_set_size(
_plugin: *const clap_plugin,
_width: u32,
_height: u32,
) -> bool {
false
}

unsafe extern "C" fn gui_set_parent(
plugin: *const clap_plugin,
window: *const clap_window,
) -> bool {
let window = &*window;

if CStr::from_ptr(window.api) != Self::API {
return false;
}

#[cfg(target_os = "windows")]
let raw_parent = { RawParent::Win32(window.specific.win32) };

#[cfg(target_os = "macos")]
let raw_parent = { RawParent::Cocoa(window.specific.cocoa) };

#[cfg(target_os = "linux")]
let raw_parent = { RawParent::X11(window.specific.x11) };

let instance = &*(plugin as *const Self);
let main_thread_state = &mut *instance.main_thread_state.get();

let editor = main_thread_state.plugin.editor(Parent::from_raw(raw_parent));
main_thread_state.editor = Some(editor);

true
}

unsafe extern "C" fn gui_set_transient(
_plugin: *const clap_plugin,
_window: *const clap_window,
) -> bool {
false
}

unsafe extern "C" fn gui_suggest_title(_plugin: *const clap_plugin, _title: *const c_char) {}

unsafe extern "C" fn gui_show(_plugin: *const clap_plugin) -> bool {
false
}

unsafe extern "C" fn gui_hide(_plugin: *const clap_plugin) -> bool {
false
}
}
38 changes: 23 additions & 15 deletions src/format/clap/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::ptr::NonNull;
use std::sync::Arc;
use std::{io, ptr, slice};

use clap_sys::ext::{audio_ports::*, audio_ports_config::*, params::*, state::*};
use clap_sys::ext::{audio_ports::*, audio_ports_config::*, gui::*, params::*, state::*};
use clap_sys::{events::*, id::*, plugin::*, process::*, stream::*};

use crate::buffers::{Buffers, BusData};
Expand All @@ -15,7 +15,7 @@ use crate::events::{Data, Event, Events};
use crate::param::Range;
use crate::sync::params::ParamValues;
use crate::util::{copy_cstring, slice_from_raw_parts_checked};
use crate::{Config, Host, ParamId, Plugin, PluginInfo, Processor};
use crate::{Config, Editor, Host, ParamId, Plugin, PluginInfo, Processor};

fn port_type_from_format(format: &Format) -> &'static CStr {
match format {
Expand All @@ -24,12 +24,13 @@ fn port_type_from_format(format: &Format) -> &'static CStr {
}
}

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

struct ProcessState<P: Plugin> {
pub struct ProcessState<P: Plugin> {
buses: Vec<BusData>,
buffer_ptrs: Vec<*mut f32>,
events: Vec<Event>,
Expand All @@ -39,15 +40,15 @@ struct ProcessState<P: Plugin> {
#[repr(C)]
pub struct Instance<P: Plugin> {
#[allow(unused)]
clap_plugin: clap_plugin,
info: Arc<PluginInfo>,
input_bus_map: Vec<usize>,
output_bus_map: Vec<usize>,
param_map: HashMap<ParamId, usize>,
plugin_params: ParamValues,
processor_params: ParamValues,
main_thread_state: UnsafeCell<MainThreadState<P>>,
process_state: UnsafeCell<ProcessState<P>>,
pub clap_plugin: clap_plugin,
pub info: Arc<PluginInfo>,
pub input_bus_map: Vec<usize>,
pub output_bus_map: Vec<usize>,
pub param_map: HashMap<ParamId, usize>,
pub plugin_params: ParamValues,
pub processor_params: ParamValues,
pub main_thread_state: UnsafeCell<MainThreadState<P>>,
pub process_state: UnsafeCell<ProcessState<P>>,
}

unsafe impl<P: Plugin> Sync for Instance<P> {}
Expand Down Expand Up @@ -96,6 +97,7 @@ impl<P: Plugin> Instance<P> {
main_thread_state: UnsafeCell::new(MainThreadState {
layout_index: 0,
plugin: P::new(Host {}),
editor: None,
}),
process_state: UnsafeCell::new(ProcessState {
buses: Vec::new(),
Expand Down Expand Up @@ -318,6 +320,12 @@ impl<P: Plugin> Instance<P> {
return &Self::STATE as *const _ as *const c_void;
}

if P::Editor::exists() {
if id == CLAP_EXT_GUI {
return &Self::GUI as *const _ as *const c_void;
}
}

ptr::null()
}

Expand Down
1 change: 1 addition & 0 deletions src/format/clap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::ffi::{c_char, c_void};
use clap_sys::{entry::*, version::*};

mod factory;
mod gui;
mod instance;

#[doc(hidden)]
Expand Down

0 comments on commit 10f30c2

Please sign in to comment.