From 217c753eb8eafa28874a4a874374ac96f4d7e167 Mon Sep 17 00:00:00 2001 From: Boof2015 <75185879+Boof2015@users.noreply.github.com> Date: Tue, 2 Jun 2026 12:24:42 -0400 Subject: [PATCH] initial support for linux vst --- .github/workflows/release.yml | 87 +++++++++++++-- README.md | 10 +- package.json | 38 ++++++- plugin/CMakeLists.txt | 10 +- plugin/README.md | 37 +++++- .../linux/install-vst3-from-package.sh | 60 ++++++++++ resources/installer/linux/install-vst3.sh | 105 ++++++++++++++++++ .../linux/remove-vst3-from-system.sh | 21 ++++ 8 files changed, 349 insertions(+), 19 deletions(-) create mode 100755 resources/installer/linux/install-vst3-from-package.sh create mode 100755 resources/installer/linux/install-vst3.sh create mode 100755 resources/installer/linux/remove-vst3-from-system.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 830df4e..206f24d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,7 +25,7 @@ jobs: - os: macos-latest dist_cmd: dist:mac - os: ubuntu-latest - dist_cmd: dist:linux + dist_cmd: dist:linux:packages # Pinned to windows-2022 because windows-latest now ships VS 2026 # (internal version 18), which the @electron/node-gyp version in our # lockfile rejects as "unsupported". 2022 has VS 2022 only, no ambiguity. @@ -54,14 +54,12 @@ jobs: uses: mozilla-actions/sccache-action@v0.0.10 - name: Cache JUCE - if: runner.os != 'Linux' uses: actions/cache@v4 with: path: .ci-cache/juce/JUCE-${{ env.PRISM_JUCE_VERSION }} key: ${{ runner.os }}-juce-${{ env.PRISM_JUCE_VERSION }}-v1 - name: Prepare JUCE checkout - if: runner.os != 'Linux' shell: bash run: | juce_dir=".ci-cache/juce/JUCE-${PRISM_JUCE_VERSION}" @@ -80,7 +78,29 @@ jobs: if: runner.os == 'Linux' run: | sudo apt-get update - sudo apt-get install -y libpulse-dev + sudo apt-get install -y \ + build-essential \ + cmake \ + ninja-build \ + pkg-config \ + libpulse-dev \ + libasound2-dev \ + libjack-jackd2-dev \ + ladspa-sdk \ + libcurl4-openssl-dev \ + libfreetype-dev \ + libfontconfig1-dev \ + libx11-dev \ + libxcomposite-dev \ + libxcursor-dev \ + libxext-dev \ + libxinerama-dev \ + libxrandr-dev \ + libxrender-dev \ + libwebkit2gtk-4.1-dev \ + libglu1-mesa-dev \ + mesa-common-dev \ + rpm - name: Build native DSP module run: npm run rebuild:native @@ -94,11 +114,25 @@ jobs: fi echo "Native module built successfully: $(ls -lh native/build/Release/visualizer_dsp.node)" - # --- JUCE plugins (macOS + Windows). Linux defers; we still create the - # staging dir so electron-builder's extraResources entry doesn't choke. --- + # Linux AppImage is app-only. Build it before staging DAW plugins so the + # portable artifact does not carry installable VST3 resources. + - name: Prepare empty Linux plugin resources for AppImage + if: runner.os == 'Linux' + shell: bash + run: | + rm -rf plugin/dist-installer + mkdir -p plugin/dist-installer + + - name: Build Linux AppImage + if: runner.os == 'Linux' + run: npm run dist:linux:appimage + env: + CSC_IDENTITY_AUTO_DISCOVERY: 'false' + + # --- JUCE plugins. These are staged into installer resources after the + # app-only AppImage has already been built on Linux. --- - name: Build plugin webview bundle - if: runner.os != 'Linux' run: npm run plugin-ui:build - name: Configure JUCE plugins (macOS) @@ -112,6 +146,15 @@ jobs: -DCMAKE_C_COMPILER_LAUNCHER=sccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=sccache + - name: Configure JUCE plugins (Linux) + if: runner.os == 'Linux' + run: | + cmake -B plugin/build -S plugin -G Ninja \ + -DCMAKE_BUILD_TYPE=Release \ + -DJUCE_PATH="$GITHUB_WORKSPACE/.ci-cache/juce/JUCE-${PRISM_JUCE_VERSION}" \ + -DPRISM_PLUGIN_FORMATS=VST3 \ + -DPRISM_COPY_PLUGIN_AFTER_BUILD=OFF + # JUCE's NEEDS_WEBVIEW2 expects the Microsoft.Web.WebView2 NuGet package # to already be installed locally; it doesn't fetch it itself. Install it # and point CMake at the resulting folder via JUCE_WEBVIEW2_PACKAGE_LOCATION. @@ -148,6 +191,10 @@ jobs: if: runner.os == 'macOS' run: cmake --build plugin/build --target PrismInstallerPlugins --parallel 4 + - name: Build JUCE plugins (Linux) + if: runner.os == 'Linux' + run: cmake --build plugin/build --target PrismInstallerPlugins --parallel 4 + - name: Build JUCE plugins (Windows) if: runner.os == 'Windows' shell: cmd @@ -165,10 +212,6 @@ jobs: run: | rm -rf plugin/dist-installer mkdir -p plugin/dist-installer - if [ "$RUNNER_OS" = "Linux" ]; then - echo "Linux: skipping plugin staging (no DAW-plugin install path yet)." - exit 0 - fi mkdir -p plugin/dist-installer/VST3 [ "$RUNNER_OS" = "macOS" ] && mkdir -p plugin/dist-installer/AU for art in PrismSpectrum PrismOscilloscope PrismVUMeter PrismLUFSMeter PrismVectorscope PrismSpectrogram PrismWaveform; do @@ -186,6 +229,16 @@ jobs: echo "ERROR: expected 7 VST3 plugins, found $vst3_count" exit 1 fi + if [ "$RUNNER_OS" = "Linux" ]; then + for vst3 in plugin/dist-installer/VST3/*.vst3; do + if [ ! -d "$vst3/Contents/x86_64-linux" ]; then + echo "ERROR: Linux VST3 bundle is missing Contents/x86_64-linux: $vst3" + exit 1 + fi + done + cp resources/installer/linux/install-vst3.sh plugin/dist-installer/install-vst3.sh + chmod +x plugin/dist-installer/install-vst3.sh + fi if [ "$RUNNER_OS" = "macOS" ]; then echo "--- staged AU ---" ls -la plugin/dist-installer/AU @@ -197,10 +250,20 @@ jobs: fi - name: Build distributable + if: runner.os != 'Linux' run: npm run ${{ matrix.dist_cmd }} env: CSC_IDENTITY_AUTO_DISCOVERY: 'false' + - name: Build Linux packages with VST3 plugins + if: runner.os == 'Linux' + shell: bash + run: | + rm -rf dist/linux-unpacked + npm run ${{ matrix.dist_cmd }} + env: + CSC_IDENTITY_AUTO_DISCOVERY: 'false' + - name: Upload artifacts uses: actions/upload-artifact@v4 with: @@ -211,5 +274,7 @@ jobs: dist/*.zip dist/*.AppImage dist/*.deb + dist/*.rpm + dist/*.tar.gz if-no-files-found: error retention-days: 30 diff --git a/README.md b/README.md index 723253d..c09adf7 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ Prebuilt binaries for Windows, macOS, and Linux are available on the [Releases]( |----------|-----------| | macOS | Xcode Command Line Tools | | Windows | Visual Studio Build Tools | -| Linux | `build-essential`, `python3`, `libasound2-dev`, `libpulse-dev` | +| Linux | `build-essential`, `python3`, `libasound2-dev`, `libpulse-dev`, `libwebkit2gtk-4.1-dev` | ```bash git clone https://github.com/Boof2015/prism.git @@ -75,9 +75,15 @@ npm run build # Build application assets npm run dist # Package for current platform npm run dist:mac # macOS (DMG + ZIP) npm run dist:win # Windows (NSIS + Portable) -npm run dist:linux # Linux (AppImage + DEB) +npm run dist:linux # Linux (AppImage + DEB + RPM + tar.gz) ``` +Linux `.deb` and `.rpm` releases install the seven Prism VST3 plugins to +`/usr/lib/vst3`. The Linux `tar.gz` release includes a `resources/plugins/install-vst3.sh` +helper that installs them to `$HOME/.vst3` by default. The AppImage is app-only; +it does not install DAW plugins. DAWs commonly scan `$HOME/.vst3`, `/usr/lib/vst3`, +and `/usr/local/lib/vst3`. + ## Astra Integration If you use [Astra](https://github.com/Boof2015/astra), Prism can connect to its local API to show what's playing, cover art, track info, and playback controls, alongside your scopes. diff --git a/package.json b/package.json index 6affe64..fbcfe80 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,9 @@ "dist": "npm run build && electron-builder --publish never", "dist:mac": "npm run build && electron-builder --mac --publish never", "dist:win": "npm run build && electron-builder --win --publish never", - "dist:linux": "npm run build && electron-builder --linux --publish never" + "dist:linux": "npm run build && electron-builder --linux AppImage deb rpm tar.gz --publish never", + "dist:linux:appimage": "npm run build && electron-builder --linux AppImage --publish never", + "dist:linux:packages": "electron-builder --linux deb rpm tar.gz --publish never" }, "repository": { "type": "git", @@ -124,9 +126,41 @@ "include": "resources/installer/windows-vst3.nsh" }, "linux": { - "target": ["AppImage", "deb"], + "target": ["AppImage", "deb", "rpm", "tar.gz"], "icon": "resources/icon.png", "category": "Audio" + }, + "deb": { + "afterInstall": "resources/installer/linux/install-vst3-from-package.sh", + "afterRemove": "resources/installer/linux/remove-vst3-from-system.sh", + "depends": [ + "libgtk-3-0", + "libnotify4", + "libnss3", + "libxss1", + "libxtst6", + "xdg-utils", + "libatspi2.0-0", + "libuuid1", + "libsecret-1-0", + "libwebkit2gtk-4.1-0" + ] + }, + "rpm": { + "afterInstall": "resources/installer/linux/install-vst3-from-package.sh", + "afterRemove": "resources/installer/linux/remove-vst3-from-system.sh", + "depends": [ + "gtk3", + "libnotify", + "nss", + "libXScrnSaver", + "libXtst", + "xdg-utils", + "at-spi2-core", + "libuuid", + "libsecret", + "webkit2gtk4.1" + ] } } } diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index a4ee81c..8a6b42f 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -34,8 +34,14 @@ set(PRISM_NATIVE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../native/src) option(PRISM_DEV_SERVER "Load the webview UI from the Vite dev server instead of the embedded bundle" OFF) # Build controls. Defaults preserve the full local build; CI narrows these to -# the formats that are actually packaged. -set(PRISM_PLUGIN_FORMATS "AU;VST3;Standalone" CACHE STRING "JUCE plugin formats to build") +# the formats that are actually packaged. AU is macOS-only, so Linux/Windows +# default to the portable VST3 + Standalone set. +if(APPLE) + set(PRISM_DEFAULT_PLUGIN_FORMATS "AU;VST3;Standalone") +else() + set(PRISM_DEFAULT_PLUGIN_FORMATS "VST3;Standalone") +endif() +set(PRISM_PLUGIN_FORMATS "${PRISM_DEFAULT_PLUGIN_FORMATS}" CACHE STRING "JUCE plugin formats to build") option(PRISM_COPY_PLUGIN_AFTER_BUILD "Copy built plugins into user plugin folders after build" ON) # Embed the built webview bundle once; every scope plugin shares it (the C++ tells diff --git a/plugin/README.md b/plugin/README.md index 9c1fbce..6c961f0 100644 --- a/plugin/README.md +++ b/plugin/README.md @@ -4,8 +4,8 @@ JUCE 8 plugins (VST3 / AU / Standalone) that render Prism's scopes inside a DAW one plugin per scope: **spectrum, oscilloscope, vectorscope, spectrogram, VU meter, loudness meter, waveform**. They **reuse Prism's existing C++ DSP** (`native/src/*.cpp`) and the **existing React canvas UI** (`src/plugin-ui`, importing the unchanged -visualizers from `src/renderer/visualizers/`). Built for macOS and Windows; Linux -untested but should follow the same recipe. +visualizers from `src/renderer/visualizers/`). VST3 is built for macOS, Windows, +and Linux; AU is macOS-only. ## How it fits together @@ -79,6 +79,39 @@ DAWs scan both. Dev-server mode works the same as macOS: `-DPRISM_DEV_SERVER=ON` + `npm run plugin-ui:dev`. +## Build & run (Linux) + +Prereqs: CMake >= 3.22, Ninja, GCC/Clang, Node.js, and JUCE's Linux GUI/WebView +dependencies. On Ubuntu 24.04+: + +```sh +sudo apt-get install build-essential cmake ninja-build pkg-config \ + libasound2-dev libjack-jackd2-dev ladspa-sdk libcurl4-openssl-dev \ + libfreetype-dev libfontconfig1-dev libx11-dev libxcomposite-dev \ + libxcursor-dev libxext-dev libxinerama-dev libxrandr-dev libxrender-dev \ + libwebkit2gtk-4.1-dev libglu1-mesa-dev mesa-common-dev +``` + +```sh +npm install +npm run plugin-ui:build +cmake -B plugin/build -S plugin -G Ninja -DCMAKE_BUILD_TYPE=Release -DPRISM_PLUGIN_FORMATS=VST3 +cmake --build plugin/build --target PrismInstallerPlugins --parallel +``` + +Built bundles land under `plugin/build/Prism*_artefacts/Release/VST3/`. Copy the +seven `Prism *.vst3` directories to one of the standard Linux VST3 scan paths: + +- User-local: `$HOME/.vst3` +- System-wide: `/usr/lib/vst3` +- System-wide local: `/usr/local/lib/vst3` + +The Linux `.deb` and `.rpm` release packages install Prism's VST3 bundles to +`/usr/lib/vst3` and remove only those seven bundles on package removal. The Linux +`tar.gz` release includes `resources/plugins/install-vst3.sh`, which installs to +`$HOME/.vst3` by default or `/usr/lib/vst3` with `--system`. The AppImage is +portable app-only and does not install DAW plugins. + ## Notes - **Refresh rate (macOS):** frames are emitted on `juce::VBlankAttachment` (synced to the diff --git a/resources/installer/linux/install-vst3-from-package.sh b/resources/installer/linux/install-vst3-from-package.sh new file mode 100755 index 0000000..6ca4171 --- /dev/null +++ b/resources/installer/linux/install-vst3-from-package.sh @@ -0,0 +1,60 @@ +#!/bin/sh +# Package post-install hook for Linux .deb/.rpm builds. The app package installs +# Prism under /opt, then this copies the bundled native Linux VST3 bundles into +# the global VST3 scan path used by Linux DAWs. + +set -eu + +DEST_DIR="${PRISM_VST3_DEST_DIR:-/usr/lib/vst3}" + +find_source_dir() { + if [ -n "${PRISM_VST3_SOURCE_DIR:-}" ] && [ -d "$PRISM_VST3_SOURCE_DIR" ]; then + printf '%s\n' "$PRISM_VST3_SOURCE_DIR" + return 0 + fi + + for dir in \ + /opt/Prism/resources/plugins/VST3 \ + /opt/prism/resources/plugins/VST3 + do + if [ -d "$dir" ]; then + printf '%s\n' "$dir" + return 0 + fi + done + + return 1 +} + +install_plugin() { + plugin_name="$1" + source_plugin="$SOURCE_DIR/$plugin_name" + dest_plugin="$DEST_DIR/$plugin_name" + + if [ ! -d "$source_plugin" ]; then + echo "Prism VST3 install: missing bundled plugin: $source_plugin" >&2 + return 1 + fi + + rm -rf "$dest_plugin" + cp -a "$source_plugin" "$DEST_DIR/" +} + +SOURCE_DIR="$(find_source_dir || true)" +if [ -z "$SOURCE_DIR" ]; then + echo "Prism VST3 install: bundled VST3 directory not found; skipping plugin install." >&2 + exit 0 +fi + +mkdir -p "$DEST_DIR" + +install_plugin "Prism Spectrum.vst3" +install_plugin "Prism Oscilloscope.vst3" +install_plugin "Prism VU Meter.vst3" +install_plugin "Prism Loudness Meter.vst3" +install_plugin "Prism Vectorscope.vst3" +install_plugin "Prism Spectrogram.vst3" +install_plugin "Prism Waveform.vst3" + +chmod -R a+rX "$DEST_DIR"/Prism*.vst3 2>/dev/null || true +echo "Prism VST3 plugins installed to $DEST_DIR" diff --git a/resources/installer/linux/install-vst3.sh b/resources/installer/linux/install-vst3.sh new file mode 100755 index 0000000..4509ccd --- /dev/null +++ b/resources/installer/linux/install-vst3.sh @@ -0,0 +1,105 @@ +#!/bin/sh +# Helper bundled in the Linux tarball under resources/plugins/. By default it +# installs Prism's native Linux VST3 bundles to the current user's VST3 folder. + +set -eu + +usage() { + cat <<'EOF' +Usage: install-vst3.sh [--system] [--dest PATH] [--source PATH] + +Installs the bundled Prism VST3 plugins. + +Options: + --system Install to /usr/lib/vst3 instead of $HOME/.vst3. + --dest PATH Install to a custom VST3 directory. + --source PATH Read Prism *.vst3 bundles from a custom source directory. + -h, --help Show this help. +EOF +} + +SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)" +SOURCE_DIR="${PRISM_VST3_SOURCE_DIR:-}" +DEST_DIR="${PRISM_VST3_DEST_DIR:-$HOME/.vst3}" + +while [ "$#" -gt 0 ]; do + case "$1" in + --system) + DEST_DIR="/usr/lib/vst3" + ;; + --dest) + shift + if [ "$#" -eq 0 ]; then + echo "install-vst3.sh: --dest requires a path" >&2 + exit 2 + fi + DEST_DIR="$1" + ;; + --source) + shift + if [ "$#" -eq 0 ]; then + echo "install-vst3.sh: --source requires a path" >&2 + exit 2 + fi + SOURCE_DIR="$1" + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "install-vst3.sh: unknown option: $1" >&2 + usage >&2 + exit 2 + ;; + esac + shift +done + +if [ -z "$SOURCE_DIR" ]; then + if [ -d "$SCRIPT_DIR/VST3" ]; then + SOURCE_DIR="$SCRIPT_DIR/VST3" + elif [ -d "$SCRIPT_DIR/plugins/VST3" ]; then + SOURCE_DIR="$SCRIPT_DIR/plugins/VST3" + else + SOURCE_DIR="$SCRIPT_DIR" + fi +fi + +if [ ! -d "$SOURCE_DIR" ]; then + echo "install-vst3.sh: source directory not found: $SOURCE_DIR" >&2 + exit 1 +fi + +install_plugin() { + plugin_name="$1" + source_plugin="$SOURCE_DIR/$plugin_name" + dest_plugin="$DEST_DIR/$plugin_name" + + if [ ! -d "$source_plugin" ]; then + echo "install-vst3.sh: missing bundled plugin: $source_plugin" >&2 + return 1 + fi + + rm -rf "$dest_plugin" + cp -a "$source_plugin" "$DEST_DIR/" +} + +mkdir -p "$DEST_DIR" + +install_plugin "Prism Spectrum.vst3" +install_plugin "Prism Oscilloscope.vst3" +install_plugin "Prism VU Meter.vst3" +install_plugin "Prism Loudness Meter.vst3" +install_plugin "Prism Vectorscope.vst3" +install_plugin "Prism Spectrogram.vst3" +install_plugin "Prism Waveform.vst3" + +chmod -R u+rwX,go+rX "$DEST_DIR"/Prism*.vst3 2>/dev/null || true + +cat <