Phase 5: add OnAfterTune hook so all tune paths run channel orchestration

Channel orchestration (deactivate-on-tune-away, auto-CTCSS/pre-channel-drive
restore) was glued to MainForm.ApplyVfoA, so only desktop/web-freq tuning ran it.
Add TRadioController.OnAfterTune, fired at the very end of SetVfoA (after the
rfVfoA render returns — outside its guard, no re-entrancy), wired to
ChannelController.OnVfoTuned.

Now every SetVfoA caller (desktop, web, CAT, encoder TuneActiveBy, SetActiveVfo,
channel apply) is uniformly channel-aware and headless-compatible. ApplyVfoA
becomes a thin delegate. Minor improvement: encoder tune-away now deactivates an
active channel like desktop; SetActiveVfo/channel-apply are no-ops (freq matches).

Foundation for moving RestoreBand's retune into the controller (Band command).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Uladzimir Karpenka
2026-06-09 09:49:16 +03:00
co-authored by Claude Opus 4.8
parent 5f5558e4a2
commit 7b40eae174
2 changed files with 14 additions and 7 deletions
+5 -7
View File
@@ -769,6 +769,8 @@ begin
FChannelController.OnActiveChanged := OnChannelActiveChanged;
FChannelController.OnActivateXvtr := ActivateXvtrBand;
FChannelController.OnDeactivateXvtr := DeactivateXvtr;
// Канал-оркестрация фаером из контроллера в конце SetVfoA (любой путь тюнинга).
FController.OnAfterTune := FChannelController.OnVfoTuned;
FController.FVfoA := 14200000;
FController.FVfoB := 7100000;
FController.FActiveVfo := 0;
@@ -3760,14 +3762,10 @@ end;
// ---------------------------------------------------------------------------
procedure TMainForm.ApplyVfoA(NewFreq: Int64);
begin
// Движок (XVTR-клэмп, CTUN shift/center/scroll, детект диапазона, FM авто-RPT,
// сеть) — в контроллере SetVfoA; рендер FreqDisp/спектра/band-кнопок — в
// OnControllerState(rfVfoA/rfBand).
// Тонкий делегат: движок (XVTR-клэмп, CTUN, band-detect, FM авто-RPT, сеть) —
// в SetVfoA; канальная оркестрация — в FController.OnAfterTune (хук в конце
// SetVfoA → FChannelController.OnVfoTuned); рендер — OnControllerState.
FController.SetVfoA(NewFreq);
// Канальная оркестрация (авто-CTCSS/pre-channel-drive + деактивация при уходе
// с частоты канала) — в адаптере каналов.
FChannelController.OnVfoTuned;
end;
// ---------------------------------------------------------------------------
+9
View File
@@ -109,6 +109,7 @@ type
private
FOnInvoke: TUIInvokeEvent;
FOnStateChanged: TRadioStateEvent;
FOnAfterTune: TThreadMethod; // пост-тюн хук: канал-оркестрация после SetVfoA
procedure Changed(Field: TRadioField);
procedure ApplyAGCToEngine; // применяет FAGCMode к WDSP (единый маппинг)
procedure ApplyModeDefaults; // дефолтный фильтр/девиация под текущий FMode
@@ -423,6 +424,10 @@ type
// ---- События наружу ----
property OnInvoke: TUIInvokeEvent read FOnInvoke write FOnInvoke;
property OnStateChanged: TRadioStateEvent read FOnStateChanged write FOnStateChanged;
// Пост-тюн хук: вызывается в КОНЦЕ SetVfoA (после Changed(rfVfoA), т.е. вне
// рендера) — сюда вешается канальная оркестрация (ChannelController.OnVfoTuned),
// чтобы любой путь тюнинга (desktop/web/CAT/энкодер) был канал-aware headless.
property OnAfterTune: TThreadMethod read FOnAfterTune write FOnAfterTune;
end;
implementation
@@ -1233,6 +1238,10 @@ begin
PushNetworkState;
Changed(rfVfoA);
// Канальная оркестрация — ПОСЛЕ рендера rfVfoA (вне его try/finally-гарда), без
// ре-ентранси: OnVfoTuned зовёт команды (SetDrive/SetFMRpt), которым нужен
// чистый верхний уровень OnControllerState.
if Assigned(FOnAfterTune) then FOnAfterTune;
end;
procedure TRadioController.SetVfoB(Hz: Double);