Skip to main content

xmrs/
mix_plugin.rs

1//! IT-style mix-plugin table (OpenMPT extension).
2//!
3//! ScreamTracker / Impulse Tracker file formats can carry an
4//! optional plugin section, originally introduced by OpenMPT, that
5//! describes a chain of DSP / VST plugins applied to channels and
6//! buses at mix time. The plugin payloads themselves are opaque
7//! binary blobs (typically VST chunk dumps) — xmrs does not host
8//! the plugins, but it preserves them verbatim so a round-trip
9//! through the editor doesn't lose the author's mix settings.
10//!
11//! Non-IT formats leave the containing `Module::mix_plugins` field
12//! at `None`.
13
14use serde::{Deserialize, Serialize};
15
16use alloc::vec::Vec;
17
18/// Identification + routing fields for a single plugin slot,
19/// mirroring OpenMPT's `SNDMIXPLUGININFO`. Identifiers are kept as
20/// raw `u32`s because the four-character codes used by the format
21/// are not always valid UTF-8 (and aren't always meaningful as
22/// FOURCCs — some are numeric IDs).
23#[derive(Serialize, Deserialize, Debug, Clone, Default)]
24pub struct MixPluginInfo {
25    /// Primary plugin ID (typically a packed four-character code
26    /// such as `'VstP'` for a generic VST host slot, or a built-in
27    /// identifier for OpenMPT's bundled effects).
28    pub id1: u32,
29    /// Secondary plugin ID, used by the host to disambiguate
30    /// between plugins that share the same `id1`.
31    pub id2: u32,
32    /// Source bus for plugin input. Routing semantics follow
33    /// OpenMPT — see its docs for the exact field encoding.
34    pub input_routing: u32,
35    /// Destination bus for plugin output.
36    pub output_routing: u32,
37}
38
39/// One plugin slot. The `data` blob is the plugin's serialised
40/// state (typically a VST chunk produced by `effGetChunk`); xmrs
41/// treats it as opaque bytes.
42#[derive(Serialize, Deserialize, Debug, Clone, Default)]
43pub struct MixPlugin {
44    pub info: MixPluginInfo,
45    /// Plugin-specific binary state. `None` when the slot exists
46    /// in the file but carries no chunk (i.e., a default-state
47    /// plugin or an empty slot kept for indexing).
48    pub data: Option<Vec<u8>>,
49}
50
51/// Mix-plugin table for one module. Two parallel pieces of data:
52/// per-channel routing assignments, and a flat list of plugin
53/// slots referenced by those assignments.
54#[derive(Serialize, Deserialize, Debug, Clone, Default)]
55pub struct MixPlugins {
56    /// Per-channel plugin assignment. Index = channel number.
57    /// Value `0` = no plugin on that channel; value `N` (1-based)
58    /// means the channel is routed through `plugins[N - 1]`. The
59    /// IT format reserves up to 64 entries.
60    pub channel_assignments: Vec<u32>,
61    /// Flat list of plugin slots, addressed 1-based by
62    /// `channel_assignments`. Up to 64 entries.
63    pub plugins: Vec<MixPlugin>,
64}