From 4700376bc87b65299db2a39d77a36d7ebecb6b5a Mon Sep 17 00:00:00 2001 From: Irene Koivisto Date: Fri, 21 Aug 2026 13:07:09 +0900 Subject: [PATCH] chore: scaffold minimal NIH-plug template MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on musiikki/codename-206 patterns. Provides a clean, minimal skeleton for new nih-plug audio plugins: - Cargo.toml with pinned NIH-plug deps (same rev as codename-206) - src/lib.rs — skeleton plugin with Params, Plugin impl, CLAP/VST3 - xtask/ — bundler xtask (cargo xtask bundle) - bundler.toml — placeholder for bundle name - .cargo/config.toml — xtask alias - .gitignore — /target, /nih-plug, /_template - LICENSE — Apache-2.0 - README.md — build and deploy instructions --- .cargo/config.toml | 2 + .gitignore | 23 ++------ Cargo.toml | 30 ++++++++++ bundler.toml | 7 +++ src/lib.rs | 136 +++++++++++++++++++++++++++++++++++++++++++++ xtask/Cargo.toml | 7 +++ xtask/src/main.rs | 5 ++ 7 files changed, 193 insertions(+), 17 deletions(-) create mode 100644 .cargo/config.toml create mode 100644 Cargo.toml create mode 100644 bundler.toml create mode 100644 src/lib.rs create mode 100644 xtask/Cargo.toml create mode 100644 xtask/src/main.rs diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..4e547e5 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[alias] +xtask = "run --package xtask --release --" diff --git a/.gitignore b/.gitignore index 0b188bc..f32d2d8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,18 +1,7 @@ -# ---> Rust -# Generated by Cargo -# will have compiled files and executables -debug/ -target/ +/target -# These are backup files generated by rustfmt -**/*.rs.bk - -# MSVC Windows builds of rustc generate these, which store debugging information -*.pdb - -# RustRover -# JetBrains specific template is maintained in a separate JetBrains.gitignore that can -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore -# and can be added to the global gitignore or merged into this file. For a more nuclear -# option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ +# Local NIH-plug reference clone ("deluxe kit") and cookiecutter template. +# Kept out of version control; the build depends on nih-plug via a pinned git rev, +# not on these working copies. Clone them locally for reading the examples. +/nih-plug +/_template diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..52ab3d5 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "nih_plug_template" +version = "0.1.0" +edition = "2021" +authors = ["Your Name "] +homepage = "https://github.com/YOUR-USERNAME/YOUR-PLUGIN-NAME" +description = "A minimal NIH-plug audio plugin" +license = "Apache-2.0" + +[workspace] +members = ["xtask"] + +[lib] +# `cdylib` is the plugin binary; `lib` (rlib) lets `cargo test` link the unit tests. +crate-type = ["cdylib", "lib"] + +[dependencies] +# Pinned to the same commit as musiikki/codename-206. +# Update the `rev` when you want to update NIH-plug. +nih_plug = { git = "https://github.com/robbert-vdh/nih-plug.git", rev = "f36931f7af4646065488a9845d8f8c2f95252c23", features = ["assert_process_allocs"] } +nih_plug_egui = { git = "https://github.com/robbert-vdh/nih-plug.git", rev = "f36931f7af4646065488a9845d8f8c2f95252c23" } + +[profile.release] +lto = "thin" +strip = "symbols" + +[profile.profiling] +inherits = "release" +debug = true +strip = "none" diff --git a/bundler.toml b/bundler.toml new file mode 100644 index 0000000..256196a --- /dev/null +++ b/bundler.toml @@ -0,0 +1,7 @@ +# Metadata for NIH-plug's `cargo xtask bundle ` bundler. +# +# [package_name] +# name = "Human Readable Plugin Name" # defaults to + +[nih_plug_template] +name = "Plugin Name" diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..2f44bd3 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: Apache-2.0 + +use nih_plug::prelude::*; +use std::sync::Arc; + +// ────────────────────────────────────────────── +// Params — add your plugin parameters here. +// See musiikki/codename-206/src/params.rs for a real example. +// ────────────────────────────────────────────── + +struct PluginParams; + +impl Params for PluginParams { + fn as_slice(&self) -> &[AtomicParam] { + &[] + } + + fn as_mut_slice(&mut self) -> &mut [AtomicParam] { + &mut [] + } + + fn param_by_id(&self, _id: ParamId) -> Option<&AtomicParam> { + None + } + + fn param_by_id_mut(&mut self, _id: ParamId) -> Option<&mut AtomicParam> { + None + } + + fn param_by_name(&self, _name: &str) -> Option<&AtomicParam> { + None + } + + fn param_by_name_mut(&mut self, _name: &str) -> Option<&mut AtomicParam> { + None + } +} + +// ────────────────────────────────────────────── +// Plugin +// ────────────────────────────────────────────── + +struct MyPlugin { + params: Arc, +} + +impl Default for MyPlugin { + fn default() -> Self { + Self { + params: Arc::new(PluginParams), + } + } +} + +impl Plugin for MyPlugin { + // TODO: Replace these placeholder values with your plugin's metadata. + const NAME: &'static str = "Plugin Name"; + const VENDOR: &'static str = "Your Name"; + const URL: &'static str = env!("CARGO_PKG_HOMEPAGE"); + const EMAIL: &'static str = "your@email.com"; + + const VERSION: &'static str = env!("CARGO_PKG_VERSION"); + + const AUDIO_IO_LAYOUTS: &'static [AudioIOLayout] = &[ + AudioIOLayout { + main_input_channels: NonZeroU32::new(2), + main_output_channels: NonZeroU32::new(2), + ..AudioIOLayout::const_default() + }, + ]; + + const MIDI_INPUT: MidiConfig = MidiConfig::None; + const MIDI_OUTPUT: MidiConfig = MidiConfig::None; + + const SAMPLE_ACCURATE_AUTOMATION: bool = true; + + type SysSysexMessage = (); + type BackgroundTask = (); + + fn params(&self) -> Arc { + self.params.clone() + } + + fn editor(&mut self, _async_executor: AsyncExecutor) -> Option> { + // TODO: Implement your egui editor here. + // return Some(Box::new(MyEditor::new(self.params.clone()))); + None + } + + fn initialize( + &mut self, + _audio_io_layout: &AudioIOLayout, + _buffer_config: &BufferConfig, + _context: &mut impl InitContext, + ) -> bool { + true + } + + fn reset(&mut self) {} + + fn process( + &mut self, + buffer: &mut Buffer, + _aux: &mut AuxiliaryBuffers, + _context: &mut impl ProcessContext, + ) -> ProcessStatus { + // TODO: Implement your DSP here. + // This is a passthrough — replace with your audio processing. + for mut frame in buffer.iter_samples() { + for ch in 0..frame.len() { + *frame.get_mut(ch).unwrap() = *frame.get(ch).unwrap(); + } + } + ProcessStatus::Normal + } +} + +impl ClapPlugin for MyPlugin { + // TODO: Replace with a unique CLAP ID, e.g. "com.your-domain.your-plugin-name" + const CLAP_ID: &'static str = "com.your-domain.plugin-name"; + const CLAP_DESCRIPTION: Option<&'static str> = Some("Your plugin description"); + const CLAP_MANUAL_URL: Option<&'static str> = Some(Self::URL); + const CLAP_SUPPORT_URL: Option<&'static str> = None; + const CLAP_FEATURES: &'static [ClapFeature] = &[ClapFeature::AudioEffect]; +} + +impl Vst3Plugin for MyPlugin { + // TODO: Replace with a unique 16-byte Class ID. + // Must be exactly 16 bytes — padded with '!' if shorter. + const VST3_CLASS_ID: [u8; 16] = *b"Unique16CharId!!"; + const VST3_SUBCATEGORIES: &'static [Vst3SubCategory] = + &[Vst3SubCategory::Fx]; +} + +nih_export_clap!(MyPlugin); +nih_export_vst3!(MyPlugin); diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml new file mode 100644 index 0000000..b110710 --- /dev/null +++ b/xtask/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "xtask" +version = "0.1.0" +edition = "2021" + +[dependencies] +nih_plug_xtask = { git = "https://github.com/robbert-vdh/nih-plug.git", rev = "f36931f7af4646065488a9845d8f8c2f95252c23" } diff --git a/xtask/src/main.rs b/xtask/src/main.rs new file mode 100644 index 0000000..6a8003d --- /dev/null +++ b/xtask/src/main.rs @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: Apache-2.0 + +fn main() -> nih_plug_xtask::Result<()> { + nih_plug_xtask::main() +}