1
0
Fork 0

Make CLAP descriptions and special URLs optional

This closes #14.
This commit is contained in:
Robbert van der Helm 2022-07-04 12:44:30 +02:00
parent 5cbd8827e9
commit 7cd7294b22
16 changed files with 85 additions and 66 deletions

View file

@ -6,6 +6,12 @@ new and what's changed, this document lists all breaking changes in reverse
chronological order. If a new feature did not require any changes to existing chronological order. If a new feature did not require any changes to existing
code then it will not be listed here. code then it will not be listed here.
## [2022-07-04]
- The `CLAP_DESCRIPTION`, `CLAP_MANUAL_URL`, and `CLAP_SUPPORT_URL` associated
constants from the `ClapPlugin` are now optional and have the type
`Option<&'static str>` instead of `&'static str`.
## [2022-07-02] ## [2022-07-02]
- The `Params::serialize_fields()` and `Params::deserialize_fields()` methods - The `Params::serialize_fields()` and `Params::deserialize_fields()` methods

View file

@ -481,15 +481,16 @@ impl Crisp {
impl ClapPlugin for Crisp { impl ClapPlugin for Crisp {
const CLAP_ID: &'static str = "nl.robbertvanderhelm.crisp"; const CLAP_ID: &'static str = "nl.robbertvanderhelm.crisp";
const CLAP_DESCRIPTION: &'static str = "Adds a bright crispy top end to low bass sounds"; const CLAP_DESCRIPTION: Option<&'static str> =
Some("Adds a bright crispy top end to low bass sounds");
const CLAP_MANUAL_URL: Option<&'static str> = Some(Self::URL);
const CLAP_SUPPORT_URL: Option<&'static str> = None;
const CLAP_FEATURES: &'static [ClapFeature] = &[ const CLAP_FEATURES: &'static [ClapFeature] = &[
ClapFeature::AudioEffect, ClapFeature::AudioEffect,
ClapFeature::Stereo, ClapFeature::Stereo,
ClapFeature::Mono, ClapFeature::Mono,
ClapFeature::Distortion, ClapFeature::Distortion,
]; ];
const CLAP_MANUAL_URL: &'static str = Self::URL;
const CLAP_SUPPORT_URL: &'static str = Self::URL;
} }
impl Vst3Plugin for Crisp { impl Vst3Plugin for Crisp {

View file

@ -385,14 +385,15 @@ impl Crossover {
impl ClapPlugin for Crossover { impl ClapPlugin for Crossover {
const CLAP_ID: &'static str = "nl.robbertvanderhelm.crossover"; const CLAP_ID: &'static str = "nl.robbertvanderhelm.crossover";
const CLAP_DESCRIPTION: &'static str = "Cleanly split a signal into multiple bands"; const CLAP_DESCRIPTION: Option<&'static str> =
Some("Cleanly split a signal into multiple bands");
const CLAP_MANUAL_URL: Option<&'static str> = Some(Self::URL);
const CLAP_SUPPORT_URL: Option<&'static str> = None;
const CLAP_FEATURES: &'static [ClapFeature] = &[ const CLAP_FEATURES: &'static [ClapFeature] = &[
ClapFeature::AudioEffect, ClapFeature::AudioEffect,
ClapFeature::Stereo, ClapFeature::Stereo,
ClapFeature::Utility, ClapFeature::Utility,
]; ];
const CLAP_MANUAL_URL: &'static str = Self::URL;
const CLAP_SUPPORT_URL: &'static str = Self::URL;
} }
impl Vst3Plugin for Crossover { impl Vst3Plugin for Crossover {

View file

@ -408,15 +408,15 @@ fn unnormalize_automation_precision(normalized: f32) -> u32 {
impl ClapPlugin for Diopser { impl ClapPlugin for Diopser {
const CLAP_ID: &'static str = "nl.robbertvanderhelm.diopser"; const CLAP_ID: &'static str = "nl.robbertvanderhelm.diopser";
const CLAP_DESCRIPTION: &'static str = "A totally original phase rotation plugin"; const CLAP_DESCRIPTION: Option<&'static str> = Some("A totally original phase rotation plugin");
const CLAP_MANUAL_URL: Option<&'static str> = Some(Self::URL);
const CLAP_SUPPORT_URL: Option<&'static str> = None;
const CLAP_FEATURES: &'static [ClapFeature] = &[ const CLAP_FEATURES: &'static [ClapFeature] = &[
ClapFeature::AudioEffect, ClapFeature::AudioEffect,
ClapFeature::Stereo, ClapFeature::Stereo,
ClapFeature::Filter, ClapFeature::Filter,
ClapFeature::Utility, ClapFeature::Utility,
]; ];
const CLAP_MANUAL_URL: &'static str = Self::URL;
const CLAP_SUPPORT_URL: &'static str = Self::URL;
} }
impl Vst3Plugin for Diopser { impl Vst3Plugin for Diopser {

View file

@ -153,15 +153,15 @@ impl Plugin for Gain {
impl ClapPlugin for Gain { impl ClapPlugin for Gain {
const CLAP_ID: &'static str = "com.moist-plugins-gmbh.gain"; const CLAP_ID: &'static str = "com.moist-plugins-gmbh.gain";
const CLAP_DESCRIPTION: &'static str = "A smoothed gain parameter example plugin"; const CLAP_DESCRIPTION: Option<&'static str> = Some("A smoothed gain parameter example plugin");
const CLAP_MANUAL_URL: Option<&'static str> = Some(Self::URL);
const CLAP_SUPPORT_URL: Option<&'static str> = None;
const CLAP_FEATURES: &'static [ClapFeature] = &[ const CLAP_FEATURES: &'static [ClapFeature] = &[
ClapFeature::AudioEffect, ClapFeature::AudioEffect,
ClapFeature::Stereo, ClapFeature::Stereo,
ClapFeature::Filter, ClapFeature::Mono,
ClapFeature::Utility, ClapFeature::Utility,
]; ];
const CLAP_MANUAL_URL: &'static str = Self::URL;
const CLAP_SUPPORT_URL: &'static str = Self::URL;
} }
impl Vst3Plugin for Gain { impl Vst3Plugin for Gain {

View file

@ -191,15 +191,15 @@ impl Plugin for Gain {
impl ClapPlugin for Gain { impl ClapPlugin for Gain {
const CLAP_ID: &'static str = "com.moist-plugins-gmbh-egui.gain-gui"; const CLAP_ID: &'static str = "com.moist-plugins-gmbh-egui.gain-gui";
const CLAP_DESCRIPTION: &'static str = "A smoothed gain parameter example plugin"; const CLAP_DESCRIPTION: Option<&'static str> = Some("A smoothed gain parameter example plugin");
const CLAP_MANUAL_URL: Option<&'static str> = Some(Self::URL);
const CLAP_SUPPORT_URL: Option<&'static str> = None;
const CLAP_FEATURES: &'static [ClapFeature] = &[ const CLAP_FEATURES: &'static [ClapFeature] = &[
ClapFeature::AudioEffect, ClapFeature::AudioEffect,
ClapFeature::Stereo, ClapFeature::Stereo,
ClapFeature::Mono, ClapFeature::Mono,
ClapFeature::Utility, ClapFeature::Utility,
]; ];
const CLAP_MANUAL_URL: &'static str = Self::URL;
const CLAP_SUPPORT_URL: &'static str = Self::URL;
} }
impl Vst3Plugin for Gain { impl Vst3Plugin for Gain {

View file

@ -137,15 +137,15 @@ impl Plugin for Gain {
impl ClapPlugin for Gain { impl ClapPlugin for Gain {
const CLAP_ID: &'static str = "com.moist-plugins-gmbh.gain-gui-iced"; const CLAP_ID: &'static str = "com.moist-plugins-gmbh.gain-gui-iced";
const CLAP_DESCRIPTION: &'static str = "A smoothed gain parameter example plugin"; const CLAP_DESCRIPTION: Option<&'static str> = Some("A smoothed gain parameter example plugin");
const CLAP_MANUAL_URL: Option<&'static str> = Some(Self::URL);
const CLAP_SUPPORT_URL: Option<&'static str> = None;
const CLAP_FEATURES: &'static [ClapFeature] = &[ const CLAP_FEATURES: &'static [ClapFeature] = &[
ClapFeature::AudioEffect, ClapFeature::AudioEffect,
ClapFeature::Stereo, ClapFeature::Stereo,
ClapFeature::Mono, ClapFeature::Mono,
ClapFeature::Utility, ClapFeature::Utility,
]; ];
const CLAP_MANUAL_URL: &'static str = Self::URL;
const CLAP_SUPPORT_URL: &'static str = Self::URL;
} }
impl Vst3Plugin for Gain { impl Vst3Plugin for Gain {

View file

@ -137,15 +137,15 @@ impl Plugin for Gain {
impl ClapPlugin for Gain { impl ClapPlugin for Gain {
const CLAP_ID: &'static str = "com.moist-plugins-gmbh.gain-gui-vizia"; const CLAP_ID: &'static str = "com.moist-plugins-gmbh.gain-gui-vizia";
const CLAP_DESCRIPTION: &'static str = "A smoothed gain parameter example plugin"; const CLAP_DESCRIPTION: Option<&'static str> = Some("A smoothed gain parameter example plugin");
const CLAP_MANUAL_URL: Option<&'static str> = Some(Self::URL);
const CLAP_SUPPORT_URL: Option<&'static str> = None;
const CLAP_FEATURES: &'static [ClapFeature] = &[ const CLAP_FEATURES: &'static [ClapFeature] = &[
ClapFeature::AudioEffect, ClapFeature::AudioEffect,
ClapFeature::Stereo, ClapFeature::Stereo,
ClapFeature::Filter, ClapFeature::Mono,
ClapFeature::Utility, ClapFeature::Utility,
]; ];
const CLAP_MANUAL_URL: &'static str = Self::URL;
const CLAP_SUPPORT_URL: &'static str = Self::URL;
} }
impl Vst3Plugin for Gain { impl Vst3Plugin for Gain {

View file

@ -186,11 +186,11 @@ impl Plugin for MidiInverter {
impl ClapPlugin for MidiInverter { impl ClapPlugin for MidiInverter {
const CLAP_ID: &'static str = "com.moist-plugins-gmbh.midi-inverter"; const CLAP_ID: &'static str = "com.moist-plugins-gmbh.midi-inverter";
const CLAP_DESCRIPTION: &'static str = const CLAP_DESCRIPTION: Option<&'static str> =
"Inverts all note and MIDI signals in ways you don't want to"; Some("Inverts all note and MIDI signals in ways you don't want to");
const CLAP_MANUAL_URL: Option<&'static str> = Some(Self::URL);
const CLAP_SUPPORT_URL: Option<&'static str> = None;
const CLAP_FEATURES: &'static [ClapFeature] = &[ClapFeature::NoteEffect, ClapFeature::Utility]; const CLAP_FEATURES: &'static [ClapFeature] = &[ClapFeature::NoteEffect, ClapFeature::Utility];
const CLAP_MANUAL_URL: &'static str = Self::URL;
const CLAP_SUPPORT_URL: &'static str = Self::URL;
} }
impl Vst3Plugin for MidiInverter { impl Vst3Plugin for MidiInverter {

View file

@ -195,15 +195,16 @@ impl Plugin for Sine {
impl ClapPlugin for Sine { impl ClapPlugin for Sine {
const CLAP_ID: &'static str = "com.moist-plugins-gmbh.sine"; const CLAP_ID: &'static str = "com.moist-plugins-gmbh.sine";
const CLAP_DESCRIPTION: &'static str = "An optionally MIDI controlled sine test tone"; const CLAP_DESCRIPTION: Option<&'static str> =
Some("An optionally MIDI controlled sine test tone");
const CLAP_MANUAL_URL: Option<&'static str> = Some(Self::URL);
const CLAP_SUPPORT_URL: Option<&'static str> = None;
const CLAP_FEATURES: &'static [ClapFeature] = &[ const CLAP_FEATURES: &'static [ClapFeature] = &[
ClapFeature::Synthesizer, ClapFeature::Synthesizer,
ClapFeature::Stereo, ClapFeature::Stereo,
ClapFeature::Mono, ClapFeature::Mono,
ClapFeature::Utility, ClapFeature::Utility,
]; ];
const CLAP_MANUAL_URL: &'static str = Self::URL;
const CLAP_SUPPORT_URL: &'static str = Self::URL;
} }
impl Vst3Plugin for Sine { impl Vst3Plugin for Sine {

View file

@ -163,15 +163,15 @@ impl Plugin for Stft {
impl ClapPlugin for Stft { impl ClapPlugin for Stft {
const CLAP_ID: &'static str = "com.moist-plugins-gmbh.stft"; const CLAP_ID: &'static str = "com.moist-plugins-gmbh.stft";
const CLAP_DESCRIPTION: &'static str = "An example plugin using the STFT helper"; const CLAP_DESCRIPTION: Option<&'static str> = Some("An example plugin using the STFT helper");
const CLAP_MANUAL_URL: Option<&'static str> = Some(Self::URL);
const CLAP_SUPPORT_URL: Option<&'static str> = None;
const CLAP_FEATURES: &'static [ClapFeature] = &[ const CLAP_FEATURES: &'static [ClapFeature] = &[
ClapFeature::AudioEffect, ClapFeature::AudioEffect,
ClapFeature::Stereo, ClapFeature::Stereo,
ClapFeature::Mono, ClapFeature::Mono,
ClapFeature::Utility, ClapFeature::Utility,
]; ];
const CLAP_MANUAL_URL: &'static str = Self::URL;
const CLAP_SUPPORT_URL: &'static str = Self::URL;
} }
impl Vst3Plugin for Stft { impl Vst3Plugin for Stft {

View file

@ -242,7 +242,9 @@ impl LoudnessWarWinner {
impl ClapPlugin for LoudnessWarWinner { impl ClapPlugin for LoudnessWarWinner {
const CLAP_ID: &'static str = "nl.robbertvanderhelm.loudness-war-winner"; const CLAP_ID: &'static str = "nl.robbertvanderhelm.loudness-war-winner";
const CLAP_DESCRIPTION: &'static str = "Win the loudness war with ease"; const CLAP_DESCRIPTION: Option<&'static str> = Some("Win the loudness war with ease");
const CLAP_MANUAL_URL: Option<&'static str> = Some(Self::URL);
const CLAP_SUPPORT_URL: Option<&'static str> = None;
const CLAP_FEATURES: &'static [ClapFeature] = &[ const CLAP_FEATURES: &'static [ClapFeature] = &[
ClapFeature::AudioEffect, ClapFeature::AudioEffect,
ClapFeature::Stereo, ClapFeature::Stereo,
@ -252,8 +254,6 @@ impl ClapPlugin for LoudnessWarWinner {
ClapFeature::Utility, ClapFeature::Utility,
ClapFeature::Custom("pain"), ClapFeature::Custom("pain"),
]; ];
const CLAP_MANUAL_URL: &'static str = Self::URL;
const CLAP_SUPPORT_URL: &'static str = Self::URL;
} }
impl Vst3Plugin for LoudnessWarWinner { impl Vst3Plugin for LoudnessWarWinner {

View file

@ -415,15 +415,15 @@ impl PubertySimulator {
impl ClapPlugin for PubertySimulator { impl ClapPlugin for PubertySimulator {
const CLAP_ID: &'static str = "nl.robbertvanderhelm.puberty-simulator"; const CLAP_ID: &'static str = "nl.robbertvanderhelm.puberty-simulator";
const CLAP_DESCRIPTION: &'static str = "Simulates a pitched down cracking voice"; const CLAP_DESCRIPTION: Option<&'static str> = Some("Simulates a pitched down cracking voice");
const CLAP_MANUAL_URL: Option<&'static str> = Some(Self::URL);
const CLAP_SUPPORT_URL: Option<&'static str> = None;
const CLAP_FEATURES: &'static [ClapFeature] = &[ const CLAP_FEATURES: &'static [ClapFeature] = &[
ClapFeature::AudioEffect, ClapFeature::AudioEffect,
ClapFeature::Stereo, ClapFeature::Stereo,
ClapFeature::Glitch, ClapFeature::Glitch,
ClapFeature::PitchShifter, ClapFeature::PitchShifter,
]; ];
const CLAP_MANUAL_URL: &'static str = Self::URL;
const CLAP_SUPPORT_URL: &'static str = Self::URL;
} }
impl Vst3Plugin for PubertySimulator { impl Vst3Plugin for PubertySimulator {

View file

@ -304,15 +304,15 @@ impl SafetyLimiter {
impl ClapPlugin for SafetyLimiter { impl ClapPlugin for SafetyLimiter {
const CLAP_ID: &'static str = "nl.robbertvanderhelm.safety-limiter"; const CLAP_ID: &'static str = "nl.robbertvanderhelm.safety-limiter";
const CLAP_DESCRIPTION: &'static str = "Plays SOS in Morse code when redlining"; const CLAP_DESCRIPTION: Option<&'static str> = Some("Plays SOS in Morse code when redlining");
const CLAP_MANUAL_URL: Option<&'static str> = Some(Self::URL);
const CLAP_SUPPORT_URL: Option<&'static str> = None;
const CLAP_FEATURES: &'static [ClapFeature] = &[ const CLAP_FEATURES: &'static [ClapFeature] = &[
ClapFeature::AudioEffect, ClapFeature::AudioEffect,
ClapFeature::Stereo, ClapFeature::Stereo,
ClapFeature::Mono, ClapFeature::Mono,
ClapFeature::Utility, ClapFeature::Utility,
]; ];
const CLAP_MANUAL_URL: &'static str = Self::URL;
const CLAP_SUPPORT_URL: &'static str = Self::URL;
} }
impl Vst3Plugin for SafetyLimiter { impl Vst3Plugin for SafetyLimiter {

View file

@ -192,17 +192,15 @@ pub trait ClapPlugin: Plugin {
/// A unique ID that identifies this particular plugin. This is usually in reverse domain name /// A unique ID that identifies this particular plugin. This is usually in reverse domain name
/// notation, e.g. `com.manufacturer.plugin-name`. /// notation, e.g. `com.manufacturer.plugin-name`.
const CLAP_ID: &'static str; const CLAP_ID: &'static str;
/// A short description for the plugin. /// An optional short description for the plugin.
const CLAP_DESCRIPTION: &'static str; const CLAP_DESCRIPTION: Option<&'static str>;
/// Arbitrary keywords describing the plugin. See the CLAP specification for examples: /// The URL to the plugin's manual, if available.
/// <https://github.com/free-audio/clap/blob/main/include/clap/plugin.h>. const CLAP_MANUAL_URL: Option<&'static str>;
/// The URL to the plugin's support page, if available.
const CLAP_SUPPORT_URL: Option<&'static str>;
/// Keywords describing the plugin. The host may use this to classify the plugin in its plugin
/// browser.
const CLAP_FEATURES: &'static [ClapFeature]; const CLAP_FEATURES: &'static [ClapFeature];
/// A URL to the plugin's manual, CLAP does not specify what to do when there is none.
//
// TODO: CLAP does not specify this, can these manual fields be null pointers?
const CLAP_MANUAL_URL: &'static str;
/// A URL to the plugin's support page, CLAP does not specify what to do when there is none.
const CLAP_SUPPORT_URL: &'static str;
/// If this is set to true, then the plugin will report itself as having a hard realtime /// If this is set to true, then the plugin will report itself as having a hard realtime
/// processing requirement when the host asks for it. Supported hosts will never ask the plugin /// processing requirement when the host asks for it. Supported hosts will never ask the plugin

View file

@ -4,7 +4,6 @@ use std::ffi::{CStr, CString};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::os::raw::c_char; use std::os::raw::c_char;
use std::ptr;
use crate::plugin::ClapPlugin; use crate::plugin::ClapPlugin;
@ -19,10 +18,10 @@ pub struct PluginDescriptor<P: ClapPlugin> {
name: CString, name: CString,
vendor: CString, vendor: CString,
url: CString, url: CString,
clap_manual_url: CString,
clap_support_url: CString,
version: CString, version: CString,
clap_description: CString, clap_manual_url: Option<CString>,
clap_support_url: Option<CString>,
clap_description: Option<CString>,
clap_features: Vec<CString>, clap_features: Vec<CString>,
clap_features_ptrs: MaybeUninit<Vec<*const c_char>>, clap_features_ptrs: MaybeUninit<Vec<*const c_char>>,
@ -42,13 +41,14 @@ impl<P: ClapPlugin> Default for PluginDescriptor<P> {
name: CString::new(P::NAME).expect("`NAME` contained null bytes"), name: CString::new(P::NAME).expect("`NAME` contained null bytes"),
vendor: CString::new(P::VENDOR).expect("`VENDOR` contained null bytes"), vendor: CString::new(P::VENDOR).expect("`VENDOR` contained null bytes"),
url: CString::new(P::URL).expect("`URL` contained null bytes"), url: CString::new(P::URL).expect("`URL` contained null bytes"),
clap_manual_url: CString::new(P::CLAP_MANUAL_URL)
.expect("`CLAP_MANUAL_URL` contained null bytes"),
clap_support_url: CString::new(P::CLAP_SUPPORT_URL)
.expect("`CLAP_SUPPORT_URL` contained null bytes"),
version: CString::new(P::VERSION).expect("`VERSION` contained null bytes"), version: CString::new(P::VERSION).expect("`VERSION` contained null bytes"),
clap_description: CString::new(P::CLAP_DESCRIPTION) clap_manual_url: P::CLAP_MANUAL_URL
.expect("`CLAP_DESCRIPTION` contained null bytes"), .map(|url| CString::new(url).expect("`CLAP_MANUAL_URL` contained null bytes")),
clap_support_url: P::CLAP_SUPPORT_URL
.map(|url| CString::new(url).expect("`CLAP_SUPPORT_URL` contained null bytes")),
clap_description: P::CLAP_DESCRIPTION.map(|description| {
CString::new(description).expect("`CLAP_DESCRIPTION` contained null bytes")
}),
clap_features: P::CLAP_FEATURES clap_features: P::CLAP_FEATURES
.iter() .iter()
.map(|feat| feat.as_str()) .map(|feat| feat.as_str())
@ -67,7 +67,7 @@ impl<P: ClapPlugin> Default for PluginDescriptor<P> {
.iter() .iter()
.map(|feature| feature.as_ptr()) .map(|feature| feature.as_ptr())
.collect(); .collect();
clap_features_ptrs.push(ptr::null()); clap_features_ptrs.push(std::ptr::null());
descriptor.clap_features_ptrs.write(clap_features_ptrs); descriptor.clap_features_ptrs.write(clap_features_ptrs);
// We couldn't initialize this directly because of all the CStrings // We couldn't initialize this directly because of all the CStrings
@ -77,10 +77,22 @@ impl<P: ClapPlugin> Default for PluginDescriptor<P> {
name: descriptor.name.as_ptr(), name: descriptor.name.as_ptr(),
vendor: descriptor.vendor.as_ptr(), vendor: descriptor.vendor.as_ptr(),
url: descriptor.url.as_ptr(), url: descriptor.url.as_ptr(),
manual_url: descriptor.clap_manual_url.as_ptr(),
support_url: descriptor.clap_support_url.as_ptr(),
version: descriptor.version.as_ptr(), version: descriptor.version.as_ptr(),
description: descriptor.clap_description.as_ptr(), manual_url: descriptor
.clap_manual_url
.as_ref()
.map(|url| url.as_ptr())
.unwrap_or(std::ptr::null()),
support_url: descriptor
.clap_support_url
.as_ref()
.map(|url| url.as_ptr())
.unwrap_or(std::ptr::null()),
description: descriptor
.clap_description
.as_ref()
.map(|description| description.as_ptr())
.unwrap_or(std::ptr::null()),
features: unsafe { descriptor.clap_features_ptrs.assume_init_ref() }.as_ptr(), features: unsafe { descriptor.clap_features_ptrs.assume_init_ref() }.as_ptr(),
}); });