Quickstart: Build a Plugin from Scratch
1. Create Plugin Project
dotnet new classlib -n RetroWaveLab.Plugins.MyPlugin
# Target framework should match host plugin build (currently net8.0-windows for WinForms plugins)
Reference RetroWaveLab.Core.Abstractions and any UI/helper assemblies you need.
2. Implement Entry Class
using RetroWaveLab.Core.Abstractions;
namespace RetroWaveLab.Plugins.MyPlugin;
public sealed class MyPlugin : IPlugin
{
private IHostContext? _context;
public string Id => "my-plugin";
public string DisplayName => "My Plugin";
public Version Version => new(1, 0, 0);
public void OnLoad(IHostContext context)
{
_context = context;
context.WindowManager.AddMenuContribution(
100,
"Tools.100.My Plugin.Run",
_ => Run(),
() => _context?.SampleControllerBus.Buffer is { InterleavedSamples.Length: > 0 });
}
public void OnUnload()
{
_context = null;
}
private void Run()
{
// plugin action
}
}
3. Create Plugin Manifest
{
"id": "my-plugin",
"displayName": "My Plugin",
"version": "1.0.0",
"assembly": "RetroWaveLab.Plugins.MyPlugin.dll",
"entryType": "RetroWaveLab.Plugins.MyPlugin.MyPlugin"
}
Place this file as *.plugin.json under your plugin deployment folder.
4. Deploy Layout
Plugins/MyPlugin/
my-plugin.plugin.json
RetroWaveLab.Plugins.MyPlugin.dll
RetroWaveLab.Plugins.MyPlugin.deps.json (if generated)
...plugin dependencies...
5. First Validation
- Host starts without loader errors.
- Your menu entry appears in the expected root/group/item path.
- Command callback executes.
- Unload/reload does not leak event handlers.
6. Add UI Pane (Optional)
public sealed class MyPlugin : IPlugin, IProvidesDockPanes
{
public IEnumerable<DockPaneRegistration> GetDockPanes()
{
yield return new DockPaneRegistration(
PaneId: "my-plugin.main",
Title: "My Plugin",
DefaultPlacement: DockPlacement.Right,
CreateView: CreatePaneView,
AllowVerticalNeighbour: true,
AllowHorizontalNeighbour: true,
CanUndock: true);
}
private object CreatePaneView()
{
var panel = new Panel { Dock = DockStyle.Fill };
panel.Controls.Add(new Label { Dock = DockStyle.Fill, Text = "Ready", TextAlign = ContentAlignment.MiddleCenter });
return panel;
}
}
7. Add Effect Preview (Optional)
Use this lifecycle:
- Copy source range from
IDocumentService. - Run DSP into preview buffer.
- Send preview loop to audio bus with owner id.
- On Apply: either commit the preview session, or replace active range directly (pick one model).
- On Cancel/Close: stop preview and cancel/restore.