Skip to content

Commit

Permalink
More docs, clippy fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
prokopyl committed Apr 5, 2024
1 parent 9c5c9e4 commit 08be143
Show file tree
Hide file tree
Showing 39 changed files with 182 additions and 74 deletions.
9 changes: 4 additions & 5 deletions common/src/extensions.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Traits and associated utilities to handle and implement CLAP extensions.
//!
//! See the documentation of the `extensions` module in `clack-plugin` and `clack-host` for
//! implementation examples.
//! See the documentation of the `extensions` module in the `clack-plugin` and `clack-host` crates
//! for implementation examples.
use std::ffi::CStr;

Expand Down Expand Up @@ -35,11 +35,10 @@ mod private {
impl Sealed for HostExtensionSide {}
}

// TODO: update docs
/// A type representing a CLAP extension ABI.
/// A type representing a CLAP extension pointer.
///
/// The role of this trait is to tie a type to a standard CLAP extension identifier.
/// This is then used by some Clack methods to retrieve the correct extension type from its
/// This is then used by the Clack APIs to always match the correct extension type from its
/// identifier.
///
/// This trait also defines how an extension pointer should be transformed to a reference to the
Expand Down
102 changes: 88 additions & 14 deletions common/src/extensions/raw.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,66 @@
#![deny(missing_docs)]
use crate::extensions::{ExtensionSide, HostExtensionSide, PluginExtensionSide};
use clap_sys::host::clap_host;
use clap_sys::plugin::clap_plugin;
use std::ffi::c_void;
use std::fmt::{Debug, Formatter};
use std::marker::PhantomData;
use std::ptr::NonNull;

#[derive(Copy, Clone)]
/// A raw extension pointer.
///
/// This type is used by extension implementations to abstract away most of the safety concerns of
/// using extension pointers.
///
/// Using the `S` type parameter with either [`PluginExtensionSide`] or [`HostExtensionSide`], this
/// can be used as either a plugin-side extension or a host-side extension, respectively.
///
/// The `T` type parameter is the extension struct this points to (e.g. `clap_plugin_state`), or
/// `()` if the extension pointer is untyped.
///
/// Internally, this holds two pointers: a pointer to the actual extension struct, and a pointer
/// to the matching `clap_plugin` or `clap_host`. These are compared on each use to make sure
/// that the right extensions are always called with the right instance.
///
/// This type does not directly track the lifetimes of its pointers at all, they may become dangling
/// at any time. However, it is part of the safety contract of this type that the extension pointer
/// *MUST* be valid as long as the matching `clap_plugin` or `clap_host` still is, as per the CLAP
/// specification.
///
/// This property is then extrapolated so that if any valid `clap_plugin` or `clap_host` reference,
/// that also matches the pointer stored in this type, is encountered, then it must mean that the
/// inner extension pointer is also valid, and can be safely de-referenced.
///
/// To safely get valid references to the extension struct out of this type, you have to use the
/// `use_extension()` method on one of the handle types:
///
/// * For plugin-side extensions (from the `clack-host` crate): `PluginSharedHandle`,
/// `PluginMainThreadHandle`, or `PluginAudioThreadHandle`;
/// * For host-side extensions (from the `clack-plugin` crate): `HostSharedHandle`,
/// `HostMainThreadHandle`, or `HostAudioThreadHandle`.
///
/// This pointer type is only useful for *consuming* extension pointers. For producing extension
/// pointers from an extension implementation, use the [`RawExtensionImplementation`] type instead.
#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct RawExtension<S: ExtensionSide, T = ()> {
extension_ptr: NonNull<T>,
host_or_plugin_ptr: NonNull<c_void>, // Can be either clap_host or clap_plugin
_side: PhantomData<fn() -> S>,
}

impl<S: ExtensionSide, T> PartialEq for RawExtension<S, T> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.extension_ptr == other.extension_ptr
}
}

impl<S: ExtensionSide, T> Eq for RawExtension<S, T> {}

// SAFETY: this is just a couple of pointers, and the type doesn't care being used on any thread.
// Thread-safety is enforced by the plugin handle type that is passed to the methods.
unsafe impl<S: ExtensionSide, T> Send for RawExtension<S, T> {}
// SAFETY: same as above.
unsafe impl<S: ExtensionSide, T> Sync for RawExtension<S, T> {}

impl<S: ExtensionSide, T> RawExtension<S, T> {
/// Returns the raw pointer to the extension struct.
///
/// This pointer may be dangling at any time.
///
/// See the [`RawExtension`] type documentation for more information on how to get a valid
/// reference to the extension struct instead.
#[inline]
pub fn as_ptr(&self) -> NonNull<T> {
self.extension_ptr
Expand Down Expand Up @@ -59,15 +92,22 @@ impl<T> RawExtension<PluginExtensionSide, T> {
/// plugin instance.
///
/// The given `plugin_ptr` however doesn't have to be valid, and may be dangling.
pub unsafe fn from_raw(extension_ptr: NonNull<T>, plugin_ptr: NonNull<clap_plugin>) -> Self {
pub unsafe fn from_raw_plugin_extension(
extension_ptr: NonNull<T>,
plugin_ptr: NonNull<clap_plugin>,
) -> Self {
Self {
extension_ptr,
host_or_plugin_ptr: plugin_ptr.cast(),
_side: PhantomData,
}
}

// TODO: docs: this can be dangling
/// Returns the raw pointer to the plugin instance the extension originated from.
///
/// This pointer may be dangling at any time, and is not meant to be de-referenced, only
/// compared to.
/// See the [`RawExtension`] type documentation for more information.
pub fn plugin_ptr(&self) -> NonNull<clap_plugin> {
self.host_or_plugin_ptr.cast()
}
Expand All @@ -83,33 +123,67 @@ impl<T> RawExtension<HostExtensionSide, T> {
/// plugin instance.
///
/// The given `host_ptr` however doesn't have to be valid, and may be dangling.
pub unsafe fn from_raw(extension_ptr: NonNull<T>, host_ptr: NonNull<clap_host>) -> Self {
pub unsafe fn from_raw_host_extension(
extension_ptr: NonNull<T>,
host_ptr: NonNull<clap_host>,
) -> Self {
Self {
extension_ptr,
host_or_plugin_ptr: host_ptr.cast(),
_side: PhantomData,
}
}

// TODO: docs: this can be dangling
/// Returns the raw pointer to the host instance the extension originated from.
///
/// This pointer may be dangling at any time, and is not meant to be de-referenced, only
/// compared to.
/// See the [`RawExtension`] type documentation for more information.
pub fn host_ptr(&self) -> NonNull<clap_host> {
self.host_or_plugin_ptr.cast()
}
}

/// A pointer to an extension's implementation struct.
///
/// This type is used to type-erase a reference to the implementation struct of an extension before
/// transferring it to the consumer through `get_extension`.
///
/// This type is also used to enforce the extension pointer is always valid, as extension
/// implementations produced from Clack always come from statics and therefore always have the
/// `'static` lifetime.
///
/// Note this is *not* the case for all CLAP plugins: extension pointers are only guaranteed to be
/// valid for the lifetime of the instance (plugin or host) they originate from.
///
/// Use the [`RawExtension`] type to properly use and track the lifetime of extension pointers on
/// the consumer-side.
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct RawExtensionImplementation {
inner: NonNull<c_void>,
}

impl RawExtensionImplementation {
/// Creates a new pointer from a `'static` reference to an implementation struct.
pub const fn new<I>(implementation: &'static I) -> Self {
Self {
// SAFETY: pointer comes from a reference, so it's guaranteed to always be valid.
inner: unsafe { NonNull::new_unchecked(implementation as *const _ as *mut _) },
}
}

/// Returns the raw pointer to the extension implementation struct.
///
/// This pointer is always valid and never dangling, as it originates from a `'static`
/// reference.
pub const fn as_ptr(&self) -> NonNull<c_void> {
self.inner
}
}

impl Debug for RawExtensionImplementation {
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "RawExtensionImplementation({:p})", self.inner)
}
}
4 changes: 2 additions & 2 deletions extensions/src/__doc_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ mod diva_stub {
shared: &'a DivaPluginStubShared<'a>,
}
pub struct DivaPluginStubShared<'a> {
host: HostHandle<'a>,
host: HostSharedHandle<'a>,
}

pub struct DivaPluginStubMainThread {}
Expand Down Expand Up @@ -63,7 +63,7 @@ mod diva_stub {
PluginDescriptor::new("com.u-he.diva", "Diva").with_features([SYNTHESIZER, STEREO])
}

fn new_shared(host: HostHandle) -> Result<Self::Shared<'_>, PluginError> {
fn new_shared(host: HostSharedHandle) -> Result<Self::Shared<'_>, PluginError> {
Ok(DivaPluginStubShared { host })
}

Expand Down
2 changes: 2 additions & 0 deletions extensions/src/audio_ports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ use std::ffi::CStr;
use std::fmt::{Debug, Formatter};

#[derive(Copy, Clone)]
#[allow(dead_code)]
pub struct PluginAudioPorts(RawExtension<PluginExtensionSide, clap_plugin_audio_ports>);

#[derive(Copy, Clone)]
#[allow(dead_code)]
pub struct HostAudioPorts(RawExtension<HostExtensionSide, clap_host_audio_ports>);

#[derive(Copy, Clone, Eq, PartialEq, Debug)]
Expand Down
2 changes: 2 additions & 0 deletions extensions/src/audio_ports_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use std::fmt::{Display, Formatter};

/// The Plugin-side of the Audio Ports Configurations extension.
#[derive(Copy, Clone)]
#[allow(dead_code)]
pub struct PluginAudioPortsConfig(
RawExtension<PluginExtensionSide, clap_plugin_audio_ports_config>,
);
Expand All @@ -41,6 +42,7 @@ unsafe impl Extension for PluginAudioPortsConfig {

/// The Host-side of the Audio Ports Configurations extension.
#[derive(Copy, Clone)]
#[allow(dead_code)]
pub struct HostAudioPortsConfig(RawExtension<HostExtensionSide, clap_host_audio_ports_config>);

// SAFETY: This type is repr(C) and ABI-compatible with the matching extension type.
Expand Down
1 change: 1 addition & 0 deletions extensions/src/event_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use clap_sys::ext::event_registry::{clap_host_event_registry, CLAP_EXT_EVENT_REG
use std::ffi::CStr;

#[derive(Copy, Clone)]
#[allow(dead_code)]
pub struct HostEventRegistry(RawExtension<HostExtensionSide, clap_host_event_registry>);

// SAFETY: This type is repr(C) and ABI-compatible with the matching extension type.
Expand Down
2 changes: 2 additions & 0 deletions extensions/src/gui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ pub enum AspectRatioStrategy {

/// The Plugin-side of the GUI extension.
#[derive(Copy, Clone)]
#[allow(dead_code)]
pub struct PluginGui(RawExtension<PluginExtensionSide, clap_plugin_gui>);

// SAFETY: This type is repr(C) and ABI-compatible with the matching extension type.
Expand All @@ -165,6 +166,7 @@ unsafe impl Extension for PluginGui {

/// The Host-side of the GUI extension.
#[derive(Copy, Clone)]
#[allow(dead_code)]
pub struct HostGui(RawExtension<HostExtensionSide, clap_host_gui>);

// SAFETY: This type is repr(C) and ABI-compatible with the matching extension type.
Expand Down
10 changes: 5 additions & 5 deletions extensions/src/gui/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::os::raw::c_char;
impl HostGui {
/// Notify the host that the plugin window's [`GuiResizeHints`] have changed, and
/// `get_resize_hints` should be called again.
pub fn resize_hints_changed(&self, host: &HostHandle) {
pub fn resize_hints_changed(&self, host: &HostSharedHandle) {
if let Some(resize_hints_changed) = host.use_extension(&self.0).resize_hints_changed {
// SAFETY: This type ensures the function pointer is valid.
unsafe { resize_hints_changed(host.as_raw()) }
Expand All @@ -27,7 +27,7 @@ impl HostGui {
/// `set_size` method to revert the operation.
pub fn request_resize(
&self,
host: &HostHandle,
host: &HostSharedHandle,
width: u32,
height: u32,
) -> Result<(), GuiError> {
Expand All @@ -49,7 +49,7 @@ impl HostGui {
///
/// This may return a [`GuiError::RequestShowError`] if the host denied or was unable to fulfill the
/// request.
pub fn request_show(&self, host: &HostHandle) -> Result<(), GuiError> {
pub fn request_show(&self, host: &HostSharedHandle) -> Result<(), GuiError> {
// SAFETY: This type ensures the function pointer is valid.
if unsafe {
host.use_extension(&self.0)
Expand All @@ -68,7 +68,7 @@ impl HostGui {
///
/// This may return a [`GuiError::RequestHideError`] if the host denied or was unable to fulfill the
/// request.
pub fn request_hide(&self, host: &HostHandle) -> Result<(), GuiError> {
pub fn request_hide(&self, host: &HostSharedHandle) -> Result<(), GuiError> {
// SAFETY: This type ensures the function pointer is valid.
if unsafe {
host.use_extension(&self.0)
Expand All @@ -85,7 +85,7 @@ impl HostGui {
/// the GUI was lost.
///
/// If `is_destroyed` is true, then the host must call `destroy` to acknowledge the GUI destruction.
pub fn closed(&self, host: &HostHandle, was_destroyed: bool) {
pub fn closed(&self, host: &HostSharedHandle, was_destroyed: bool) {
if let Some(closed) = host.use_extension(&self.0).closed {
// SAFETY: This type ensures the function pointer is valid.
unsafe { closed(host.as_raw(), was_destroyed) }
Expand Down
2 changes: 2 additions & 0 deletions extensions/src/latency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use clap_sys::ext::latency::{clap_host_latency, clap_plugin_latency, CLAP_EXT_LA
use std::ffi::CStr;

#[derive(Copy, Clone)]
#[allow(dead_code)]
pub struct PluginLatency(RawExtension<PluginExtensionSide, clap_plugin_latency>);

// SAFETY: This type is repr(C) and ABI-compatible with the matching extension type.
Expand All @@ -17,6 +18,7 @@ unsafe impl Extension for PluginLatency {
}

#[derive(Copy, Clone)]
#[allow(dead_code)]
pub struct HostLatency(RawExtension<HostExtensionSide, clap_host_latency>);

// SAFETY: This type is repr(C) and ABI-compatible with the matching extension type.
Expand Down
5 changes: 3 additions & 2 deletions extensions/src/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ impl Display for LogSeverity {
}

#[derive(Copy, Clone)]
#[allow(dead_code)]
pub struct HostLog(RawExtension<HostExtensionSide, clap_host_log>);

// SAFETY: This type is repr(C) and ABI-compatible with the matching extension type.
Expand All @@ -81,11 +82,11 @@ unsafe impl Extension for HostLog {
#[cfg(feature = "clack-plugin")]
mod plugin {
use super::*;
use clack_plugin::host::HostHandle;
use clack_plugin::host::HostSharedHandle;

impl HostLog {
#[inline]
pub fn log(&self, host: &HostHandle, log_severity: LogSeverity, message: &CStr) {
pub fn log(&self, host: &HostSharedHandle, log_severity: LogSeverity, message: &CStr) {
if let Some(log) = host.use_extension(&self.0).log {
// SAFETY: This type ensures the function pointer is valid.
unsafe { log(host.as_raw(), log_severity.to_raw(), message.as_ptr()) }
Expand Down
2 changes: 2 additions & 0 deletions extensions/src/note_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use std::ffi::CStr;

/// The Plugin-side of the Note Name extension.
#[derive(Copy, Clone)]
#[allow(dead_code)]
pub struct PluginNoteName(RawExtension<PluginExtensionSide, clap_plugin_note_name>);

// SAFETY: This type is repr(C) and ABI-compatible with the matching extension type.
Expand All @@ -23,6 +24,7 @@ unsafe impl Extension for PluginNoteName {

/// The Host-side of the Note Name extension.
#[derive(Copy, Clone)]
#[allow(dead_code)]
pub struct HostNoteName(RawExtension<HostExtensionSide, clap_host_note_name>);

// SAFETY: This type is repr(C) and ABI-compatible with the matching extension type.
Expand Down
2 changes: 2 additions & 0 deletions extensions/src/note_ports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ use clap_sys::ext::note_ports::*;
use std::ffi::CStr;

#[derive(Copy, Clone)]
#[allow(dead_code)]
pub struct PluginNotePorts(RawExtension<PluginExtensionSide, clap_plugin_note_ports>);

#[derive(Copy, Clone)]
#[allow(dead_code)]
pub struct HostNotePorts(RawExtension<HostExtensionSide, clap_host_note_ports>);

bitflags! {
Expand Down
2 changes: 2 additions & 0 deletions extensions/src/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ impl ParamInfoFlags {
}

#[derive(Copy, Clone)]
#[allow(dead_code)]
pub struct PluginParams(RawExtension<PluginExtensionSide, clap_plugin_params>);

// SAFETY: This type is repr(C) and ABI-compatible with the matching extension type.
Expand All @@ -90,6 +91,7 @@ unsafe impl Extension for PluginParams {
}

#[derive(Copy, Clone)]
#[allow(dead_code)]
pub struct HostParams(RawExtension<HostExtensionSide, clap_host_params>);

// SAFETY: This type is repr(C) and ABI-compatible with the matching extension type.
Expand Down
Loading

0 comments on commit 08be143

Please sign in to comment.