From 7b40eae17445c17e0d706cd25c947ffa3cbdc966 Mon Sep 17 00:00:00 2001 From: Uladzimir Karpenka Date: Tue, 9 Jun 2026 09:49:16 +0300 Subject: [PATCH] Phase 5: add OnAfterTune hook so all tune paths run channel orchestration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- MainForm.pas | 12 +++++------- RadioController.pas | 9 +++++++++ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/MainForm.pas b/MainForm.pas index 33954e4..c926ab0 100644 --- a/MainForm.pas +++ b/MainForm.pas @@ -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; // --------------------------------------------------------------------------- diff --git a/RadioController.pas b/RadioController.pas index 2e97e2d..bd1ef92 100644 --- a/RadioController.pas +++ b/RadioController.pas @@ -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);