Skip to content

VST Host

KB2UKA edited this page May 3, 2026 · 2 revisions

VST Host

Zeus's VST Host loads third-party audio plugins into the TX chain so operators can run their own EQ, compression, gating, harmonic-exciter or other DSP between Zeus's mic input and the radio's modulator. The host is an out-of-process C++ sidecar — plugin crashes can't take the radio down with them.

Status

Platforms Linux x64 only in this release. macOS and Windows are planned future work.
Plugin formats VST3, VST2 (Vestige headers), CLAP
Chain depth 8 slots, ordered, individually bypassable
Remote operation Zeus's web UI reaches the VST host fine over the network, but you can't make adjustments yet — chain edits and plugin tweaking need to happen at the server. Remote-side adjustment support is on the roadmap.
Plugin GUI Native plugin editor windows are X11-only and open on the server's display

When Zeus is running on a non-Linux host, the TX Audio Tools → VST Host submenu is hidden and /api/capabilities reports vstHost.available = false with "VST host is only supported on Linux in this release."

Running Zeus remote with the VST host

Zeus normally separates its backend (radio host) from its frontend (browser PWA), so an operator's browser can be on a different machine from the radio. The VST host page in the browser will load and show the chain when accessed remotely — but adjustments (adding plugins, changing parameters, opening editors) aren't supported remote in this release. To set up or tune the chain, you need to be at the server.

The native plugin editor in particular is server-local by design: it's an X11 window opened on the server's display, not transited to the remote browser. A future cut will close the remote-adjustment gap.

How the VST host works

┌──────────────────┐    SignalR / REST     ┌────────────────────┐    Unix-domain     ┌──────────────────┐
│  zeus-web (PWA)  │ ────────────────────▶ │  Zeus.Server (C#)  │ ─────────────────▶ │  zeus-plughost   │
│  TX Audio Tools  │ ◀──────────────────── │  Zeus.PluginHost   │ ◀───────────────── │  (C++ sidecar)   │
│  VST Host submenu│                       │  PluginHostManager │     framed IPC     │  + plugin .so/.vst3/.clap │
└──────────────────┘                       └────────────────────┘                    └──────────────────┘
                                                     │                                         │
                                                     ▼                                         ▼
                                            TX audio path:                          Native plugin code runs
                                            mic → DSP → CHAIN → modulator           in sidecar process — a
                                                                                    crashing plugin only
                                                                                    takes the sidecar down

The C# side — Zeus.PluginHost

PluginHostManager is the C# façade that the rest of Zeus talks to. It owns:

  • DiscoveryPluginScanner walks OS-standard plugin directories (~/.vst3, /usr/lib/vst3, CLAP equivalents, etc.) plus any user-added search paths, and produces a PluginManifest per plugin.
  • The chain — an ordered list of up to 8 ChainSlots, each holding one loaded plugin instance.
  • Sidecar lifecycle — launches the C++ sidecar binary (located via SidecarLocator), handles IPC handshake, restarts on crash.
  • State persistence — chain layout, parameter values, and bypass flags are stored in LiteDB and reapplied at startup.

The C++ side — sidecar

The sidecar is a bare C++ binary built against:

  • The Steinberg vst3sdk (MIT)
  • Vestige headers for VST2 (license-clean, no Steinberg VST2 SDK)
  • CLAP headers (MIT)

It owns the actual plugin process: scanning for plugin metadata, loading .so / .vst3 / .clap files, hosting plugin instances, processing audio buffers handed to it over IPC, and rendering native plugin GUI windows (X11). Plugin format dispatch is by file extension.

Obtaining the sidecar

The sidecar binary (zeus-plughost) lives in its own repository, maintained by Doug:

https://github.com/Kb2uka/openhpsdr-zeus-plughost

To use the VST host, clone and build that repo. Zeus then needs to be able to find the resulting binary — see Where Zeus looks for the sidecar below.

Where Zeus looks for the sidecar

Zeus checks four locations in order, first hit wins:

  1. ZEUS_PLUGHOST_BIN environment variable — if set, it's used verbatim. The value may be an absolute path to the binary, or a bare name that resolves on PATH. This is the override for non-standard install locations.
  2. Sibling checkout — Zeus walks up from its own binary location looking for openhpsdr-zeus-plughost/build/zeus-plughost next to the Zeus repo. This is the developer default: clone Doug's repo as a sibling of openhpsdr-zeus, run the build, and Zeus picks it up automatically.
  3. $HOME/Projects/openhpsdr-zeus-plughost/build/zeus-plughost — explicit fallback for the common Linux layout where both repos live under ~/Projects/.
  4. zeus-plughost on PATH — last resort. If you've installed the binary system-wide (e.g. into /usr/local/bin), Zeus finds it here.

The binary is named zeus-plughost on Linux and macOS, zeus-plughost.exe on Windows.

If none of these turn up the binary, /api/capabilities reports vstHost.available = false with "Sidecar binary 'zeus-plughost' was not found via ZEUS_PLUGHOST_BIN, sibling checkout, or PATH." and the TX Audio Tools → VST Host submenu stays hidden.

Why a sidecar — process isolation

Audio plugins are third-party native code. A buggy plugin segfaulting inside Zeus.Server would take the radio down. By running plugins in a separate process, a crashed plugin only kills the sidecar, which Zeus then restarts. The IPC layer is framed and length-prefixed, so partial-state corruption between Zeus and a misbehaving plugin can't happen.

Audio insertion point

The VST chain sits in the TX audio path, after Zeus's own DSP (EQ / compression / leveler / noise gate) and before the CFC (Continuous Frequency Compressor). CFC always remains last. The chain is invoked per audio block; when the chain master is disabled or all slots are bypassed, the path is a pass-through with no measurable overhead.

TX monitor (audition)

Zeus exposes a "TX monitor" that lets operators audition the post-chain TX audio off-air. With monitor on, the VST chain runs even when MOX is off, so you can dial in a plugin's settings against your own voice without keying the radio. (TX-monitor adjustment, like everything else, is server-local in this release.)

Where to find it

In the Zeus UI: TX Audio Tools → VST Host (sibling to the CFC submenu inside TxAudioToolsPanel). The submenu surfaces the chain, plugin browser, search paths editor, and per-slot parameter view.

Plugin format notes

  • VST3 is the most-tested format; the native plugin editor window is wired up here.
  • VST2 loads via Vestige (license-clean headers, no Steinberg VST2 SDK). Plugin editor windows for VST2 are not yet wired up in this cut.
  • CLAP loads, with parameter introspection. CLAP editor windows are not yet wired up either.

If a particular plugin loads but doesn't behave as expected, the first triage is: is the chain master enabled, is the plugin slot enabled, is TX monitor on (or are you keyed)? Then check whether the plugin's format has full editor support in this release (today: VST3 only).

Roadmap

  • macOS and Windows sidecar binaries (per-arch builds, same IPC protocol)
  • Remote-side adjustment support — making the VST host editable from a browser that isn't on the server box
  • Native plugin editor windows for VST2 and CLAP

Clone this wiki locally