mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 17:27:32 +00:00
feat(dxcluster): споты на всех панадаптерах + кнопка DX в блоке RX
Подписи спотов рисовались только на главном пане. Теперь их видит каждый пан, в чьё окно попадает частота спота. Оверлей — ЭКЗЕМПЛЯР НА ПАН, а не один общий: кэш полосы подписей ключуется центром/спаном/шириной, а у панов они свои — общий оверлей пересобирался бы на каждый пан каждый кадр, то есть ровно то, ради чего кэш и заводился. Живёт в TPanafallPanel (AttachDXSpots/DetachDXSpots/DXOverlay, Owner=панель), база спотов по-прежнему одна на всех. FDXSpotOverlay в MainForm стал алиасом на оверлей пана 0 — как FSpecView для FPan.View: настройки, тема и тик затухания идут общим циклом по FPans, и главный пан перестал быть особым случаем (иначе тумблер DX гасил бы подписи только на нём). ★ Version стора глобальна, а окно у пана своё, поэтому в EnsureRendered на смену версии сначала берётся снимок окна и сверяется его подпись (FNV-1a по позывному, частоте, моде и метке времени). Совпала — ни пересборки битмапа, ни перезаливки GL-текстуры: спот, севший на чужой диапазон, до этого пана не доходит. Без этого цена пересборки множилась бы на число панов. Снимок берётся один раз и переиспользуется раскладкой — стор второй раз не дёргаем. Клик по подписи на пане N = QSY слайса ЭТОГО пана (активного, если он здесь, иначе первого; нет ни одного — создаём в точке) с модой по комментарию кластера и полосой пресета этой моды. Своего VFO у панов N нет, а ретюнить их DDC под спот нельзя — увезло бы весь пан. Мода спота → режим вынесена в общую DXSpotRadioMode для обоих путей. Низкий пан (грид): полоса подписей и штрихи пропускаются целиком — раньше в GL-пути полоса легла бы поверх спектра, а штрихи пошли бы снизу вверх. Кнопка DX переехала из тулбара в блок RX левой панели, сразу после CTUN (ряд стал четырёхколоночным: CTUN | DX | Channel | BEACON): споты — часть приёмного вида, а не глобальная команда уровня DISCOVER/START/SETUP. Заодно снят расчёт SafeLeft, резервировавший под неё место в шапке. Подписи по умолчанию ВЫКЛЮЧЕНЫ (show_spots: дефолт и фолбэк чтения были True), состояние переживает перезапуск. Клик по кнопке подливает состояние в открытый SETUP: там своя копия конфига, и первая же правка любого поля страницы вернула бы подписи обратно. fix: Stop клиента кластера больше не держит главный поток. Он делал Terminate + WaitFor, а поток в этот момент сидит в блокирующем recv и просыпается лишь по своему кванту (до 1 с), на застрявшем send — до SO_SNDTIMEO. Всё это время окно висело на выходе и на переподключении после правки настроек. Теперь Stop рвёт живой сокет SockShutdown (хэндл — зеркало под тем же локом, поток снимает его ДО close, поэтому shutdown по закрытому fd невозможен), а FormDestroy зовёт неблокирующий RequestStop первой строкой: поток доживает параллельно с разборкой радио, и join в конце уже никого не ждёт. Сборка ewsdr (--ws=qt6) и ewsdrd — ОК. На железе не проверено: доп. паны требуют подключённого радио. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -35,6 +35,7 @@ uses
|
||||
LCLIntf, LCLType,
|
||||
OpenGLContextEx,
|
||||
AppTheme, WDSPEngine, RadioController, DMRDecoder, VfoOverlay,
|
||||
DXSpotStore, DXSpotOverlay,
|
||||
SpectrumView, SpectrumViewOpengl, PanZoomBar, FlatButton, DpiUtils;
|
||||
|
||||
type
|
||||
@@ -83,6 +84,10 @@ type
|
||||
FSliceFlags: array of TVfoOverlay; // флаги B+ (Owner=Self)
|
||||
FActiveFlag: TVfoOverlay; // чьё событие сейчас обрабатывается
|
||||
FPendingSliceClose: Integer; // SliceId к удалению после мыши (0=нет)
|
||||
// Подписи DX-спотов на спектре ЭТОГО пана. Экземпляр свой на каждый пан:
|
||||
// кэш полосы подписей ключуется центром/спаном/шириной, а у панов они свои
|
||||
// — общий оверлей пересобирался бы на каждый пан каждый кадр.
|
||||
FDXOverlay: TDXSpotOverlay; // Owner=Self, база спотов общая
|
||||
FMainFlagPinned: Boolean; // True = левая панель хозяина скрыта
|
||||
FMainFlagForced: Boolean; // True = есть доп. панадаптеры
|
||||
FLastSliceMeterMs: QWord; // троттлинг S-метра слайсов (~10 Гц)
|
||||
@@ -268,6 +273,14 @@ type
|
||||
// полный пересчёт (у него wideband/S-метр/оверлеи).
|
||||
property OnSplitterMoved: TNotifyEvent read FOnSplitterMoved write FOnSplitterMoved;
|
||||
|
||||
// ---- Подписи DX-спотов ----
|
||||
// Своя копия оверлея на пан; база спотов (стор) — общая, её владелец хозяин.
|
||||
// Вид (центр/спан) пана заливает хозяин, как и прочие параметры вьюхи.
|
||||
procedure AttachDXSpots(AStore: TDXSpotStore);
|
||||
// Отвязать от базы (хозяин освобождает стор раньше панов).
|
||||
procedure DetachDXSpots;
|
||||
property DXOverlay: TDXSpotOverlay read FDXOverlay;
|
||||
|
||||
// ---- Флаги слайсов ----
|
||||
// Главный флаг (слайс A) создаёт хозяин (проводка событий у него) и отдаёт
|
||||
// сюда; панель подключает его к view и включает в раскладку/диспетчер.
|
||||
@@ -1108,6 +1121,21 @@ begin
|
||||
FView.VfoOverlay := O;
|
||||
end;
|
||||
|
||||
procedure TPanafallPanel.AttachDXSpots(AStore: TDXSpotStore);
|
||||
begin
|
||||
if FDXOverlay = nil then
|
||||
begin
|
||||
FDXOverlay := TDXSpotOverlay.Create(Self);
|
||||
FView.DXSpotOverlay := FDXOverlay;
|
||||
end;
|
||||
FDXOverlay.Attach(AStore);
|
||||
end;
|
||||
|
||||
procedure TPanafallPanel.DetachDXSpots;
|
||||
begin
|
||||
if FDXOverlay <> nil then FDXOverlay.Attach(nil);
|
||||
end;
|
||||
|
||||
function TPanafallPanel.CurSliceId: Integer;
|
||||
begin
|
||||
if Assigned(FActiveFlag) then Result := FActiveFlag.SliceId else Result := 0;
|
||||
|
||||
Reference in New Issue
Block a user