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, then place the resulting binary where Zeus's SidecarLocator can find it. If the binary is missing, Zeus reports vstHost.available = false from /api/capabilities with a reason describing what's missing, 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