Bus and Lifecycle Rules
1. Plugin lifecycle
- Host creates plugin instance.
OnLoad(IHostContext)is called once.- Plugin subscribes to buses, registers menus/panes.
- On unload, plugin must unsubscribe and release references in
OnUnload().
2. Bus event usage model
| Bus | Event | Use |
|---|---|---|
ISampleControllerBus | StateChanged | cursor/view/selection UI sync |
ISampleControllerBus | BufferChanged | buffer-dependent refresh |
ISelectionEventBus | SelectionChanged | selection lifecycle; heavy work on Finished |
IAudioSystemBus | PlaybackStateChanged | playhead state |
IAudioSystemBus | MeterFrameAvailable | VU meters |
IWaveHoverEventBus | HoverChanged | status bar hover data |
3. Selection lifecycle phases
Started: mouse down / selection begins.Dragging: mouse move while selecting.Finished: mouse up / selection final.Programmatic: non-mouse updates.
Do not process full-buffer DSP on
Dragging. Use Finished.4. Preview lifecycle for effect dialogues
// 1) capture source
var source = _context.DocumentService.CopyEffectiveRangeToBuffer(start, end);
// 2) create preview session
using var preview = _context.DocumentService.BeginPreview(start, end);
// 3) apply preview buffer for visual/audio preview
preview.ApplyPreview(previewBuffer);
// 4a) Apply
preview.Commit();
// 4b) Cancel/Close
preview.Cancel();
Audio preview should also be stopped on close/unload using a stable PreviewOwnerId.
5. UI thread requirements
private void OnStateChanged(object? sender, SampleControllerState state)
{
if (_label is null) return;
if (_label.InvokeRequired)
{
_label.BeginInvoke(new Action(() => OnStateChanged(sender, state)));
return;
}
_label.Text = state.Cursor.ToString();
}
Never update controls directly from worker/background threads.
6. Active document changed while dialogue is open
- Capture active document id at dialogue open.
- Before Apply/Commit, verify current active document id matches.
- If it changed, abort apply and prompt user.
7. Menus
Menu structure, ordering, grouping, and context-menu subscription are documented in Menus.
Quick format reminder:
Main menu: <Root>.<Group>.<Item>[.<SubMenu>...]
Context menu: <Group>.<Item>[.<SubMenu>...]
Example:
context.WindowManager.AddMenuContribution(30, "Effects.100.Amplitude.Amplify", _ => OpenAmplify());
context.WindowManager.AddContextMenuContribution("SampleEditor.Wave", 200, "effectsgroup.Smooth", _ => OpenSmooth());