Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The plugin file and its manifest

The file

A plugin file is the plugin crate built as a C dynamic library, renamed to NAME.oxp. Inside it are the plugin’s code and its manifest, in a section of its own (oxg_manifest; oxgmanif on Windows, whose section names hold eight characters). OxiGuitar reads that section with a parser of library files, so it learns what the plugin adds without running any of its code. Plugin files carry no signature: OxiGuitar checks that the file is whole (a truncated download is refused before it is loaded), that it is a library for this system and processor, and that it asks for an interface version OxiGuitar has.

You never write the section yourself: you write manifest.json beside Cargo.toml, and export_plugin! puts its bytes in the section when the file is built.

manifest.json

The template’s:

{
  "interface": "1.1",
  "id": "yourname.example",
  "name": "Example",
  "version": "0.1.0",
  "description": "Opens Example tab files (.extab), counts the notes on each string of the open score, and names notes for other plugins.",
  "authors": ["Your Name"],
  "license": "MIT OR Apache-2.0",
  "homepage": "https://example.org/your-plugin",
  "formats": [
    {
      "id": "extab",
      "name": "Example tab",
      "extensions": ["extab"],
      "read": true,
      "write": true,
      "signatures": [{ "at": 0, "text": "EXAMPLE TAB" }]
    }
  ],
  "services": [
    { "interface": "note-names", "id": "example", "name": "Example note names" }
  ],
  "tabs": [
    { "id": "statistics", "title": "Statistics", "area": "right" }
  ],
  "events": ["score"]
}
KeyRequiredWhat it is
interfaceyesThe interface version the plugin was built for, "MAJOR.MINOR": "1.0", or the version that brought what it uses (Interface versions)
idyesUnique among all plugins: 1 to 64 lowercase letters and digits, in parts joined by single . or -. Start it with your own name (jane.chord-finder); ids starting oxiguitar. are ours. Never change it once released: settings and the disabled list refer to it
nameyesWhat users see, in the plugin manager and in footer messages
versionyesMAJOR.MINOR.PATCH, optionally -PRERELEASE (1.2.0-beta.1), equal to the crate’s version. Of two files with the same id, the higher version is used
descriptionnoOne or two sentences for the plugin manager
authorsnoA list of names
licensenoAn SPDX expression, such as "MIT OR Apache-2.0"
homepagenoWhere the plugin comes from
conditionsnoWhere it can run (below); it is never loaded elsewhere
requiresnoThe service interfaces it calls through the host (Services)
formatsnoThe file formats it reads or writes (Formats)
servicesnoThe services it implements (Services)
instrumentsnoThe instruments it offers the player; used from interface 1.3 (Instruments)
effectsnoThe effects it offers a track, after its instrument; interface 1.3 (Instruments)
tabsnoIts tabs; interface 1.1 (Tabs)
eventsnoThe kinds of event it wants: "score", "selection", "playback"; interface 1.1 (Events)
toolsnoIts entries in the Tools menu; interface 1.2 (Tools)
settings_windownotrue for a settings window, opened from the plugin manager; interface 1.3 (Settings)
track_sectionsnoIts sections of the track dialog; interface 1.3 (Track sections)
foldersnoThe shared folders it reads, "soundfonts" and "nam", which OxiGuitar creates at start; interface 1.3 (Settings)

Unknown keys are refused when you build and ignored when OxiGuitar reads. The test export_plugin! adds fails on a key the SDK doesn’t know, so a typing mistake ("servces") shows up in cargo test. An older OxiGuitar reading a newer plugin’s manifest skips keys it doesn’t know, so new keys never stop a plugin from loading.

A manifest is at most 1 MiB. Real ones are a few hundred bytes.

Conditions

"conditions": { "os": ["linux"], "arch": ["x86_64", "aarch64"], "display": ["wayland"] }

Every list given must hold the running system’s value; an empty or missing list allows any.

KeyValues
oslinux, macos, windows (later android, ios)
archx86_64, aarch64
displaywayland, x11, windows, macos: the display system OxiGuitar was built for. On Linux there are two builds of OxiGuitar, Wayland (the default) and X11
cpuProcessor features the code needs, all of them, as Rust names them: avx2, fma, avx512f… on x86-64, neon, dotprod, sve… on ARM64. Since interface 1.3: a manifest asking for an older interface can’t use it

A plugin whose conditions don’t hold is listed in Tools → Plugins with the reason, and never loaded. A plugin file is already built for one system and processor, so you need os and arch only for a file that would load but can’t work (a universal macOS file that works on Apple Silicon only, say). display matters for plugins that talk to the windowing system. Services have conditions of their own, beside the plugin’s.

cpu lets you ship a faster build beside a plain one. Build the plugin twice, with the same id and version: once plainly, and once with -C target-cpu=x86-64-v3 and "cpu": ["avx2", "fma"] in its manifest. On a processor without those features that file can’t be used and the plain one is; where both can be used, the one needing more features is. A feature name OxiGuitar doesn’t know counts as missing, so a build is never loaded on a guess.

Rules the checks enforce

OxiGuitar refuses a manifest that breaks these, and Tools → Plugins names the first problem; cargo test (through export_plugin!) names them all:

  • the ids are valid and unique: the plugin’s; each format’s; each instrument’s; each tab’s; each service’s within its interface;
  • names and tab titles aren’t empty;
  • a format reads or writes, and one that reads has at least one signature;
  • extensions are lowercase and without the dot ("gp5", not ".GP5");
  • tabs and events need interface 1.1.

cargo test also checks what only the code can tell:

  • the manifest asks for an interface this SDK has (1.0 or 1.1), and its version is the crate’s;
  • it has no key the SDK doesn’t know;
  • every format, service and tab declared is implemented, and every tab’s contents can be shown.