Repository navigation
OwnAudioVST3 V1.5.20
OwnAudioVST3 — v1.5.20
Overview
This release focuses on macOS stability, VST3 plugin state save/restore, and thread-safety improvements. The changes span a major stabilization push covering plugin loading, editor lifecycle, parameter synchronization, and binary state serialization.
New Features
GetState / SetState API
Full VST3 binary state save and restore support via GetStateAsync / SetStateAsync on ThreadedVst3Wrapper. State is returned as a managed byte[] and can be re-applied at any time (e.g. project load).
SetParameterAsync
New task-based parameter setter that executes on the dedicated plugin thread, ensuring immediate visibility to subsequent reads without waiting for an audio processing cycle. Designed for non-realtime use cases such as project state restoration.
Bug Fixes
macOS — Modal / Dropdown Deadlocks
- Replaced
CFRunLoopTimerwithdispatch_async_finDispatchToMainAsyncto prevent UI freeze when dropdown menus or popup browsers are opened inside a VST3 editor.CFRunLoopTimerfired duringNSEventTrackingRunLoopMode, causing a.NETP/Invoke deadlock on Apple Silicon (macOS 12+). CreateEditorandCloseEditornow dispatch to the macOS main thread viaInvoke(). JUCE'sMessageManagerrecords the calling thread on first use; calling from a non-main.NETthread causedisThisTheMessageThread()to returnfalse, makingrunModalLoop()deadlock incallFunctionOnMessageThread.loadPlugindispatched to macOS main thread so JUCE'sMessageManageralways initializes on the native main thread.
macOS — Thread Safety & Destruction
- Plugin destruction now uses a GCD drain-signal pattern instead of
SynchronizationContextto avoid deadlocks during shutdown. - macOS main queue handle resolved via
libdispatchsymbol lookup instead of a private API import. setParamNormalizeddispatched to the macOS main thread.getState()andsetState()dispatched to the macOS main thread (matches existingloadPluginguard), fixing silent failures with plugins that touch AppKit during serialization (e.g. Classic EQ v6).
State Serialization
ISizeableStreamimplemented inMemoryIBStreamImpl— plugins that query this interface before writing state (e.g. JUCE-based effects) no longer skip their state blob, resolving emptygetState()results.getState()result accepted regardless of return code — plugins that returnkResultFalsebut still write valid state data are now captured correctly.- Controller state fallback added: if the processor-side
getState()yields no data, the controller state is used instead. - Removed spec-violating zero-sample
process()call from thegetState()path; parameter flushing before serialization is now handled cleanly via the parameter queue. setState()callsupdateParameters()after restore to sync the host parameter cache.performEdit()routes editor-driven parameter changes back through the host cache and the audio-thread SPSC queue.getState()callsupdateParameters()before reading state so plugins that bypassperformEdit()are captured correctly.
Parameter Synchronization
- Editor UI re-synced with host parameters after
view->attached()— plugins that reset their UI to processor state during editor creation now correctly reflect host-set parameter values. restartComponent(kParamValuesChanged)schedules a parameter refresh on the UI thread.updateParameters()now usesoperator[]instead ofemplaceso controller values are always overwritten, not skipped on duplicate keys.PARAM_QUEUE_CAPACITYraised to 8192 to accommodate large parameter sets during state restore.- Restored parameters are pushed into the SPSC queue so the audio thread receives state-restored values before the first
processAudio()block. activeNoteIdsmade thread-safe usingatomic<int32_t>array.StringCacheprotected with a mutex for concurrentGetName/GetVendor/GetPluginInfocalls.
Initialization
- UI thread
SynchronizationContextis set before any VST3 plugin load, ensuring correct thread affinity throughout the plugin lifecycle.
Version History (this cycle)
| Version | Highlight |
|---|---|
| 1.5.20 | Thread-safe activeNoteIds/StringCache, restartComponent param refresh, getState cleanup |
| 1.5.19 | Flush paramQueue before state serialization |
| 1.5.18 | OwnVST3 v1.5.4: state serialization + thread-safe param sync |
| 1.5.17 | Remove DSP flush from getState, add controller state fallback |
| 1.5.16 | Flush parameters to processor before getState |
| 1.5.15 | Accept getState() data regardless of return code |
| 1.5.14 | Re-sync editor UI with host parameters after attach |
| 1.5.13 | ISizeableStream support in MemoryIBStreamImpl |
| 1.5.12 | macOS main thread setParamNormalized |
| 1.5.11 | State restore fix: SPSC queue push + updateParameters on setState |
| 1.5.10 | GetState/SetState API + SetParameterAsync |
| 1.5.9 | macOS main thread dispatching for loadPlugin, CreateEditor, CloseEditor |
| 1.5.8 | Fix CFRunLoopTimer dropdown deadlock, GCD drain-signal destruction |