Phase 3 (batch 3): route Volume, AGC-top, WfAGC/WfNF through controller

First sliders through the controller, exercising the FSyncingFromController
re-entrancy guard:
- SetVolume/SetAGCTop clamp, apply to the DSP engine, update band cache,
  and fire OnStateChanged. SetAGCTop reuses ApplyAGCToEngine (the unified
  AGC index->enum mapping), fixing the same bad TWDSPAGCMode(index) cast
  that TrkAGCChange/SyncWebAGCTop used when re-applying AGC on level change.
- OnControllerState updates the slider/label/spectrum (rfAGCTop also
  refreshes the FSpecView AGC line, now consistent for web-initiated
  changes too) and the FSpecView waterfall flags (rfWfAGC/rfWfNF).
- TrkVolumeChange/TrkAGCChange (guarded), SyncWebVolume/AGCTop/WfAGC/WfNF,
  and ApplyWfAGCNF all call the commands.

Builds clean (cocoa).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Uladzimir Karpenka
2026-06-04 14:58:03 +03:00
co-authored by Claude Opus 4.8
parent f76533f209
commit b3e4360a5d
2 changed files with 48 additions and 39 deletions
+24 -34
View File
@@ -1439,6 +1439,20 @@ begin
rfANF: UpdateANFButton; rfANF: UpdateANFButton;
rfAGCMode: rfAGCMode:
for i := 0 to 4 do StyleButton(BtnAGCMode[i], i = FController.FAGCMode); for i := 0 to 4 do StyleButton(BtnAGCMode[i], i = FController.FAGCMode);
rfVolume:
TrkVolume.Position := FController.FVolume;
rfAGCTop:
begin
TrkAGC.Position := FController.FAGCTop;
LblAGCTop.Caption := Format('%ddB', [FController.FAGCTop]);
FSpecView.AGCTop := FController.FAGCTop;
FSpecView.DrawSpectrum;
PbSpectrum.Invalidate;
end;
rfWfAGC:
FSpecView.WfAGCEnabled := FController.FWfAGCEnabled;
rfWfNF:
FSpecView.WfNFEnabled := FController.FWfNFEnabled;
end; end;
finally finally
FSyncingFromController := False; FSyncingFromController := False;
@@ -5945,10 +5959,8 @@ end;
procedure TMainForm.ApplyWfAGCNF(WfAGC, WfNF: Boolean); procedure TMainForm.ApplyWfAGCNF(WfAGC, WfNF: Boolean);
begin begin
FController.FWfAGCEnabled := WfAGC; FController.SetWfAGC(WfAGC);
FController.FWfNFEnabled := WfNF; FController.SetWfNF(WfNF);
FSpecView.WfAGCEnabled := FController.FWfAGCEnabled;
FSpecView.WfNFEnabled := FController.FWfNFEnabled;
end; end;
procedure TMainForm.ApplyADCSettings(Dither, Random: Boolean); procedure TMainForm.ApplyADCSettings(Dither, Random: Boolean);
@@ -6301,15 +6313,7 @@ end;
procedure TMainForm.SyncWebAGCTop; procedure TMainForm.SyncWebAGCTop;
begin begin
FController.FAGCTop := Max(20, Min(120, FWebSyncInt)); FController.SetAGCTop(FWebSyncInt); // клампит, применяет, OnControllerState обновит UI
TrkAGC.Position := FController.FAGCTop;
LblAGCTop.Caption := Format('%ddB', [FController.FAGCTop]);
if FController.FWDSPReady then
begin
FController.FDSPEngine.SetAGCTop(FController.FAGCTop);
FController.FDSPEngine.SetAGC(TWDSPAGCMode(FController.FAGCMode), 50.0);
end;
FController.FBandCache[FController.FCurrentBand].AGCTop := FController.FAGCTop;
end; end;
procedure TMainForm.WebOnBand(Idx: Integer); procedure TMainForm.WebOnBand(Idx: Integer);
@@ -6386,9 +6390,7 @@ end;
procedure TMainForm.SyncWebVolume; procedure TMainForm.SyncWebVolume;
begin begin
FController.FVolume := Max(0, Min(100, FWebSyncInt)); FController.SetVolume(FWebSyncInt);
TrkVolume.Position := FController.FVolume;
if FController.FWDSPReady then FController.FDSPEngine.SetVolume(FController.FVolume / 100.0);
end; end;
procedure TMainForm.WebOnWfAGC(On_: Boolean); procedure TMainForm.WebOnWfAGC(On_: Boolean);
@@ -6400,8 +6402,7 @@ end;
procedure TMainForm.SyncWebWfAGC; procedure TMainForm.SyncWebWfAGC;
begin begin
FController.FWfAGCEnabled := FWebSyncBool; FController.SetWfAGC(FWebSyncBool);
FSpecView.WfAGCEnabled := FController.FWfAGCEnabled;
end; end;
procedure TMainForm.WebOnWfNF(On_: Boolean); procedure TMainForm.WebOnWfNF(On_: Boolean);
@@ -6413,8 +6414,7 @@ end;
procedure TMainForm.SyncWebWfNF; procedure TMainForm.SyncWebWfNF;
begin begin
FController.FWfNFEnabled := FWebSyncBool; FController.SetWfNF(FWebSyncBool);
FSpecView.WfNFEnabled := FController.FWfNFEnabled;
end; end;
// ── Run ──────────────────────────────────────────────────────────────────── // ── Run ────────────────────────────────────────────────────────────────────
@@ -7229,9 +7229,8 @@ end;
procedure TMainForm.TrkVolumeChange(Sender: TObject); procedure TMainForm.TrkVolumeChange(Sender: TObject);
begin begin
FController.FVolume := TrkVolume.Position; if FSyncingFromController then Exit;
if FController.FWDSPReady then FController.SetVolume(TrkVolume.Position);
FController.FDSPEngine.SetVolume(FController.FVolume / 100.0);
end; end;
// =========================================================================== // ===========================================================================
@@ -7293,17 +7292,8 @@ end;
procedure TMainForm.TrkAGCChange(Sender: TObject); procedure TMainForm.TrkAGCChange(Sender: TObject);
begin begin
FController.FAGCTop := TrkAGC.Position; if FSyncingFromController then Exit;
LblAGCTop.Caption := Format('%ddB', [FController.FAGCTop]); FController.SetAGCTop(TrkAGC.Position);
if FController.FWDSPReady then
begin
FController.FDSPEngine.SetAGCTop(FController.FAGCTop);
FController.FDSPEngine.SetAGC(TWDSPAGCMode(FController.FAGCMode), 50.0);
end;
FController.FBandCache[FController.FCurrentBand].AGCTop := FController.FAGCTop;
FSpecView.AGCTop := FController.FAGCTop;
FSpecView.DrawSpectrum;
PbSpectrum.Invalidate;
end; end;
// =========================================================================== // ===========================================================================
+24 -5
View File
@@ -108,6 +108,7 @@ type
FOnInvoke: TUIInvokeEvent; FOnInvoke: TUIInvokeEvent;
FOnStateChanged: TRadioStateEvent; FOnStateChanged: TRadioStateEvent;
procedure Changed(Field: TRadioField); procedure Changed(Field: TRadioField);
procedure ApplyAGCToEngine; // применяет FAGCMode к WDSP (единый маппинг)
public public
// ============================================================ // ============================================================
// ПУБЛИЧНЫЕ ПОЛЯ (миграционные — имена совпадают с TMainForm). // ПУБЛИЧНЫЕ ПОЛЯ (миграционные — имена совпадают с TMainForm).
@@ -381,27 +382,45 @@ begin FFilter := Idx; Changed(rfFilter); { TODO wiring } end;
procedure TRadioController.SetFilterBW(BWHz: Integer); procedure TRadioController.SetFilterBW(BWHz: Integer);
begin FFilterBW := BWHz; Changed(rfFilterBW); { TODO wiring } end; begin FFilterBW := BWHz; Changed(rfFilterBW); { TODO wiring } end;
procedure TRadioController.SetAGCMode(M: Integer); procedure TRadioController.ApplyAGCToEngine;
const const
// UI-индекс 0..4 (FAST/MED/SLOW/LONG/OFF) -> WDSP enum. Единый маппинг для // UI-индекс 0..4 (FAST/MED/SLOW/LONG/OFF) -> WDSP enum. Единый маппинг для
// всех фронтендов (раньше web ошибочно кастовал индекс прямо в enum). // всех фронтендов (раньше web/слайдер ошибочно кастовали индекс прямо в enum).
AGCModes: array[0..4] of TWDSPAGCMode = (agcFast, agcMedium, agcSlow, agcLong, agcOff); AGCModes: array[0..4] of TWDSPAGCMode = (agcFast, agcMedium, agcSlow, agcLong, agcOff);
begin
if FWDSPReady and Assigned(FDSPEngine) and (FAGCMode >= 0) and (FAGCMode <= 4) then
FDSPEngine.SetAGC(AGCModes[FAGCMode], 50.0);
end;
procedure TRadioController.SetAGCMode(M: Integer);
begin begin
if (M < 0) or (M > 4) then Exit; if (M < 0) or (M > 4) then Exit;
FAGCMode := M; FAGCMode := M;
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetAGC(AGCModes[M], 50.0); ApplyAGCToEngine;
FBandCache[FCurrentBand].AGCMode := FAGCMode; FBandCache[FCurrentBand].AGCMode := FAGCMode;
Changed(rfAGCMode); Changed(rfAGCMode);
end; end;
procedure TRadioController.SetAGCTop(DB: Integer); procedure TRadioController.SetAGCTop(DB: Integer);
begin FAGCTop := DB; Changed(rfAGCTop); { TODO wiring } end; begin
if DB < 20 then DB := 20 else if DB > 120 then DB := 120;
FAGCTop := DB;
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetAGCTop(FAGCTop);
ApplyAGCToEngine; // ре-применяем режим с новым уровнем
FBandCache[FCurrentBand].AGCTop := FAGCTop;
Changed(rfAGCTop);
end;
procedure TRadioController.AGCTopBy(Delta: Integer); procedure TRadioController.AGCTopBy(Delta: Integer);
begin SetAGCTop(FAGCTop + Delta); end; begin SetAGCTop(FAGCTop + Delta); end;
procedure TRadioController.SetVolume(V: Integer); procedure TRadioController.SetVolume(V: Integer);
begin FVolume := V; Changed(rfVolume); { TODO wiring: FDSPEngine.SetVolume } end; begin
if V < 0 then V := 0 else if V > 100 then V := 100;
FVolume := V;
if FWDSPReady and Assigned(FDSPEngine) then FDSPEngine.SetVolume(FVolume / 100.0);
Changed(rfVolume);
end;
procedure TRadioController.VolumeBy(Delta: Integer); procedure TRadioController.VolumeBy(Delta: Integer);
begin SetVolume(FVolume + Delta); end; begin SetVolume(FVolume + Delta); end;