diff --git a/ColorControl/ColorControl.csproj b/ColorControl/ColorControl.csproj
index 4a89af4..2e95144 100644
--- a/ColorControl/ColorControl.csproj
+++ b/ColorControl/ColorControl.csproj
@@ -18,8 +18,8 @@
Maassoft
Maassoft
0
- 5.6.0.0
- 5.6.0.0
+ 5.7.0.0
+ 5.7.0.0
false
true
false
diff --git a/ColorControl/LgDevice.cs b/ColorControl/LgDevice.cs
index e54b283..915cce2 100644
--- a/ColorControl/LgDevice.cs
+++ b/ColorControl/LgDevice.cs
@@ -53,7 +53,7 @@ namespace ColorControl
public static Func ExternalServiceHandler;
public static List DefaultActionsOnGameBar = new() { "backlight", "contrast", "brightness", "color" };
- public string Name { get; private set; }
+ public string Name { get; private set; }
public string IpAddress { get; private set; }
public string MacAddress { get; private set; }
public bool IsCustom { get; private set; }
@@ -66,7 +66,9 @@ namespace ColorControl
public bool PowerOffOnStandby { get; set; }
public bool PowerSwitchOnScreenSaver { get; set; }
public bool PowerOnAfterManualPowerOff { get; set; }
+ public bool PowerByWindows { get; set; }
public bool TriggersEnabled { get; set; }
+ public int HDMIPortNumber { get; set; }
private List _actionsForGameBar;
@@ -113,6 +115,9 @@ namespace ColorControl
[JsonIgnore]
public LgDevicePictureSettings PictureSettings { get; private set; }
+ [JsonIgnore]
+ public string CurrentAppId { get; private set; }
+
public event EventHandler PictureSettingsChangedEvent;
public event EventHandler PowerStateChangedEvent;
@@ -284,6 +289,7 @@ namespace ColorControl
//await _lgTvApi.SubscribeVolume(VolumeChanged);
await _lgTvApi.SubscribePowerState(PowerStateChanged);
await _lgTvApi.SubscribePictureSettings(PictureSettingsChanged);
+ await _lgTvApi.SubscribeForegroundApp(ForegroundAppChanged);
//await _lgTvApi.Reboot();
@@ -323,7 +329,7 @@ namespace ColorControl
{
var settings = payload.settings;
- Logger.Debug($"PictureSettingsChanged: {JsonConvert.SerializeObject(settings)}");
+ Logger.Debug($"[{Name}] PictureSettingsChanged: {JsonConvert.SerializeObject(settings)}");
if (settings.backlight != null)
{
@@ -385,6 +391,18 @@ namespace ColorControl
return true;
}
+ public bool ForegroundAppChanged(dynamic payload)
+ {
+ Logger.Debug($"[{Name}] ForegroundAppChanged: {JsonConvert.SerializeObject(payload)}");
+
+ if (payload.appId != null)
+ {
+ CurrentAppId = payload.appId;
+ }
+
+ return true;
+ }
+
public bool IsConnected()
{
return !_lgTvApi?.ConnectionClosed ?? false;
@@ -586,6 +604,11 @@ namespace ColorControl
public async Task> GetApps(bool force = false)
{
+ if (!force)
+ {
+ await Task.Delay(5000);
+ }
+
if (!await Connected(force))
{
Logger.Debug("Cannot refresh apps: no connection could be made");
@@ -595,17 +618,30 @@ namespace ColorControl
return await _lgTvApi.GetApps(force);
}
- internal async Task PowerOff()
+ internal async Task PowerOff(bool checkHdmi = false)
{
if (!await Connected(true) || CurrentState != PowerState.Active)
{
return false;
}
+ if (checkHdmi && CurrentAppId != null && HDMIPortNumber != 0 && !CurrentAppId.EndsWith($".hdmi{HDMIPortNumber}", StringComparison.InvariantCulture))
+ {
+ Logger.Debug($"[{Name}] PowerOff is ignored because current app {CurrentAppId} does not match configured HDMI port {HDMIPortNumber}");
+ return true;
+ }
+
PoweredOffViaApp = true;
_poweredOffViaAppDateTime = DateTimeOffset.Now;
- await _lgTvApi.TurnOff();
+ try
+ {
+ await _lgTvApi.TurnOff().WaitAsync(TimeSpan.FromSeconds(2));
+ }
+ catch (TimeoutException ex)
+ {
+ Logger.Debug($"Timeout when turning off tv: {ex.Message}");
+ }
return true;
}
@@ -702,15 +738,6 @@ namespace ColorControl
}
}
- if (result)
- {
- var resumeScript = Path.Combine(Program.DataDir, "ResumeScript.bat");
- if (File.Exists(resumeScript))
- {
- Utils.StartProcess(resumeScript, hidden: true);
- }
- }
-
return result;
}
diff --git a/ColorControl/LgService.cs b/ColorControl/LgService.cs
index 17a881c..fbd49ac 100644
--- a/ColorControl/LgService.cs
+++ b/ColorControl/LgService.cs
@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
+using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
@@ -23,6 +24,13 @@ namespace ColorControl
StandBy = 5
}
+ internal enum WindowsPowerSetting
+ {
+ Off = 0,
+ On = 1,
+ Dimmed = 2
+ }
+
internal class ProcessMonitorContext
{
public List Devices { get; set; }
@@ -66,6 +74,7 @@ namespace ColorControl
private Task _monitorTask;
private int _monitorTaskCounter;
private LgPreset _lastTriggeredPreset;
+ private RestartDetector _restartDetector;
public LgService(string dataPath, bool allowPowerOn) : base(dataPath, "LgPresets.json")
{
@@ -73,6 +82,8 @@ namespace ColorControl
LgPreset.LgApps = _lgApps;
+ _restartDetector = new RestartDetector();
+
LoadConfig();
LoadPresets();
LoadRemoteControlButtons();
@@ -140,21 +151,25 @@ namespace ColorControl
presets = JsonConvert.DeserializeObject>(json);
}
-
+
return presets;
}
private void LoadConfig()
{
_configFilename = Path.Combine(_dataPath, "LgConfig.json");
- if (File.Exists(_configFilename))
+ try
{
- Config = JsonConvert.DeserializeObject(File.ReadAllText(_configFilename));
+ if (File.Exists(_configFilename))
+ {
+ Config = JsonConvert.DeserializeObject(File.ReadAllText(_configFilename));
+ }
}
- else
+ catch (Exception ex)
{
- Config = new LgServiceConfig();
+ Logger.Error($"LoadConfig: {ex.Message}");
}
+ Config ??= new LgServiceConfig();
LgPreset.LgDevices = Config.Devices;
}
@@ -289,7 +304,7 @@ namespace ColorControl
Devices.RemoveAll(d => !d.IsCustom && !autoIpAddresses.Contains(d.IpAddress));
- var newAutoDevices = autoDevices.Where(ad => !Devices.Any(d => d.IpAddress.Equals(ad.IpAddress)));
+ var newAutoDevices = autoDevices.Where(ad => ad.IpAddress != null && !Devices.Any(d => d.IpAddress != null && d.IpAddress.Equals(ad.IpAddress)));
Devices.AddRange(newAutoDevices);
if (Devices.Any())
@@ -404,22 +419,6 @@ namespace ColorControl
return await SelectedDevice?.PowerOff();
}
- internal Task PowerOffOnShutdownOrResume(PowerOnOffState state = PowerOnOffState.ShutDown)
- {
- var devices = Devices.Where(d => state == PowerOnOffState.ShutDown && d.PowerOffOnShutdown ||
- state == PowerOnOffState.StandBy && d.PowerOffOnStandby);
-
- var tasks = new List();
- foreach (var device in devices)
- {
- var task = device.PowerOff();
-
- tasks.Add(task);
- }
-
- return Task.WhenAll(tasks.ToArray());
- }
-
internal bool WakeSelectedDevice()
{
return SelectedDevice?.Wake() ?? false;
@@ -427,26 +426,11 @@ namespace ColorControl
internal void WakeAfterStartupOrResume(PowerOnOffState state = PowerOnOffState.StartUp, bool checkUserSession = true)
{
- if (checkUserSession && !UserSessionInfo.UserLocalSession)
- {
- Logger.Debug($"WakeAfterStartupOrResume: not waking because session info indicates no local session");
- return;
- }
-
- var wakeDevices = Devices.Where(d => state == PowerOnOffState.StartUp && d.PowerOnAfterStartup ||
- state == PowerOnOffState.Resume && d.PowerOnAfterResume ||
+ var wakeDevices = Devices.Where(d => state == PowerOnOffState.StartUp && d.PowerOnAfterStartup ||
+ state == PowerOnOffState.Resume && d.PowerOnAfterResume ||
state == PowerOnOffState.ScreenSaver && d.PowerSwitchOnScreenSaver);
- foreach (var device in wakeDevices)
- {
- if (!device.PowerOnAfterManualPowerOff && device.PoweredOffBy == LgDevice.PowerOffSource.Manually)
- {
- Logger.Debug($"[{device.Name}]: device was manually powered off by user, not powering on");
- continue;
- }
- device.DisposeConnection();
- var _ = device.WakeAndConnectWithRetries(Config.PowerOnRetries);
- }
+ PowerOnDevices(wakeDevices, state, checkUserSession);
}
public void InstallEventHandlers()
@@ -492,27 +476,8 @@ namespace ColorControl
return;
}
- if (Devices.Any(d => d.PowerOffOnStandby))
- {
- NativeMethods.SetThreadExecutionState(NativeConstants.ES_CONTINUOUS | NativeConstants.ES_SYSTEM_REQUIRED | NativeConstants.ES_AWAYMODE_REQUIRED);
- try
- {
- var standByScript = Path.Combine(Program.DataDir, "StandByScript.bat");
- if (File.Exists(standByScript))
- {
- Utils.StartProcess(standByScript, hidden: true);
- }
-
- Logger.Debug("Powering off tv...");
- var task = PowerOffOnShutdownOrResume(PowerOnOffState.StandBy);
- Utils.WaitForTask(task);
- Logger.Debug("Done powering off tv");
- }
- finally
- {
- NativeMethods.SetThreadExecutionState(NativeConstants.ES_CONTINUOUS);
- }
- }
+ var devices = Devices.Where(d => d.PowerOffOnStandby);
+ PowerOffDevices(devices, PowerOnOffState.StandBy);
}
private void SessionEnded(object sender, SessionEndedEventArgs e)
@@ -644,84 +609,15 @@ namespace ColorControl
wasConnected = true;
}
+ if (connectedDevices.Any(d => d.PowerSwitchOnScreenSaver))
+ {
+ lastProcessId = await HandleScreenSaverProcessAsync(lastProcessId, processes, connectedDevices);
+ }
+
MonitorContext.Devices = connectedDevices.Where(d => d.TriggersEnabled).ToList();
MonitorContext.RunningProcesses = processes;
- //if (lastProcesses != null)
- //{
- // monitorContext.StartedProcesses = processes.Where(p => !lastProcesses.Any(lp => lp.Id == p.Id)).ToArray();
- // monitorContext.StoppedProcesses = lastProcesses.Where(lp => !processes.Any(p => p.Id == lp.Id)).ToArray();
- //}
- //else
- //{
- // monitorContext.StartedProcesses = null;
- // monitorContext.StoppedProcesses = null;
- //}
- //if (monitorContext.StartedProcesses?.Any() ?? false)
- //{
- // Logger.Debug("Started processes: " + string.Join(", ", monitorContext.StartedProcesses.Select(p => p.ProcessName)));
- //}
- //lastProcesses = processes;
-
- var process = processes.FirstOrDefault(p => p.ProcessName.ToLowerInvariant().EndsWith(".scr"));
-
- if (process != null)
- {
- 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)
- {
- 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().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;
- }
- }
- else
- {
- await ExecuteProcessPresets(MonitorContext);
- }
+ await ExecuteProcessPresets(MonitorContext);
}
catch (Exception ex)
{
@@ -730,12 +626,75 @@ namespace ColorControl
}
}
+ private async Task HandleScreenSaverProcessAsync(int lastProcessId, Process[] processes, List connectedDevices)
+ {
+ var process = processes.FirstOrDefault(p => p.ProcessName.ToLowerInvariant().EndsWith(".scr"));
+
+ if (process == null)
+ {
+ return 0;
+ }
+
+ 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)
+ {
+ 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().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) &&
- ((string.IsNullOrEmpty(p.DeviceMacAddress) && selectedDevice?.TriggersEnabled == true)
+ var presets = _presets.Where(p => p.Triggers.Any(t => t.Trigger == PresetTriggerType.ProcessSwitch) &&
+ ((string.IsNullOrEmpty(p.DeviceMacAddress) && selectedDevice?.TriggersEnabled == true)
|| Devices.Any(d => d.TriggersEnabled && p.DeviceMacAddress.Equals(d.MacAddress, StringComparison.OrdinalIgnoreCase))));
if (!presets.Any())
{
@@ -753,7 +712,14 @@ namespace ColorControl
if (processId > 0)
{
- context.ForegroundProcess = context.RunningProcesses.FirstOrDefault(p => p.Id == processId);
+ var process = context.RunningProcesses.FirstOrDefault(p => p.Id == processId);
+
+ if (process?.ProcessName?.Contains(".scr") ?? false)
+ {
+ return;
+ }
+
+ context.ForegroundProcess = process;
context.ForegroundProcessIsFullScreen = isFullScreen;
}
else
@@ -851,5 +817,122 @@ namespace ColorControl
SelectedDevice = Devices.Any() ? Devices.First() : null;
}
}
+
+ public void PowerSettingChanged(WindowsPowerSetting setting)
+ {
+ var devices = Devices.Where(d => d.PowerByWindows).ToList();
+
+ if (setting == WindowsPowerSetting.Off)
+ {
+ PowerOffDevices(devices, PowerOnOffState.StandBy);
+ }
+ else if (setting == WindowsPowerSetting.On)
+ {
+ PowerOnDevices(devices);
+ }
+ }
+
+ public void PowerOffDevices(IEnumerable devices, PowerOnOffState state = PowerOnOffState.ShutDown)
+ {
+ if (!devices.Any())
+ {
+ return;
+ }
+
+ if (NativeMethods.GetAsyncKeyState(NativeConstants.VK_CONTROL) < 0 || NativeMethods.GetAsyncKeyState(NativeConstants.VK_RCONTROL) < 0)
+ {
+ Logger.Debug("Not powering off because CONTROL-key is down");
+ return;
+ }
+
+ NativeMethods.SetThreadExecutionState(NativeConstants.ES_CONTINUOUS | NativeConstants.ES_SYSTEM_REQUIRED | NativeConstants.ES_AWAYMODE_REQUIRED);
+ try
+ {
+ if (state == PowerOnOffState.ShutDown)
+ {
+ var sleep = Config.ShutdownDelay;
+
+ Logger.Debug($"PowerOffDevices: Waiting for {sleep} milliseconds...");
+
+ while (sleep > 0 && _restartDetector?.PowerOffDetected == false)
+ {
+ Thread.Sleep(100);
+
+ if (_restartDetector != null && (_restartDetector.RestartDetected || _restartDetector.IsRebootInProgress()))
+ {
+ Logger.Debug("Not powering off because of a restart");
+ return;
+ }
+
+ sleep -= 100;
+ }
+ }
+ else if (state == PowerOnOffState.StandBy)
+ {
+ var standByScript = Path.Combine(Program.DataDir, "StandByScript.bat");
+ if (File.Exists(standByScript))
+ {
+ Utils.StartProcess(standByScript, hidden: true);
+ }
+ }
+
+ Logger.Debug("Powering off tv(s)...");
+ var tasks = new List();
+ foreach (var device in devices)
+ {
+ var task = device.PowerOff(true);
+
+ tasks.Add(task);
+ }
+
+ var waitTask = Task.WhenAll(tasks.ToArray());
+ Utils.WaitForTask(waitTask);
+ Logger.Debug("Done powering off tv(s)");
+ }
+ finally
+ {
+ NativeMethods.SetThreadExecutionState(NativeConstants.ES_CONTINUOUS);
+ }
+ }
+
+ public void PowerOnDevices(IEnumerable devices, PowerOnOffState state = PowerOnOffState.StartUp, bool checkUserSession = true)
+ {
+ if (!devices.Any())
+ {
+ return;
+ }
+
+ if (checkUserSession && !UserSessionInfo.UserLocalSession)
+ {
+ Logger.Debug($"WakeAfterStartupOrResume: not waking because session info indicates no local session");
+ return;
+ }
+
+ var resumeScript = Path.Combine(Program.DataDir, "ResumeScript.bat");
+
+ var tasks = new List();
+
+ foreach (var device in devices)
+ {
+ if (!device.PowerOnAfterManualPowerOff && device.PoweredOffBy == LgDevice.PowerOffSource.Manually)
+ {
+ Logger.Debug($"[{device.Name}]: device was manually powered off by user, not powering on");
+ continue;
+ }
+
+ device.DisposeConnection();
+
+ var task = device.WakeAndConnectWithRetries(Config.PowerOnRetries);
+ tasks.Add(task);
+ }
+
+ if (File.Exists(resumeScript))
+ {
+ var waitTask = Task.WhenAll(tasks.ToArray());
+ Utils.WaitForTask(waitTask);
+
+ Utils.StartProcess(resumeScript, hidden: true);
+ }
+ }
}
-}
+}
\ No newline at end of file
diff --git a/ColorControl/MainForm.Designer.cs b/ColorControl/MainForm.Designer.cs
index 7c9c856..c378320 100644
--- a/ColorControl/MainForm.Designer.cs
+++ b/ColorControl/MainForm.Designer.cs
@@ -104,9 +104,11 @@
this.lvAmdPresets = new System.Windows.Forms.ListView();
this.tabLG = new System.Windows.Forms.TabPage();
this.scLgController = new System.Windows.Forms.SplitContainer();
+ this.cbxLgPcHdmiPort = new System.Windows.Forms.ComboBox();
+ this.lblLgPcHdmiPort = new System.Windows.Forms.Label();
+ this.edtLgPresetDescription = new System.Windows.Forms.TextBox();
+ this.lblLgPresetDescription = new System.Windows.Forms.Label();
this.btnLgDeviceOptionsHelp = new System.Windows.Forms.Button();
- this.lblGameBarShortcut = new System.Windows.Forms.Label();
- this.edtLgGameBarShortcut = new System.Windows.Forms.TextBox();
this.btnLgGameBar = new System.Windows.Forms.Button();
this.btnLgPresetEditTriggerConditions = new System.Windows.Forms.Button();
this.edtLgPresetTriggerConditions = new System.Windows.Forms.TextBox();
@@ -172,6 +174,8 @@
this.lblFixChromeFontsDescription = new System.Windows.Forms.Label();
this.chkFixChromeFonts = new System.Windows.Forms.CheckBox();
this.grpLGOptions = new System.Windows.Forms.GroupBox();
+ this.lblGameBarShortcut = new System.Windows.Forms.Label();
+ this.edtLgGameBarShortcut = new System.Windows.Forms.TextBox();
this.lblLgOptionShutdownDelayHelp = new System.Windows.Forms.Label();
this.edtLgOptionShutdownDelay = new System.Windows.Forms.NumericUpDown();
this.lblLgOptionShutdownDelay = new System.Windows.Forms.Label();
@@ -201,8 +205,6 @@
this.lbPlugins = new System.Windows.Forms.ListBox();
this.label7 = new System.Windows.Forms.Label();
this.lblInfo = new System.Windows.Forms.Label();
- this.edtLgPresetDescription = new System.Windows.Forms.TextBox();
- this.lblLgPresetDescription = new System.Windows.Forms.Label();
this.tcMain.SuspendLayout();
this.tabNVIDIA.SuspendLayout();
this.mnuNvPresets.SuspendLayout();
@@ -988,11 +990,11 @@
//
// scLgController.Panel1
//
+ this.scLgController.Panel1.Controls.Add(this.cbxLgPcHdmiPort);
+ this.scLgController.Panel1.Controls.Add(this.lblLgPcHdmiPort);
this.scLgController.Panel1.Controls.Add(this.edtLgPresetDescription);
this.scLgController.Panel1.Controls.Add(this.lblLgPresetDescription);
this.scLgController.Panel1.Controls.Add(this.btnLgDeviceOptionsHelp);
- this.scLgController.Panel1.Controls.Add(this.lblGameBarShortcut);
- this.scLgController.Panel1.Controls.Add(this.edtLgGameBarShortcut);
this.scLgController.Panel1.Controls.Add(this.btnLgGameBar);
this.scLgController.Panel1.Controls.Add(this.btnLgPresetEditTriggerConditions);
this.scLgController.Panel1.Controls.Add(this.edtLgPresetTriggerConditions);
@@ -1040,6 +1042,56 @@
this.scLgController.SplitterWidth = 5;
this.scLgController.TabIndex = 43;
//
+ // cbxLgPcHdmiPort
+ //
+ this.cbxLgPcHdmiPort.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.cbxLgPcHdmiPort.FormattingEnabled = true;
+ this.cbxLgPcHdmiPort.Items.AddRange(new object[] {
+ "None",
+ "HDMI1",
+ "HDMI2",
+ "HDMI3",
+ "HDMI4"});
+ this.cbxLgPcHdmiPort.Location = new System.Drawing.Point(667, 42);
+ this.cbxLgPcHdmiPort.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ this.cbxLgPcHdmiPort.Name = "cbxLgPcHdmiPort";
+ this.cbxLgPcHdmiPort.Size = new System.Drawing.Size(86, 23);
+ this.cbxLgPcHdmiPort.TabIndex = 62;
+ this.cbxLgPcHdmiPort.SelectedIndexChanged += new System.EventHandler(this.cbxLgPcHdmiPort_SelectedIndexChanged);
+ //
+ // lblLgPcHdmiPort
+ //
+ this.lblLgPcHdmiPort.AutoSize = true;
+ this.lblLgPcHdmiPort.Location = new System.Drawing.Point(577, 45);
+ this.lblLgPcHdmiPort.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.lblLgPcHdmiPort.Name = "lblLgPcHdmiPort";
+ this.lblLgPcHdmiPort.Size = new System.Drawing.Size(84, 15);
+ this.lblLgPcHdmiPort.TabIndex = 61;
+ this.lblLgPcHdmiPort.Text = "PC HDMI port:";
+ //
+ // edtLgPresetDescription
+ //
+ this.edtLgPresetDescription.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.edtLgPresetDescription.Enabled = false;
+ this.edtLgPresetDescription.Location = new System.Drawing.Point(100, 469);
+ this.edtLgPresetDescription.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ this.edtLgPresetDescription.Multiline = true;
+ this.edtLgPresetDescription.Name = "edtLgPresetDescription";
+ this.edtLgPresetDescription.Size = new System.Drawing.Size(694, 43);
+ this.edtLgPresetDescription.TabIndex = 60;
+ //
+ // lblLgPresetDescription
+ //
+ this.lblLgPresetDescription.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this.lblLgPresetDescription.AutoSize = true;
+ this.lblLgPresetDescription.Location = new System.Drawing.Point(6, 474);
+ this.lblLgPresetDescription.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.lblLgPresetDescription.Name = "lblLgPresetDescription";
+ this.lblLgPresetDescription.Size = new System.Drawing.Size(70, 15);
+ this.lblLgPresetDescription.TabIndex = 59;
+ this.lblLgPresetDescription.Text = "Description:";
+ //
// btnLgDeviceOptionsHelp
//
this.btnLgDeviceOptionsHelp.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
@@ -1052,28 +1104,6 @@
this.btnLgDeviceOptionsHelp.UseVisualStyleBackColor = true;
this.btnLgDeviceOptionsHelp.Click += new System.EventHandler(this.btnLgDeviceOptionsHelp_Click);
//
- // lblGameBarShortcut
- //
- this.lblGameBarShortcut.AutoSize = true;
- this.lblGameBarShortcut.Location = new System.Drawing.Point(597, 45);
- this.lblGameBarShortcut.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
- this.lblGameBarShortcut.Name = "lblGameBarShortcut";
- this.lblGameBarShortcut.Size = new System.Drawing.Size(55, 15);
- this.lblGameBarShortcut.TabIndex = 57;
- this.lblGameBarShortcut.Text = "Shortcut:";
- //
- // edtLgGameBarShortcut
- //
- this.edtLgGameBarShortcut.Location = new System.Drawing.Point(667, 42);
- this.edtLgGameBarShortcut.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
- this.edtLgGameBarShortcut.Name = "edtLgGameBarShortcut";
- this.edtLgGameBarShortcut.ReadOnly = true;
- this.edtLgGameBarShortcut.Size = new System.Drawing.Size(128, 23);
- this.edtLgGameBarShortcut.TabIndex = 56;
- this.edtLgGameBarShortcut.TextChanged += new System.EventHandler(this.edtLgGameBarShortcut_TextChanged);
- this.edtLgGameBarShortcut.KeyDown += new System.Windows.Forms.KeyEventHandler(this.edtLgGameBarShortcut_KeyDown);
- this.edtLgGameBarShortcut.KeyUp += new System.Windows.Forms.KeyEventHandler(this.edtLgGameBarShortcut_KeyUp);
- //
// btnLgGameBar
//
this.btnLgGameBar.Location = new System.Drawing.Point(478, 40);
@@ -1606,7 +1636,8 @@
"Automatically power off on standby",
"Automatically power off/on when screensaver activates/deactivates",
"Power on even after manual power off",
- "Allow triggers to be fired for this device"});
+ "Allow triggers to be fired for this device",
+ "Use Windows power settings"});
this.clbLgPower.Location = new System.Drawing.Point(6, 70);
this.clbLgPower.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
this.clbLgPower.MultiColumn = true;
@@ -1805,6 +1836,8 @@
//
// grpLGOptions
//
+ this.grpLGOptions.Controls.Add(this.lblGameBarShortcut);
+ this.grpLGOptions.Controls.Add(this.edtLgGameBarShortcut);
this.grpLGOptions.Controls.Add(this.lblLgOptionShutdownDelayHelp);
this.grpLGOptions.Controls.Add(this.edtLgOptionShutdownDelay);
this.grpLGOptions.Controls.Add(this.lblLgOptionShutdownDelay);
@@ -1822,6 +1855,28 @@
this.grpLGOptions.TabStop = false;
this.grpLGOptions.Text = "LG controller";
//
+ // lblGameBarShortcut
+ //
+ this.lblGameBarShortcut.AutoSize = true;
+ this.lblGameBarShortcut.Location = new System.Drawing.Point(201, 127);
+ this.lblGameBarShortcut.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.lblGameBarShortcut.Name = "lblGameBarShortcut";
+ this.lblGameBarShortcut.Size = new System.Drawing.Size(108, 15);
+ this.lblGameBarShortcut.TabIndex = 59;
+ this.lblGameBarShortcut.Text = "Game Bar shortcut:";
+ //
+ // edtLgGameBarShortcut
+ //
+ this.edtLgGameBarShortcut.Location = new System.Drawing.Point(307, 121);
+ this.edtLgGameBarShortcut.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
+ this.edtLgGameBarShortcut.Name = "edtLgGameBarShortcut";
+ this.edtLgGameBarShortcut.ReadOnly = true;
+ this.edtLgGameBarShortcut.Size = new System.Drawing.Size(128, 23);
+ this.edtLgGameBarShortcut.TabIndex = 58;
+ this.edtLgGameBarShortcut.TextChanged += new System.EventHandler(this.edtLgGameBarShortcut_TextChanged);
+ this.edtLgGameBarShortcut.KeyDown += new System.Windows.Forms.KeyEventHandler(this.edtLgGameBarShortcut_KeyDown);
+ this.edtLgGameBarShortcut.KeyUp += new System.Windows.Forms.KeyEventHandler(this.edtLgGameBarShortcut_KeyUp);
+ //
// lblLgOptionShutdownDelayHelp
//
this.lblLgOptionShutdownDelayHelp.AutoSize = true;
@@ -2192,29 +2247,6 @@
this.lblInfo.TabIndex = 1;
this.lblInfo.Text = "Info";
//
- // edtLgPresetDescription
- //
- this.edtLgPresetDescription.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- this.edtLgPresetDescription.Enabled = false;
- this.edtLgPresetDescription.Location = new System.Drawing.Point(100, 469);
- this.edtLgPresetDescription.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
- this.edtLgPresetDescription.Multiline = true;
- this.edtLgPresetDescription.Name = "edtLgPresetDescription";
- this.edtLgPresetDescription.Size = new System.Drawing.Size(694, 43);
- this.edtLgPresetDescription.TabIndex = 60;
- //
- // lblLgPresetDescription
- //
- this.lblLgPresetDescription.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
- this.lblLgPresetDescription.AutoSize = true;
- this.lblLgPresetDescription.Location = new System.Drawing.Point(6, 474);
- this.lblLgPresetDescription.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
- this.lblLgPresetDescription.Name = "lblLgPresetDescription";
- this.lblLgPresetDescription.Size = new System.Drawing.Size(70, 15);
- this.lblLgPresetDescription.TabIndex = 59;
- this.lblLgPresetDescription.Text = "Description:";
- //
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
@@ -2440,8 +2472,6 @@
private System.Windows.Forms.CheckBox chkCheckForUpdates;
private System.Windows.Forms.CheckBox chkLgShowAdvancedActions;
private System.Windows.Forms.Button btnLgGameBar;
- private System.Windows.Forms.Label lblGameBarShortcut;
- private System.Windows.Forms.TextBox edtLgGameBarShortcut;
private System.Windows.Forms.CheckBox chkGdiScaling;
private System.Windows.Forms.Button btnLgDeviceOptionsHelp;
private System.Windows.Forms.Label lblLgOptionShutdownDelayHelp;
@@ -2449,6 +2479,10 @@
private System.Windows.Forms.Label lblLgOptionShutdownDelay;
private System.Windows.Forms.TextBox edtLgPresetDescription;
private System.Windows.Forms.Label lblLgPresetDescription;
+ private System.Windows.Forms.Label lblGameBarShortcut;
+ private System.Windows.Forms.TextBox edtLgGameBarShortcut;
+ private System.Windows.Forms.ComboBox cbxLgPcHdmiPort;
+ private System.Windows.Forms.Label lblLgPcHdmiPort;
}
}
diff --git a/ColorControl/MainForm.cs b/ColorControl/MainForm.cs
index 70db8eb..268c3b9 100644
--- a/ColorControl/MainForm.cs
+++ b/ColorControl/MainForm.cs
@@ -15,8 +15,8 @@ using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
+using System.Runtime.InteropServices;
using System.Text;
-using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
@@ -42,7 +42,6 @@ namespace ColorControl
private bool _disableEvents = false;
private Config _config;
private bool _setVisibleCalled = false;
- private RestartDetector _restartDetector;
private LgService _lgService;
@@ -63,6 +62,7 @@ namespace ColorControl
private LgGameBar _gameBarForm;
private KeyboardHookManager _keyboardHookManager;
+ private IntPtr _screenStateNotify;
public MainForm(AppContext appContext)
{
@@ -121,8 +121,7 @@ namespace ColorControl
InitInfo();
UserSessionInfo.Install();
-
- _restartDetector = new RestartDetector();
+ _screenStateNotify = Utils.RegisterPowerSettingNotification(Handle, ref Utils.GUID_CONSOLE_DISPLAY_STATE, 0);
//Scale(new SizeF(1.25F, 1.25F));
@@ -183,7 +182,7 @@ namespace ColorControl
try
{
_lgService = new LgService(_dataDir, StartUpParams.RunningFromScheduledTask);
- _lgService.RefreshDevices(afterStartUp: true).ContinueWith((_) => BeginInvoke(new Action(AfterLgServiceRefreshDevices)));
+ _lgService.RefreshDevices(afterStartUp: true).ContinueWith((_) => BeginInvoke(() => AfterLgServiceRefreshDevices()));
FillLgPresets();
@@ -232,7 +231,7 @@ namespace ColorControl
private void Invoke()
{
- BeginInvoke(new Action(ToggleGameBar));
+ BeginInvoke(() => ToggleGameBar());
}
private void AfterLgServiceRefreshDevices()
@@ -479,46 +478,13 @@ namespace ColorControl
GlobalSave();
- if (SystemShutdown && _lgService.Devices.Any(d => d.PowerOffOnShutdown))
+ if (SystemShutdown && _lgService != null)
{
Logger.Debug($"MainForm_FormClosing: SystemShutdown");
- if (NativeMethods.GetAsyncKeyState(NativeConstants.VK_CONTROL) < 0 || NativeMethods.GetAsyncKeyState(NativeConstants.VK_RCONTROL) < 0)
- {
- Logger.Debug("Not powering off because CONTROL-key is down");
- return;
- }
+ var devices = _lgService.Devices.Where(d => d.PowerOffOnShutdown);
- var sleep = _lgService.Config.ShutdownDelay;
-
- Logger.Debug($"MainForm_FormClosing: Waiting for {sleep} milliseconds...");
-
- NativeMethods.SetThreadExecutionState(NativeConstants.ES_CONTINUOUS | NativeConstants.ES_SYSTEM_REQUIRED | NativeConstants.ES_AWAYMODE_REQUIRED);
- try
- {
- while (sleep > 0 && _restartDetector?.PowerOffDetected == false)
- {
- Thread.Sleep(100);
-
- if (_restartDetector != null && (_restartDetector.RestartDetected || _restartDetector.IsRebootInProgress()))
- {
- Logger.Debug("Not powering off because of a restart");
- return;
- }
-
- sleep -= 100;
- }
-
- Logger.Debug("Powering off tv...");
- var task = _lgService.PowerOffOnShutdownOrResume();
- Utils.WaitForTask(task);
- Logger.Debug("Done powering off tv");
- //ExecPowerOffPreset(true);
- }
- finally
- {
- NativeMethods.SetThreadExecutionState(NativeConstants.ES_CONTINUOUS);
- }
+ _lgService.PowerOffDevices(devices);
}
}
@@ -626,6 +592,26 @@ namespace ColorControl
Logger.Debug("WM_BRINGTOFRONT message received, opening form");
OpenForm(this, EventArgs.Empty);
}
+ else if (m.Msg == NativeConstants.WM_SYSCOMMAND)
+ {
+ //Logger.Debug($"WM_SYSCOMMAND: {m.WParam.ToInt32()}");
+
+ if (m.WParam.ToInt32() == NativeConstants.SC_MONITORPOWER)
+ {
+
+ }
+ }
+ else if (m.Msg == NativeConstants.WM_POWERBROADCAST)
+ {
+ if (m.WParam.ToInt32() == Utils.PBT_POWERSETTINGCHANGE)
+ {
+ var ps = Marshal.PtrToStructure(m.LParam);
+
+ Logger.Debug($"PBT_POWERSETTINGCHANGE: {ps.Data}");
+
+ _lgService?.PowerSettingChanged((LgService.WindowsPowerSetting)ps.Data);
+ }
+ }
base.WndProc(ref m);
}
@@ -668,6 +654,12 @@ namespace ColorControl
{
// Hide tray icon, otherwise it will remain shown until user mouses over it
_trayIcon.Visible = false;
+
+ if (_screenStateNotify != IntPtr.Zero)
+ {
+ Utils.UnregisterPowerSettingNotification(_screenStateNotify);
+ _screenStateNotify = IntPtr.Zero;
+ }
}
private void MainForm_Resize(object sender, EventArgs e)
@@ -781,7 +773,7 @@ namespace ColorControl
if (_lgService == null)
{
ShowControls(tabLG, false, lblLgError);
- lblLgError.Text = "Error while initializing the LG-controller. You either don't have a LG TV or it is disabled.";
+ lblLgError.Text = "Error while initializing the LG-controller. You either don't have a LG TV, it is disabled or a configuration file is corrupt.";
lblLgError.Visible = true;
}
@@ -1404,6 +1396,11 @@ namespace ColorControl
private void InitLgTab()
{
+ if (_lgService == null)
+ {
+ return;
+ }
+
if (scLgController.Panel2.Controls.Count == 0)
{
var rcPanel = new RemoteControlPanel(_lgService, _lgService.GetRemoteControlButtons());
@@ -1501,7 +1498,7 @@ namespace ColorControl
if (cbxLgApps.Items.Count == 0 && device != null)
{
- _lgService.RefreshApps().ContinueWith((task) => BeginInvoke(new Action(FillLgApps)));
+ _lgService.RefreshApps().ContinueWith((task) => BeginInvoke(() => FillLgApps(false)));
}
btnLgDeviceConvertToCustom.Enabled = devices.Any();
@@ -1526,6 +1523,7 @@ namespace ColorControl
clbLgPower.SetItemChecked(4, device?.PowerSwitchOnScreenSaver ?? false);
clbLgPower.SetItemChecked(5, device?.PowerOnAfterManualPowerOff ?? false);
clbLgPower.SetItemChecked(6, device?.TriggersEnabled ?? true);
+ clbLgPower.SetItemChecked(7, device?.PowerByWindows ?? false);
}
finally
{
@@ -1533,10 +1531,10 @@ namespace ColorControl
}
}
- private void FillLgApps()
+ private void FillLgApps(bool forced)
{
var lgApps = _lgService?.GetApps();
- if (lgApps == null || !lgApps.Any())
+ if (forced && (lgApps == null || !lgApps.Any()))
{
MessageForms.WarningOk("Could not refresh the apps. Check the log for details.");
return;
@@ -1769,7 +1767,7 @@ namespace ColorControl
return;
}
- var applyTask = _lgService.ApplyPreset(preset, reconnect).ContinueWith((task) => BeginInvoke(new Action>(LgPresetApplied), new[] { task }));
+ var applyTask = _lgService.ApplyPreset(preset, reconnect).ContinueWith((task) => BeginInvoke(() => LgPresetApplied(task)));
if (wait)
{
Utils.WaitForTask(applyTask);
@@ -1807,18 +1805,21 @@ namespace ColorControl
private void btnLgRefreshApps_Click(object sender, EventArgs e)
{
- _lgService.RefreshApps(true).ContinueWith((task) => BeginInvoke(new Action(FillLgApps)));
+ _lgService.RefreshApps(true).ContinueWith((task) => BeginInvoke(() => FillLgApps(true)));
}
private void cbxLgDevices_SelectedIndexChanged(object sender, EventArgs e)
{
+ cbxLgPcHdmiPort.Enabled = cbxLgDevices.SelectedIndex > -1;
if (cbxLgDevices.SelectedIndex == -1)
{
_lgService.SelectedDevice = null;
+ cbxLgPcHdmiPort.SelectedIndex = 0;
}
else
{
_lgService.SelectedDevice = (LgDevice)cbxLgDevices.SelectedItem;
+ cbxLgPcHdmiPort.SelectedIndex = _lgService.SelectedDevice.HDMIPortNumber;
}
chkLgRemoteControlShow.Enabled = _lgService.SelectedDevice != null;
btnLgRemoveDevice.Enabled = _lgService.SelectedDevice != null && _lgService.SelectedDevice.IsCustom;
@@ -2006,7 +2007,7 @@ You can also activate this option by using the Expert-button and selecting Wake-
);
}
- BeginInvoke(new Action(() =>
+ BeginInvoke(() =>
{
device.PowerOnAfterStartup = clbLgPower.GetItemChecked(0);
device.PowerOnAfterResume = clbLgPower.GetItemChecked(1);
@@ -2015,9 +2016,10 @@ You can also activate this option by using the Expert-button and selecting Wake-
device.PowerSwitchOnScreenSaver = clbLgPower.GetItemChecked(4);
device.PowerOnAfterManualPowerOff = clbLgPower.GetItemChecked(5);
device.TriggersEnabled = clbLgPower.GetItemChecked(6);
+ device.PowerByWindows = clbLgPower.GetItemChecked(7);
_lgService.InstallEventHandlers();
- }));
+ });
}
private void edtLgPowerOnAfterResumeDelay_ValueChanged(object sender, EventArgs e)
@@ -2123,7 +2125,7 @@ Do you want to continue?";
private void RefreshLgDevices()
{
- _lgService.RefreshDevices(false).ContinueWith((task) => BeginInvoke(new Action(FillLgDevices)));
+ _lgService.RefreshDevices(false).ContinueWith((task) => BeginInvoke(() => FillLgDevices()));
}
private void FillGradient()
@@ -2211,7 +2213,7 @@ Do you want to continue?";
private void InitHandleCheckForUpdates(dynamic latest)
{
- BeginInvoke(new Action(HandleCheckForUpdates), new[] { latest });
+ BeginInvoke(() => HandleCheckForUpdates(latest));
}
private void HandleCheckForUpdates(dynamic latest)
@@ -2267,7 +2269,7 @@ Do you want to continue?";
Task.Run(async () =>
{
await Task.Delay(2000);
- BeginInvoke(new Action(() => ApplyNvPresetOnStartup(attempts)));
+ BeginInvoke(() => ApplyNvPresetOnStartup(attempts));
});
}
}
@@ -2303,7 +2305,7 @@ Do you want to continue?";
Task.Run(async () =>
{
await Task.Delay(2000);
- BeginInvoke(new Action(() => ApplyAmdPresetOnStartup(attempts)));
+ BeginInvoke(() => ApplyAmdPresetOnStartup(attempts));
});
}
}
@@ -3131,6 +3133,7 @@ The InStart and Software Update items are now visible under the Expert-button."
- power on after startup requires ""Automatically start after login"" - see Options
- power on after resume from standby may need some retries for waking TV - see Options
- power off on shutdown: because this app cannot detect a restart, restarting could also trigger this. Hold down Ctrl on restart to prevent power off.
+- Use Windows power settings: powering on/off of TV will follow Windows settings. If activated, it's better to disable all other power options except power off on shutdown.
");
}
@@ -3138,5 +3141,15 @@ The InStart and Software Update items are now visible under the Expert-button."
{
_lgService.Config.ShutdownDelay = (int)edtLgOptionShutdownDelay.Value;
}
+
+ private void cbxLgPcHdmiPort_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ if (_lgService?.SelectedDevice == null)
+ {
+ return;
+ }
+
+ _lgService.SelectedDevice.HDMIPortNumber = cbxLgPcHdmiPort.SelectedIndex;
+ }
}
}
\ No newline at end of file
diff --git a/ColorControl/Program.cs b/ColorControl/Program.cs
index fcf84b6..dada269 100644
--- a/ColorControl/Program.cs
+++ b/ColorControl/Program.cs
@@ -118,15 +118,19 @@ namespace ColorControl
{
ConfigFilename = Path.Combine(DataDir, "Settings.json");
- if (File.Exists(ConfigFilename))
+ try
{
- var data = File.ReadAllText(ConfigFilename);
- Config = JsonConvert.DeserializeObject(data);
+ if (File.Exists(ConfigFilename))
+ {
+ var data = File.ReadAllText(ConfigFilename);
+ Config = JsonConvert.DeserializeObject(data);
+ }
}
- else
+ catch (Exception ex)
{
- Config = new Config();
+ Logger.Error($"LoadConfig: {ex.Message}");
}
+ Config ??= new Config();
}
private static bool HandleStartupParams(StartUpParams startUpParams, Process existingProcess)
diff --git a/ColorControl/Utils.cs b/ColorControl/Utils.cs
index 7c92bcd..8b614d6 100644
--- a/ColorControl/Utils.cs
+++ b/ColorControl/Utils.cs
@@ -53,6 +53,14 @@ namespace ColorControl
UserNotificationState.QUNS_PRESENTATION_MODE,
};
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ internal struct POWERBROADCAST_SETTING
+ {
+ public Guid PowerSetting;
+ public uint DataLength;
+ public byte Data;
+ }
+
public const int WM_BRINGTOFRONT = NativeConstants.WM_USER + 1;
public const int ENUM_CURRENT_SETTINGS = -1;
@@ -60,6 +68,8 @@ namespace ColorControl
public static string PKEY_PNPX_IpAddress = "{656a3bb3-ecc0-43fd-8477-4ae0404a96cd} 12297";
public static string PKEY_PNPX_PhysicalAddress = "{656a3bb3-ecc0-43fd-8477-4ae0404a96cd} 12294";
+ public static Guid GUID_CONSOLE_DISPLAY_STATE = Guid.Parse("6FE69556-704A-47A0-8F24-C28D936FDA47");
+ public static int PBT_POWERSETTINGCHANGE = 32787;
public delegate void PCREATE_PROCESS_NOTIFY_ROUTINE(IntPtr ParentId, IntPtr ProcessId, bool Create);
@@ -96,6 +106,12 @@ namespace ColorControl
[DllImport("user32.dll", SetLastError = true)]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
+ [DllImport(@"User32", SetLastError = true)]
+ public static extern IntPtr RegisterPowerSettingNotification(IntPtr hRecipient, ref Guid PowerSettingGuid, Int32 Flags);
+
+ [DllImport("User32.dll", SetLastError = true)]
+ public static extern bool UnregisterPowerSettingNotification(IntPtr hWnd);
+
//[DllImport("Wtsapi32.dll")]
//public extern static bool WTSRegisterSessionNotification(IntPtr hWnd, uint dwFlags);
diff --git a/ColorControl/lgtv/LgTvApi.cs b/ColorControl/lgtv/LgTvApi.cs
index b5e7b93..bdb9d15 100644
--- a/ColorControl/lgtv/LgTvApi.cs
+++ b/ColorControl/lgtv/LgTvApi.cs
@@ -491,6 +491,13 @@ namespace LgTv
await _connection.SubscribeAsync(requestMessage, callback);
}
+ public async Task SubscribeForegroundApp(Func callback, dynamic payload = null)
+ {
+ var requestMessage = new RequestMessage("ssap://com.webos.applicationManager/getForegroundAppInfo", null, "subscribe");
+
+ await _connection.SubscribeAsync(requestMessage, callback);
+ }
+
public async Task SubscribePictureSettings(Func callback, dynamic payload = null)
{
if (payload == null)