mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
Prevent OS sleep and display blanking while SDR is running
Add PowerInhibit.pas with InhibitSleep/UninhibitSleep: - Windows: SetThreadExecutionState (kernel32, no child process) - macOS: caffeinate -d -i -s -w <PID> (auto-exits on crash via -w flag) - Linux: systemd-inhibit with kill-0 poll loop (releases within 5s on crash) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+7
-1
@@ -39,7 +39,8 @@ uses
|
|||||||
WinFirewall,
|
WinFirewall,
|
||||||
BoardUtils, WisdomBuilder, UISync,
|
BoardUtils, WisdomBuilder, UISync,
|
||||||
FlatEdit, FMRepeater,
|
FlatEdit, FMRepeater,
|
||||||
ChannelStore, ChannelsForm;
|
ChannelStore, ChannelsForm,
|
||||||
|
PowerInhibit;
|
||||||
|
|
||||||
const
|
const
|
||||||
CLR_BG = TColor($00101010);
|
CLR_BG = TColor($00101010);
|
||||||
@@ -1464,6 +1465,7 @@ begin
|
|||||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), 0, False, True, True);
|
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), 0, False, True, True);
|
||||||
FNetwork.SetRunAndFreq(False, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), 0);
|
FNetwork.SetRunAndFreq(False, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), 0);
|
||||||
FRunning := False;
|
FRunning := False;
|
||||||
|
UninhibitSleep;
|
||||||
FTransmitting := False;
|
FTransmitting := False;
|
||||||
if FWDSPReady then FDSPEngine.SetTXRun(False);
|
if FWDSPReady then FDSPEngine.SetTXRun(False);
|
||||||
end;
|
end;
|
||||||
@@ -3046,6 +3048,7 @@ begin
|
|||||||
BtnStartStop.Caption := 'START';
|
BtnStartStop.Caption := 'START';
|
||||||
StyleButton(BtnStartStop, False);
|
StyleButton(BtnStartStop, False);
|
||||||
FRunning := False;
|
FRunning := False;
|
||||||
|
UninhibitSleep;
|
||||||
FNetwork.SetRunAndFreq(False, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), 0);
|
FNetwork.SetRunAndFreq(False, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), 0);
|
||||||
SetRadioOfflineStatus('Hardware timeout');
|
SetRadioOfflineStatus('Hardware timeout');
|
||||||
BtnMOX.Enabled := False;
|
BtnMOX.Enabled := False;
|
||||||
@@ -3057,6 +3060,7 @@ begin
|
|||||||
BtnStartStop.Caption := 'START';
|
BtnStartStop.Caption := 'START';
|
||||||
StyleButton(BtnStartStop, False);
|
StyleButton(BtnStartStop, False);
|
||||||
FRunning := False;
|
FRunning := False;
|
||||||
|
UninhibitSleep;
|
||||||
FNetwork.SetRunAndFreq(False, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), 0);
|
FNetwork.SetRunAndFreq(False, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), 0);
|
||||||
SetRadioOfflineStatus('Connection lost');
|
SetRadioOfflineStatus('Connection lost');
|
||||||
BtnMOX.Enabled := False;
|
BtnMOX.Enabled := False;
|
||||||
@@ -3897,6 +3901,7 @@ begin
|
|||||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), 0, False, True, True);
|
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), 0, False, True, True);
|
||||||
FNetwork.SetRunAndFreq(False, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), 0);
|
FNetwork.SetRunAndFreq(False, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), 0);
|
||||||
FRunning := False;
|
FRunning := False;
|
||||||
|
UninhibitSleep;
|
||||||
FTransmitting := False;
|
FTransmitting := False;
|
||||||
if FWDSPReady then FDSPEngine.SetTXRun(False);
|
if FWDSPReady then FDSPEngine.SetTXRun(False);
|
||||||
StyleButton(BtnMOX, False);
|
StyleButton(BtnMOX, False);
|
||||||
@@ -4220,6 +4225,7 @@ begin
|
|||||||
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), FDriveLevel, False, True, True);
|
FNetwork.UpdateState(XvtrTranslate(FCenterFreq), XvtrTranslate(ActiveTXFreqHz), FDriveLevel, False, True, True);
|
||||||
FNetwork.SetRunAndFreq(True, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), FDriveLevel);
|
FNetwork.SetRunAndFreq(True, XvtrTranslate(FCenterFreq), XvtrTranslate(FCenterFreq), FDriveLevel);
|
||||||
FRunning := True;
|
FRunning := True;
|
||||||
|
InhibitSleep;
|
||||||
FRXStartTime := GetTickCount64;
|
FRXStartTime := GetTickCount64;
|
||||||
FRXLastPktTime := 0;
|
FRXLastPktTime := 0;
|
||||||
FRXPacketCount := 0;
|
FRXPacketCount := 0;
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
unit PowerInhibit;
|
||||||
|
|
||||||
|
{$IFDEF FPC}
|
||||||
|
{$MODE Delphi}
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
{
|
||||||
|
Prevents OS idle sleep and display blanking while the SDR is running.
|
||||||
|
|
||||||
|
Windows : SetThreadExecutionState (kernel32) — one call, no child process.
|
||||||
|
macOS : spawns /usr/bin/caffeinate -d -i -s -w <OurPID>
|
||||||
|
caffeinate exits automatically when our process exits (crash-safe).
|
||||||
|
Linux : spawns systemd-inhibit in --mode=block with a shell loop that
|
||||||
|
polls kill -0 <OurPID> so the inhibitor is released within
|
||||||
|
~5 s even on a crash (no orphan leak).
|
||||||
|
}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
procedure InhibitSleep;
|
||||||
|
procedure UninhibitSleep;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
uses
|
||||||
|
SysUtils, Process
|
||||||
|
{$IFDEF WINDOWS}, Windows{$ENDIF};
|
||||||
|
|
||||||
|
{$IFDEF WINDOWS}
|
||||||
|
type
|
||||||
|
EXECUTION_STATE = DWORD;
|
||||||
|
const
|
||||||
|
ES_CONTINUOUS = DWORD($80000000);
|
||||||
|
ES_SYSTEM_REQUIRED = DWORD($00000001);
|
||||||
|
ES_DISPLAY_REQUIRED = DWORD($00000002);
|
||||||
|
function SetThreadExecutionState(esFlags: EXECUTION_STATE): EXECUTION_STATE; stdcall;
|
||||||
|
external 'kernel32.dll' name 'SetThreadExecutionState';
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
var
|
||||||
|
FInhibitProc: TProcess = nil;
|
||||||
|
|
||||||
|
procedure InhibitSleep;
|
||||||
|
{$IF DEFINED(DARWIN) OR DEFINED(LINUX)}
|
||||||
|
var
|
||||||
|
PidStr: string;
|
||||||
|
{$ENDIF}
|
||||||
|
begin
|
||||||
|
{$IFDEF WINDOWS}
|
||||||
|
SetThreadExecutionState(ES_CONTINUOUS or ES_SYSTEM_REQUIRED or ES_DISPLAY_REQUIRED);
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
{$IF DEFINED(DARWIN) OR DEFINED(LINUX)}
|
||||||
|
if FInhibitProc <> nil then Exit;
|
||||||
|
PidStr := IntToStr(GetProcessID);
|
||||||
|
FInhibitProc := TProcess.Create(nil);
|
||||||
|
try
|
||||||
|
{$IFDEF DARWIN}
|
||||||
|
FInhibitProc.Executable := '/usr/bin/caffeinate';
|
||||||
|
FInhibitProc.Parameters.Add('-d'); // prevent display sleep
|
||||||
|
FInhibitProc.Parameters.Add('-i'); // prevent idle sleep
|
||||||
|
FInhibitProc.Parameters.Add('-s'); // prevent system sleep (AC power)
|
||||||
|
FInhibitProc.Parameters.Add('-w'); // watch our PID — caffeinate auto-exits with us
|
||||||
|
FInhibitProc.Parameters.Add(PidStr);
|
||||||
|
{$ENDIF}
|
||||||
|
{$IFDEF LINUX}
|
||||||
|
// systemd-inhibit holds the lock until the sh loop exits.
|
||||||
|
// The loop polls kill -0 <PID> every 5 s, so if we crash the
|
||||||
|
// inhibitor is released within 5 s (no orphan process leak).
|
||||||
|
FInhibitProc.Executable := 'systemd-inhibit';
|
||||||
|
FInhibitProc.Parameters.Add('--what=idle:sleep:handle-lid-switch');
|
||||||
|
FInhibitProc.Parameters.Add('--why=SDR running');
|
||||||
|
FInhibitProc.Parameters.Add('--who=ewsdr');
|
||||||
|
FInhibitProc.Parameters.Add('--mode=block');
|
||||||
|
FInhibitProc.Parameters.Add('sh');
|
||||||
|
FInhibitProc.Parameters.Add('-c');
|
||||||
|
FInhibitProc.Parameters.Add('while kill -0 ' + PidStr + ' 2>/dev/null; do sleep 5; done');
|
||||||
|
{$ENDIF}
|
||||||
|
FInhibitProc.Options := [poNoConsole];
|
||||||
|
FInhibitProc.Execute;
|
||||||
|
except
|
||||||
|
FreeAndNil(FInhibitProc);
|
||||||
|
end;
|
||||||
|
{$ENDIF}
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure UninhibitSleep;
|
||||||
|
begin
|
||||||
|
{$IFDEF WINDOWS}
|
||||||
|
SetThreadExecutionState(ES_CONTINUOUS);
|
||||||
|
{$ENDIF}
|
||||||
|
|
||||||
|
{$IF DEFINED(DARWIN) OR DEFINED(LINUX)}
|
||||||
|
if FInhibitProc <> nil then
|
||||||
|
begin
|
||||||
|
if FInhibitProc.Running then
|
||||||
|
FInhibitProc.Terminate(0);
|
||||||
|
FreeAndNil(FInhibitProc);
|
||||||
|
end;
|
||||||
|
{$ENDIF}
|
||||||
|
end;
|
||||||
|
|
||||||
|
initialization
|
||||||
|
FInhibitProc := nil;
|
||||||
|
|
||||||
|
finalization
|
||||||
|
UninhibitSleep;
|
||||||
|
|
||||||
|
end.
|
||||||
@@ -229,6 +229,10 @@
|
|||||||
<Filename Value="PlatformUtils.pas"/>
|
<Filename Value="PlatformUtils.pas"/>
|
||||||
<IsPartOfProject Value="True"/>
|
<IsPartOfProject Value="True"/>
|
||||||
</Unit>
|
</Unit>
|
||||||
|
<Unit>
|
||||||
|
<Filename Value="PowerInhibit.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
</Unit>
|
||||||
<Unit>
|
<Unit>
|
||||||
<Filename Value="BoardUtils.pas"/>
|
<Filename Value="BoardUtils.pas"/>
|
||||||
<IsPartOfProject Value="True"/>
|
<IsPartOfProject Value="True"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user