Skip to main content

truce_core/
info.rs

1/// Static metadata about a plugin.
2#[derive(Clone, Debug)]
3pub struct PluginInfo {
4    pub name: &'static str,
5    pub vendor: &'static str,
6    pub url: &'static str,
7    pub version: &'static str,
8    pub category: PluginCategory,
9
10    // Format-specific IDs
11    pub vst3_id: &'static str,
12    pub clap_id: &'static str,
13    pub au_type: [u8; 4],
14    pub au_subtype: [u8; 4],
15    pub au_manufacturer: [u8; 4],
16    pub aax_id: Option<&'static str>,
17    /// AAX plugin category string (e.g. "EQ", "Dynamics", "Reverb").
18    /// Maps to AAX_ePlugInCategory constants.
19    pub aax_category: Option<&'static str>,
20}
21
22#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23pub enum PluginCategory {
24    Effect,
25    Instrument,
26    Analyzer,
27    Tool,
28}
29
30/// Convert a category string to [`PluginCategory`] at compile time.
31/// Used by the `plugin_info!()` macro.
32pub const fn category_from_str(s: &str) -> PluginCategory {
33    match s.as_bytes() {
34        b"Instrument" => PluginCategory::Instrument,
35        b"Analyzer" => PluginCategory::Analyzer,
36        b"Tool" => PluginCategory::Tool,
37        _ => PluginCategory::Effect,
38    }
39}
40
41/// Helper to convert a 4-char string literal to `[u8; 4]` at compile time.
42/// Panics if the string is not exactly 4 ASCII bytes.
43pub const fn fourcc(s: &[u8]) -> [u8; 4] {
44    assert!(s.len() == 4, "FourCC must be exactly 4 bytes");
45    [s[0], s[1], s[2], s[3]]
46}
47
48/// Construct a [`PluginInfo`] from build-time metadata.
49///
50/// # Zero-arg form (recommended)
51///
52/// All metadata derived from `truce.toml` + `Cargo.toml`.
53/// Requires `truce-build` in `[build-dependencies]` and a `build.rs`:
54///
55/// ```ignore
56/// // build.rs
57/// fn main() { truce_build::emit_plugin_env(); }
58///
59/// // lib.rs
60/// fn info() -> PluginInfo { plugin_info!() }
61/// ```
62///
63/// # 6-arg form (explicit)
64///
65/// ```ignore
66/// plugin_info!("My Gain", Effect, "com.myco.gain", "aufx", "MyGn", "MyCo")
67/// ```
68#[macro_export]
69macro_rules! plugin_info {
70    // Zero-arg form: everything from env vars set by truce-build + cargo
71    () => {
72        $crate::PluginInfo {
73            name: env!("TRUCE_PLUGIN_NAME"),
74            vendor: env!("TRUCE_VENDOR_NAME"),
75            url: env!("TRUCE_VENDOR_URL"),
76            version: $crate::plugin_info!(@version),
77            category: $crate::info::category_from_str(env!("TRUCE_CATEGORY")),
78            vst3_id: env!("TRUCE_PLUGIN_ID"),
79            clap_id: env!("TRUCE_PLUGIN_ID"),
80            au_type: $crate::info::fourcc(env!("TRUCE_AU_TYPE").as_bytes()),
81            au_subtype: $crate::info::fourcc(env!("TRUCE_AU_SUBTYPE").as_bytes()),
82            au_manufacturer: $crate::info::fourcc(env!("TRUCE_AU_MANUFACTURER").as_bytes()),
83            aax_id: None,
84            aax_category: option_env!("TRUCE_AAX_CATEGORY"),
85        }
86    };
87    // Version: prefer TRUCE_PLUGIN_VERSION from truce.toml, fall back to CARGO_PKG_VERSION
88    (@version) => {
89        match option_env!("TRUCE_PLUGIN_VERSION") {
90            Some(v) => v,
91            None => env!("CARGO_PKG_VERSION"),
92        }
93    };
94    // 6-arg form: explicit, vendor/url/version still from config
95    ($name:expr, $cat:ident, $id:expr, $au_type:expr, $au_sub:expr, $au_mfr:expr) => {
96        $crate::PluginInfo {
97            name: $name,
98            vendor: env!("TRUCE_VENDOR_NAME"),
99            url: env!("TRUCE_VENDOR_URL"),
100            version: $crate::plugin_info!(@version),
101            category: $crate::PluginCategory::$cat,
102            vst3_id: $id,
103            clap_id: $id,
104            au_type: $crate::info::fourcc($au_type.as_bytes()),
105            au_subtype: $crate::info::fourcc($au_sub.as_bytes()),
106            au_manufacturer: $crate::info::fourcc($au_mfr.as_bytes()),
107            aax_id: None,
108            aax_category: option_env!("TRUCE_AAX_CATEGORY"),
109        }
110    };
111}