1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
//! 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.ExtensionDescriptor.html) trait for every plugin that implements the extension. This descriptor is then used by the [`match_extensions`](../macro.match_extensions.html) 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);
//! ```
use Any;
use UriBound;
/// A descriptor for a plugin extension.
///
/// This trait is very minimal: It only contains a constant, static reference to the extension interface.
///
/// [For a usage example, see the module documentation.](index.html)
/// Generate the body of a plugin's `extension_data` function.
///
/// This macro takes a URI as it's first argument, followed by a list of extension descriptors. This will
/// create a match expression that matches the given URI with the URIs of the extension descriptors. If one of the extension URIs matches, the statement returns the interface of the descriptor.
///
/// The generated statement returns a value of `Option<&'static dyn std::any::Any>`.
///
/// See the documentation of the `extension` module for more information on how to use this macro.
pub use cratematch_extensions;