From cfb4a33b6eb05db67406010299dfb883de9b60ed Mon Sep 17 00:00:00 2001 From: sr55 Date: Fri, 5 Jul 2019 23:11:04 +0100 Subject: WinGui: Build out code for active monitoring of storage and battery power on the system. (Similar to what the LinUI does) - Automatic pause on "Low" or "Critical" battery alarms. The % level is set in Windows power settings. Automatic Resume when AC returns, if it was paused by an alarm. - Automatic encode pause when destination drive drops below 2GB. (May make this a preference set later) - Behaviour of pause queue on low disk space with a user defined level in preferences is unchanged. #2109 #2181 --- .../Services/Encode/Interfaces/IEncode.cs | 6 + win/CS/HandBrakeWPF/Services/Encode/LibEncode.cs | 11 ++ .../Services/Interfaces/ISystemService.cs | 16 +++ win/CS/HandBrakeWPF/Services/Queue/QueueService.cs | 2 +- win/CS/HandBrakeWPF/Services/SystemService.cs | 143 +++++++++++++++++++++ 5 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 win/CS/HandBrakeWPF/Services/Interfaces/ISystemService.cs create mode 100644 win/CS/HandBrakeWPF/Services/SystemService.cs (limited to 'win/CS/HandBrakeWPF/Services') diff --git a/win/CS/HandBrakeWPF/Services/Encode/Interfaces/IEncode.cs b/win/CS/HandBrakeWPF/Services/Encode/Interfaces/IEncode.cs index 489f46925..871f31615 100644 --- a/win/CS/HandBrakeWPF/Services/Encode/Interfaces/IEncode.cs +++ b/win/CS/HandBrakeWPF/Services/Encode/Interfaces/IEncode.cs @@ -94,5 +94,11 @@ namespace HandBrakeWPF.Services.Encode.Interfaces /// Kill the process /// void Stop(); + + + /// + /// Get a copy of the Active job + /// + EncodeTask GetActiveJob(); } } \ No newline at end of file diff --git a/win/CS/HandBrakeWPF/Services/Encode/LibEncode.cs b/win/CS/HandBrakeWPF/Services/Encode/LibEncode.cs index 3b9e01280..f3ff75fcc 100644 --- a/win/CS/HandBrakeWPF/Services/Encode/LibEncode.cs +++ b/win/CS/HandBrakeWPF/Services/Encode/LibEncode.cs @@ -169,6 +169,17 @@ namespace HandBrakeWPF.Services.Encode } } + public EncodeTask GetActiveJob() + { + if (this.currentTask != null) + { + EncodeTask task = new EncodeTask(this.currentTask); // Decouple our current copy. + return task; + } + + return null; + } + #region HandBrakeInstance Event Handlers. /// diff --git a/win/CS/HandBrakeWPF/Services/Interfaces/ISystemService.cs b/win/CS/HandBrakeWPF/Services/Interfaces/ISystemService.cs new file mode 100644 index 000000000..79461a8ec --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/Interfaces/ISystemService.cs @@ -0,0 +1,16 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// +// +// Defines +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services.Interfaces +{ + public interface ISystemService + { + void Start(); + } +} \ No newline at end of file diff --git a/win/CS/HandBrakeWPF/Services/Queue/QueueService.cs b/win/CS/HandBrakeWPF/Services/Queue/QueueService.cs index 3d8af90b3..90c9d7ded 100644 --- a/win/CS/HandBrakeWPF/Services/Queue/QueueService.cs +++ b/win/CS/HandBrakeWPF/Services/Queue/QueueService.cs @@ -485,7 +485,7 @@ namespace HandBrakeWPF.Services.Queue QueueTask job = this.GetNextJobForProcessing(); if (job != null) { - if (this.userSettingService.GetUserSetting(UserSettingConstants.PauseOnLowDiskspace) && !DriveUtilities.HasMinimumDiskSpace(job.Task.Destination, this.userSettingService.GetUserSetting(UserSettingConstants.PauseOnLowDiskspaceLevel))) + if (this.userSettingService.GetUserSetting(UserSettingConstants.PauseOnLowDiskspace) && !DriveUtilities.HasMinimumDiskSpace(job.Task.Destination, this.userSettingService.GetUserSetting(UserSettingConstants.PauseQueueOnLowDiskspaceLevel))) { LogService.GetLogger().LogMessage(Resources.PauseOnLowDiskspace, LogMessageType.ScanOrEncode, LogLevel.Info); job.Status = QueueItemStatus.Waiting; diff --git a/win/CS/HandBrakeWPF/Services/SystemService.cs b/win/CS/HandBrakeWPF/Services/SystemService.cs new file mode 100644 index 000000000..4bbc89f94 --- /dev/null +++ b/win/CS/HandBrakeWPF/Services/SystemService.cs @@ -0,0 +1,143 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// +// +// Monitor the system health for common problems that will directly impact encodes. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrakeWPF.Services +{ + using System; + using System.Runtime.CompilerServices; + using System.Timers; + + using HandBrakeWPF.Properties; + using HandBrakeWPF.Services.Encode.Interfaces; + using HandBrakeWPF.Services.Encode.Model; + using HandBrakeWPF.Services.Interfaces; + using HandBrakeWPF.Services.Logging; + using HandBrakeWPF.Services.Logging.Interfaces; + using HandBrakeWPF.Services.Logging.Model; + using HandBrakeWPF.Utilities; + + using Ookii.Dialogs.Wpf; + + public class SystemService : ISystemService + { + private readonly IUserSettingService userSettingService; + private readonly IEncode encodeService; + private readonly ILog log = LogService.GetLogger(); + private Timer pollTimer; + + private bool criticalStateHit = false; + private bool lowStateHit = false; + private bool lowPowerPause = false; + private bool storageLowPause = false; + + public SystemService(IUserSettingService userSettingService, IEncode encodeService) + { + this.userSettingService = userSettingService; + this.encodeService = encodeService; + } + + public void Start() + { + if (this.pollTimer == null) + { + this.pollTimer = new Timer(); + this.pollTimer.Interval = 10000; // Check every 10 seconds. + this.pollTimer.Elapsed += (o, e) => + { + this.CheckSystem(); + }; + + this.pollTimer.Start(); + } + } + + private void CheckSystem() + { + this.PowerCheck(); + this.StorageCheck(); + } + + private void StorageCheck() + { + string directory = this.encodeService.GetActiveJob()?.Destination; + if (!string.IsNullOrEmpty(directory) && this.encodeService.IsEncoding) + { + long lowLevel = this.userSettingService.GetUserSetting(UserSettingConstants.PauseEncodeOnLowDiskspaceLevel); + if (!this.storageLowPause && this.userSettingService.GetUserSetting(UserSettingConstants.PauseOnLowDiskspace) && !DriveUtilities.HasMinimumDiskSpace(directory, lowLevel)) + { + LogService.GetLogger().LogMessage( + string.Format( + Resources.SystemService_LowDiskSpaceLog, + lowLevel / 1000 / 1000 / 1000), + LogMessageType.Application, + LogLevel.Info); + this.encodeService.Pause(); + this.storageLowPause = true; + } + } + } + + private void PowerCheck() + { + Win32.PowerState state = Win32.PowerState.GetPowerState(); + + if (state == null || state.BatteryFlag == Win32.BatteryFlag.NoSystemBattery || state.BatteryFlag == Win32.BatteryFlag.Unknown) + { + return; // Only run if we have a battery. + } + + if (state.ACLineStatus == Win32.ACLineStatus.Offline && state.BatteryFlag == Win32.BatteryFlag.Low && !this.lowStateHit) + { + if (this.encodeService.IsEncoding && !this.encodeService.IsPasued) + { + this.lowPowerPause = true; + this.encodeService.Pause(); + } + + Win32.AllowSleep(); + + this.ServiceLogMessage(string.Format(Resources.SystemService_LowBatteryLog, state.BatteryLifePercent)); + this.lowStateHit = true; + } + + if (state.ACLineStatus == Win32.ACLineStatus.Offline && state.BatteryFlag == Win32.BatteryFlag.Critical && !this.criticalStateHit) + { + if (this.encodeService.IsEncoding && !this.encodeService.IsPasued) + { + this.lowPowerPause = true; + this.encodeService.Pause(); // In case we missed the low state! + } + + Win32.AllowSleep(); + + this.ServiceLogMessage(string.Format(Resources.SystemService_CriticalBattery, state.BatteryLifePercent)); + this.criticalStateHit = true; + } + + // Reset the flags when we start charging. + if (state.ACLineStatus == Win32.ACLineStatus.Online && state.BatteryFlag >= Win32.BatteryFlag.Low) + { + if (this.lowPowerPause && this.encodeService.IsPasued) + { + this.encodeService.Resume(); + this.ServiceLogMessage(string.Format(Resources.SystemService_ACMains, state.BatteryLifePercent)); + } + + this.lowPowerPause = false; + this.criticalStateHit = false; + this.lowStateHit = false; + } + } + + private void ServiceLogMessage(string message) + { + this.log.LogMessage(string.Format("{0}# {1}{0}", Environment.NewLine, message), LogMessageType.Application, LogLevel.Info); + } + } +} -- cgit v1.2.3