Skip to main content

nice_plug/
lib.rs

1//! Documentation is still a work in progress. The best way to learn right now is to browse through
2//! the examples and to browse through these docs. There is no full guide yet, but here are some
3//! pointers to get started:
4//!
5//! - All useful functionality is exported through the [`prelude`] module. Add
6//!   `use nice_plug::prelude::*;` to the top of your `lib.rs` file to get started.
7//! - Make sure to check out the macros from the [`debug`] module. These should be used instead of,
8//!   `println!()`/`eprint!()`, `dbg!()` and similar macros, and they are re-exported from the
9//!   prelude. nice-plug sets up a flexible logger for you that all of these functions will output
10//!   to. By default, the output is logged to STDERR unless you're running Windows and a Windows
11//!   debugger is attached, in which case the output is logged to the debug console instead. The
12//!   `NICE_LOG` environment variable controls whether output is logged to STDERR, the Windows debug
13//!   console, or to a file. Check the [`nice_log!()`] macro for more information.
14//! - The aforementioned debug module also contains non-fatal debug-assertions macros that are only
15//!   evaluated during debug builds. The framework uses these all over the place to check for
16//!   invariants, so it's important to test your plugins using debug builds while developing.
17//! - Check out the features list in nice-plug's `Cargo.toml` file for optional features you can
18//!   enable. This includes things like SIMD support for the buffer adapters and panicking on
19//!   allocations during DSP code in debug mode.
20//!
21//! - An nice-plug plugin consists of an implementation of the [`Plugin`][prelude::Plugin] trait and
22//!   a call to [`nice_export_vst3!()`] and/or [`nice_export_clap!()`] in your `lib.rs` file to expose
23//!   the plugin functionality. Some of these traits will require you to implement an additional
24//!   trait containing API-specific information for the plugin.
25//!
26//!   Check the `Plugin` trait's documentation for more information on nice-plug's general structure
27//!   and approach with respect to declarativity.
28//! - nice-plug comes with a bundler that creates plugin bundles for you based on the exported plugin
29//!   formats and the operating system and architecture you're compiling for. Check out the
30//!   readme for
31//!   [`nice-plug-xtask`](https://codeberg.org/BillyDM/nice-plug/src/branch/main/crates/nice-plug-xtask)
32//!   for instructions on how to use this within your own project.
33//! - It's also possible to export a standalone application from a plugin using the
34//!   [`nice_export_standalone()`] function. Check that function's documentation to learn how to do
35//!   this. This requires enabling the `standalone` crate feature.
36//! - Everything is described in more detail on the [`Plugin`][prelude::Plugin] trait and everything
37//!   linked from there, but a plugin's general lifecycle involves the following function calls.
38//!
39//!   1. When the host loads the plugin, your plugin object will be instantiated using its
40//!      [`Default`] implementation. The plugin should refrain from performing expensive
41//!      calculations or IO at this point.
42//!   2. The host will select an audio IO layout from
43//!      [`Plugin::AUDIO_IO_LAYOUTS`][prelude::Plugin::AUDIO_IO_LAYOUTS]. The first layout is always
44//!      used as the default one, and should reflect the plugin's most commonly used configuration.
45//!      Usually this is a stereo layout.
46//!   3. After that, [`Plugin::initialize()`][prelude::Plugin::initialize()] will be called with the
47//!      the selected IO configuration and the audio buffer settings. Here you should allocate any
48//!      data structures you need or precompute data that depends on the sample rate or maximum
49//!      buffer size. This is the only place where you can safely allocate memory.
50//!   4. The [`Plugin::reset()`][prelude::Plugin::reset()] function is always called immediately
51//!      after `initialize()`. This is where you should clear out coefficients, envelopes, phases,
52//!      and other runtime data. The reason for this split is that this function may be called at
53//!      any time by the host from the audio thread, and it thus needs to be realtime-safe.
54//!
55//!      Whenever a preset is loaded, both of these functions will be called again.
56//!   5. After that the [`Plugin::process()`][prelude::Plugin::process()] function will be called
57//!      repeatedly until the plugin is deactivated. Here the plugin receives a
58//!      [`Buffer`][prelude::Buffer] object that contains the input audio (if the plugin has inputs)
59//!      which the plugin should overwrite with output audio. Check the documentation on the
60//!      `Buffer` object for all of the ways you can use this API. You can access note events,
61//!      transport data, and more through the [`ProcessContext`][prelude::ProcessContext] that's
62//!      also passed to the process function.
63//!   6. [`Plugin::deactivate()`][prelude::Plugin::deactivate()] is called from the when the plugin
64//!      gets deactivated. You probably don't need to do anything here, but you could deallocate or
65//!      clean up resources here.
66//!
67//!  - Plugin parameters are managed automatically by creating a struct deriving the
68//!    [`Params`][prelude::Params] trait and returning a handle to it from the
69//!    [`Plugin::params()`][prelude::Plugin::params()] function. Any
70//!    [`FloatParam`][prelude::FloatParam], [`IntParam`][prelude::IntParam],
71//!    [`BoolParam`][prelude::BoolParam] or [`EnumParam`][prelude::EnumParam] fields on that struct
72//!    will automatically be registered as a parameter if they have an `#[id = "foobar"]` attribute.
73//!    The string `"foobar"` here uniquely identifies the parameter, making it possible to reorder
74//!    and rename parameters as long as this string stays constant. You can also store persistent
75//!    non-parameter data and other parameter objects in a `Params` struct. Check out the trait's
76//!    documentation for details on all supported features, and also be sure to take a look at the
77//!    [example plugins](https://codeberg.org/BillyDM/nice-plug/src/branch/main/examples).
78//!  - After calling `.with_smoother()` during an integer or floating point parameter's creation,
79//!    you can use `param.smoothed` to access smoothed values for that parameter. Be sure to check
80//!    out the [`Smoother`][prelude::Smoother] API for more details.
81//!
82//! There's a whole lot more to discuss, but once you understand the above you should be able to
83//! figure out the rest by reading through the examples and the API documentation. Good luck!
84
85pub use nice_plug_core::*;
86
87/// Everything you'll need to use nice-plug. Import this with `use nice_plug::prelude::*;`.
88pub mod prelude;
89pub mod wrapper;
90
91mod event_loop;
92
93// This is also re-exported from the prelude but since the other export entry points are macros and
94// macros are always accessible from the crate's root, it seems like a good idea to keep the
95// symmetry and also export this function in the same places
96#[cfg(feature = "standalone")]
97pub use wrapper::standalone::nice_export_standalone;