When changing frequency with shared monitor active, the monitor retune
could be silently dropped if a previous retune was still in-flight,
leaving the UI stuck on "Starting <freq>". After stopping and restarting
the waterfall, the monitor button could remain disabled because
_startingMonitor was never reset and _monitorRetuneTimer was not cleared.
- Cancel in-flight monitor start when queuing a new retune
- Always clear _pendingSharedMonitorRearm in started handler
- Clear _monitorRetuneTimer and reset _startingMonitor in stop()
stop() sets _ws = null before the async onclose fires, so the handler
now early-returns when _ws is null instead of showing the misleading
"WebSocket closed before ready" retry message.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- _waitForPlayback now only succeeds on playing/timeupdate events, not
loadeddata/canplay which fire from just the WAV header before real
audio arrives
- stopMonitor() pauses audio and updates UI immediately instead of
blocking on the backend stop request (1+ second delay)
- Reduced backend audio stop sleep from 1.0s to 0.15s; the start
retry loop already handles USB contention
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>