Skip to main content

Module extensions

Module extensions 

Source
Expand description

Traits and associated utilities to handle and implement CLAP extensions.

These traits are designed to be used for implementing custom or unsupported extensions. If you want to use an existing extension in your plugin, see the clack_extensions crate instead.

§Example

This example shows a basic implementation for the plugin side of the CLAP State extension.

The implementation wrapper leverages the PluginWrapper utility to handle things like error management and unwind safety. See its documentation for more information.

use std::ffi::CStr;
use clap_sys::ext::state::{CLAP_EXT_STATE, clap_plugin_state};
use clack_plugin::extensions::prelude::*;

// The struct end-users will actually interact with.
#[derive(Copy, Clone)]
pub struct PluginState(RawExtension<PluginExtensionSide, clap_plugin_state>);

unsafe impl Extension for PluginState {
    const IDENTIFIERS: &[&CStr] = &[CLAP_EXT_STATE];
    type ExtensionSide = PluginExtensionSide;

    #[inline]
    unsafe fn from_raw(raw: RawExtension<Self::ExtensionSide>) -> Self {
        Self(raw.cast())
    }
}

// For implementors of the extensions (here, on the plugin side):
// first define a trait the extension has to implement
use clack_common::stream::{InputStream, OutputStream};
use clack_plugin::plugin::{Plugin, PluginError};

pub trait PluginStateImplementation {
    fn load(&self, input: &mut InputStream) -> Result<(), PluginError>;
}

// Then, implement the ExtensionImplementation trait for the given implementors
// to provide the C FFI-compatible struct.

// SAFETY: The given struct is the CLAP extension struct for the matching side of this extension.
unsafe impl<P: Plugin> ExtensionImplementation<P> for PluginState
where
    // In this case, all the CLAP State methods belong to the main thread.
    // Other extensions may have other requirements, possibly split between multiple threads.
    for<'a> P::MainThread<'a>: PluginStateImplementation,
{
    const IMPLEMENTATION: RawExtensionImplementation =
        RawExtensionImplementation::new(&clap_plugin_state {
            // For the sake of this example, we are only implementing the load() method.
            load: Some(load::<P>),
        });
}

// Finally, implement the C FFI functions that will be exposed to the host.
use clap_sys::stream::clap_istream;

unsafe extern "C" fn load<P: Plugin>(
    plugin: *const clap_plugin,
    stream: *const clap_istream,
) -> bool
where
    for<'a> P::MainThread<'a>: PluginStateImplementation,
{
    PluginWrapper::<P>::handle(plugin, |p| {
        let input = InputStream::from_raw_mut(&mut *(stream as *mut _));
        // Retrieve the plugin's main thread struct, and call load() on it
        p.main_thread().load(input)?;
        Ok(())
    })
    .is_some()
}

Modules§

prelude
A prelude which re-exports all the types and traits used for custom extension implementation.
wrapper
Utilities to manipulate Plugin instances from an FFI context.

Structs§

HostExtensionSide
A marker struct that represents extensions to be implemented by the host side.
PluginExtensionSide
A marker struct that represents extensions to be implemented by the plugin side.
PluginExtensions
A collection of all extensions supported for a given plugin type P.
RawExtension
A raw extension pointer.
RawExtensionImplementation
A pointer to an extension’s implementation struct.

Traits§

Extension
A type representing a CLAP extension pointer.
ExtensionImplementation
Provides an implementation of this extension for a given type I (typically either a host or plugin structure).
ExtensionSide
An extension side marker: either PluginExtensionSide or HostExtensionSide.