Skip to content

DAX digital audio model can read stale: setDax() omits the optimistic local update (latent) #3721

Description

@jensenpat

Summary

TransmitModel::setDax(bool on) sends the radio command but never updates its local member m_daxOn. Same omission as #3712 (AM carrier) and the TX-monitor / CW-sidetone issues — but currently latent: the radio echoes dax= promptly so the model converges fast in practice. Worth fixing for consistency and to remove the race.

Location

src/models/TransmitModel.cpp:556:

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

m_daxOn is declared at TransmitModel.h:304 (default false).

Why it's worth fixing

It's the same pattern the rest of the TX setters follow inconsistently: optimistic local update (setSpeechProcessorEnable at TransmitModel.cpp:536; setAmCarrierLevel per #3712) vs none here. Unlike TX monitor / CW sidetone, the desync isn't user-visible today because the radio echoes dax= quickly.

Impact

Severity: low / latent. Measured live on a FLEX-8400M via the agent automation bridge: after toggling "DAX digital audio", transmit.dax converged in ~80 ms (radio echo), so no stale read was observed — but the model is briefly inconsistent and relies on the echo arriving, unlike the optimistic setters which are correct at 0 ms. A slow or dropped echo would surface the same stale-read as the sibling bugs.

Steps to reproduce

  1. Connect to a radio.
  2. Toggle DAX digital audio in the Phone/CW applet (or send transmit set dax=1).
  3. Read transmitModel().daxOn() in the same tick — it reflects the change only after the radio echo, not optimistically.

Suggested fix

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

Verify before committing: confirm the right NOTIFY signal for the "DAX digital audio" button's model-sync listener (control lives in PhoneCwApplet), and that the applet's model→widget sync is guarded (m_updatingFromModel / QSignalBlocker) so the optimistic update doesn't re-emit the command — same check as #3712.

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); flagged as the masked/latent member of the same setter-inconsistency family.

Metadata

Metadata

Assignees

No one assigned

    Labels

    GUIUser interfaceaudioAudio engine and streamingbugSomething 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