[fix](trx-frontend-http): make vchan wrapper fire-and-forget on freq change

The vchan setRigFrequency wrapper was awaiting vchanTakeSchedulerControl()
(HTTP PUT to /scheduler-control) and vchanSetChannelFreq() (HTTP PUT to
channel freq endpoint) before calling the original setRigFrequency. This
added a full HTTP round-trip of latency to every frequency change. Make
both fire-and-forget: optimistic local update happens first, network calls
run in background.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
2026-03-22 08:57:50 +01:00
parent faf86faff9
commit 3ad5f7a3b7
@@ -433,7 +433,7 @@ function vchanSyncAccentUI() {
// Saved reference to the original refreshFreqDisplay from app.js. // Saved reference to the original refreshFreqDisplay from app.js.
let _origRefreshFreqDisplay = null; let _origRefreshFreqDisplay = null;
async function vchanSetChannelFreq(freqHz) { function vchanSetChannelFreq(freqHz) {
if (!vchanRigId || !vchanActiveId) return; if (!vchanRigId || !vchanActiveId) return;
// Validate against current SDR capture window. // Validate against current SDR capture window.
if (typeof lastSpectrumData !== "undefined" && lastSpectrumData && if (typeof lastSpectrumData !== "undefined" && lastSpectrumData &&
@@ -450,20 +450,16 @@ async function vchanSetChannelFreq(freqHz) {
return; return;
} }
} }
try { // Fire-and-forget: scheduler control + channel freq PUT run in background.
await vchanTakeSchedulerControl(); vchanTakeSchedulerControl();
const resp = await fetch( fetch(
`/channels/${encodeURIComponent(vchanRigId)}/${encodeURIComponent(vchanActiveId)}/freq`, `/channels/${encodeURIComponent(vchanRigId)}/${encodeURIComponent(vchanActiveId)}/freq`,
{ {
method: "PUT", method: "PUT",
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
body: JSON.stringify({ freq_hz: Math.round(freqHz) }), body: JSON.stringify({ freq_hz: Math.round(freqHz) }),
} }
); ).catch(e => console.error("vchan: set freq error", e));
if (!resp.ok) console.warn("vchan: set freq failed", resp.status);
} catch (e) {
console.error("vchan: set freq error", e);
}
} }
async function vchanSetChannelBandwidth(bwHz) { async function vchanSetChannelBandwidth(bwHz) {
@@ -524,13 +520,22 @@ window.vchanInterceptBandwidth = async function(bwHz) {
// the server when on a non-primary channel. // the server when on a non-primary channel.
(function() { (function() {
const _orig = window.setRigFrequency; const _orig = window.setRigFrequency;
window.setRigFrequency = async function(freqHz) { window.setRigFrequency = function(freqHz) {
if (vchanIsOnVirtual()) { if (vchanIsOnVirtual()) {
await vchanSetChannelFreq(freqHz); // Optimistic local update first, then fire-and-forget channel API.
if (typeof applyLocalTunedFrequency === "function") {
if (typeof _freqOptimisticSeq !== "undefined") {
++_freqOptimisticSeq;
_freqOptimisticHz = Math.round(freqHz);
}
applyLocalTunedFrequency(Math.round(freqHz));
}
vchanSetChannelFreq(freqHz);
return; return;
} }
await vchanTakeSchedulerControl(); // Scheduler control is fire-and-forget — don't block the freq change.
if (typeof _orig === "function") return _orig(freqHz); vchanTakeSchedulerControl();
if (typeof _orig === "function") _orig(freqHz);
}; };
})(); })();