mirror of
https://github.com/Maassoft/ColorControl.git
synced 2026-10-22 00:22:18 -05:00
fix LG device settings not saving, upgrade to .NET 7
This commit is contained in:
1 parent
6318d37247
commit
52fd635fda
20 files changed
+1164
-967
No files matched your search
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<LangVersion>10.0</LangVersion>
|
||||
<TargetFramework>net6.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetFramework>net7.0-windows10.0.20348.0</TargetFramework>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
@@ -19,8 +19,8 @@
|
||||
<PublisherName>Maassoft</PublisherName>
|
||||
<Company>Maassoft</Company>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>9.0.0.0</ApplicationVersion>
|
||||
<Version>9.0.0.0</Version>
|
||||
<ApplicationVersion>9.1.0.0</ApplicationVersion>
|
||||
<Version>9.1.0.0</Version>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<PublishWizardCompleted>true</PublishWizardCompleted>
|
||||
<BootstrapperEnabled>false</BootstrapperEnabled>
|
||||
@@ -89,17 +89,17 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.1" />
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.0" />
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="7.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="NLog" Version="5.0.4" />
|
||||
<PackageReference Include="NStandard" Version="0.15.2" />
|
||||
<PackageReference Include="NWin32" Version="1.2.3" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="NLog" Version="5.1.2" />
|
||||
<PackageReference Include="NStandard" Version="0.24.0" />
|
||||
<PackageReference Include="NWin32" Version="1.2.6" />
|
||||
<PackageReference Include="System.Management" Version="7.0.0" />
|
||||
<PackageReference Include="TaskScheduler" Version="2.10.1" />
|
||||
<PackageReference Include="Vanara.PInvoke.IpHlpApi" Version="3.4.9" />
|
||||
<PackageReference Include="Vanara.PInvoke.IpHlpApi" Version="3.4.13" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Nspector\Nspector.csproj" />
|
||||
|
||||
@@ -296,7 +296,7 @@ The best and suggested method to provide this is via a Windows Service. Only whe
|
||||
return key != null && key.GetValue(null).ToString().Contains("--disable-lcd-text");
|
||||
}
|
||||
|
||||
internal static bool InstallChromeFix(bool install)
|
||||
internal static bool InstallChromeFix(bool install, string applicationDataFolder)
|
||||
{
|
||||
var argument = "--disable-lcd-text";
|
||||
|
||||
@@ -312,7 +312,7 @@ The best and suggested method to provide this is via a Windows Service. Only whe
|
||||
key.SetValue(null, value);
|
||||
}
|
||||
|
||||
var roamingFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
||||
var roamingFolder = applicationDataFolder ?? Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
||||
|
||||
UpdateShortcut(Path.Combine(roamingFolder, @"Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Google Chrome.lnk"), argument, !install);
|
||||
UpdateShortcut(Path.Combine(roamingFolder, @"Microsoft\Internet Explorer\Quick Launch\Google Chrome.lnk"), argument, !install);
|
||||
|
||||
@@ -45,12 +45,14 @@ namespace ColorControl.Forms
|
||||
|
||||
public static void SetNotifyIconText(NotifyIcon ni, string text)
|
||||
{
|
||||
text = text.Substring(0, Math.Min(text.Length, 127));
|
||||
Type t = typeof(NotifyIcon);
|
||||
BindingFlags hidden = BindingFlags.NonPublic | BindingFlags.Instance;
|
||||
t.GetField("text", hidden).SetValue(ni, text);
|
||||
if ((bool)t.GetField("added", hidden).GetValue(ni))
|
||||
t.GetMethod("UpdateIcon", hidden).Invoke(ni, new object[] { true });
|
||||
ni.Text = text;
|
||||
|
||||
//text = text.Substring(0, Math.Min(text.Length, 127));
|
||||
//Type t = typeof(NotifyIcon);
|
||||
//BindingFlags hidden = BindingFlags.NonPublic | BindingFlags.Instance;
|
||||
//t.GetField("text", hidden).SetValue(ni, text);
|
||||
//if ((bool)t.GetField("added", hidden).GetValue(ni))
|
||||
// t.GetMethod("UpdateIcon", hidden).Invoke(ni, new object[] { true });
|
||||
}
|
||||
|
||||
public static ToolStripMenuItem BuildDropDownMenuEx(ToolStripItemCollection items, string parentName, string name, Type enumType, EventHandler clickEvent, object tag = null, int min = 0, int max = 0, bool noSubItems = false)
|
||||
|
||||
+16
-17
@@ -140,7 +140,6 @@ namespace ColorControl
|
||||
InitInfo();
|
||||
UpdateServiceInfo();
|
||||
|
||||
UserSessionInfo.Install();
|
||||
_screenStateNotify = WinApi.RegisterPowerSettingNotification(Handle, ref Utils.GUID_CONSOLE_DISPLAY_STATE, 0);
|
||||
|
||||
//Scale(new SizeF(1.25F, 1.25F));
|
||||
@@ -320,9 +319,7 @@ namespace ColorControl
|
||||
{
|
||||
try
|
||||
{
|
||||
var appContextProvider = Program.ServiceProvider.GetRequiredService<AppContextProvider>();
|
||||
|
||||
_lgService = new LgService(appContextProvider, StartUpParams.RunningFromScheduledTask);
|
||||
_lgService = Program.ServiceProvider.GetRequiredService<LgService>();
|
||||
|
||||
_lgPanel = new LgPanel(_lgService, _nvService, _amdService, _trayIcon, Handle);
|
||||
_lgPanel.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
||||
@@ -562,20 +559,24 @@ namespace ColorControl
|
||||
{
|
||||
//Logger.Debug($"WM_SYSCOMMAND: {m.WParam.ToInt32()}");
|
||||
|
||||
if (m.WParam.ToInt32() == NativeConstants.SC_MONITORPOWER)
|
||||
{
|
||||
//if (m.WParam.ToInt32() == NativeConstants.SC_MONITORPOWER)
|
||||
//{
|
||||
|
||||
}
|
||||
//}
|
||||
}
|
||||
else if (m.Msg == NativeConstants.WM_POWERBROADCAST)
|
||||
{
|
||||
//Logger.Debug($"WM_POWERBROADCAST: {m.WParam.ToInt32()}");
|
||||
|
||||
if (m.WParam.ToInt32() == WinApi.PBT_POWERSETTINGCHANGE)
|
||||
{
|
||||
var ps = Marshal.PtrToStructure<WinApi.POWERBROADCAST_SETTING>(m.LParam);
|
||||
|
||||
Logger.Debug($"PBT_POWERSETTINGCHANGE: {ps.Data}");
|
||||
var power = (LgService.WindowsPowerSetting)ps.Data;
|
||||
|
||||
_lgService?.PowerSettingChanged((LgService.WindowsPowerSetting)ps.Data);
|
||||
Logger.Debug($"PBT_POWERSETTINGCHANGE: {power}");
|
||||
|
||||
_lgService?.PowerSettingChanged(power);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1398,14 +1399,12 @@ Currently ColorControl is {(Utils.IsAdministrator() ? "" : "not ")}running as ad
|
||||
if (_initialized)
|
||||
{
|
||||
_config.FixChromeFonts = chkFixChromeFonts.Checked;
|
||||
if (chkFixChromeFonts.Checked)
|
||||
{
|
||||
Utils.ExecuteElevated(StartUpParams.ActivateChromeFontFixParam);
|
||||
}
|
||||
else
|
||||
{
|
||||
Utils.ExecuteElevated(StartUpParams.DeactivateChromeFontFixParam);
|
||||
}
|
||||
|
||||
var param = chkFixChromeFonts.Checked ? StartUpParams.ActivateChromeFontFixParam : StartUpParams.DeactivateChromeFontFixParam;
|
||||
|
||||
var folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
||||
|
||||
Utils.ExecuteElevated($"{param} {folder}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using ColorControl.Forms;
|
||||
using ColorControl.Services.AMD;
|
||||
using ColorControl.Services.Common;
|
||||
using ColorControl.Services.EventDispatcher;
|
||||
using ColorControl.Services.LG;
|
||||
using ColorControl.Services.NVIDIA;
|
||||
using ColorControl.Svc;
|
||||
@@ -207,7 +208,7 @@ namespace ColorControl
|
||||
{
|
||||
if (startUpParams.ActivateChromeFontFix || startUpParams.DeactivateChromeFontFix)
|
||||
{
|
||||
Utils.InstallChromeFix(startUpParams.ActivateChromeFontFix);
|
||||
Utils.InstallChromeFix(startUpParams.ActivateChromeFontFix, startUpParams.ChromeFontFixApplicationDataFolder);
|
||||
return true;
|
||||
}
|
||||
if (startUpParams.EnableAutoStart || startUpParams.DisableAutoStart)
|
||||
@@ -353,6 +354,9 @@ namespace ColorControl
|
||||
{
|
||||
//services.AddSingleton<NvService>();
|
||||
services.RegisterSharedServices();
|
||||
services.AddSingleton<LgService>();
|
||||
services.AddSingleton<PowerEventDispatcher>();
|
||||
services.AddSingleton<ProcessEventDispatcher>();
|
||||
});
|
||||
}
|
||||
private static async Task RunService(string[] args)
|
||||
@@ -377,6 +381,7 @@ namespace ColorControl
|
||||
private static void RegisterSharedServices(this IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<AppContextProvider>();
|
||||
services.AddSingleton<SessionSwitchDispatcher>();
|
||||
}
|
||||
|
||||
public static int EnumThreadWindows(IntPtr handle, IntPtr param)
|
||||
|
||||
@@ -87,8 +87,9 @@ namespace ColorControl.Services.Common
|
||||
DEVMODEA devMode;
|
||||
while (NativeMethods.EnumDisplaySettingsA(displayName, i, out devMode))
|
||||
{
|
||||
if ((!portrait && devMode.dmPelsWidth == horizontal && devMode.dmPelsHeight == vertical) ||
|
||||
(portrait && devMode.dmPelsWidth == vertical && devMode.dmPelsHeight == horizontal))
|
||||
if (((!portrait && devMode.dmPelsWidth == horizontal && devMode.dmPelsHeight == vertical) ||
|
||||
(portrait && devMode.dmPelsWidth == vertical && devMode.dmPelsHeight == horizontal)) &&
|
||||
!list.Contains(devMode.dmDisplayFrequency))
|
||||
{
|
||||
list.Add(devMode.dmDisplayFrequency);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using static ColorControl.Services.EventDispatcher.EventExtensions;
|
||||
|
||||
namespace ColorControl.Services.EventDispatcher;
|
||||
|
||||
public class EventDispatcher<T> where T : EventArgs
|
||||
{
|
||||
private Dictionary<string, EventHandler<T>> eventHandlers = new Dictionary<string, EventHandler<T>>();
|
||||
private Dictionary<string, AsyncEventHandler<T>> asyncEventHandlers = new Dictionary<string, AsyncEventHandler<T>>();
|
||||
|
||||
public void RegisterEventHandler(string eventName, EventHandler<T> eventHandler)
|
||||
{
|
||||
if (!eventHandlers.ContainsKey(eventName))
|
||||
{
|
||||
eventHandlers.Add(eventName, eventHandler);
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterAsyncEventHandler(string eventName, AsyncEventHandler<T> eventHandler)
|
||||
{
|
||||
if (!asyncEventHandlers.ContainsKey(eventName))
|
||||
{
|
||||
asyncEventHandlers.Add(eventName, eventHandler);
|
||||
}
|
||||
}
|
||||
|
||||
public void UnregisterEventHandler(string eventName)
|
||||
{
|
||||
eventHandlers.Remove(eventName);
|
||||
}
|
||||
|
||||
public void DispatchEvent(string eventName, T eventArgs)
|
||||
{
|
||||
if (eventHandlers.ContainsKey(eventName))
|
||||
{
|
||||
eventHandlers[eventName]?.Invoke(this, eventArgs);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task DispatchEventAsync(string eventName, T eventArgs)
|
||||
{
|
||||
if (asyncEventHandlers.ContainsKey(eventName))
|
||||
{
|
||||
await asyncEventHandlers[eventName]?.InvokeAsync(this, eventArgs);
|
||||
}
|
||||
}
|
||||
|
||||
protected bool HasHandlers(string eventName)
|
||||
{
|
||||
return eventHandlers.ContainsKey(eventName) || asyncEventHandlers.ContainsKey(eventName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ColorControl.Services.EventDispatcher
|
||||
{
|
||||
public static class EventExtensions
|
||||
{
|
||||
public delegate Task AsyncEventHandler<TEventArgs>(object sender, TEventArgs e, CancellationToken token);
|
||||
|
||||
public static Task InvokeAsync<TArgs>(this AsyncEventHandler<TArgs> func, object sender, TArgs e)
|
||||
{
|
||||
return func == null ? Task.CompletedTask
|
||||
: Task.WhenAll(func.GetInvocationList().Cast<AsyncEventHandler<TArgs>>().Select(f => f(sender, e, CancellationToken.None)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace ColorControl.Services.EventDispatcher
|
||||
{
|
||||
public class PowerEventDispatcher : EventDispatcher<PowerModeChangedEventArgs>
|
||||
{
|
||||
public const string Event_Suspend = "Suspend";
|
||||
public const string Event_Resume = "Resume";
|
||||
|
||||
public PowerEventDispatcher()
|
||||
{
|
||||
SystemEvents.PowerModeChanged += OnPowerModeChanged;
|
||||
}
|
||||
|
||||
private void OnPowerModeChanged(object sender, PowerModeChangedEventArgs e)
|
||||
{
|
||||
if (e.Mode == PowerModes.Suspend)
|
||||
{
|
||||
DispatchEvent(Event_Suspend, e);
|
||||
}
|
||||
else if (e.Mode == PowerModes.Resume)
|
||||
{
|
||||
DispatchEvent(Event_Resume, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
using ColorControl.Common;
|
||||
using ColorControl.Forms;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Management;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ColorControl.Services.EventDispatcher
|
||||
{
|
||||
public class ProcessChangedEventArgs : EventArgs
|
||||
{
|
||||
public IList<Process> StartedProcesses { get; set; }
|
||||
public IList<Process> StoppedProcesses { get; set; }
|
||||
public IList<Process> RunningProcesses { get; set; }
|
||||
public bool IsNotificationDisabled { get; set; }
|
||||
public Process ForegroundProcess { get; set; }
|
||||
public bool ForegroundProcessIsFullScreen { get; set; }
|
||||
public string LastFullScreenProcessName = string.Empty;
|
||||
public bool StoppedFullScreen { get; set; }
|
||||
public bool IsScreenSaverActive { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class ProcessEventDispatcher : EventDispatcher<ProcessChangedEventArgs>
|
||||
{
|
||||
public const string Event_ProcessChanged = "ProcessChanged";
|
||||
public bool IsRunning { get; set; }
|
||||
|
||||
protected static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
private ProcessChangedEventArgs MonitorContext { get; set; }
|
||||
|
||||
public ProcessEventDispatcher()
|
||||
{
|
||||
IsRunning = true;
|
||||
|
||||
var _ = CheckProcesses();
|
||||
}
|
||||
|
||||
private async Task CheckProcesses()
|
||||
{
|
||||
await Task.Delay(2000);
|
||||
|
||||
//var startWatch = new ManagementEventWatcher("SELECT * FROM Win32_ProcessStartTrace");
|
||||
//startWatch.EventArrived += startWatch_EventArrived;
|
||||
//startWatch.Start();
|
||||
|
||||
MonitorContext ??= new ProcessChangedEventArgs();
|
||||
//Process[] lastProcesses = null;
|
||||
|
||||
while (IsRunning)
|
||||
{
|
||||
await Task.Delay(1000);
|
||||
|
||||
if (!HasHandlers(Event_ProcessChanged))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
FillContext(MonitorContext);
|
||||
|
||||
// Ignore if own process has the foreground
|
||||
if (MonitorContext.ForegroundProcess?.Id == Environment.ProcessId)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
await DispatchEventAsync(Event_ProcessChanged, MonitorContext);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error("CheckProcesses: " + ex.ToLogString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void FillContext(ProcessChangedEventArgs context)
|
||||
{
|
||||
var processes = Process.GetProcesses();
|
||||
|
||||
context.RunningProcesses = processes;
|
||||
|
||||
context.IsNotificationDisabled = FormUtils.IsNotificationDisabled();
|
||||
|
||||
var (processId, isFullScreen) = FormUtils.GetForegroundProcessIdAndIfFullScreen();
|
||||
|
||||
if (processId > 0)
|
||||
{
|
||||
var process = context.RunningProcesses.FirstOrDefault(p => p.Id == processId);
|
||||
|
||||
context.IsScreenSaverActive = process?.ProcessName?.Contains(".scr") == true;
|
||||
context.ForegroundProcess = process;
|
||||
context.ForegroundProcessIsFullScreen = isFullScreen;
|
||||
|
||||
if (isFullScreen)
|
||||
{
|
||||
context.LastFullScreenProcessName = context.ForegroundProcess.ProcessName;
|
||||
//Logger.Debug($"Foreground fullscreen app detected: {context.ForegroundProcess.ProcessName}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
context.StoppedFullScreen = context.ForegroundProcessIsFullScreen;
|
||||
context.ForegroundProcess = null;
|
||||
context.ForegroundProcessIsFullScreen = false;
|
||||
context.LastFullScreenProcessName = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
private void startWatch_EventArrived(object sender, EventArrivedEventArgs e)
|
||||
{
|
||||
//Logger.Debug("Process started: " + e.NewEvent.Properties["ProcessName"].Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
-11
@@ -1,29 +1,29 @@
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace ColorControl
|
||||
namespace ColorControl.Services.EventDispatcher
|
||||
{
|
||||
static class UserSessionInfo
|
||||
public class SessionSwitchDispatcher : EventDispatcher<SessionSwitchEventArgs>
|
||||
{
|
||||
public const string Event_SessionSwitch = "SessionSwitch";
|
||||
|
||||
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
public static bool UserLocalSession { get; private set; } = true;
|
||||
public static SessionSwitchReason LastSessionSwitchReason { get; private set; } = 0;
|
||||
public bool UserLocalSession { get; private set; } = true;
|
||||
public SessionSwitchReason LastSessionSwitchReason { get; private set; } = 0;
|
||||
|
||||
public delegate void UserSessionSwitchHandler(bool toLocal);
|
||||
public static event UserSessionSwitchHandler UserSessionSwitch;
|
||||
|
||||
public static void Install()
|
||||
public SessionSwitchDispatcher()
|
||||
{
|
||||
SystemEvents.SessionSwitch += SessionSwitchHandler;
|
||||
}
|
||||
|
||||
public static void SessionSwitchHandler(object sender, SessionSwitchEventArgs evt)
|
||||
public void SessionSwitchHandler(object sender, SessionSwitchEventArgs evt)
|
||||
{
|
||||
if (evt.Reason == SessionSwitchReason.ConsoleDisconnect)
|
||||
{
|
||||
Logger.Debug("Detected a disconnect from the console");
|
||||
UserLocalSession = false;
|
||||
UserSessionSwitch(false);
|
||||
|
||||
DispatchEvent(Event_SessionSwitch, evt);
|
||||
}
|
||||
else if (evt.Reason == SessionSwitchReason.ConsoleConnect)
|
||||
{
|
||||
@@ -32,7 +32,7 @@ namespace ColorControl
|
||||
{
|
||||
Logger.Debug("Session state switched to local");
|
||||
UserLocalSession = true;
|
||||
UserSessionSwitch(true);
|
||||
DispatchEvent(Event_SessionSwitch, evt);
|
||||
}
|
||||
}
|
||||
LastSessionSwitchReason = evt.Reason;
|
||||
@@ -61,7 +61,8 @@ namespace ColorControl.Services.LG
|
||||
Series2019,
|
||||
Series2020,
|
||||
Series2021,
|
||||
Series2022
|
||||
Series2022,
|
||||
Series2023
|
||||
}
|
||||
|
||||
protected static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
@@ -80,6 +81,7 @@ namespace ColorControl.Services.LG
|
||||
public bool PowerOffOnShutdown { get; set; }
|
||||
public bool PowerOffOnStandby { get; set; }
|
||||
public bool PowerOffOnScreenSaver { get; set; }
|
||||
public int ScreenSaverMinimalDuration { get; set; }
|
||||
public bool PowerOnAfterScreenSaver { get; set; }
|
||||
public bool PowerOnAfterManualPowerOff { get; set; }
|
||||
public bool PowerOnByWindows { get; set; }
|
||||
@@ -143,6 +145,9 @@ namespace ColorControl.Services.LG
|
||||
public event EventHandler PictureSettingsChangedEvent;
|
||||
public event EventHandler PowerStateChangedEvent;
|
||||
|
||||
[JsonIgnore]
|
||||
private Timer _powerOffTimer;
|
||||
|
||||
[JsonConstructor]
|
||||
public LgDevice(string name, string ipAddress, string macAddress, bool isCustom = true, bool isDummy = false)
|
||||
{
|
||||
@@ -256,6 +261,11 @@ namespace ColorControl.Services.LG
|
||||
AddGenericPictureAction("wolwowlOnOff", typeof(FalseToTrue), category: "network", title: "Wake-On-LAN");
|
||||
}
|
||||
|
||||
~LgDevice()
|
||||
{
|
||||
_powerOffTimer?.Dispose();
|
||||
}
|
||||
|
||||
private void AddInvokableAction(string name, Func<Dictionary<string, object>, bool> function)
|
||||
{
|
||||
var action = new InvokableAction
|
||||
@@ -430,6 +440,7 @@ namespace ColorControl.Services.LG
|
||||
'X' => ModelYear.Series2020,
|
||||
'1' => ModelYear.Series2021,
|
||||
'2' => ModelYear.Series2022,
|
||||
'3' => ModelYear.Series2023,
|
||||
_ => ModelYear.None
|
||||
};
|
||||
|
||||
@@ -1083,5 +1094,23 @@ namespace ColorControl.Services.LG
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void ClearPowerOffTask()
|
||||
{
|
||||
_powerOffTimer?.Dispose();
|
||||
}
|
||||
|
||||
internal void PowerOffIn(int seconds)
|
||||
{
|
||||
_powerOffTimer = new Timer(PowerOffByTimer);
|
||||
_powerOffTimer.Change(TimeSpan.FromSeconds(seconds), TimeSpan.FromSeconds(seconds));
|
||||
}
|
||||
|
||||
private void PowerOffByTimer(object state)
|
||||
{
|
||||
_powerOffTimer?.Dispose();
|
||||
|
||||
var _ = PowerOff(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
+622
-639
File diff suppressed because it is too large.
Load diff
@@ -32,7 +32,6 @@ namespace ColorControl.Services.LG
|
||||
private NotifyIcon _trayIcon;
|
||||
|
||||
private string _lgTabMessage;
|
||||
private bool _initialized = false;
|
||||
private bool _disableEvents = false;
|
||||
private LgGameBar _gameBarForm;
|
||||
|
||||
@@ -74,7 +73,6 @@ namespace ColorControl.Services.LG
|
||||
public void Init()
|
||||
{
|
||||
_lgService.RefreshDevices(afterStartUp: true).ContinueWith((_) => BeginInvoke(() => AfterLgServiceRefreshDevices()));
|
||||
|
||||
_lgService.InstallEventHandlers();
|
||||
}
|
||||
|
||||
@@ -290,11 +288,6 @@ namespace ColorControl.Services.LG
|
||||
edtLgPresetIncludedProcesses.Text,
|
||||
edtLgPresetExcludedProcesses.Text);
|
||||
|
||||
if (triggerType != PresetTriggerType.None)
|
||||
{
|
||||
_lgService.InstallEventHandlers();
|
||||
}
|
||||
|
||||
var shortcutChanged = !shortcut.Equals(preset.shortcut);
|
||||
if (shortcutChanged)
|
||||
{
|
||||
@@ -665,7 +658,7 @@ namespace ColorControl.Services.LG
|
||||
|
||||
private void clbLgPower_ItemCheck(object sender, ItemCheckEventArgs e)
|
||||
{
|
||||
if (!_initialized || _disableEvents)
|
||||
if (_disableEvents)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -702,8 +695,6 @@ You can also activate this option by using the Expert-button and selecting Wake-
|
||||
device.PowerOnByWindows = clbLgPower.GetItemChecked(9);
|
||||
device.UseSecureConnection = clbLgPower.GetItemChecked(10);
|
||||
|
||||
_lgService.InstallEventHandlers();
|
||||
|
||||
if (e.Index == 10)
|
||||
{
|
||||
_lgService.RefreshDevices().ContinueWith((_) => BeginInvoke(() => FillLgDevices()));
|
||||
@@ -1279,5 +1270,32 @@ The InStart, EzAdjust and Software Update items are now visible under the Expert
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void clbLgPower_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
btnLgDeviceOptionsSettings.Enabled = clbLgPower.SelectedIndex == 4;
|
||||
}
|
||||
|
||||
private void btnLgDeviceOptionsSettings_Click(object sender, EventArgs e)
|
||||
{
|
||||
var device = _lgService.SelectedDevice;
|
||||
var selectedItem = clbLgPower.SelectedItem;
|
||||
|
||||
var durationField = new MessageForms.FieldDefinition
|
||||
{
|
||||
Label = "Enter the minimal duration the screen saver must be running (in seconds)",
|
||||
FieldType = MessageForms.FieldType.Numeric,
|
||||
MinValue = 0,
|
||||
MaxValue = 3600,
|
||||
Value = device.ScreenSaverMinimalDuration
|
||||
};
|
||||
|
||||
if (!MessageForms.ShowDialog($"Settings - {selectedItem}", new[] { durationField }).Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
device.ScreenSaverMinimalDuration = durationField.ValueAsInt;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using ColorControl.Common;
|
||||
using ColorControl.Forms;
|
||||
using ColorControl.Services.Common;
|
||||
using ColorControl.Services.EventDispatcher;
|
||||
using ColorControl.Svc;
|
||||
using LgTv;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@@ -12,7 +12,6 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Management;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
@@ -77,6 +76,9 @@ namespace ColorControl.Services.LG
|
||||
|
||||
private string _configFilename;
|
||||
private bool _allowPowerOn;
|
||||
private readonly PowerEventDispatcher _powerEventDispatcher;
|
||||
private readonly SessionSwitchDispatcher _sessionSwitchDispatcher;
|
||||
private readonly ProcessEventDispatcher _processEventDispatcher;
|
||||
private LgDevice _selectedDevice;
|
||||
private string _rcButtonsFilename;
|
||||
private List<LgPreset> _remoteControlButtons;
|
||||
@@ -84,15 +86,15 @@ namespace ColorControl.Services.LG
|
||||
|
||||
private bool _poweredOffByScreenSaver;
|
||||
private int _poweredOffByScreenSaverProcessId;
|
||||
private Task _monitorTask;
|
||||
private int _monitorTaskCounter;
|
||||
private LgPreset _lastTriggeredPreset;
|
||||
private RestartDetector _restartDetector;
|
||||
|
||||
public LgService(AppContextProvider appContextProvider, bool allowPowerOn) : base(appContextProvider)
|
||||
public LgService(AppContextProvider appContextProvider, PowerEventDispatcher powerEventDispatcher, SessionSwitchDispatcher sessionSwitchDispatcher, ProcessEventDispatcher processEventDispatcher) : base(appContextProvider)
|
||||
{
|
||||
_allowPowerOn = allowPowerOn;
|
||||
|
||||
_allowPowerOn = appContextProvider.GetAppContext().StartUpParams.RunningFromScheduledTask;
|
||||
_powerEventDispatcher = powerEventDispatcher;
|
||||
_sessionSwitchDispatcher = sessionSwitchDispatcher;
|
||||
_processEventDispatcher = processEventDispatcher;
|
||||
LgPreset.LgApps = _lgApps;
|
||||
|
||||
_restartDetector = new RestartDetector();
|
||||
@@ -111,9 +113,8 @@ namespace ColorControl.Services.LG
|
||||
{
|
||||
try
|
||||
{
|
||||
var appContextProvider = Program.ServiceProvider.GetRequiredService<AppContextProvider>();
|
||||
var lgService = Program.ServiceProvider.GetRequiredService<LgService>();
|
||||
|
||||
var lgService = new LgService(appContextProvider, true);
|
||||
await lgService.RefreshDevices(afterStartUp: true);
|
||||
|
||||
var result = await lgService.ApplyPreset(presetName);
|
||||
@@ -442,32 +443,35 @@ namespace ColorControl.Services.LG
|
||||
|
||||
public void InstallEventHandlers()
|
||||
{
|
||||
SystemEvents.PowerModeChanged -= PowerModeChanged;
|
||||
SystemEvents.PowerModeChanged += PowerModeChanged;
|
||||
_powerEventDispatcher.RegisterEventHandler(PowerEventDispatcher.Event_Suspend, PowerModeChanged);
|
||||
_powerEventDispatcher.RegisterEventHandler(PowerEventDispatcher.Event_Resume, PowerModeChanged);
|
||||
|
||||
//SystemEvents.SessionEnded -= SessionEnded;
|
||||
//SystemEvents.SessionEnded += SessionEnded;
|
||||
|
||||
UserSessionInfo.UserSessionSwitch -= SessionSwitched;
|
||||
UserSessionInfo.UserSessionSwitch += SessionSwitched;
|
||||
_sessionSwitchDispatcher.RegisterEventHandler(SessionSwitchDispatcher.Event_SessionSwitch, SessionSwitched);
|
||||
|
||||
MonitorProcesses();
|
||||
_processEventDispatcher.RegisterAsyncEventHandler(ProcessEventDispatcher.Event_ProcessChanged, ProcessChanged);
|
||||
}
|
||||
|
||||
private void SessionSwitched(bool toLocal)
|
||||
private void SessionSwitched(object sender, SessionSwitchEventArgs e)
|
||||
{
|
||||
if (toLocal)
|
||||
if (_sessionSwitchDispatcher.UserLocalSession)
|
||||
{
|
||||
if (_poweredOffByScreenSaver)
|
||||
{
|
||||
Logger.Debug("User switched to local and screen was powered off due to screensaver: waking up");
|
||||
_poweredOffByScreenSaver = false;
|
||||
_poweredOffByScreenSaverProcessId = 0;
|
||||
WakeAfterStartupOrResume();
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Debug("User switched to local but screen was not powered off by screensaver: NOT waking up");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (_poweredOffByScreenSaver)
|
||||
{
|
||||
Logger.Debug("User switched to local and screen was powered off due to screensaver: waking up");
|
||||
_poweredOffByScreenSaver = false;
|
||||
_poweredOffByScreenSaverProcessId = 0;
|
||||
WakeAfterStartupOrResume();
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Debug("User switched to local but screen was not powered off by screensaver: NOT waking up");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -479,6 +483,8 @@ namespace ColorControl.Services.LG
|
||||
|
||||
if (powerOn)
|
||||
{
|
||||
Devices.ForEach(d => d.ClearPowerOffTask());
|
||||
|
||||
WakeAfterStartupOrResume(PowerOnOffState.Resume);
|
||||
return;
|
||||
}
|
||||
@@ -516,199 +522,101 @@ namespace ColorControl.Services.LG
|
||||
}
|
||||
}
|
||||
|
||||
private void MonitorProcesses()
|
||||
public async Task ProcessChanged(object sender, ProcessChangedEventArgs args, CancellationToken token)
|
||||
{
|
||||
var enableMonitoring = ShouldMonitorProcesses();
|
||||
if (enableMonitoring && _monitorTask == null)
|
||||
try
|
||||
{
|
||||
_monitorTask = CheckProcesses();
|
||||
}
|
||||
else if (!enableMonitoring && _monitorTask != null)
|
||||
{
|
||||
_monitorTask = null;
|
||||
}
|
||||
}
|
||||
var wasConnected = Devices.Any(d => (d.PowerOffOnScreenSaver || d.PowerOnAfterScreenSaver) && d.IsConnected());
|
||||
|
||||
public bool ShouldMonitorProcesses()
|
||||
{
|
||||
return Devices.Any(d => d.PowerOffOnScreenSaver || d.PowerOnAfterScreenSaver) || _presets.Any(p => p.Triggers.Any(t => t.Trigger != PresetTriggerType.None));
|
||||
}
|
||||
var applicableDevices = Devices.Where(d => d.PowerOffOnScreenSaver || d.PowerOnAfterScreenSaver || d.TriggersEnabled && _presets.Any(p => p.Triggers.Any(t => t.Trigger != PresetTriggerType.None) &&
|
||||
((string.IsNullOrEmpty(p.DeviceMacAddress) && d == SelectedDevice) || p.DeviceMacAddress.Equals(d.MacAddress, StringComparison.OrdinalIgnoreCase))));
|
||||
|
||||
public async Task CheckProcesses()
|
||||
{
|
||||
var wasConnected = Devices.Any(d => (d.PowerOffOnScreenSaver || d.PowerOnAfterScreenSaver) && d.IsConnected());
|
||||
_monitorTaskCounter++;
|
||||
var validCounter = _monitorTaskCounter;
|
||||
var lastProcessId = 0;
|
||||
|
||||
await Task.Delay(2000);
|
||||
|
||||
//var startWatch = new ManagementEventWatcher("SELECT * FROM Win32_ProcessStartTrace");
|
||||
//startWatch.EventArrived += startWatch_EventArrived;
|
||||
//startWatch.Start();
|
||||
|
||||
MonitorContext ??= new ProcessMonitorContext();
|
||||
//Process[] lastProcesses = null;
|
||||
|
||||
while (validCounter == _monitorTaskCounter)
|
||||
{
|
||||
await Task.Delay(_poweredOffByScreenSaver ? 500 : 1000);
|
||||
|
||||
try
|
||||
if (!applicableDevices.Any())
|
||||
{
|
||||
var applicableDevices = Devices.Where(d => d.PowerOffOnScreenSaver || d.PowerOnAfterScreenSaver || d.TriggersEnabled && _presets.Any(p => p.Triggers.Any(t => t.Trigger != PresetTriggerType.None) &&
|
||||
((string.IsNullOrEmpty(p.DeviceMacAddress) && d == SelectedDevice) || p.DeviceMacAddress.Equals(d.MacAddress, StringComparison.OrdinalIgnoreCase))));
|
||||
|
||||
if (!applicableDevices.Any())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (_poweredOffByScreenSaver && !UserSessionInfo.UserLocalSession)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var processes = Process.GetProcesses();
|
||||
|
||||
if (_poweredOffByScreenSaver)
|
||||
{
|
||||
if (processes.Any(p => p.Id == _poweredOffByScreenSaverProcessId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Logger.Debug("Screensaver stopped, waking");
|
||||
_poweredOffByScreenSaver = false;
|
||||
_poweredOffByScreenSaverProcessId = 0;
|
||||
lastProcessId = 0;
|
||||
WakeAfterStartupOrResume(PowerOnOffState.ScreenSaver);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
var connectedDevices = applicableDevices.Where(d => d.IsConnected()).ToList();
|
||||
|
||||
if (!connectedDevices.Any())
|
||||
{
|
||||
if (wasConnected)
|
||||
{
|
||||
Logger.Debug("Process monitor: TV(s) where connected, but not any longer");
|
||||
wasConnected = false;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
var devices = applicableDevices.ToList();
|
||||
foreach (var device in devices)
|
||||
{
|
||||
Logger.Debug($"Process monitor: test connection with {device.Name}...");
|
||||
var test = await device.TestConnection();
|
||||
Logger.Debug("Process monitor: test connection result: " + test);
|
||||
}
|
||||
|
||||
connectedDevices = applicableDevices.Where(d => d.IsConnected()).ToList();
|
||||
|
||||
if (!connectedDevices.Any())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!wasConnected)
|
||||
{
|
||||
Logger.Debug("Process monitor: TV(s) where not connected, but connection has now been established");
|
||||
wasConnected = true;
|
||||
}
|
||||
|
||||
if (connectedDevices.Any(d => d.PowerOffOnScreenSaver || d.PowerOnAfterScreenSaver))
|
||||
{
|
||||
lastProcessId = await HandleScreenSaverProcessAsync(lastProcessId, processes, connectedDevices);
|
||||
}
|
||||
|
||||
MonitorContext.Devices = connectedDevices.Where(d => d.TriggersEnabled).ToList();
|
||||
MonitorContext.RunningProcesses = processes;
|
||||
|
||||
await ExecuteProcessPresets(MonitorContext);
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
if (_poweredOffByScreenSaver && !_sessionSwitchDispatcher.UserLocalSession)
|
||||
{
|
||||
Logger.Error("CheckProcesses: " + ex.ToLogString());
|
||||
return;
|
||||
}
|
||||
|
||||
var processes = args.RunningProcesses;
|
||||
|
||||
if (_poweredOffByScreenSaver)
|
||||
{
|
||||
if (processes.Any(p => p.Id == _poweredOffByScreenSaverProcessId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.Debug("Screensaver stopped, waking");
|
||||
_poweredOffByScreenSaver = false;
|
||||
_poweredOffByScreenSaverProcessId = 0;
|
||||
WakeAfterStartupOrResume(PowerOnOffState.ScreenSaver);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var connectedDevices = applicableDevices.Where(d => d.IsConnected()).ToList();
|
||||
|
||||
if (!connectedDevices.Any())
|
||||
{
|
||||
if (wasConnected)
|
||||
{
|
||||
Logger.Debug("Process monitor: TV(s) where connected, but not any longer");
|
||||
wasConnected = false;
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
var devices = applicableDevices.ToList();
|
||||
foreach (var device in devices)
|
||||
{
|
||||
Logger.Debug($"Process monitor: test connection with {device.Name}...");
|
||||
var test = await device.TestConnection();
|
||||
Logger.Debug("Process monitor: test connection result: " + test);
|
||||
}
|
||||
|
||||
connectedDevices = applicableDevices.Where(d => d.IsConnected()).ToList();
|
||||
|
||||
if (!connectedDevices.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!wasConnected)
|
||||
{
|
||||
Logger.Debug("Process monitor: TV(s) where not connected, but connection has now been established");
|
||||
wasConnected = true;
|
||||
}
|
||||
|
||||
if (connectedDevices.Any(d => d.PowerOffOnScreenSaver || d.PowerOnAfterScreenSaver))
|
||||
{
|
||||
await HandleScreenSaverProcessAsync(processes, connectedDevices);
|
||||
}
|
||||
|
||||
await ExecuteProcessPresets(args, connectedDevices);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error("ProcessChanged: " + ex.ToLogString());
|
||||
}
|
||||
}
|
||||
|
||||
private void startWatch_EventArrived(object sender, EventArrivedEventArgs e)
|
||||
private async Task ExecuteProcessPresets(ProcessChangedEventArgs context, IList<LgDevice> connectedDevices)
|
||||
{
|
||||
//Logger.Debug("Process started: " + e.NewEvent.Properties["ProcessName"].Value);
|
||||
}
|
||||
var triggerDevices = connectedDevices.Where(d => d.TriggersEnabled).ToList();
|
||||
|
||||
private async Task<int> HandleScreenSaverProcessAsync(int lastProcessId, Process[] processes, List<LgDevice> connectedDevices)
|
||||
{
|
||||
var process = processes.FirstOrDefault(p => p.ProcessName.ToLowerInvariant().EndsWith(".scr"));
|
||||
|
||||
if (process == null)
|
||||
if (context.IsScreenSaverActive)
|
||||
{
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
var parent = process.Parent(processes);
|
||||
|
||||
if (parent?.ProcessName.Contains("winlogon") ?? false)
|
||||
{
|
||||
Logger.Debug($"Screensaver started: {process.ProcessName}, parent: {parent.ProcessName}");
|
||||
try
|
||||
{
|
||||
foreach (var device in connectedDevices.Where(d => d.PowerOffOnScreenSaver))
|
||||
{
|
||||
Logger.Debug($"Screensaver check: test connection with {device.Name}...");
|
||||
var test = await device.TestConnection();
|
||||
Logger.Debug("Screensaver check: test connection result: " + test);
|
||||
if (!test)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Logger.Debug($"Screensaver check: powering off tv {device.Name} because of screensaver");
|
||||
try
|
||||
{
|
||||
_poweredOffByScreenSaver = await device.PowerOff(true).WaitAsync(TimeSpan.FromSeconds(5));
|
||||
}
|
||||
catch (TimeoutException)
|
||||
{
|
||||
// Assume powering off was successful
|
||||
_poweredOffByScreenSaver = true;
|
||||
Logger.Error($"Screensaver check: timeout exception while powering off (probably connection closed)");
|
||||
}
|
||||
catch (Exception pex)
|
||||
{
|
||||
// Assume powering off was successful
|
||||
_poweredOffByScreenSaver = true;
|
||||
Logger.Error($"Screensaver check: exception while powering off (probably connection closed): " + pex.Message);
|
||||
}
|
||||
Logger.Debug($"Screensaver check: powered off tv {device.Name}");
|
||||
}
|
||||
|
||||
_poweredOffByScreenSaverProcessId = process.Id;
|
||||
lastProcessId = 0;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error($"Screensaver check: can't power off: " + e.ToLogString());
|
||||
}
|
||||
}
|
||||
else if (process.Id != lastProcessId)
|
||||
{
|
||||
Logger.Debug($"Screensaver started: {process.ProcessName}, but invalid parent: {parent?.ProcessName ?? "no parent"}");
|
||||
lastProcessId = process.Id;
|
||||
}
|
||||
|
||||
return lastProcessId;
|
||||
}
|
||||
|
||||
private async Task ExecuteProcessPresets(ProcessMonitorContext context)
|
||||
{
|
||||
var selectedDevice = SelectedDevice;
|
||||
|
||||
var presets = _presets.Where(p => p.Triggers.Any(t => t.Trigger == PresetTriggerType.ProcessSwitch) &&
|
||||
@@ -719,33 +627,6 @@ namespace ColorControl.Services.LG
|
||||
return;
|
||||
}
|
||||
|
||||
context.IsNotificationDisabled = FormUtils.IsNotificationDisabled();
|
||||
|
||||
var (processId, isFullScreen) = FormUtils.GetForegroundProcessIdAndIfFullScreen();
|
||||
|
||||
if (processId == Environment.ProcessId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (processId > 0)
|
||||
{
|
||||
var process = context.RunningProcesses.FirstOrDefault(p => p.Id == processId);
|
||||
|
||||
if (process?.ProcessName?.Contains(".scr") ?? false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
context.ForegroundProcess = process;
|
||||
context.ForegroundProcessIsFullScreen = isFullScreen;
|
||||
}
|
||||
else
|
||||
{
|
||||
context.ForegroundProcess = null;
|
||||
context.ForegroundProcessIsFullScreen = false;
|
||||
}
|
||||
|
||||
var changedProcesses = new List<Process>();
|
||||
if (context.ForegroundProcess != null)
|
||||
{
|
||||
@@ -754,23 +635,14 @@ namespace ColorControl.Services.LG
|
||||
|
||||
if (context.ForegroundProcess != null && context.ForegroundProcessIsFullScreen)
|
||||
{
|
||||
if (!context.LastFullScreenProcessName.Equals(context.ForegroundProcess.ProcessName))
|
||||
{
|
||||
context.LastFullScreenProcessName = context.ForegroundProcess.ProcessName;
|
||||
//Logger.Debug($"Foreground fullscreen app detected: {context.ForegroundProcess.ProcessName}");
|
||||
}
|
||||
|
||||
presets = presets.Where(p => p.Triggers.Any(t => t.Conditions.HasFlag(PresetConditionType.FullScreen)));
|
||||
context.WasFullScreen = true;
|
||||
}
|
||||
else if (context.WasFullScreen)
|
||||
else if (context.StoppedFullScreen)
|
||||
{
|
||||
presets = presets.Where(p => p.Triggers.Any(t => !t.Conditions.HasFlag(PresetConditionType.FullScreen)));
|
||||
context.WasFullScreen = false;
|
||||
context.LastFullScreenProcessName = string.Empty;
|
||||
}
|
||||
|
||||
var isHDRActive = context.Devices.Any(d => d.IsUsingHDRPictureMode());
|
||||
var isHDRActive = triggerDevices.Any(d => d.IsUsingHDRPictureMode());
|
||||
|
||||
var isGsyncActive = LgDevice.ExternalServiceHandler("GsyncEnabled", new[] { "" });
|
||||
|
||||
@@ -784,27 +656,11 @@ namespace ColorControl.Services.LG
|
||||
IsNotificationDisabled = context.IsNotificationDisabled
|
||||
};
|
||||
|
||||
var toApplyPresets = new List<LgPreset>();
|
||||
foreach (var preset in presets)
|
||||
{
|
||||
if (preset.Triggers.Any(t => t.TriggerActive(triggerContext)))
|
||||
{
|
||||
toApplyPresets.Add(preset);
|
||||
}
|
||||
}
|
||||
var toApplyPresets = presets.Where(p => p.Triggers.Any(t => t.TriggerActive(triggerContext))).ToList();
|
||||
|
||||
if (toApplyPresets.Any())
|
||||
{
|
||||
LgPreset toApplyPreset;
|
||||
if (toApplyPresets.Count > 1)
|
||||
{
|
||||
toApplyPreset = toApplyPresets.FirstOrDefault(p => p.Triggers.Any(t => !t.IncludedProcesses.Contains("*")));
|
||||
toApplyPreset = toApplyPreset != null ? toApplyPreset : toApplyPresets.First();
|
||||
}
|
||||
else
|
||||
{
|
||||
toApplyPreset = toApplyPresets.First();
|
||||
}
|
||||
var toApplyPreset = toApplyPresets.FirstOrDefault(p => toApplyPresets.Count == 1 || p.Triggers.Any(t => !t.IncludedProcesses.Contains("*"))) ?? toApplyPresets.First();
|
||||
|
||||
if (_lastTriggeredPreset != toApplyPreset)
|
||||
{
|
||||
@@ -815,6 +671,78 @@ namespace ColorControl.Services.LG
|
||||
}
|
||||
}
|
||||
|
||||
private async Task HandleScreenSaverProcessAsync(IList<Process> processes, List<LgDevice> connectedDevices)
|
||||
{
|
||||
var process = processes.FirstOrDefault(p => p.ProcessName.ToLowerInvariant().EndsWith(".scr"));
|
||||
|
||||
var powerOffDevices = connectedDevices.Where(d => d.PowerOffOnScreenSaver).ToList();
|
||||
|
||||
if (process == null)
|
||||
{
|
||||
powerOffDevices.ForEach(d => d.ClearPowerOffTask());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var parent = process.Parent(processes);
|
||||
|
||||
// Ignore manually started screen savers
|
||||
if (parent?.ProcessName.Contains("winlogon") != true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.Debug($"Screensaver started: {process.ProcessName}, parent: {parent.ProcessName}");
|
||||
try
|
||||
{
|
||||
foreach (var device in powerOffDevices)
|
||||
{
|
||||
Logger.Debug($"Screensaver check: test connection with {device.Name}...");
|
||||
var test = await device.TestConnection();
|
||||
Logger.Debug("Screensaver check: test connection result: " + test);
|
||||
if (!test)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (device.ScreenSaverMinimalDuration > 0)
|
||||
{
|
||||
_poweredOffByScreenSaver = true;
|
||||
|
||||
device.PowerOffIn(device.ScreenSaverMinimalDuration);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
Logger.Debug($"Screensaver check: powering off tv {device.Name} because of screensaver");
|
||||
try
|
||||
{
|
||||
_poweredOffByScreenSaver = await device.PowerOff(true).WaitAsync(TimeSpan.FromSeconds(5));
|
||||
}
|
||||
catch (TimeoutException)
|
||||
{
|
||||
// Assume powering off was successful
|
||||
_poweredOffByScreenSaver = true;
|
||||
Logger.Error($"Screensaver check: timeout exception while powering off (probably connection closed)");
|
||||
}
|
||||
catch (Exception pex)
|
||||
{
|
||||
// Assume powering off was successful
|
||||
_poweredOffByScreenSaver = true;
|
||||
Logger.Error($"Screensaver check: exception while powering off (probably connection closed): " + pex.Message);
|
||||
}
|
||||
Logger.Debug($"Screensaver check: powered off tv {device.Name}");
|
||||
}
|
||||
|
||||
_poweredOffByScreenSaverProcessId = process.Id;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error($"Screensaver check: can't power off: " + e.ToLogString());
|
||||
}
|
||||
}
|
||||
|
||||
internal void AddCustomDevice(LgDevice device)
|
||||
{
|
||||
Devices.Add(device);
|
||||
@@ -929,7 +857,7 @@ namespace ColorControl.Services.LG
|
||||
return;
|
||||
}
|
||||
|
||||
if (checkUserSession && !UserSessionInfo.UserLocalSession)
|
||||
if (checkUserSession && !_sessionSwitchDispatcher.UserLocalSession)
|
||||
{
|
||||
Logger.Debug($"WakeAfterStartupOrResume: not waking because session info indicates no local session");
|
||||
return;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using ColorControl.Common;
|
||||
using ColorControl.Forms;
|
||||
using ColorControl.Native;
|
||||
using NLog;
|
||||
using nspector;
|
||||
using nspector.Common;
|
||||
using nspector.Common.Meta;
|
||||
@@ -24,7 +23,7 @@ namespace ColorControl.Services.NVIDIA
|
||||
{
|
||||
public static readonly int SHORTCUTID_NVQA = -200;
|
||||
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
//private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
private Config _config;
|
||||
private NvService _nvService;
|
||||
|
||||
@@ -28,6 +28,7 @@ namespace ColorControl
|
||||
public bool RunningFromScheduledTask { get; private set; }
|
||||
public bool ActivateChromeFontFix { get; private set; }
|
||||
public bool DeactivateChromeFontFix { get; private set; }
|
||||
public string ChromeFontFixApplicationDataFolder { get; private set; }
|
||||
public bool ExecuteHelp { get; private set; }
|
||||
public bool ExecuteNvidiaPreset { get; private set; }
|
||||
public string NvidiaPresetIdOrName { get; private set; }
|
||||
@@ -63,6 +64,12 @@ namespace ColorControl
|
||||
{
|
||||
switch (parseNameParam)
|
||||
{
|
||||
case ActivateChromeFontFixParam:
|
||||
case DeactivateChromeFontFixParam:
|
||||
{
|
||||
settings.ChromeFontFixApplicationDataFolder = arg;
|
||||
break;
|
||||
}
|
||||
case ExecuteNvidiaPresetParam:
|
||||
{
|
||||
settings.NvidiaPresetIdOrName = arg;
|
||||
@@ -132,11 +139,13 @@ namespace ColorControl
|
||||
case ActivateChromeFontFixParam:
|
||||
{
|
||||
settings.ActivateChromeFontFix = true;
|
||||
parseNameParam = ActivateChromeFontFixParam;
|
||||
break;
|
||||
}
|
||||
case DeactivateChromeFontFixParam:
|
||||
{
|
||||
settings.DeactivateChromeFontFix = true;
|
||||
parseNameParam = DeactivateChromeFontFixParam;
|
||||
break;
|
||||
}
|
||||
case ExecuteHelpParam:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using ColorControl.Common;
|
||||
using ColorControl.Services.EventDispatcher;
|
||||
using ColorControl.Services.LG;
|
||||
using ColorControl.Services.NVIDIA;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
@@ -18,8 +19,14 @@ namespace ColorControl.Svc
|
||||
public sealed class ColorControlBackgroundService : BackgroundService
|
||||
{
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
private readonly SessionSwitchDispatcher _sessionSwitchDispatcher;
|
||||
private static string LgConfigFile = "LgConfig.json";
|
||||
|
||||
public ColorControlBackgroundService(SessionSwitchDispatcher sessionSwitchDispatcher)
|
||||
{
|
||||
_sessionSwitchDispatcher = sessionSwitchDispatcher;
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
try
|
||||
@@ -207,7 +214,7 @@ namespace ColorControl.Svc
|
||||
|
||||
private async Task WakeDevicesAsync()
|
||||
{
|
||||
if (!UserSessionInfo.UserLocalSession)
|
||||
if (!_sessionSwitchDispatcher.UserLocalSession)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetFramework>net7.0-windows10.0.20348.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<Nullable>enable</Nullable>
|
||||
@@ -10,7 +10,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Resources.Extensions" Version="6.0.0" />
|
||||
<PackageReference Include="System.Resources.Extensions" Version="7.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0-windows10.0.20348.0</TargetFramework>
|
||||
<Version>0.8.1.101</Version>
|
||||
<TargetFramework>net7.0-windows10.0.20348.0</TargetFramework>
|
||||
<Version>0.8.1.102</Version>
|
||||
<Company>falahati.net</Company>
|
||||
<Description>NvAPIWrapper is a .Net wrapper for NVIDIA public API</Description>
|
||||
<Authors>Soroush Falahati</Authors>
|
||||
|
||||
Reference in new issue
Block a user