feat: unify sample-rate presets across desktop + web UIs

Sample-rate (span) presets were duplicated in three places and none was
authoritative: HPSDR set hardcoded in the desktop overlay (SPAN_RATES),
Pluto set in backend caps, and a separate hardcoded list in the web JS.
The web showed HPSDR rates even on Pluto, and the web adapter silently
dropped any rate outside a hardcoded HPSDR whitelist (so Pluto-only rates
like 960k/2304k never switched).

Single source of truth = backend caps -> controller:
- HPSDRNetwork.Caps now fills RatePresets [48k..1536k] (was nil).
- RadioBackend: named type TBackendRateArray.
- TRadioController.SampleRatePresets returns BackendCaps.RatePresets.

Both UIs derive from it:
- Desktop: ApplyBackendCapsToUI always feeds the overlay from
  SampleRatePresets (overlay no longer owns the HPSDR list).
- Web: WebServer.SetRatePresets + rate_presets in state JSON; hosts
  (daemon OnState/startup, GUI ApplyBackendCapsToUI/startup) push
  SampleRatePresets; JS builds span buttons dynamically from it.
- WebAdapter.SyncSpan validates against SampleRatePresets instead of a
  hardcoded whitelist, so any backend rate is accepted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-23 13:52:03 +03:00
co-authored by Claude Opus 4.8
parent d78d835485
commit 6b695ce756
8 changed files with 87 additions and 21 deletions
+8 -1
View File
@@ -55,6 +55,7 @@ type
procedure ConnectTo(const Dev: THPSDRDevice);
procedure PushDeviceList;
procedure PushXvtr;
procedure PushRatePresets; // sample-rate пресеты бэкенда → web
// Входящие web-команды (из WS-потока): запоминаем параметр и маршалим в Sync*.
procedure WebRun(On_: Boolean);
procedure WebConnect(const IP: string);
@@ -196,7 +197,7 @@ begin
// выходные web-списки, которых нет в периодическом PushState.
case Field of
rfDeviceList: PushDeviceList; // discovered обновился
rfXvtr, rfDevice: begin PushXvtr; PushDeviceList; end; // connect / xvtr-смена
rfXvtr, rfDevice: begin PushXvtr; PushDeviceList; PushRatePresets; end; // connect / xvtr / backend
end;
end;
@@ -291,6 +292,11 @@ begin
FWeb.SetXvtrBands(Arr, FCtrl.FCurrentXvtr);
end;
procedure THeadlessHost.PushRatePresets;
begin
FWeb.SetRatePresets(FCtrl.SampleRatePresets);
end;
// --- Входящие web-команды (WS-поток) → маршалинг в главный поток ---
procedure THeadlessHost.WebRun(On_: Boolean);
@@ -382,6 +388,7 @@ begin
end;
Log('Web control on http://' + WebCfg.BindAddr + ':' + IntToStr(WebCfg.Port));
PushDeviceList;
PushRatePresets; // дефолтный бэкенд (HPSDR) до connect; перезапишется на смене
// FRunning ставим ДО autostart: первый WDSP-open может занять время, и если за
// него прилетит SIGINT (RequestStop→FRunning:=False), цикл сразу завершится, а