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

  1. Host starts without loader errors.
  2. Your menu entry appears in the expected root/group/item path.
  3. Command callback executes.
  4. 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:

  1. Copy source range from IDocumentService.
  2. Run DSP into preview buffer.
  3. Send preview loop to audio bus with owner id.
  4. On Apply: either commit the preview session, or replace active range directly (pick one model).
  5. On Cancel/Close: stop preview and cancel/restore.
Next: move to API Reference and Menus for full interface/type details.

Back to top