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 caffeinate exits automatically when our process exits (crash-safe). Linux : spawns systemd-inhibit in --mode=block with a shell loop that polls kill -0 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 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.