mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
Fix window geometry scaling and close deadlock
This commit is contained in:
+14
-61
@@ -319,55 +319,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
// ===========================================================================
|
|
||||||
// Синхронизация через отдельные классы-посредники (без анонимных процедур)
|
|
||||||
// ===========================================================================
|
|
||||||
|
|
||||||
type
|
|
||||||
{ TStatusSync - передаёт HP Status в главный поток }
|
|
||||||
TStatusSync = class
|
|
||||||
private
|
|
||||||
FCallback: TOnHPStatus;
|
|
||||||
FStatus: THighPriorityStatus;
|
|
||||||
public
|
|
||||||
constructor Create(CB: TOnHPStatus; const St: THighPriorityStatus);
|
|
||||||
procedure Execute;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ TMicSync - передаёт Mic данные в главный поток }
|
|
||||||
TMicSync = class
|
|
||||||
private
|
|
||||||
FCallback: TOnMicPacket;
|
|
||||||
FPkt: TMicDataPacket;
|
|
||||||
public
|
|
||||||
constructor Create(CB: TOnMicPacket; const P: TMicDataPacket);
|
|
||||||
procedure Execute;
|
|
||||||
end;
|
|
||||||
|
|
||||||
constructor TStatusSync.Create(CB: TOnHPStatus; const St: THighPriorityStatus);
|
|
||||||
begin
|
|
||||||
inherited Create;
|
|
||||||
FCallback := CB;
|
|
||||||
FStatus := St;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TStatusSync.Execute;
|
|
||||||
begin
|
|
||||||
if Assigned(FCallback) then FCallback(FStatus);
|
|
||||||
end;
|
|
||||||
|
|
||||||
constructor TMicSync.Create(CB: TOnMicPacket; const P: TMicDataPacket);
|
|
||||||
begin
|
|
||||||
inherited Create;
|
|
||||||
FCallback := CB;
|
|
||||||
FPkt := P;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TMicSync.Execute;
|
|
||||||
begin
|
|
||||||
if Assigned(FCallback) then FCallback(FPkt);
|
|
||||||
end;
|
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
// Receive thread
|
// Receive thread
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
@@ -994,12 +945,22 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure THPSDRNetwork.StopThreads;
|
procedure THPSDRNetwork.StopThreads;
|
||||||
|
procedure WaitThreadDone(T: TThread);
|
||||||
|
begin
|
||||||
|
if T = nil then Exit;
|
||||||
|
if GetCurrentThreadId = MainThreadID then
|
||||||
|
begin
|
||||||
|
while not T.Finished do
|
||||||
|
CheckSynchronize(10);
|
||||||
|
end;
|
||||||
|
T.WaitFor;
|
||||||
|
end;
|
||||||
begin
|
begin
|
||||||
if Assigned(FDUCIQThread) then
|
if Assigned(FDUCIQThread) then
|
||||||
begin
|
begin
|
||||||
FDUCIQThread.Terminate;
|
FDUCIQThread.Terminate;
|
||||||
RTLEventSetEvent(FDUCIQSem);
|
RTLEventSetEvent(FDUCIQSem);
|
||||||
FDUCIQThread.WaitFor;
|
WaitThreadDone(FDUCIQThread);
|
||||||
FreeAndNil(FDUCIQThread);
|
FreeAndNil(FDUCIQThread);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -1011,13 +972,13 @@ begin
|
|||||||
CloseSocket(FSocket);
|
CloseSocket(FSocket);
|
||||||
FSocket := SOCK_INVALID;
|
FSocket := SOCK_INVALID;
|
||||||
end;
|
end;
|
||||||
FReceiveThread.WaitFor;
|
WaitThreadDone(FReceiveThread);
|
||||||
FreeAndNil(FReceiveThread);
|
FreeAndNil(FReceiveThread);
|
||||||
end;
|
end;
|
||||||
if Assigned(FKeepaliveThread) then
|
if Assigned(FKeepaliveThread) then
|
||||||
begin
|
begin
|
||||||
FKeepaliveThread.Terminate;
|
FKeepaliveThread.Terminate;
|
||||||
FKeepaliveThread.WaitFor;
|
WaitThreadDone(FKeepaliveThread);
|
||||||
FreeAndNil(FKeepaliveThread);
|
FreeAndNil(FKeepaliveThread);
|
||||||
end;
|
end;
|
||||||
ResetDUCIQQueue;
|
ResetDUCIQQueue;
|
||||||
@@ -1033,18 +994,10 @@ end;
|
|||||||
procedure THPSDRNetwork.HandleHPStatus(const Buf: array of Byte; Len: Integer);
|
procedure THPSDRNetwork.HandleHPStatus(const Buf: array of Byte; Len: Integer);
|
||||||
var
|
var
|
||||||
St: THighPriorityStatus;
|
St: THighPriorityStatus;
|
||||||
Sync: TStatusSync;
|
|
||||||
M: TThreadMethod;
|
|
||||||
begin
|
begin
|
||||||
if not Assigned(FOnHPStatus) then Exit;
|
if not Assigned(FOnHPStatus) then Exit;
|
||||||
Move(Buf[0], St, SizeOf(St));
|
Move(Buf[0], St, SizeOf(St));
|
||||||
Sync := TStatusSync.Create(FOnHPStatus, St);
|
FOnHPStatus(St);
|
||||||
try
|
|
||||||
M := Sync.Execute;
|
|
||||||
TThread.Synchronize(nil, M);
|
|
||||||
finally
|
|
||||||
Sync.Free;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure THPSDRNetwork.HandleDDCIQ(const Buf: array of Byte; Len: Integer;
|
procedure THPSDRNetwork.HandleDDCIQ(const Buf: array of Byte; Len: Integer;
|
||||||
|
|||||||
+54
-7
@@ -492,6 +492,7 @@ type
|
|||||||
procedure RestoreBand(BandIdx: Integer);
|
procedure RestoreBand(BandIdx: Integer);
|
||||||
procedure SaveAllAndExit;
|
procedure SaveAllAndExit;
|
||||||
procedure RestoreWindowBounds;
|
procedure RestoreWindowBounds;
|
||||||
|
procedure SaveWindowBounds;
|
||||||
function MakeGlobalSettings: TGlobalSettings;
|
function MakeGlobalSettings: TGlobalSettings;
|
||||||
function MakeBandSettings: TBandSettings;
|
function MakeBandSettings: TBandSettings;
|
||||||
procedure FreqDispBChanged(Sender: TObject; NewFreq: Int64);
|
procedure FreqDispBChanged(Sender: TObject; NewFreq: Int64);
|
||||||
@@ -924,16 +925,62 @@ end;
|
|||||||
|
|
||||||
procedure TMainForm.RestoreWindowBounds;
|
procedure TMainForm.RestoreWindowBounds;
|
||||||
var
|
var
|
||||||
L, T, Wd, Ht: Integer;
|
L, T, Wd, Ht, SavedDPI, CurDPI: Integer;
|
||||||
|
R, WA: TRect;
|
||||||
|
Mon: TMonitor;
|
||||||
begin
|
begin
|
||||||
FSettings.LoadWindowBounds(L, T, Wd, Ht);
|
FSettings.LoadWindowBounds(L, T, Wd, Ht, SavedDPI);
|
||||||
if (Wd > 400) and (Ht > 300) then
|
if (Wd > 400) and (Ht > 300) then
|
||||||
begin
|
begin
|
||||||
Left := L;
|
CurDPI := PixelsPerInch;
|
||||||
Top := T;
|
if CurDPI <= 0 then CurDPI := Screen.PixelsPerInch;
|
||||||
Width := Wd;
|
if CurDPI <= 0 then CurDPI := 96;
|
||||||
Height := Ht;
|
if SavedDPI <= 0 then SavedDPI := CurDPI;
|
||||||
|
|
||||||
|
if SavedDPI <> CurDPI then
|
||||||
|
begin
|
||||||
|
L := MulDiv(L, CurDPI, SavedDPI);
|
||||||
|
T := MulDiv(T, CurDPI, SavedDPI);
|
||||||
|
Wd := MulDiv(Wd, CurDPI, SavedDPI);
|
||||||
|
Ht := MulDiv(Ht, CurDPI, SavedDPI);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Wd := Max(MulDiv(900, CurDPI, 96), Wd);
|
||||||
|
Ht := Max(MulDiv(560, CurDPI, 96), Ht);
|
||||||
|
R := Bounds(L, T, Wd, Ht);
|
||||||
|
Mon := Screen.MonitorFromRect(R);
|
||||||
|
if Mon <> nil then WA := Mon.WorkareaRect
|
||||||
|
else WA := Screen.PrimaryMonitor.WorkareaRect;
|
||||||
|
|
||||||
|
if Wd > WA.Right - WA.Left then Wd := WA.Right - WA.Left;
|
||||||
|
if Ht > WA.Bottom - WA.Top then Ht := WA.Bottom - WA.Top;
|
||||||
|
L := EnsureRange(L, WA.Left, Max(WA.Left, WA.Right - Wd));
|
||||||
|
T := EnsureRange(T, WA.Top, Max(WA.Top, WA.Bottom - Ht));
|
||||||
|
|
||||||
|
Position := poDesigned;
|
||||||
|
SetBounds(L, T, Wd, Ht);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMainForm.SaveWindowBounds;
|
||||||
|
var
|
||||||
|
L, T, Wd, Ht, DPI: Integer;
|
||||||
|
begin
|
||||||
|
if WindowState = wsNormal then
|
||||||
|
begin
|
||||||
|
L := Left; T := Top; Wd := Width; Ht := Height;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
L := RestoredLeft; T := RestoredTop;
|
||||||
|
Wd := RestoredWidth; Ht := RestoredHeight;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (Wd <= 400) or (Ht <= 300) then Exit;
|
||||||
|
DPI := PixelsPerInch;
|
||||||
|
if DPI <= 0 then DPI := Screen.PixelsPerInch;
|
||||||
|
if DPI <= 0 then DPI := 96;
|
||||||
|
FSettings.SaveWindowBounds(L, T, Wd, Ht, DPI);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TMainForm.MakeBandSettings: TBandSettings;
|
function TMainForm.MakeBandSettings: TBandSettings;
|
||||||
@@ -1447,7 +1494,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
// Размер окна сохраняем всегда (не зависит от подключения)
|
// Размер окна сохраняем всегда (не зависит от подключения)
|
||||||
FSettings.SaveStartupPreview(FVfoA, FVfoB, FSampleRate);
|
FSettings.SaveStartupPreview(FVfoA, FVfoB, FSampleRate);
|
||||||
FSettings.SaveWindowBounds(Left, Top, Width, Height);
|
SaveWindowBounds;
|
||||||
FSettings.Save;
|
FSettings.Save;
|
||||||
FSettings.Free;
|
FSettings.Free;
|
||||||
FWebServer.Stop;
|
FWebServer.Stop;
|
||||||
|
|||||||
+7
-5
@@ -282,8 +282,8 @@ type
|
|||||||
class procedure DefaultGlobal(out G: TGlobalSettings);
|
class procedure DefaultGlobal(out G: TGlobalSettings);
|
||||||
class procedure DefaultTX(out T: TTXSettings);
|
class procedure DefaultTX(out T: TTXSettings);
|
||||||
// Размер окна — не привязан к MAC, хранится в корне JSON
|
// Размер окна — не привязан к MAC, хранится в корне JSON
|
||||||
procedure SaveWindowBounds(L, T, W, H: Integer);
|
procedure SaveWindowBounds(L, T, W, H, DPI: Integer);
|
||||||
procedure LoadWindowBounds(out L, T, W, H: Integer);
|
procedure LoadWindowBounds(out L, T, W, H, DPI: Integer);
|
||||||
procedure SaveStartupPreview(VfoA, VfoB: Double; SampleRate: Integer);
|
procedure SaveStartupPreview(VfoA, VfoB: Double; SampleRate: Integer);
|
||||||
function LoadStartupPreview(out VfoA, VfoB: Double; out SampleRate: Integer): Boolean;
|
function LoadStartupPreview(out VfoA, VfoB: Double; out SampleRate: Integer): Boolean;
|
||||||
procedure SaveAudioBufferSize(BufferSize: Integer);
|
procedure SaveAudioBufferSize(BufferSize: Integer);
|
||||||
@@ -757,7 +757,7 @@ begin
|
|||||||
B.FMStepIdx := EnsureRange(JI(O,'fmstep_idx', B.FMStepIdx), 0, 3);
|
B.FMStepIdx := EnsureRange(JI(O,'fmstep_idx', B.FMStepIdx), 0, 3);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSettingsManager.SaveWindowBounds(L, T, W, H: Integer);
|
procedure TSettingsManager.SaveWindowBounds(L, T, W, H, DPI: Integer);
|
||||||
var O: TJSONObject;
|
var O: TJSONObject;
|
||||||
begin
|
begin
|
||||||
O := EnsureObj(FRoot, 'window');
|
O := EnsureObj(FRoot, 'window');
|
||||||
@@ -765,18 +765,20 @@ begin
|
|||||||
JW(O, 'top', T);
|
JW(O, 'top', T);
|
||||||
JW(O, 'width', W);
|
JW(O, 'width', W);
|
||||||
JW(O, 'height', H);
|
JW(O, 'height', H);
|
||||||
|
JW(O, 'dpi', DPI);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSettingsManager.LoadWindowBounds(out L, T, W, H: Integer);
|
procedure TSettingsManager.LoadWindowBounds(out L, T, W, H, DPI: Integer);
|
||||||
var O: TJSONObject;
|
var O: TJSONObject;
|
||||||
begin
|
begin
|
||||||
L := 80; T := 80; W := 1400; H := 900;
|
L := 80; T := 80; W := 1400; H := 900; DPI := 0;
|
||||||
if FRoot.Find('window') = nil then Exit;
|
if FRoot.Find('window') = nil then Exit;
|
||||||
O := EnsureObj(FRoot, 'window');
|
O := EnsureObj(FRoot, 'window');
|
||||||
L := JI(O, 'left', 80);
|
L := JI(O, 'left', 80);
|
||||||
T := JI(O, 'top', 80);
|
T := JI(O, 'top', 80);
|
||||||
W := JI(O, 'width', 1400);
|
W := JI(O, 'width', 1400);
|
||||||
H := JI(O, 'height', 900);
|
H := JI(O, 'height', 900);
|
||||||
|
DPI := JI(O, 'dpi', 0);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TSettingsManager.SaveStartupPreview(VfoA, VfoB: Double; SampleRate: Integer);
|
procedure TSettingsManager.SaveStartupPreview(VfoA, VfoB: Double; SampleRate: Integer);
|
||||||
|
|||||||
Reference in New Issue
Block a user