mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:27:33 +00:00
feat(dmr): show stable status on receiver slices
This commit is contained in:
+79
-2
@@ -79,6 +79,11 @@ type
|
||||
FTxSel: Boolean; // этот слайс выбран для передачи (янтарный)
|
||||
FSlice: Char; // буква слайса ('A')
|
||||
FSMeterThreshold: Double; // мин. изменение S-метра (дБ) для перерисовки
|
||||
FDMRText: string; // стабильный краткий статус рядом с полосой
|
||||
FDMRSynced: Boolean;
|
||||
FDMRCandidateText: string; // debounce: не мигать на кратком sync-loss
|
||||
FDMRCandidateSynced: Boolean;
|
||||
FDMRCandidateSince: QWord;
|
||||
|
||||
FDevNames: TStringList; // имена устройств вывода
|
||||
FDevIdx: array of Integer; // соответствующие PortAudio-индексы (-1=default)
|
||||
@@ -182,6 +187,7 @@ type
|
||||
const CurName: string);
|
||||
procedure UpdateSMeter(DB: Double);
|
||||
procedure UpdateVfo(AVfoHz: Double);
|
||||
procedure UpdateDMRStatus(const AText: string; Synced: Boolean);
|
||||
// Тема приложения (цвета кнопок берутся отсюда — как левая панель).
|
||||
procedure SetTheme(const T: TAppTheme);
|
||||
// Привязка к слайсу: id, буква флага, признак главного (слайс A).
|
||||
@@ -450,6 +456,9 @@ begin
|
||||
FSQLOn := False; FSQLLevel := 40; FSqlDrag := False;
|
||||
FVolume := 70; FMuted := False; FSplit := False; FTx := False;
|
||||
FTxSel := True; FSlice := 'A';
|
||||
FDMRText := ''; FDMRSynced := False;
|
||||
FDMRCandidateText := ''; FDMRCandidateSynced := False;
|
||||
FDMRCandidateSince := 0;
|
||||
FSliceId := 0; FIsMain := True; // по умолчанию — главный приёмник (слайс A)
|
||||
FSMeterThreshold := 0.4; // главный флаг — чувствительный метр
|
||||
FPanel := fpNone;
|
||||
@@ -977,8 +986,8 @@ end;
|
||||
|
||||
procedure TVfoOverlay.DrawSelf(C: TCanvas; W, H: Integer);
|
||||
var
|
||||
FreqStr, SStr, BWStr: string;
|
||||
CurY, X, RW, i: Integer;
|
||||
FreqStr, SStr, BWStr, DMRStr: string;
|
||||
CurY, X, RW, i, DMRX, DMRRight: Integer;
|
||||
R: TRect;
|
||||
BarL, BarW, MeterX: Integer;
|
||||
begin
|
||||
@@ -1013,6 +1022,21 @@ begin
|
||||
C.Font.Name := 'Courier New'; C.Font.Size := 8; C.Font.Style := [];
|
||||
C.Font.Color := CLR_DIM; C.Brush.Style := bsClear;
|
||||
C.TextOut(X + 22, CurY + 1, BWStr);
|
||||
// Краткий статус дополнительного DMR-слайса. Он обновляется только при
|
||||
// устойчивом изменении sync/slot/CC/TG, поэтому не заставляет GL-текстуру
|
||||
// перезаливаться на каждом burst.
|
||||
if (not FIsMain) and (FMode = 11) and (FDMRText <> '') then
|
||||
begin
|
||||
DMRStr := FDMRText;
|
||||
DMRX := X + 22 + C.TextWidth(BWStr) + 8;
|
||||
DMRRight := W - PAD - 26 - 6 - 14 - 5; // до кнопок × и TX
|
||||
while (Length(DMRStr) > 1) and
|
||||
(C.TextWidth(DMRStr) > DMRRight - DMRX) do
|
||||
SetLength(DMRStr, Length(DMRStr) - 1);
|
||||
if FDMRSynced then C.Font.Color := CLR_ACCENT
|
||||
else C.Font.Color := CLR_SVAL;
|
||||
C.TextOut(DMRX, CurY + 1, DMRStr);
|
||||
end;
|
||||
// TX badge: a DMR slice is visibly disabled and has no hit target.
|
||||
R := Rect(W - PAD - 26, CurY, W - PAD, CurY + HDR_BADGE_H);
|
||||
if not TxSelectionAllowed then
|
||||
@@ -1405,12 +1429,29 @@ end;
|
||||
{ ---- Обновление состояния из контроллера ---- }
|
||||
|
||||
procedure TVfoOverlay.SetState(AMode, ABW: Integer; AVfoHz, ASMeterDB: Double);
|
||||
var
|
||||
OldMode: Integer;
|
||||
begin
|
||||
OldMode := FMode;
|
||||
FMode := Max(0, Min(OVL_MODE_COUNT - 1, AMode));
|
||||
FFilterBW := ABW;
|
||||
FModeFilter[FMode] := ABW;
|
||||
FVfoHz := AVfoHz;
|
||||
FSMeterDB := ASMeterDB;
|
||||
if FMode <> 11 then
|
||||
begin
|
||||
FDMRText := '';
|
||||
FDMRSynced := False;
|
||||
FDMRCandidateText := '';
|
||||
FDMRCandidateSince := 0;
|
||||
end
|
||||
else if OldMode <> 11 then
|
||||
begin
|
||||
FDMRText := 'DMR...';
|
||||
FDMRSynced := False;
|
||||
FDMRCandidateText := '';
|
||||
FDMRCandidateSince := 0;
|
||||
end;
|
||||
Height := ComputeHeight;
|
||||
RequestInvalidate;
|
||||
end;
|
||||
@@ -1487,4 +1528,40 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TVfoOverlay.UpdateDMRStatus(const AText: string; Synced: Boolean);
|
||||
var
|
||||
NowTick, HoldMs: QWord;
|
||||
begin
|
||||
if FMode <> 11 then Exit;
|
||||
if (FDMRText = AText) and (FDMRSynced = Synced) then
|
||||
begin
|
||||
FDMRCandidateText := '';
|
||||
FDMRCandidateSince := 0;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
NowTick := GetTickCount64;
|
||||
if (FDMRCandidateText <> AText) or
|
||||
(FDMRCandidateSynced <> Synced) then
|
||||
begin
|
||||
FDMRCandidateText := AText;
|
||||
FDMRCandidateSynced := Synced;
|
||||
FDMRCandidateSince := NowTick;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
// Потерю уже показанной синхронизации держим дольше, чем появление/смену
|
||||
// параметров вызова: короткие замирания не должны мигать в шапке слайса.
|
||||
if FDMRSynced and not Synced then HoldMs := 1200
|
||||
else if FDMRSynced and Synced then HoldMs := 750
|
||||
else HoldMs := 250;
|
||||
if NowTick - FDMRCandidateSince < HoldMs then Exit;
|
||||
|
||||
FDMRText := AText;
|
||||
FDMRSynced := Synced;
|
||||
FDMRCandidateText := '';
|
||||
FDMRCandidateSince := 0;
|
||||
RequestInvalidate;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
Reference in New Issue
Block a user