Add Linux GUI, audio, and LV2 plugin port - #272
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds an additive Linux port of LiveSPICE alongside the existing Windows/WPF application: a new Avalonia-based editor, Linux audio backends, a shared plugin-core for Linux plugin experiments, a native LV2 bundle (GTK3 UI + example plugins), and a Linux-focused solution file. It also factors shared audio-simulation construction into Circuit.AudioSimulationFactory and wires it into the existing VST simulation path.
Changes:
- Added
LiveSPICE.Avalonia(GUI editor + simulation scope + Linux audio configuration, including JACK/PipeWire discovery) andLiveSPICE.Avalonia.Tests. - Added Linux-facing plugin components (
LiveSPICE.PluginCore,LiveSPICE.PluginLinux) plus a native LV2 bundle underNative/LiveSPICE.LV2. - Added/updated solution and documentation for Linux/headless builds, and introduced
Circuit.AudioSimulationFactoryto unify audio simulation setup.
Reviewed changes
Copilot reviewed 54 out of 54 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Documents submodule init and headless Linux build/run examples. |
| Native/LiveSPICE.LV2/README.md | Documents native LV2 bundle, build/test/install, and URIs. |
| Native/LiveSPICE.LV2/manifest.ttl | Declares LV2 plugin entries for MXR Phase 90 and Generic shell. |
| Native/LiveSPICE.LV2/Makefile | Build/test/install targets for LV2 plugins and GTK UI. |
| Native/LiveSPICE.LV2/livespice_mxr_phase90.ttl | LV2 metadata for the MXR Phase 90-style plugin. |
| Native/LiveSPICE.LV2/livespice_mxr_phase90.c | Native LV2 DSP + state save/restore for the phaser. |
| Native/LiveSPICE.LV2/livespice_generic.ttl | LV2 metadata for the generic schematic-loader shell + GTK3 UI. |
| Native/LiveSPICE.LV2/livespice_generic.c | Native LV2 passthrough shell with atom event parsing and state. |
| Native/LiveSPICE.LV2/livespice_generic_ui.c | GTK3 LV2 UI for schematic loading and discovered controls. |
| Native/LiveSPICE.LV2/.gitignore | Ignores native LV2 build artifacts. |
| LiveSPICEVst/SimulationProcessor.cs | Uses AudioSimulationFactory for shared audio simulation setup. |
| LiveSPICE.sln | Adds LiveSPICE.Headless project to the main solution. |
| LiveSPICE.PluginLinux/LiveSPICELinuxPlugin.cs | Linux plugin host using shared processor + Avalonia editor window. |
| LiveSPICE.PluginLinux/LiveSPICE.PluginLinux.csproj | New net8 project for Linux plugin experiment (AudioPlugSharp). |
| LiveSPICE.PluginCore/Wrappers/PotWrapper.cs | Wrapper for grouped pot controls with update tracking. |
| LiveSPICE.PluginCore/Wrappers/MultiThrowWrapper.cs | Wrapper for multi-position switches with rebuild tracking. |
| LiveSPICE.PluginCore/Wrappers/IComponentWrapper.cs | Common wrapper interface for interactive components. |
| LiveSPICE.PluginCore/Wrappers/DoubleThrowWrapper.cs | Wrapper for 2-position switch behavior. |
| LiveSPICE.PluginCore/Wrappers/ComponentWrapper.cs | Base wrapper supporting multi-section grouping. |
| LiveSPICE.PluginCore/SimulationProcessor.cs | Shared processor for schematic load + async simulation rebuild/update. |
| LiveSPICE.PluginCore/PluginProgramParameters.cs | State serialization model for schematic path + controls/settings. |
| LiveSPICE.PluginCore/LiveSPICE.PluginCore.csproj | New shared plugin/core library project references. |
| LiveSPICE.Linux.sln | Adds a Linux-centric solution for Avalonia + plugin experiments. |
| LiveSPICE.Headless/WaveFile.cs | WAV IO for headless processing. |
| LiveSPICE.Headless/Program.cs | Console runner for headless simulation (sine or WAV input). |
| LiveSPICE.Headless/LiveSPICE.Headless.csproj | New net8 headless executable project. |
| LiveSPICE.Avalonia/WaveformWindow.cs | Simulation scope UI + live audio streaming integration. |
| LiveSPICE.Avalonia/VirtualAudioDriver.cs | Virtual loopback audio driver for testing/validation. |
| LiveSPICE.Avalonia/SchematicDocument.cs | Document model with undo/redo and dirty/external-change tracking. |
| LiveSPICE.Avalonia/SchematicCanvas.cs | Avalonia schematic renderer/editor interaction layer. |
| LiveSPICE.Avalonia/SavePromptWindow.cs | Unsaved-changes prompt dialog. |
| LiveSPICE.Avalonia/PropertyInspector.cs | Lightweight property editor for selected objects. |
| LiveSPICE.Avalonia/Program.cs | Avalonia app entrypoint and platform configuration. |
| LiveSPICE.Avalonia/PluginEditorWindow.cs | Plugin-style editor window with overlay controls. |
| LiveSPICE.Avalonia/MainWindow.cs | Main Avalonia editor shell: tabs, menus, edit commands, simulation entry. |
| LiveSPICE.Avalonia/LiveSPICE.Avalonia.csproj | New net8 Avalonia GUI project with references. |
| LiveSPICE.Avalonia/LiveAudioProcessor.cs | Live audio processing wrapper around AudioSimulationFactory. |
| LiveSPICE.Avalonia/LinuxAudioDriver.cs | JACK/PipeWire discovery + JACK callback stream implementation. |
| LiveSPICE.Avalonia/ConfirmWindow.cs | Generic yes/no confirmation dialog. |
| LiveSPICE.Avalonia/AvaloniaAudioDrivers.cs | Driver discovery/aggregation for Avalonia build. |
| LiveSPICE.Avalonia/AudioConfigWindow.cs | UI for driver/device/channel selection + test stream. |
| LiveSPICE.Avalonia/AppSettings.cs | Persistent settings (recent files, window size, audio selection). |
| LiveSPICE.Avalonia/App.cs | Avalonia Application initialization. |
| LiveSPICE.Avalonia.Tests/SimulationAndAudioTests.cs | Tests for simulation factory, drivers, and live processing. |
| LiveSPICE.Avalonia.Tests/SchematicCanvasInteractionTests.cs | Tests for selection, move, wire tool, undo/redo, copy/paste. |
| LiveSPICE.Avalonia.Tests/PluginPortTests.cs | Tests for Linux plugin editor + state round-tripping and processing. |
| LiveSPICE.Avalonia.Tests/MenuOpenPathTests.cs | Tests for file URI path decoding and startup doc behavior. |
| LiveSPICE.Avalonia.Tests/LiveSPICE.Avalonia.Tests.csproj | New xUnit test project for Avalonia + plugin components. |
| LiveSPICE.Avalonia.Tests/AssemblyInfo.cs | Disables parallelization for UI-sensitive tests. |
| LiveSPICE.Avalonia.Tests/AppSettingsTests.cs | Tests settings persistence and recent file behavior. |
| GUI_PORT_PLAN.md | Updated plan/notes for cross-platform GUI work. |
| Circuit/Components/Resistor.cs | Adjusts resistor label positioning for rendering parity. |
| Circuit/Circuit.csproj | Adds package references needed by new functionality. |
| Circuit/AudioSimulationFactory.cs | Centralizes “audio simulation” solve/create logic (inputs/outputs). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| install: all | ||
| mkdir -p $(PREFIX) | ||
| rm -rf $(PREFIX)/LiveSPICE-MXR-Phase90.lv2 | ||
| cp -r $(BUNDLE) $(PREFIX)/ | ||
|
|
| uint8_t buffer[4096]; | ||
| lv2_atom_forge_set_buffer(&self->forge, buffer, sizeof(buffer)); | ||
| LV2_Atom_Forge_Ref ref = lv2_atom_forge_path(&self->forge, path, (uint32_t)strlen(path) + 1); | ||
| if (ref == 0) | ||
| return; | ||
|
|
||
| LV2_Atom* atom = lv2_atom_forge_deref(&self->forge, ref); | ||
| self->write(self->controller, PORT_CONTROL_EVENTS, lv2_atom_total_size(atom), self->atom_event_transfer, atom); | ||
| } |
| static gboolean knob_scroll(GtkWidget* widget, GdkEventScroll* event, gpointer data) | ||
| { | ||
| KnobControl* knob = (KnobControl*)data; | ||
| double delta = event->direction == GDK_SCROLL_UP ? 0.025 : -0.025; | ||
| knob->value = clamp_unit(knob->value + delta); |
| lv2:extensionData state:interface ; | ||
| lv2:optionalFeature lv2:hardRTCapable ; | ||
| livespice:schematicPath "" ; |
| wrapper = button.NumPositions == 2 | ||
| ? new DoubleThrowWrapper(button, button.Group) | ||
| : new MultiThrowWrapper(button, component.Name); | ||
| buttonGroups[button.Group] = wrapper; |
| case MultiThrowWrapper multiThrowWrapper: | ||
| ComboBox comboBox = CreateOptionBox(new[] { 0, 1, 2 }, multiThrowWrapper.Position); | ||
| comboBox.SelectionChanged += (_, _) => |
| {51F8BCEC-5C29-46BA-8448-06B516715840}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
| {51F8BCEC-5C29-46BA-8448-06B516715840}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
| {51F8BCEC-5C29-46BA-8448-06B516715840}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
| {51F8BCEC-5C29-46BA-8448-06B516715840}.Release|Any CPU.Build.0 = Release|Any CPU |
| RedirectStandardError = true, | ||
| UseShellExecute = false, | ||
| CreateNoWindow = true | ||
| }; | ||
| using Process process = Process.Start(startInfo)!; | ||
| string output = process.StandardOutput.ReadToEnd(); | ||
| if (!process.WaitForExit(1000) || process.ExitCode != 0) | ||
| return Array.Empty<string>(); | ||
|
|
| JackNative.jack_connect(client, input[i].Name, JackNative.PortName(inputPorts[i])); | ||
| for (int i = 0; i < output.Length; i++) | ||
| JackNative.jack_connect(client, JackNative.PortName(outputPorts[i]), output[i].Name); |
Stage 3: Avalonia GUI on macOS (adopt upstream PR dsharlet#272 + CoreAudio wiring)
Records the known problems in this fork, from the design and documentation adherence review, so they are not rediscovered. Each item is marked as originating in this fork or in upstream PR dsharlet#272, because the latter are worth reporting back rather than only fixing locally. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Not a maintainer — just a data point that might help this PR, plus some findings. Your Avalonia port also works on macOS, essentially unmodifiedI've been porting LiveSPICE to macOS (Apple Silicon) and evaluated this branch as a starting point rather than writing an Avalonia app from scratch. It went far better than expected:
So the "Linux GUI port" label undersells it — it's a cross-platform GUI port that happens to have been developed on Linux. Might be worth saying so in the PR title/description, since that materially changes its value to the project. A macOS audio backend drops straight in. Things you'd probably want to knowFound while reviewing before adopting. All still present as of
Happy to open PRs against your branch for any of these if useful — the test-isolation fix in particular is self-contained. My working versions are at https://github.com/ledogar/LiveSPICE if you want to lift anything; treat it as reference rather than something to merge, since it's tangled with macOS-specific work. Thanks for doing this — it saved me weeks. |
|
@ledogar yeah please do open those pr's! thanks for the find and fixes! :) |
Summary
Adds a Linux-focused LiveSPICE port alongside the existing Windows application instead of replacing it.
This branch introduces an Avalonia desktop editor, Linux audio configuration and live simulation support, a shared plugin core for Linux plugin experiments, and native LV2 plugin bundles with a GTK3 UI. The main Windows solution and Windows WPF/VST UI paths are intentionally left unchanged; Linux-specific projects live in
LiveSPICE.Linux.sln.Highlights
LiveSPICE.Avaloniaas a Linux desktop editor with schematic loading, editing, property inspection, waveform viewing, and live audio controls.LiveSPICE.Avalonia.Testscoverage for editor interaction, launch/open behavior, settings, audio simulation flow, plugin port behavior, and GUI parity checks.LiveSPICE.PluginCoreandLiveSPICE.PluginLinuxfor Linux plugin-facing simulation/control logic without changing the Windows VST UI.Native/LiveSPICE.LV2, including an MXR Phase 90 plugin and a generic schematic-loader plugin shell.LiveSPICE.Linux.slnso Linux-specific projects can be built independently from the Windows WPF solution.linuxbase after the final cleanup commit.Validation
dotnet build LiveSPICE.Linux.sln --no-restoremake -C Native/LiveSPICE.LV2 clean all test ui-smoke install.carla-single lv2 https://livespice.org/plugins/generic..sln,.xaml, and.csprojfiles were reported unsupported by the configured Codacy tools.Notes for reviewers
The Linux GUI/plugin work is intentionally additive. Reviewers can focus on:
LiveSPICE.Avalonia/*LiveSPICE.Avalonia.Tests/*LiveSPICE.PluginCore/*LiveSPICE.PluginLinux/*Native/LiveSPICE.LV2/*LiveSPICE.Linux.slnThe native generic LV2 plugin currently provides host-loadable state/UI plumbing and pass-through audio; full schematic DSP execution inside the native LV2 shell remains follow-up work.
The existing Windows WPF application and Windows VST UI are not part of this port and were verified unchanged against the
linuxbranch forLiveSPICE.sln,LiveSPICE/,LiveSPICEVst/,MockVst/, andSchematicControls/.