//! Embedded bundled plugin manifests. //! //! Bundled plugins are compiled into the binary via `include_str!`. They //! provide out-of-the-box support for common hardware samplers without //! requiring any user configuration. use tracing::instrument; use crate::error::PluginError; use crate::hooks::CompiledHooks; use crate::manifest::{manifest_to_profile, parse_manifest}; use crate::registry::{LoadedPlugin, PluginRegistry}; /// Bundled manifest data: (device_name, toml_content). const BUNDLED_MANIFESTS: &[(&str, &str)] = &[ ( "sp404mkii", include_str!("../plugins/bundled/sp404mkii/manifest.toml"), ), ( "mpc", include_str!("../plugins/bundled/mpc/manifest.toml"), ), ( "digitakt", include_str!("../plugins/bundled/digitakt/manifest.toml"), ), ( "octatrack", include_str!("../plugins/bundled/octatrack/manifest.toml"), ), ( "op1", include_str!("../plugins/bundled/op1/manifest.toml"), ), ( "deluge", include_str!("../plugins/bundled/deluge/manifest.toml"), ), ( "model_samples", include_str!("../plugins/bundled/model_samples/manifest.toml"), ), ( "polyend_tracker", include_str!("../plugins/bundled/polyend_tracker/manifest.toml"), ), ( "circuit_rhythm", include_str!("../plugins/bundled/circuit_rhythm/manifest.toml"), ), ( "maschine_plus", include_str!("../plugins/bundled/maschine_plus/manifest.toml"), ), ( "m8", include_str!("../plugins/bundled/m8/manifest.toml"), ), ( "digitakt_ii", include_str!("../plugins/bundled/digitakt_ii/manifest.toml"), ), ( "blackbox", include_str!("../plugins/bundled/blackbox/manifest.toml"), ), ( "volca_sample_2", include_str!("../plugins/bundled/volca_sample_2/manifest.toml"), ), ]; /// Load all bundled plugins into a registry. #[instrument(skip_all)] pub fn load_bundled(registry: &mut PluginRegistry) -> Result<(), PluginError> { for (slug, toml_str) in BUNDLED_MANIFESTS { let manifest = parse_manifest(toml_str).map_err(|e| { PluginError::ManifestParse(format!("bundled plugin '{slug}': {e}")) })?; let profile = manifest_to_profile(&manifest)?; // Bundled plugins have no Rhai hooks (all declarative) let hooks = CompiledHooks { validate_sample: None, transform_filename: None, pre_export: None, post_export: None, }; registry.insert(LoadedPlugin { profile, hooks, bundled: true, }); } Ok(()) } #[cfg(test)] mod tests { use super::*; #[test] fn all_bundled_manifests_parse() { for (slug, toml_str) in BUNDLED_MANIFESTS { let manifest = parse_manifest(toml_str) .unwrap_or_else(|e| panic!("bundled plugin '{slug}' failed to parse: {e}")); let profile = manifest_to_profile(&manifest) .unwrap_or_else(|e| panic!("bundled plugin '{slug}' failed to convert: {e}")); assert!(!profile.name.is_empty(), "plugin '{slug}' has empty name"); assert!( !profile.audio.formats.is_empty(), "plugin '{slug}' has no formats" ); assert!( !profile.audio.sample_rates.is_empty(), "plugin '{slug}' has no sample rates" ); } } #[test] fn load_bundled_populates_registry() { let mut registry = PluginRegistry::new(); load_bundled(&mut registry).unwrap(); assert_eq!(registry.len(), 14); } }