[][src]Module lv2_core::extension

Means to extend the interface of a plugin.

This module is relatively thin: It only contains a trait and a macro. Instead, most of the extension handling is a convention:

An extension is a trait a plugin can implement and every extension has a descriptor: This is a marker struct that implements the ExtensionDescriptor trait for every plugin that implements the extension. This descriptor is then used by the match_extensions macro to generate the body of a plugin's extension_data method.

Example

This is a complete example on how to create an extension and implement it for a plugin:

use lv2_core::extension::ExtensionDescriptor;
use lv2_core::prelude::*;
use urid::*;
use std::any::Any;
use std::ffi::c_void;
use std::marker::PhantomData;
use std::path::Path;

// ######################
// Defining the extension
// ######################

/// The trait that actually extends the plugin.
pub trait MyExtension: Plugin {
    fn add_number(&mut self, number: u32);
}

/// A descriptor for the plugin. This is just a marker type to associate constants and methods with.
pub struct MyExtensionDescriptor<P: MyExtension> {
    plugin: PhantomData<P>,
}

#[repr(C)]
/// This struct would be part of a sys crate.
pub struct MyExtensionInterface {
    add_number: unsafe extern "C" fn(*mut c_void, number: u32),
}

unsafe impl<P: MyExtension> UriBound for MyExtensionDescriptor<P> {
    const URI: &'static [u8] = b"urn:my-project:my-extension\0";
}

impl<P: MyExtension> MyExtensionDescriptor<P> {
    /// The extern, unsafe version of the extending method.
    ///
    /// This is actually called by the host.
    unsafe extern "C" fn extern_add_number(handle: *mut c_void, number: u32) {
        let plugin = (handle as *mut P).as_mut().unwrap();
        plugin.add_number(number);
    }
}

// Implementing the trait that contains the interface.
impl<P: MyExtension> ExtensionDescriptor for MyExtensionDescriptor<P> {
    type ExtensionInterface = MyExtensionInterface;

    const INTERFACE: &'static MyExtensionInterface = &MyExtensionInterface {
        add_number: Self::extern_add_number,
    };
}

// ##########
// The plugin
// ##########

/// This plugin actually isn't a plugin, it only has a counter.
#[uri("urn:my-project:my-plugin")]
pub struct MyPlugin {
    internal: u32,
}

impl Plugin for MyPlugin {
    type Ports = ();
    type InitFeatures = ();
    type AudioFeatures = ();

    fn new(_: &PluginInfo, _: &mut ()) -> Option<Self> {
        Some(Self { internal: 0 })
    }

    fn run(&mut self, _: &mut (), _: &mut (), _: u32) {
        self.internal += 1;
    }

    fn extension_data(uri: &Uri) -> Option<&'static dyn Any> {
        // This macro use matches the given URI with the URIs of the given extension descriptors.
        // If one of them matches, it's interface is returned.
        //
        // Note that you have to add the type parameter. Otherwise, bad things may happen!
        match_extensions![uri, MyExtensionDescriptor<Self>]
    }
}

// Actually implementing the extension.
impl MyExtension for MyPlugin {
    fn add_number(&mut self, number: u32) {
        self.internal += number;
    }
}

// ########
// The host
// ########

let plugin_uri: &Uri = MyPlugin::uri();
let bundle_path = Path::new("");
let sample_rate = 44100.0;
let plugin_info = PluginInfo::new(plugin_uri, bundle_path, sample_rate);

let mut plugin = MyPlugin::new(&plugin_info, &mut ()).unwrap();

let extension = MyPlugin::extension_data(MyExtensionDescriptor::<MyPlugin>::uri())
    .and_then(|interface| interface.downcast_ref::<MyExtensionInterface>())
    .unwrap();

unsafe { (extension.add_number)(&mut plugin as *mut _ as *mut c_void, 42) };

assert_eq!(42, plugin.internal);

Re-exports

pub use crate::match_extensions;

Traits

ExtensionDescriptor

A descriptor for a plugin extension.