Skip to content

TX monitor (sub-band monitor) reads stale: setSbMonitor() omits the optimistic local update #3719

Description

@jensenpat

Summary

TransmitModel::setSbMonitor(bool on) sends the radio command but never updates its local member m_sbMonitor, so transmitModel().sbMonitor() returns a stale value until the radio's status echo arrives. Same defect class as the AM carrier bug fixed in #3712.

Location

src/models/TransmitModel.cpp:561:

void TransmitModel::setSbMonitor(bool on)
{
    emit commandReady(QString("transmit set mon=%1").arg(on ? 1 : 0));   // <-- m_sbMonitor never set
}

m_sbMonitor is declared at TransmitModel.h:305 (default false).

Why it's a bug

Sibling setters update their member optimistically before/with the command, e.g. setSpeechProcessorEnable (TransmitModel.cpp:536) does m_speechProcEnable = on; emit micStateChanged();, and the AM carrier fix #3712 (setAmCarrierLevel, ~line 618) established the canonical pattern. setSbMonitor is missing that, so any reader right after a change (GUI re-read, TCI client, the agent automation bridge's get transmit) sees the old value.

Impact

Severity: low. The command is sent correctly and the radio applies it; the model just lags the widget until the radio echoes mon=. Measured live on a FLEX-8400M via the agent automation bridge: after toggling "TX monitor", transmit.monitor did not converge within a 410 ms poll window, whereas the optimistic setters converge in ~0 ms.

Steps to reproduce

  1. Connect to a radio.
  2. Toggle TX monitor in the Phone/CW applet (or send transmit set mon=1).
  3. Immediately read transmitModel().sbMonitor() — it still reports the old state.

Suggested fix

Mirror #3712 / the sibling pattern:

void TransmitModel::setSbMonitor(bool on)
{
    if (m_sbMonitor != on) {
        m_sbMonitor = on;  // optimistic — radio status echo supersedes
        emit phoneStateChanged();
    }
    emit commandReady(QString("transmit set mon=%1").arg(on ? 1 : 0));
}

Verify before committing: (1) confirm phoneStateChanged() is the signal the "TX monitor" button's model-sync listener binds to (the control lives in PhoneCwApplet); (2) ensure no feedback loop — the applet's model→widget sync must be guarded (e.g. m_updatingFromModel / QSignalBlocker) so the optimistic update doesn't re-emit the command, exactly as the #3712 fix checked for the PhoneApplet AM-carrier slider.

How it was found

Surfaced during a control-surface validation sweep on a FLEX-8400M using the agent automation bridge (get transmit model cross-check).

Metadata

Metadata

Assignees

No one assigned

    Labels

    GUIUser interfaceaudioAudio engine and streamingbugSomething isn't workingmaintainer-reviewRequires maintainer review before any action is takenpriority: lowLow priority

    Type

    No type

    Fields

    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