mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 17:27:32 +00:00
Phase 5: make XVTR enter/exit full controller commands
Move the xvtr wrapper render-extras (wideband view + web push) into the rfXvtr render handler, and the HF-return (RestoreBand) into core DeactivateXvtr — emitting rfXvtr *after* RestoreBand so the extras render sees the settled HF state. MainForm.ActivateXvtrBand/DeactivateXvtr collapse to thin delegates. ChannelController drops its OnActivateXvtr/OnDeactivateXvtr host callbacks and calls FRadio.SetXvtrBand directly — no host coupling left, only the OnActiveChanged out-event. Also fixes a latent regression from the OnAfterTune hook: an intermediate SetVfoA during channel Apply (xvtr-exit → RestoreBand → retune to the old freq) fired OnVfoTuned and deactivated the channel mid-apply. Apply is now atomic w.r.t. channel orchestration via an FApplying guard. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
de1f4b772d
commit
cc8380ae85
+17
-14
@@ -12,10 +12,8 @@ unit ChannelController;
|
||||
// + мощность «до канала») — это снимает последний UI-блокер для headless-режима.
|
||||
//
|
||||
// Наружу юнит эмитит собственное событие OnActiveChanged (рендер кнопки Channel).
|
||||
// Две UI-композитные XVTR-операции (вход/выход трансвертера с wideband-видом и
|
||||
// web-пушем) пока живут в MainForm-обёртках — юнит зовёт их через колбэки
|
||||
// OnActivateXvtr/OnDeactivateXvtr (сократятся при переносе xvtr render-extras в
|
||||
// OnControllerState).
|
||||
// Вход/выход трансвертера идёт через FRadio.SetXvtrBand (команда несёт DSP/сеть +
|
||||
// рендер/wideband/web через rfXvtr) — host-колбэков у юнита больше нет.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
{$mode delphi}{$H+}
|
||||
@@ -29,8 +27,6 @@ uses
|
||||
type
|
||||
// Рендер активного канала: Active=True → подсветка + Name; False → сброс.
|
||||
TChannelActiveEvent = procedure(Idx: Integer; const Name: string; Active: Boolean) of object;
|
||||
TChannelXvtrEvent = procedure(Idx: Integer) of object;
|
||||
TChannelNotifyEvent = procedure of object;
|
||||
|
||||
TChannelController = class
|
||||
private
|
||||
@@ -38,9 +34,8 @@ type
|
||||
FActiveIdx: Integer; // -1 = нет активного канала
|
||||
FPreChannelPower: Integer; // drive % до применения канала (-1 = не сохранён)
|
||||
FRestoringDrive: Boolean; // True пока юнит сам ставит drive (apply/restore)
|
||||
FApplying: Boolean; // True пока идёт Apply (гасит промежуточный OnVfoTuned)
|
||||
FOnActiveChanged: TChannelActiveEvent;
|
||||
FOnActivateXvtr: TChannelXvtrEvent;
|
||||
FOnDeactivateXvtr: TChannelNotifyEvent;
|
||||
procedure EmitActive(Active: Boolean; const Name: string);
|
||||
procedure SetDriveGuarded(V: Integer); // SetDrive, не сбрасывающий память канала
|
||||
public
|
||||
@@ -54,8 +49,6 @@ type
|
||||
|
||||
property ActiveIdx: Integer read FActiveIdx write FActiveIdx;
|
||||
property OnActiveChanged: TChannelActiveEvent read FOnActiveChanged write FOnActiveChanged;
|
||||
property OnActivateXvtr: TChannelXvtrEvent read FOnActivateXvtr write FOnActivateXvtr;
|
||||
property OnDeactivateXvtr: TChannelNotifyEvent read FOnDeactivateXvtr write FOnDeactivateXvtr;
|
||||
end;
|
||||
|
||||
implementation
|
||||
@@ -107,6 +100,12 @@ procedure TChannelController.Apply(const Ch: TChannel);
|
||||
var
|
||||
i, NewBand, XvtrIdx: Integer;
|
||||
begin
|
||||
// Промежуточные retune внутри Apply (XVTR-выход → RestoreBand → SetVfoA на
|
||||
// СТАРУЮ частоту) фаерят OnAfterTune→OnVfoTuned; без этого гарда CheckActive
|
||||
// деактивировал бы канал прямо посреди его применения. Финальное состояние
|
||||
// (FActiveIdx + Ch.RXFreq) выставляем сами — оркестрация снаружи Apply.
|
||||
FApplying := True;
|
||||
try
|
||||
// Сохраняем текущее состояние до любых изменений
|
||||
FRadio.SaveCurrentBand;
|
||||
|
||||
@@ -125,15 +124,15 @@ begin
|
||||
if XvtrIdx >= 0 then
|
||||
begin
|
||||
// Канал на трансвертерном диапазоне — активируем XVTR если не активен
|
||||
if (FRadio.FCurrentXvtr <> XvtrIdx) and Assigned(FOnActivateXvtr) then
|
||||
FOnActivateXvtr(XvtrIdx);
|
||||
if FRadio.FCurrentXvtr <> XvtrIdx then
|
||||
FRadio.SetXvtrBand(XvtrIdx); // вход в слот + рендер/wideband/web (rfXvtr)
|
||||
end
|
||||
else
|
||||
begin
|
||||
// Канал на HF (или неизвестная частота). Если были на XVTR — выходим в HF,
|
||||
// иначе SetVfoA заклэмпит частоту.
|
||||
if (FRadio.FCurrentXvtr >= 0) and Assigned(FOnDeactivateXvtr) then
|
||||
FOnDeactivateXvtr;
|
||||
if FRadio.FCurrentXvtr >= 0 then
|
||||
FRadio.SetXvtrBand(-1); // выход в HF (DeactivateXvtr несёт HF-возврат)
|
||||
NewBand := FreqToBandIdx(Ch.RXFreq);
|
||||
if (NewBand >= 0) and (NewBand <> FRadio.FCurrentBand) then
|
||||
FRadio.SetCurrentBandIdx(NewBand); // band-индекс + drive-кал + рендер кнопок
|
||||
@@ -170,6 +169,9 @@ begin
|
||||
// Сохраняем итог в band/XVTR-кэш
|
||||
if (XvtrIdx >= 0) or (NewBand >= 0) then
|
||||
FRadio.SaveCurrentBand;
|
||||
finally
|
||||
FApplying := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TChannelController.CheckActive;
|
||||
@@ -217,6 +219,7 @@ procedure TChannelController.OnVfoTuned;
|
||||
// Без активного канала: сброс авто-CTCSS + восстановление pre-channel drive.
|
||||
// С активным каналом: CheckActive деактивирует при уходе с частоты канала.
|
||||
begin
|
||||
if FApplying then Exit; // промежуточные retune внутри Apply — не трогаем канал
|
||||
if FActiveIdx < 0 then
|
||||
begin
|
||||
if FRadio.FFMCTCSSAutoActive then
|
||||
|
||||
Reference in New Issue
Block a user