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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
//! General Plugin-related traits and functions.
use crate::raw;

use std::ffi::CStr;
use std::os::raw::*;

/// LV2 plugin trait.
///
/// This trait helps you implementing plugins, since it requires you to implement all
/// necessary functions.
///
/// Almost every plugin function call from the host will be checked and "safed" before these trait
/// functions may be called. Therefore, most of them are safe, except for one:
/// [`connect_port`](#tymethod.connect_port). See it's documentations for more information on why it
/// is unsafe.
pub trait Plugin {
    /// Create a new instance of the plugin.
    ///
    /// Here, you should instantiate the plugin and supply it with general information. You can look
    /// at the plugin descriptor (although you shouldn't), the audio frame rate of the current
    /// session, the path from which the host has loaded the plugin and an iterator over features
    /// supported by the host.
    fn instantiate(
        descriptor: &raw::Descriptor,
        rate: f64,
        bundle_path: &CStr,
        features: Option<Vec<&mut raw::Feature>>,
    ) -> Self;

    /// Set internal data pointers.
    ///
    /// This function will be called by the host when the location of a port has changed and the
    /// plugin should update it's internal pointers. This function is highly unsafe, since the type
    /// of the pointed data is generally unknown. The only thing that gives a clue on the type is
    /// the id of the port, which should match with the port specified in the plugin's turtle
    /// document.
    ///
    /// When this function is called, the data pointers may not be valid yet and therefore, you
    /// shouldn't use them. Also, if the host passes pointers that will never be valid, you cannot
    /// defend yourselves from undefined behaviour, and you should not, in any case, call this
    /// function on your own.
    unsafe fn connect_port(&mut self, port: u32, data: *mut ());

    /// Activate the plugin.
    ///
    /// If your plugin can be turned on or off, you should override this function and set the plugin
    /// up for active use.
    ///
    /// The default implementation does nothing.
    fn activate(&mut self) {}

    /// Run plugin specific operations.
    ///
    /// This is where the action happens! Here, you should execute the actions that make your plugin
    /// unique.
    ///
    /// Pointers, which were previously set by the [`connect_port`](#tyfunction.connect_port)
    /// function are guaranteed to be valid now. If they aren't, it's the host's fault, not yours.
    /// Also, sample arrays or atom sequence will have a length  of `n_samples` elements. This
    /// number may change during the life time of the plugin and therefore, you should not store
    /// it somewhere.
    fn run(&mut self, n_samples: u32);

    /// Deactivate the plugin.
    ///
    /// If your plugin can be turned on or off, you should override this function and destroy the
    /// plugins active state.
    ///
    /// The default implementation does nothing.
    fn deactivate(&mut self) {}

    /// Return extension specific data to the host.
    ///
    /// Some LV2 extensions require special data from a plugin in order to work. This is where you
    /// provide the data. The passed C string reference is the URI of the extension in question and
    /// you can return a static reference to some data. If you do not know the passed URI, you
    /// should return `None`.
    ///
    /// The return value must be a static reference since we don't know how long it needs to be
    /// alive; as stated in the [LV2 header](http://lv2plug.in/doc/html/group__core.html#ae907a7668d6579f099ac08c134b2e634),
    /// the host is not responsible for freeing the returned value. Therefore, the referenced data
    /// need to live for the entirety of the program.
    fn extension_data(_uri: &CStr) -> Option<&'static ExtensionData> {
        None
    }
}

/// Marker trait for extension data.
///
/// This trait was introduced in order to make a [`Plugin`](trait.Plugin.html)'s
/// [`extension_data`](trait.Plugin.html#method.extension_data) function more dynamic.
/// Apart from that, it has absolutely no meaning.
pub trait ExtensionData {}

/// Helper function for the `instantiate` plugin call.
///
/// This function takes the raw parameters provided by the C API and turns them into safe Rust data
/// types. Only functions generated by the `lv2_main` should call the function any other should not.
pub unsafe fn instantiate<P: Plugin>(
    descriptor: *const raw::Descriptor,
    rate: f64,
    bundle_path: *const c_char,
    features: *const *const raw::Feature,
) -> crate::raw::Handle {
    let descriptor = match descriptor.as_ref() {
        Some(desc) => desc,
        None => return std::ptr::null_mut(),
    };
    let bundle_path = if bundle_path.is_null() {
        return std::ptr::null_mut();
    } else {
        CStr::from_ptr(bundle_path as *const c_char)
    };
    let features = raw::Feature::features_from_ptr(features);

    let instance = Box::new(P::instantiate(descriptor, rate, bundle_path, features));

    Box::leak(instance) as *const P as raw::Handle
}

/// Helper function for the `connect_port` plugin call.
///
/// This function takes the raw parameters provided by the C API and turns them into safe Rust data
/// types. Only functions generated by the `lv2_main` should call the function any other should not.
pub unsafe fn connect_port<P: Plugin>(instance: raw::Handle, port: u32, data: *mut c_void) {
    let instance = (instance as *mut P).as_mut().unwrap();
    instance.connect_port(port, data as *mut ());
}

/// Helper function for the `activate` plugin call.
///
/// This function takes the raw parameters provided by the C API, turns them into safe Rust data
/// types, and calls the trait's function. Only functions generated by the `lv2_main` should call
/// this function, any other must not.
pub unsafe fn activate<P: Plugin>(instance: raw::Handle) {
    let instance = (instance as *mut P).as_mut().unwrap();
    instance.activate();
}

/// Helper function for the `run` plugin call.
///
/// This function takes the raw parameters provided by the C API, turns them into safe Rust data
/// types, and calls the trait's function. Only functions generated by the `lv2_main` should call
/// this function, any other must not.
pub unsafe fn run<P: Plugin>(instance: raw::Handle, n_samples: u32) {
    let instance = (instance as *mut P).as_mut().unwrap();
    instance.run(n_samples);
}

/// Helper function for the `deactivate` plugin call.
///
/// This function takes the raw parameters provided by the C API, turns them into safe Rust data
/// types, and calls the trait's function. Only functions generated by the `lv2_main` should call
/// this function, any other must not.
pub unsafe fn deactivate<P: Plugin>(instance: raw::Handle) {
    let instance = (instance as *mut P).as_mut().unwrap();
    instance.deactivate();
}

/// Helper function for the `cleanup` plugin call.
///
/// This function takes the raw parameters provided by the C API, turns them into safe Rust data
/// types, and calls the trait's function. Only functions generated by the `lv2_main` should call
/// this function, any other must not.
pub unsafe fn cleanup<P: Plugin>(instance: raw::Handle) {
    core::ptr::drop_in_place(instance as *mut P);
}

/// Helper function for the `extension_data` plugin call.
///
/// This function takes the raw parameters provided by the C API, turns them into safe Rust data
/// types, and calls the trait's function. Only functions generated by the `lv2_main` should call
/// this function, any other must not.
pub unsafe fn extension_data<P: Plugin>(uri: *const c_char) -> *const c_void {
    let uri = CStr::from_ptr(uri);
    let result = P::extension_data(uri);
    std::mem::forget(uri);
    match result {
        Some(ext_data) => ext_data as *const ExtensionData as *const c_void,
        None => std::ptr::null(),
    }
}