Skip to content

CW sidetone reads stale: setCwSidetone() omits the optimistic local update #3720

Description

@jensenpat

Summary

TransmitModel::setCwSidetone(bool on) sends the radio command but never updates its local member m_cwSidetone, so transmitModel().cwSidetone() 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:705:

void TransmitModel::setCwSidetone(bool on)
{
    emit commandReady(QString("cw sidetone %1").arg(on ? 1 : 0));   // <-- m_cwSidetone never set
}

m_cwSidetone is declared at TransmitModel.h:327 (default true).

Why it's a bug

Sibling setters update their member optimistically — e.g. setSpeechProcessorEnable (TransmitModel.cpp:536: m_speechProcEnable = on; emit micStateChanged();) — and #3712 (setAmCarrierLevel) established the canonical pattern. setCwSidetone is missing it, 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 and the radio applies it; the model lags the widget until the radio echoes cw sidetone. Measured live on a FLEX-8400M via the agent automation bridge: after toggling "CW sidetone", transmit.cwSidetone did not converge within a 416 ms poll window, vs ~0 ms for the optimistic setters.

Steps to reproduce

  1. Connect to a radio.
  2. Toggle CW sidetone in the Phone/CW applet (or send cw sidetone 0).
  3. Immediately read transmitModel().cwSidetone() — it still reports the old state.

Suggested fix

void TransmitModel::setCwSidetone(bool on)
{
    if (m_cwSidetone != on) {
        m_cwSidetone = on;  // optimistic — radio status echo supersedes
        emit phoneStateChanged();
    }
    emit commandReady(QString("cw sidetone %1").arg(on ? 1 : 0));
}

Verify before committing: (1) confirm phoneStateChanged() is the signal the "CW sidetone" button's model-sync listener binds to (control lives in PhoneCwApplet, alongside the other CW setters); (2) ensure no feedback loop — the applet's model→widget sync must be guarded (m_updatingFromModel / QSignalBlocker) so the optimistic update doesn't re-emit the command, as the #3712 fix verified for the PhoneApplet.

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

    CWCW keying, decode, and operationGUIUser interfacebugSomething isn't workinggood first issueGood for newcomersmaintainer-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