Skip to content

On restart, AetherSDR restores persisted broken panadapter state instead of defaulting to single-pan safe mode #269

@chibondking

Description

@chibondking

On restart, AetherSDR restores persisted broken panadapter state instead of defaulting to single-pan safe mode

Labels: bug, GUI, priority: medium
Related: multi-panadapter FFT/waterfall broken state issue (filed separately)
Related: #152 (multi-panadapter support)


What

When AetherSDR is restarted after a session where the second panadapter was
in a broken state (FFT blank, not closeable), it restores the broken
panadapter layout from persisted settings
rather than defaulting to a
clean single-panadapter state. The user is immediately back in the broken
state with no path to recovery short of manually editing the settings file.


Why This Happens

AetherSDR persists panadapter layout state (number of open pans, pan IDs,
geometry) across sessions via AppSettings. On restart, it reads this
state and attempts to recreate the saved layout. When the saved layout
includes a panadapter that was corrupt at save time, the corruption is
faithfully reproduced on the next launch.

This is a fundamental dirty-state persistence problem: the app saves
whatever state it is in at shutdown — including broken states — and
unconditionally restores it on startup, with no validation that the
persisted state is actually healthy.


Why It Matters

A user who encounters the broken-panadapter bug (filed separately) and
restarts AetherSDR expecting a clean slate instead finds themselves in the
same broken state immediately. The restart that should be the recovery
path becomes a trap. Combined with the inability to close the faulty pan
from the UI, the user has no in-app recovery option at all.


How SmartSDR Handles It

SmartSDR for Windows never persists multi-panadapter layout client-side.
On connect, it requests the radio's current panadapter state and builds the
UI from live radio data only. If the radio reports only one panadapter,
SmartSDR shows one — regardless of what the previous session looked like.
There is no "dirty load" because there is no client-side layout persistence
to go stale. The radio is the single source of truth for panadapter count
and configuration.


The Design Tradeoff

This is a conscious architectural decision with two valid positions:

Option A — Radio as source of truth (SmartSDR approach)

On connect, request panadapter state from the radio (sub pan all) and
build the UI entirely from the radio's response. Do not persist panadapter
count or pan IDs client-side. If the radio reports one pan, show one. If it
reports two, show two.

  • Pro: can never load a stale or corrupt layout. Always reflects actual
    radio state.
  • Con: loses any client-side display preferences (zoom, dBm range,
    waterfall speed) that the radio does not store. These would need to be
    re-applied heuristically (e.g. by pan frequency match) on reconnect.

Option B — Persist with validation (safer client-side persistence)

Continue persisting layout client-side but add a health check on load:
before restoring a saved panadapter, verify that the radio actually has a
live panadapter with that ID. If validation fails, silently discard the
saved pan and default to single-pan layout.

// In RadioModel or PanadapterStack — on connect, after sub pan all
for (const auto& savedPanId : savedPanIds) {
    if (!m_activePanIds.contains(savedPanId)) {
        // Radio doesn't know about this pan — don't restore it
        AppSettings::instance().remove("Pan2Id");  // clean up stale entry
        continue;
    }
    restorePanadapter(savedPanId);
}
  • Pro: preserves client-side display preferences across sessions.
  • Con: more complex; validation logic must be correct or it silently
    discards valid state.

Option C — Fail safe, no alert (recommended minimum)

Regardless of which option is chosen for the long term, implement an
immediate fail-safe fallback: if any panadapter fails to initialise
correctly on load (FFT stream not arriving within a timeout, stream ID
not confirmed by the radio, widget in error state), silently drop that
pan and continue with a single-pan layout
. No popup, no error dialog —
consistent with SmartSDR's behaviour. The user gets a working app rather
than a broken one.


Suggested Behavior (Recommended: Option C now, Option A or B later)

Immediate fix (Option C)

Add a startup health check in PanadapterStack or RadioModel: after
connect and after VITA-49 streaming begins, verify each restored panadapter
has received at least one valid FFT frame (PCC 0x8003) within a
reasonable timeout (e.g. 5 seconds). If a pan fails this check:

  1. Silently remove it from the layout.
  2. Clean up its persisted state from AppSettings so it does not come
    back on the next restart.
  3. Log a diagnostic message (no user-facing alert).

Long-term (Option A or B — design decision for Jeremy)

Decide whether panadapter layout should be radio-authoritative (Option A)
or client-persisted-with-validation (Option B). This decision affects
AppSettings key design for pan state, the wirePanadapter() / reconnect
flow, and how client-side display preferences (zoom, gain, black level) are
associated with pans across sessions.


Protocol Hints

Confirming live panadapter IDs from radio (on connect)

sub pan all

The radio responds with display pan <id> status objects for each active
panadapter. The set of IDs in these responses is the ground truth for what
pans actually exist. Any persisted pan ID not in this set should be
discarded on load.

Confirming FFT stream is live (health check)

A panadapter is healthy if PCC 0x8003 packets for its stream ID arrive
within ~5 seconds of client udpport registration. If no packets arrive,
the radio is not streaming FFT for that pan and the pan should be
considered invalid.

Relevant source locations

  • src/core/AppSettings — pan layout persistence keys (pan count, pan
    IDs, geometry); identify which keys need to be cleared on failed load
  • src/gui/PanadapterStack — pan creation on startup; add health check
    timeout per pan; silent removal of failed pans
  • src/models/RadioModelsub pan all response handling; expose set
    of live pan IDs for validation against persisted state
  • src/core/PanadapterStream — FFT packet arrival; add per-pan
    "first frame received" signal for health check timeout logic

Metadata

Metadata

Assignees

No one assigned

    Labels

    GUIUser interfacebugSomething isn't workingmaintainer-reviewRequires maintainer review before any action is takenmulti-panMulti-panadapter layout and slicingpriority: mediumMedium priorityprotocolSmartSDR protocol

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions