diff --git a/ColorControl/App.config b/ColorControl/App.config index 7d67223..f79ebd0 100644 --- a/ColorControl/App.config +++ b/ColorControl/App.config @@ -9,6 +9,14 @@ + + + + + + + + diff --git a/ColorControl/ColorControl.csproj b/ColorControl/ColorControl.csproj index cbecb74..af8ce9f 100644 --- a/ColorControl/ColorControl.csproj +++ b/ColorControl/ColorControl.csproj @@ -26,8 +26,8 @@ https://www.maassoft.com/downloads/ColorControl/ ColorControl Maassoft - 1 - 1.0.3.%2a + 0 + 1.1.0.%2a false true true @@ -122,11 +122,31 @@ ..\packages\NWin32.1.0.6\lib\net46\NWin32.dll + + ..\packages\PacketDotNet.1.0.5\lib\net45\PacketDotNet.dll + + + + ..\packages\SharpPcap.5.2.0\lib\netstandard2.0\SharpPcap.dll + + + ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + + ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll + + + + ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll + False @@ -149,8 +169,12 @@ ..\..\..\..\..\..\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.18362.0\Windows.winmd + + + + @@ -234,5 +258,16 @@ + + + {F935DC20-1CF0-11D0-ADB9-00C04FD58A0B} + 1 + 0 + 0 + tlbimp + False + True + + \ No newline at end of file diff --git a/ColorControl/Config.cs b/ColorControl/Config.cs index 12c055d..a33af3d 100644 --- a/ColorControl/Config.cs +++ b/ColorControl/Config.cs @@ -6,9 +6,17 @@ public int DisplaySettingsDelay { get; set; } + public string ScreenSaverShortcut { get; set; } + + public int FormWidth { get; set; } + public int FormHeight { get; set; } + public Config() { DisplaySettingsDelay = 1000; + ScreenSaverShortcut = string.Empty; + FormWidth = 900; + FormHeight = 600; } } } diff --git a/ColorControl/ExceptionExtensions.cs b/ColorControl/ExceptionExtensions.cs index 8feafdb..4ad20dc 100644 --- a/ColorControl/ExceptionExtensions.cs +++ b/ColorControl/ExceptionExtensions.cs @@ -16,7 +16,7 @@ namespace ColorControl /// /// Exception object. /// Environment stack trace, for pulling additional stack frames. - public static string ToLogString(this Exception exception, string environmentStackTrace) + public static string ToLogString(this Exception exception, string environmentStackTrace = "") { List environmentStackTraceLines = ExceptionExtensions.GetUserStackTraceLines(environmentStackTrace); environmentStackTraceLines.RemoveAt(0); diff --git a/ColorControl/LgService.cs b/ColorControl/LgService.cs index eab0044..0dd8ff6 100644 --- a/ColorControl/LgService.cs +++ b/ColorControl/LgService.cs @@ -1,4 +1,6 @@ using LgTv; +using Newtonsoft.Json; +using NLog.Config; using System; using System.Collections.Generic; using System.Diagnostics; @@ -17,6 +19,8 @@ namespace ColorControl public static string LgControllerExe = "LgController.exe"; public static string LgListAppsJson = "listApps.json"; + public static string LgDeviceSearchKey = "OLED55C9PLA"; + private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); public string FriendlyScreenName { get; private set; } @@ -24,10 +28,19 @@ namespace ColorControl public List Devices { get; private set; } public PnpDev SelectedDevice { get; set; } - private LgTvApi _lgTvApi; + public LgServiceConfig Config { get; private set; } - public LgService() + private LgTvApi _lgTvApi; + private string _dataDir; + private string _configFilename; + private bool _allowPowerOn; + + public LgService(string dataDir, bool allowPowerOn) { + _dataDir = dataDir; + _allowPowerOn = allowPowerOn; + LoadConfig(); + foreach (var screen in Screen.AllScreens) { var name = screen.DeviceFriendlyName(); @@ -42,17 +55,44 @@ namespace ColorControl ~LgService() { + SaveConfig(); + } + + private void LoadConfig() + { + _configFilename = Path.Combine(_dataDir, "LgConfig.json"); + if (File.Exists(_configFilename)) + { + Config = JsonConvert.DeserializeObject(File.ReadAllText(_configFilename)); + } + else + { + Config = new LgServiceConfig(); + } + } + + public void SaveConfig() + { + var json = JsonConvert.SerializeObject(Config); + File.WriteAllText(_configFilename, json); } public void RefreshDevices(Action callBack = null) { - Utils.GetPnpDevices("[LG]", Utils.PKEY_PNPX_IpAddress).ContinueWith((task) => + Utils.GetPnpDevices(LgDeviceSearchKey).ContinueWith((task) => { SetDevicesTask(task); callBack?.Invoke(); if (callBack == null && SelectedDevice != null) { - ConnectToSelectedDevice(); + if (Config.PowerOnAfterStartup && _allowPowerOn) + { + WakeAndConnectToSelectedDevice(0); + } + else + { + ConnectToSelectedDevice(); + } } } ); @@ -67,23 +107,23 @@ namespace ColorControl } } - public async Task ConnectToSelectedDevice(int retries = 1) + public async Task ConnectToSelectedDevice(int retries = 3) { try { DisposeConnection(); - _lgTvApi = await LgTvApi.CreateLgTvApi(SelectedDevice.ipAddress, retries); - return true; + _lgTvApi = await LgTvApi.CreateLgTvApi(SelectedDevice.IpAddress, retries); + return _lgTvApi != null; } catch (Exception ex) { string logMessage = ex.ToLogString(Environment.StackTrace); - Logger.Error($"Error while connecting to {SelectedDevice.ipAddress}: {logMessage}"); + Logger.Error($"Error while connecting to {SelectedDevice.IpAddress}: {logMessage}"); return false; } } - public async Task ApplyPreset(LgPreset preset, bool reconnect = false) + private async Task Connected(bool reconnect = false) { if (SelectedDevice == null) { @@ -91,7 +131,7 @@ namespace ColorControl return false; } - if (reconnect || _lgTvApi == null || !string.Equals(_lgTvApi.GetIpAddress(), SelectedDevice.ipAddress)) + if (reconnect || _lgTvApi == null || !string.Equals(_lgTvApi.GetIpAddress(), SelectedDevice.IpAddress)) { if (!await ConnectToSelectedDevice()) { @@ -99,6 +139,16 @@ namespace ColorControl return false; } } + return true; + } + + + public async Task ApplyPreset(LgPreset preset, bool reconnect = false) + { + if (!await Connected(reconnect)) + { + return false; + } var hasApp = !string.IsNullOrEmpty(preset.appId); @@ -128,6 +178,12 @@ namespace ColorControl return true; } + public async Task PowerOn() + { + var mouse = await _lgTvApi.GetMouse(); + mouse.SendButton(ButtonType.POWER); + } + private async Task ExecuteSteps(LgTvApi api, LgPreset preset) { var mouse = await api.GetMouse(); @@ -164,7 +220,7 @@ namespace ColorControl return null; } - var api = await LgTvApi.CreateLgTvApi(SelectedDevice.ipAddress); + var api = await LgTvApi.CreateLgTvApi(SelectedDevice.IpAddress); var list = await api.GetApps(force); return list.ToList(); @@ -178,5 +234,63 @@ namespace ColorControl _lgTvApi = null; } } + + internal async Task PowerOff() + { + if (!await Connected(true)) + { + return false; + } + + await _lgTvApi.TurnOff(); + return true; + } + + internal void WakeSelectedDevice() + { + if (SelectedDevice != null) + { + WOL.WakeFunction(SelectedDevice.MacAddress); + } + else + { + Logger.Debug("Cannot wake device: no device has been selected"); + } + } + + internal void WakeAfterResume() + { + if (Config.PowerOnAfterResume) + { + WakeAndConnectToSelectedDevice(Config.PowerOnDelayAfterResume); + } + } + + private void WakeAndConnectToSelectedDevice(int wakeDelay = 5000, int connectDelay = 1000) + { + Task.Run(async () => + { + try + { + //if (wakeDelay == 0) + //{ + // if (await ConnectToSelectedDevice()) + // { + // Logger.Debug("Already connected, no wake needed?"); + // return; + // }; + //} + + await Task.Delay(wakeDelay); + WakeSelectedDevice(); + await Task.Delay(connectDelay); + await ConnectToSelectedDevice(); + } + catch (Exception e) + { + Logger.Error("WakeAndConnectToSelectedDevice: " + e.ToLogString()); + } + }); + } } } diff --git a/ColorControl/LgServiceConfig.cs b/ColorControl/LgServiceConfig.cs new file mode 100644 index 0000000..833c4f5 --- /dev/null +++ b/ColorControl/LgServiceConfig.cs @@ -0,0 +1,20 @@ +namespace ColorControl +{ + class LgServiceConfig + { + public bool PowerOnAfterStartup { get; set; } + + public bool PowerOnAfterResume { get; set; } + + public bool PowerOffOnShutdown { get; set; } + + public bool PowerOffOnStandby { get; set; } + + public int PowerOnDelayAfterResume { get; set; } + + public LgServiceConfig() + { + PowerOnDelayAfterResume = 5000; + } + } +} diff --git a/ColorControl/MainForm.Designer.cs b/ColorControl/MainForm.Designer.cs index 075fca9..54d2c33 100644 --- a/ColorControl/MainForm.Designer.cs +++ b/ColorControl/MainForm.Designer.cs @@ -59,6 +59,7 @@ this.btnApply = new System.Windows.Forms.Button(); this.lvNvPresets = new System.Windows.Forms.ListView(); this.tabLG = new System.Windows.Forms.TabPage(); + this.clbLgPower = new System.Windows.Forms.CheckedListBox(); this.btnLgAddButton = new System.Windows.Forms.Button(); this.mnuLgButtons = new System.Windows.Forms.ContextMenuStrip(this.components); this.label3 = new System.Windows.Forms.Label(); @@ -82,10 +83,21 @@ this.btnApplyLg = new System.Windows.Forms.Button(); this.lvLgPresets = new System.Windows.Forms.ListView(); this.tabOptions = new System.Windows.Forms.TabPage(); - this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.grpMiscellaneousOptions = new System.Windows.Forms.GroupBox(); + this.btnSetShortcutScreenSaver = new System.Windows.Forms.Button(); + this.label11 = new System.Windows.Forms.Label(); + this.edtBlankScreenSaverShortcut = new System.Windows.Forms.TextBox(); + this.label10 = new System.Windows.Forms.Label(); + this.chkFixChromeFonts = new System.Windows.Forms.CheckBox(); + this.grpLGOptions = new System.Windows.Forms.GroupBox(); + this.btnLGTestPower = new System.Windows.Forms.Button(); + this.label9 = new System.Windows.Forms.Label(); + this.edtLgPowerOnAfterResumeDelay = new System.Windows.Forms.NumericUpDown(); + this.label8 = new System.Windows.Forms.Label(); + this.grpHDROptions = new System.Windows.Forms.GroupBox(); this.edtDelayDisplaySettings = new System.Windows.Forms.NumericUpDown(); this.label6 = new System.Windows.Forms.Label(); - this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.grpGeneralOptions = new System.Windows.Forms.GroupBox(); this.chkStartMinimized = new System.Windows.Forms.CheckBox(); this.chkStartAfterLogin = new System.Windows.Forms.CheckBox(); this.tabLog = new System.Windows.Forms.TabPage(); @@ -103,9 +115,12 @@ this.mnuNvPresets.SuspendLayout(); this.tabLG.SuspendLayout(); this.tabOptions.SuspendLayout(); - this.groupBox2.SuspendLayout(); + this.grpMiscellaneousOptions.SuspendLayout(); + this.grpLGOptions.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.edtLgPowerOnAfterResumeDelay)).BeginInit(); + this.grpHDROptions.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.edtDelayDisplaySettings)).BeginInit(); - this.groupBox1.SuspendLayout(); + this.grpGeneralOptions.SuspendLayout(); this.tabLog.SuspendLayout(); this.tabInfo.SuspendLayout(); this.grpNVIDIAInfo.SuspendLayout(); @@ -400,6 +415,7 @@ // // tabLG // + this.tabLG.Controls.Add(this.clbLgPower); this.tabLG.Controls.Add(this.btnLgAddButton); this.tabLG.Controls.Add(this.label3); this.tabLG.Controls.Add(this.cbxLgDevices); @@ -429,6 +445,27 @@ this.tabLG.Text = "LG controller"; this.tabLG.UseVisualStyleBackColor = true; // + // clbLgPower + // + this.clbLgPower.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.clbLgPower.CheckOnClick = true; + this.clbLgPower.FormattingEnabled = true; + this.clbLgPower.Items.AddRange(new object[] { + "Automatically power on after startup. Requires \"Automatically start after login\" " + + "- see Options.", + "Automatically power on after resume from standby. Needs a system dependent delay " + + "before waking TV, see Options.", + "Automatically power off on shutdown. Because this app cannot detect a restart, re" + + "starting could also trigger this. Hold down SHIFT on restart to prevent power of" + + "f.", + "Automatically power off on standby"}); + this.clbLgPower.Location = new System.Drawing.Point(6, 33); + this.clbLgPower.Name = "clbLgPower"; + this.clbLgPower.Size = new System.Drawing.Size(829, 64); + this.clbLgPower.TabIndex = 34; + this.clbLgPower.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.clbLgPower_ItemCheck); + // // btnLgAddButton // this.btnLgAddButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); @@ -525,7 +562,7 @@ // label4 // this.label4.AutoSize = true; - this.label4.Location = new System.Drawing.Point(384, 10); + this.label4.Location = new System.Drawing.Point(466, 9); this.label4.Name = "label4"; this.label4.Size = new System.Drawing.Size(110, 13); this.label4.TabIndex = 24; @@ -534,7 +571,7 @@ // edtLgTvName // this.edtLgTvName.Enabled = false; - this.edtLgTvName.Location = new System.Drawing.Point(497, 7); + this.edtLgTvName.Location = new System.Drawing.Point(579, 6); this.edtLgTvName.Name = "edtLgTvName"; this.edtLgTvName.Size = new System.Drawing.Size(142, 20); this.edtLgTvName.TabIndex = 23; @@ -654,10 +691,10 @@ | System.Windows.Forms.AnchorStyles.Right))); this.lvLgPresets.FullRowSelect = true; this.lvLgPresets.HideSelection = false; - this.lvLgPresets.Location = new System.Drawing.Point(6, 33); + this.lvLgPresets.Location = new System.Drawing.Point(6, 103); this.lvLgPresets.MultiSelect = false; this.lvLgPresets.Name = "lvLgPresets"; - this.lvLgPresets.Size = new System.Drawing.Size(829, 315); + this.lvLgPresets.Size = new System.Drawing.Size(829, 245); this.lvLgPresets.TabIndex = 8; this.lvLgPresets.UseCompatibleStateImageBehavior = false; this.lvLgPresets.View = System.Windows.Forms.View.Details; @@ -666,8 +703,10 @@ // // tabOptions // - this.tabOptions.Controls.Add(this.groupBox2); - this.tabOptions.Controls.Add(this.groupBox1); + this.tabOptions.Controls.Add(this.grpMiscellaneousOptions); + this.tabOptions.Controls.Add(this.grpLGOptions); + this.tabOptions.Controls.Add(this.grpHDROptions); + this.tabOptions.Controls.Add(this.grpGeneralOptions); this.tabOptions.Location = new System.Drawing.Point(4, 22); this.tabOptions.Name = "tabOptions"; this.tabOptions.Padding = new System.Windows.Forms.Padding(3); @@ -676,16 +715,140 @@ this.tabOptions.Text = "Options"; this.tabOptions.UseVisualStyleBackColor = true; // - // groupBox2 + // grpMiscellaneousOptions // - this.groupBox2.Controls.Add(this.edtDelayDisplaySettings); - this.groupBox2.Controls.Add(this.label6); - this.groupBox2.Location = new System.Drawing.Point(6, 119); - this.groupBox2.Name = "groupBox2"; - this.groupBox2.Size = new System.Drawing.Size(376, 107); - this.groupBox2.TabIndex = 3; - this.groupBox2.TabStop = false; - this.groupBox2.Text = "HDR"; + this.grpMiscellaneousOptions.Controls.Add(this.btnSetShortcutScreenSaver); + this.grpMiscellaneousOptions.Controls.Add(this.label11); + this.grpMiscellaneousOptions.Controls.Add(this.edtBlankScreenSaverShortcut); + this.grpMiscellaneousOptions.Controls.Add(this.label10); + this.grpMiscellaneousOptions.Controls.Add(this.chkFixChromeFonts); + this.grpMiscellaneousOptions.Location = new System.Drawing.Point(6, 275); + this.grpMiscellaneousOptions.Name = "grpMiscellaneousOptions"; + this.grpMiscellaneousOptions.Size = new System.Drawing.Size(400, 130); + this.grpMiscellaneousOptions.TabIndex = 5; + this.grpMiscellaneousOptions.TabStop = false; + this.grpMiscellaneousOptions.Text = "Miscellaneous"; + // + // btnSetShortcutScreenSaver + // + this.btnSetShortcutScreenSaver.Location = new System.Drawing.Point(154, 90); + this.btnSetShortcutScreenSaver.Name = "btnSetShortcutScreenSaver"; + this.btnSetShortcutScreenSaver.Size = new System.Drawing.Size(34, 23); + this.btnSetShortcutScreenSaver.TabIndex = 10; + this.btnSetShortcutScreenSaver.Text = "Set"; + this.btnSetShortcutScreenSaver.UseVisualStyleBackColor = true; + this.btnSetShortcutScreenSaver.Click += new System.EventHandler(this.btnSetShortcutScreenSaver_Click); + // + // label11 + // + this.label11.AutoSize = true; + this.label11.Location = new System.Drawing.Point(3, 74); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(219, 13); + this.label11.TabIndex = 9; + this.label11.Text = "Set a shortcut to start the blank screensaver:"; + // + // edtBlankScreenSaverShortcut + // + this.edtBlankScreenSaverShortcut.Location = new System.Drawing.Point(6, 92); + this.edtBlankScreenSaverShortcut.Name = "edtBlankScreenSaverShortcut"; + this.edtBlankScreenSaverShortcut.ReadOnly = true; + this.edtBlankScreenSaverShortcut.Size = new System.Drawing.Size(142, 20); + this.edtBlankScreenSaverShortcut.TabIndex = 7; + this.edtBlankScreenSaverShortcut.KeyDown += new System.Windows.Forms.KeyEventHandler(this.edtShortcut_KeyDown); + this.edtBlankScreenSaverShortcut.KeyUp += new System.Windows.Forms.KeyEventHandler(this.edtShortcut_KeyUp); + // + // label10 + // + this.label10.AutoSize = true; + this.label10.Location = new System.Drawing.Point(3, 39); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(373, 13); + this.label10.TabIndex = 6; + this.label10.Text = "This will add the parameter --disable-lcd-text to Chrome and requires elevation."; + // + // chkFixChromeFonts + // + this.chkFixChromeFonts.AutoSize = true; + this.chkFixChromeFonts.Location = new System.Drawing.Point(6, 19); + this.chkFixChromeFonts.Name = "chkFixChromeFonts"; + this.chkFixChromeFonts.Size = new System.Drawing.Size(335, 17); + this.chkFixChromeFonts.TabIndex = 4; + this.chkFixChromeFonts.Text = "ClearType: fix bad fonts in Chrome (turn on grayscale anti-aliasing)"; + this.chkFixChromeFonts.UseVisualStyleBackColor = true; + this.chkFixChromeFonts.CheckedChanged += new System.EventHandler(this.chkFixChromeFonts_CheckedChanged); + // + // grpLGOptions + // + this.grpLGOptions.Controls.Add(this.btnLGTestPower); + this.grpLGOptions.Controls.Add(this.label9); + this.grpLGOptions.Controls.Add(this.edtLgPowerOnAfterResumeDelay); + this.grpLGOptions.Controls.Add(this.label8); + this.grpLGOptions.Location = new System.Drawing.Point(6, 162); + this.grpLGOptions.Name = "grpLGOptions"; + this.grpLGOptions.Size = new System.Drawing.Size(403, 107); + this.grpLGOptions.TabIndex = 4; + this.grpLGOptions.TabStop = false; + this.grpLGOptions.Text = "LG controller"; + // + // btnLGTestPower + // + this.btnLGTestPower.Location = new System.Drawing.Point(9, 68); + this.btnLGTestPower.Name = "btnLGTestPower"; + this.btnLGTestPower.Size = new System.Drawing.Size(143, 23); + this.btnLGTestPower.TabIndex = 6; + this.btnLGTestPower.Text = "Test power off/on"; + this.btnLGTestPower.UseVisualStyleBackColor = true; + this.btnLGTestPower.Click += new System.EventHandler(this.btnLGTestPower_Click); + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point(6, 40); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(332, 13); + this.label9.TabIndex = 5; + this.label9.Text = "This delay is necessary to wait for the network link to be established. "; + // + // edtLgPowerOnAfterResumeDelay + // + this.edtLgPowerOnAfterResumeDelay.Increment = new decimal(new int[] { + 100, + 0, + 0, + 0}); + this.edtLgPowerOnAfterResumeDelay.Location = new System.Drawing.Point(299, 17); + this.edtLgPowerOnAfterResumeDelay.Maximum = new decimal(new int[] { + 5000, + 0, + 0, + 0}); + this.edtLgPowerOnAfterResumeDelay.Name = "edtLgPowerOnAfterResumeDelay"; + this.edtLgPowerOnAfterResumeDelay.ReadOnly = true; + this.edtLgPowerOnAfterResumeDelay.Size = new System.Drawing.Size(74, 20); + this.edtLgPowerOnAfterResumeDelay.TabIndex = 1; + this.edtLgPowerOnAfterResumeDelay.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; + this.edtLgPowerOnAfterResumeDelay.ValueChanged += new System.EventHandler(this.edtLgPowerOnAfterResumeDelay_ValueChanged); + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(6, 19); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(214, 13); + this.label8.TabIndex = 0; + this.label8.Text = "Delay before powering on after resume (ms):"; + // + // grpHDROptions + // + this.grpHDROptions.Controls.Add(this.edtDelayDisplaySettings); + this.grpHDROptions.Controls.Add(this.label6); + this.grpHDROptions.Location = new System.Drawing.Point(6, 84); + this.grpHDROptions.Name = "grpHDROptions"; + this.grpHDROptions.Size = new System.Drawing.Size(400, 72); + this.grpHDROptions.TabIndex = 3; + this.grpHDROptions.TabStop = false; + this.grpHDROptions.Text = "HDR"; // // edtDelayDisplaySettings // @@ -716,16 +879,16 @@ this.label6.TabIndex = 0; this.label6.Text = "Delay opening display settings (ms):"; // - // groupBox1 + // grpGeneralOptions // - this.groupBox1.Controls.Add(this.chkStartMinimized); - this.groupBox1.Controls.Add(this.chkStartAfterLogin); - this.groupBox1.Location = new System.Drawing.Point(6, 6); - this.groupBox1.Name = "groupBox1"; - this.groupBox1.Size = new System.Drawing.Size(376, 107); - this.groupBox1.TabIndex = 2; - this.groupBox1.TabStop = false; - this.groupBox1.Text = "General"; + this.grpGeneralOptions.Controls.Add(this.chkStartMinimized); + this.grpGeneralOptions.Controls.Add(this.chkStartAfterLogin); + this.grpGeneralOptions.Location = new System.Drawing.Point(6, 6); + this.grpGeneralOptions.Name = "grpGeneralOptions"; + this.grpGeneralOptions.Size = new System.Drawing.Size(400, 72); + this.grpGeneralOptions.TabIndex = 2; + this.grpGeneralOptions.TabStop = false; + this.grpGeneralOptions.Text = "General"; // // chkStartMinimized // @@ -881,11 +1044,16 @@ this.tabLG.ResumeLayout(false); this.tabLG.PerformLayout(); this.tabOptions.ResumeLayout(false); - this.groupBox2.ResumeLayout(false); - this.groupBox2.PerformLayout(); + this.grpMiscellaneousOptions.ResumeLayout(false); + this.grpMiscellaneousOptions.PerformLayout(); + this.grpLGOptions.ResumeLayout(false); + this.grpLGOptions.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.edtLgPowerOnAfterResumeDelay)).EndInit(); + this.grpHDROptions.ResumeLayout(false); + this.grpHDROptions.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.edtDelayDisplaySettings)).EndInit(); - this.groupBox1.ResumeLayout(false); - this.groupBox1.PerformLayout(); + this.grpGeneralOptions.ResumeLayout(false); + this.grpGeneralOptions.PerformLayout(); this.tabLog.ResumeLayout(false); this.tabLog.PerformLayout(); this.tabInfo.ResumeLayout(false); @@ -941,10 +1109,10 @@ private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; private System.Windows.Forms.Button btnDeleteLg; private System.Windows.Forms.Button btnAddLg; - private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.GroupBox grpGeneralOptions; private System.Windows.Forms.CheckBox chkStartMinimized; private System.Windows.Forms.CheckBox chkStartAfterLogin; - private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.GroupBox grpHDROptions; private System.Windows.Forms.NumericUpDown edtDelayDisplaySettings; private System.Windows.Forms.Label label6; private System.Windows.Forms.ToolStripMenuItem mnuNvDisplay; @@ -966,6 +1134,18 @@ private System.Windows.Forms.ContextMenuStrip mnuLgButtons; private System.Windows.Forms.ToolStripMenuItem mnuNvPresetsColorSettings; private System.Windows.Forms.ToolStripMenuItem miNvPresetColorSettings; + private System.Windows.Forms.CheckedListBox clbLgPower; + private System.Windows.Forms.GroupBox grpLGOptions; + private System.Windows.Forms.NumericUpDown edtLgPowerOnAfterResumeDelay; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.Button btnLGTestPower; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.GroupBox grpMiscellaneousOptions; + private System.Windows.Forms.CheckBox chkFixChromeFonts; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.Button btnSetShortcutScreenSaver; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.TextBox edtBlankScreenSaverShortcut; } } diff --git a/ColorControl/MainForm.cs b/ColorControl/MainForm.cs index 7eec61a..935ae43 100644 --- a/ColorControl/MainForm.cs +++ b/ColorControl/MainForm.cs @@ -45,6 +45,7 @@ namespace ColorControl private static int WM_HOTKEY = 0x0312; private static string TS_TASKNAME = "ColorControl"; private static bool SystemShutdown = false; + private static int SHORTCUTID_SCREENSAVER = -100; private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); @@ -74,9 +75,12 @@ namespace ColorControl private MenuItem _nvTrayMenu; private MenuItem _lgTrayMenu; - public MainForm() + private StartUpParams StartUpParams { get; } + + public MainForm(StartUpParams startUpParams) { InitializeComponent(); + StartUpParams = startUpParams; _dataDir = Utils.GetDataPath(); @@ -103,6 +107,12 @@ namespace ColorControl chkStartAfterLogin.Checked = TaskExists(true); + chkFixChromeFonts.Enabled = Utils.IsChromeInstalled(); + if (chkFixChromeFonts.Enabled) + { + chkFixChromeFonts.Checked = Utils.IsChromeFixInstalled(); + } + _JsonSerializer = new JavaScriptSerializer(); _JsonDeserializer = new JavaScriptSerializer(); @@ -139,14 +149,18 @@ namespace ColorControl } try { - _lgService = new LgService(); + _lgService = new LgService(_dataDir, StartUpParams.RunningFromScheduledTask); + + clbLgPower.SetItemChecked(0, _lgService.Config.PowerOnAfterStartup); + clbLgPower.SetItemChecked(1, _lgService.Config.PowerOnAfterResume); + clbLgPower.SetItemChecked(2, _lgService.Config.PowerOffOnShutdown); + clbLgPower.SetItemChecked(3, _lgService.Config.PowerOffOnStandby); + edtLgPowerOnAfterResumeDelay.Value = _lgService.Config.PowerOnDelayAfterResume; } catch (Exception e) { Debug.WriteLine(e); } - //_nvService.SetDithering(true); - //_nvService.SetRefreshRate(120); InitInfo(); @@ -162,11 +176,16 @@ namespace ColorControl item.Click += miLgAddButton_Click; } - SystemEvents.SessionEnded += new SessionEndedEventHandler(SessionEnded); - SystemEvents.PowerModeChanged += new PowerModeChangedEventHandler(PowerModeChanged); + if (_lgService != null) + { + SystemEvents.SessionEnded += new SessionEndedEventHandler(SessionEnded); + SystemEvents.PowerModeChanged += new PowerModeChangedEventHandler(PowerModeChanged); + } _restartDetector = new RestartDetector(); + //Scale(new SizeF(1.25F, 1.25F)); + _initialized = true; } @@ -174,35 +193,32 @@ namespace ColorControl { var powerOn = e.Mode == PowerModes.Resume; + Logger.Debug($"PowerModeChanged: {e.Mode}"); + if (powerOn) { _lgService.DisposeConnection(); + _lgService.WakeAfterResume(); return; } - Logger.Debug($"PowerModeChanged: {e.Mode}"); - - ExecPowerOffPreset(); + if (_lgService.Config.PowerOffOnStandby) + { + _lgService.PowerOff(); + } } private void SessionEnded(object sender, SessionEndedEventArgs e) { - if (e.Reason == SessionEndReasons.SystemShutdown) - { - Logger.Debug($"SessionEnded: {e.Reason}"); + //if (e.Reason == SessionEndReasons.SystemShutdown) + //{ + // Logger.Debug($"SessionEnded: {e.Reason}"); - ExecPowerOffPreset(); - } - } - - private void ExecPowerOffPreset(bool wait = false) - { - var preset = _lgPresets.FirstOrDefault(x => x.steps.Contains("POWER")); - if (preset != null) - { - Logger.Debug($"ExecPowerOffPreset: preset found: {preset.name}"); - ApplyLgPreset(preset, wait: wait); - } + // if (_lgService.Config.PowerOffOnShutdown) + // { + // _lgService.PowerOff(); + // } + //} } private void InitLogger() @@ -316,23 +332,23 @@ namespace ColorControl foreach (var preset in _presets) { AddOrUpdateItem(preset); - RegisterShortcut(preset); + RegisterShortcut(preset.id, preset.shortcut); } //UpdateTrayMenuNv(); } - private void RegisterShortcut(PresetBase preset, bool clear = false) + private void RegisterShortcut(int id, string shortcut, bool clear = false) { if (clear) { - UnregisterHotKey(Handle, preset.id); + UnregisterHotKey(Handle, id); } - if (!string.IsNullOrEmpty(preset.shortcut)) + if (!string.IsNullOrEmpty(shortcut)) { - var (mods, key) = Utils.ParseShortcut(preset.shortcut); - bool registered = RegisterHotKey(Handle, preset.id, mods, key); + var (mods, key) = Utils.ParseShortcut(shortcut); + bool registered = RegisterHotKey(Handle, id, mods, key); } } @@ -380,18 +396,24 @@ namespace ColorControl SaveLgPresets(); SaveConfig(); - - if (SystemShutdown) + + if (SystemShutdown && _lgService.Config.PowerOffOnShutdown) { Logger.Debug($"MainForm_FormClosing: SystemShutdown"); - if (_restartDetector != null && _restartDetector.RestartDetected) + if (_restartDetector != null && (_restartDetector.RestartDetected || _restartDetector.IsRebootInProgress())) { Logger.Debug("Not powering off because of a restart"); } + else if (NativeMethods.GetAsyncKeyState(NativeConstants.VK_LSHIFT) < 0 || NativeMethods.GetAsyncKeyState(NativeConstants.VK_RSHIFT) < 0) + { + Logger.Debug("Not powering off because SHIFT-key is down"); + } else { - ExecPowerOffPreset(true); + var task = _lgService.PowerOff(); + Utils.WaitForTask(task); + //ExecPowerOffPreset(true); } } } @@ -443,17 +465,24 @@ namespace ColorControl // MessageBox.Show(string.Format("Hotkey #{0} pressed", id)); // 6. Handle what will happen once a respective hotkey is pressed - - var preset = _presets.FirstOrDefault(x => x.id == id); - if (preset != null) + if (id == SHORTCUTID_SCREENSAVER) { - ApplyNvPreset(preset); + var screenSaver = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "scrnsave.scr"); + Process.Start(screenSaver); } - - var lgPreset = _lgPresets.FirstOrDefault(x => x.id == id); - if (lgPreset != null) + else { - ApplyLgPreset(lgPreset); + var preset = _presets.FirstOrDefault(x => x.id == id); + if (preset != null) + { + ApplyNvPreset(preset); + } + + var lgPreset = _lgPresets.FirstOrDefault(x => x.id == id); + if (lgPreset != null) + { + ApplyLgPreset(lgPreset); + } } //switch (id) @@ -523,7 +552,7 @@ namespace ColorControl AddOrUpdateItem(); - RegisterShortcut(preset, clear); + RegisterShortcut(preset.id, preset.shortcut, clear); } private void MainForm_FormClosed(object sender, FormClosedEventArgs e) @@ -555,24 +584,31 @@ namespace ColorControl var file = Assembly.GetExecutingAssembly().Location; var directory = Path.GetDirectoryName(file); - using (TaskService ts = new TaskService()) + try { - if (enabled) + using (TaskService ts = new TaskService()) { - TaskDefinition td = ts.NewTask(); - td.RegistrationInfo.Description = "Start ColorControl"; + if (enabled) + { + TaskDefinition td = ts.NewTask(); + td.RegistrationInfo.Description = "Start ColorControl"; - td.Triggers.Add(new LogonTrigger { UserId = WindowsIdentity.GetCurrent().Name }); + td.Triggers.Add(new LogonTrigger { UserId = WindowsIdentity.GetCurrent().Name }); - td.Actions.Add(new ExecAction(file, null, directory)); + td.Actions.Add(new ExecAction(file, StartUpParams.RunningFromScheduledTaskParam, directory)); - ts.RootFolder.RegisterTaskDefinition(TS_TASKNAME, td); - } - else - { - ts.RootFolder.DeleteTask(TS_TASKNAME, false); + ts.RootFolder.RegisterTaskDefinition(TS_TASKNAME, td); + } + else + { + ts.RootFolder.DeleteTask(TS_TASKNAME, false); + } } } + catch (Exception e) + { + ErrorOk("Could not create/delete task: " + e.Message); + } } private bool TaskExists(bool update) @@ -617,14 +653,32 @@ namespace ColorControl chkStartMinimized.Checked = _config.StartMinimized; edtDelayDisplaySettings.Value = _config.DisplaySettingsDelay; + edtBlankScreenSaverShortcut.Text = _config.ScreenSaverShortcut; + + if (!string.IsNullOrEmpty(_config.ScreenSaverShortcut)) + { + RegisterShortcut(SHORTCUTID_SCREENSAVER, _config.ScreenSaverShortcut); + } + + Width = _config.FormWidth; + Height = _config.FormHeight; } private void SaveConfig() { _config.StartMinimized = chkStartMinimized.Checked; + _config.FormWidth = Width; + _config.FormHeight = Height; - var data = _JsonSerializer.Serialize(_config); - File.WriteAllText(_configFilename, data); + try + { + var data = _JsonSerializer.Serialize(_config); + File.WriteAllText(_configFilename, data); + } + catch (Exception e) + { + Logger.Error(e.ToLogString()); + } } private void MainForm_Load(object sender, EventArgs e) @@ -1021,7 +1075,7 @@ namespace ColorControl foreach (var preset in _lgPresets) { AddOrUpdateItemLg(preset); - RegisterShortcut(preset); + RegisterShortcut(preset.id, preset.shortcut); } } @@ -1183,7 +1237,7 @@ namespace ColorControl if (shortcutChanged) { - RegisterShortcut(preset, clear); + RegisterShortcut(preset.id, preset.shortcut, clear); } } @@ -1474,11 +1528,7 @@ namespace ColorControl var applyTask = _lgService.ApplyPreset(preset, reconnect).ContinueWith((task) => BeginInvoke(new Action>(LgPresetApplied), new[] { task })); if (wait) { - while (applyTask != null && (applyTask.Status < TaskStatus.WaitingForChildrenToComplete)) - { - Thread.Sleep(100); - Application.DoEvents(); - } + Utils.WaitForTask(applyTask); } } @@ -1540,6 +1590,11 @@ namespace ColorControl MessageBox.Show(text, Text, MessageBoxButtons.OK, MessageBoxIcon.Information); } + private DialogResult QuestionYesNo(string text) + { + return MessageBox.Show(text, Text, MessageBoxButtons.YesNo, MessageBoxIcon.Information); + } + private void lvLgPresets_DoubleClick(object sender, EventArgs e) { ApplySelectedLgPreset(); @@ -1600,5 +1655,92 @@ namespace ColorControl } edtStepsLg.Text = text.Trim(); } + + private void clbLgPower_ItemCheck(object sender, ItemCheckEventArgs e) + { + if (!_initialized) + { + return; + } + + if (!(_lgService.Config.PowerOnAfterResume || _lgService.Config.PowerOnAfterStartup)) + { + InfoOk( +@"Be sure to activate the following setting on the TV, or the app will not be able to wake the TV: + +Connection > Mobile TV On > Turn on via Wi-Fi + +See Options to test this functionality." + ); + } + + this.BeginInvoke(new Action(() => + { + _lgService.Config.PowerOnAfterStartup = clbLgPower.GetItemChecked(0); + _lgService.Config.PowerOnAfterResume = clbLgPower.GetItemChecked(1); + _lgService.Config.PowerOffOnShutdown = clbLgPower.GetItemChecked(2); + _lgService.Config.PowerOffOnStandby = clbLgPower.GetItemChecked(3); + })); + } + + private void edtLgPowerOnAfterResumeDelay_ValueChanged(object sender, EventArgs e) + { + _lgService.Config.PowerOnDelayAfterResume = (int)edtLgPowerOnAfterResumeDelay.Value; + } + + private void chkFixChromeFonts_CheckedChanged(object sender, EventArgs e) + { + if (_initialized) + { + if (chkFixChromeFonts.Checked) + { + Utils.ExecuteElevated(StartUpParams.ActivateChromeFontFixParam); + } + else + { + Utils.ExecuteElevated(StartUpParams.DeactivateChromeFontFixParam); + } + } + } + + private void btnLGTestPower_Click(object sender, EventArgs e) + { + var text = +@"The TV will now power off. Please wait for the TV to be powered off completely (relay click) and press ENTER to wake it again. +For waking up to work, you need to activate the following setting on the TV: + +Connection > Mobile TV On > Turn on via Wi-Fi + +It will also work over a wired connection. +Do you want to continue?"; + + if (QuestionYesNo(text) == DialogResult.Yes) + { + _lgService.PowerOff(); + + InfoOk("Press ENTER to wake the TV."); + + _lgService.WakeSelectedDevice(); + } + } + + private void btnSetShortcutScreenSaver_Click(object sender, EventArgs e) + { + var shortcut = edtBlankScreenSaverShortcut.Text.Trim(); + + if (!string.IsNullOrWhiteSpace(shortcut) && !shortcut.Contains("+")) + { + WarningOk("Invalid shortcut. The shortcut should have modifiers and a normal key."); + return; + } + + var oldShortcut = _config.ScreenSaverShortcut; + + var clear = !string.IsNullOrEmpty(oldShortcut); + + _config.ScreenSaverShortcut = shortcut; + + RegisterShortcut(SHORTCUTID_SCREENSAVER, shortcut, clear); + } } } \ No newline at end of file diff --git a/ColorControl/PnpDev.cs b/ColorControl/PnpDev.cs index 922dfcb..7133ed4 100644 --- a/ColorControl/PnpDev.cs +++ b/ColorControl/PnpDev.cs @@ -1,22 +1,30 @@ -using System.Collections.Generic; -using System.Linq; +using Windows.Devices.Enumeration; +using Windows.Devices.Enumeration.Pnp; namespace ColorControl { class PnpDev { - public string name { get; set; } - public string ipAddress { get; set; } + public DeviceInformation DevInfo { get; private set; } + public PnpObject PnpObject { get; private set; } - public PnpDev(string name, string ipAddress) + public string Name { get; private set; } + public string IpAddress { get; private set; } + + public string MacAddress { get; private set; } + + public PnpDev(DeviceInformation devInfo, PnpObject pnpObject, string name, string ipAddress, string macAddress) { - this.name = name; - this.ipAddress = ipAddress; + DevInfo = devInfo; + PnpObject = pnpObject; + Name = name; + IpAddress = ipAddress; + MacAddress = macAddress; } public override string ToString() { - return name + " (" + ipAddress + ")"; + return Name + " (" + IpAddress + ")"; } } } diff --git a/ColorControl/Program.cs b/ColorControl/Program.cs index 03ccad2..33b5224 100644 --- a/ColorControl/Program.cs +++ b/ColorControl/Program.cs @@ -1,8 +1,5 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Threading; -using System.Threading.Tasks; using System.Windows.Forms; namespace ColorControl @@ -13,8 +10,16 @@ namespace ColorControl /// The main entry point for the application. /// [STAThread] - static void Main() + static void Main(string[] args) { + var startUpParams = StartUpParams.Parse(args); + + if (startUpParams.ActivateChromeFontFix || startUpParams.DeactivateChromeFontFix) + { + Utils.InstallChromeFix(startUpParams.ActivateChromeFontFix); + return; + } + string mutexId = $"Global\\{typeof(MainForm).GUID}"; bool mutexCreated; var mutex = new Mutex(true, mutexId, out mutexCreated); @@ -28,7 +33,7 @@ namespace ColorControl { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); - Application.Run(new MainForm()); + Application.Run(new MainForm(startUpParams)); } } finally diff --git a/ColorControl/Properties/AssemblyInfo.cs b/ColorControl/Properties/AssemblyInfo.cs index a9a23a4..316cf9e 100644 --- a/ColorControl/Properties/AssemblyInfo.cs +++ b/ColorControl/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.3.0")] -[assembly: AssemblyFileVersion("1.0.3.0")] +[assembly: AssemblyVersion("1.1.0.0")] +[assembly: AssemblyFileVersion("1.1.0.0")] diff --git a/ColorControl/RestartDetector.cs b/ColorControl/RestartDetector.cs index 9e35821..e4618b4 100644 --- a/ColorControl/RestartDetector.cs +++ b/ColorControl/RestartDetector.cs @@ -1,6 +1,8 @@ -using NLog; +using Microsoft.Win32; +using NLog; using System; using System.Diagnostics.Eventing.Reader; +using System.Linq; namespace ColorControl { @@ -35,6 +37,13 @@ namespace ColorControl } } + public bool IsRebootInProgress() + { + var registry = Registry.LocalMachine; + var subKey = registry.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Component Based Servicing"); + return subKey.GetValueNames().Any(x => x.Equals("RebootInProgress")); + } + public void EventLogEventRead(object obj, EventRecordWrittenEventArgs arg) { RestartDetected = false; diff --git a/ColorControl/StartUpParams.cs b/ColorControl/StartUpParams.cs new file mode 100644 index 0000000..39040e7 --- /dev/null +++ b/ColorControl/StartUpParams.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; + +namespace ColorControl +{ + public class StartUpParams + { + public const string RunningFromScheduledTaskParam = "--scheduled"; + public const string ActivateChromeFontFixParam = "--activate-chrome-font-fix"; + public const string DeactivateChromeFontFixParam = "--deactivate-chrome-font-fix"; + + public bool RunningFromScheduledTask { get; private set; } + public bool ActivateChromeFontFix { get; private set; } + public bool DeactivateChromeFontFix { get; private set; } + + public static StartUpParams Parse(IEnumerable args) + { + var settings = new StartUpParams(); + foreach (var arg in args) + { + switch (arg.ToLowerInvariant()) + { + case RunningFromScheduledTaskParam: + { + settings.RunningFromScheduledTask = true; + break; + } + case ActivateChromeFontFixParam: + { + settings.ActivateChromeFontFix = true; + break; + } + case DeactivateChromeFontFixParam: + { + settings.DeactivateChromeFontFix = true; + break; + } + } + } + return settings; + } + } +} diff --git a/ColorControl/Utils.cs b/ColorControl/Utils.cs index efd212b..6db7262 100644 --- a/ColorControl/Utils.cs +++ b/ColorControl/Utils.cs @@ -1,10 +1,12 @@ -using NWin32.NativeTypes; +using Microsoft.Win32; using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; +using System.Reflection; +using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using Windows.Devices.Enumeration; @@ -23,7 +25,8 @@ namespace ColorControl Win = 8 } - public static string PKEY_PNPX_IpAddress = "{656a3bb3-ecc0-43fd-8477-4ae0404a96cd} 12297"; + public static string PKEY_PNPX_IpAddress = "{656a3bb3-ecc0-43fd-8477-4ae0404a96cd} 12297"; + public static string PKEY_PNPX_PhysicalAddress = "{656a3bb3-ecc0-43fd-8477-4ae0404a96cd} 12294"; private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); @@ -121,76 +124,150 @@ namespace ColorControl return (mods, key); } - public static async Task GetDeviceProperty(string deviceName, string propertyName) + internal static bool ExecuteElevated(string args) { - string value = null; - string name = null; - var list = await DeviceInformation.FindAllAsync("", new List()); - - var reqs = new List(); - reqs.Add(propertyName); - - foreach (var dev in list) + var info = new ProcessStartInfo(Assembly.GetEntryAssembly().Location, args) { - name = dev.Name; - if (dev.IsEnabled && dev.Name.Contains(deviceName)) + Verb = "runas", // indicates to elevate privileges + }; + + var process = new Process + { + EnableRaisingEvents = true, // enable WaitForExit() + StartInfo = info + }; + try + { + process.Start(); + process.WaitForExit(); // sleep calling process thread until evoked process exit + return true; + } + catch (Exception e) + { + Logger.Error("ExecuteElevated: " + e.Message); + } + return false; + } + + internal static bool IsChromeFixInstalled() + { + var key = Registry.ClassesRoot.OpenSubKey(@"ChromeHTML\shell\open\command"); + return key != null && key.GetValue(null).ToString().Contains("--disable-lcd-text"); + } + + internal static bool InstallChromeFix(bool install) + { + //var key = Registry.ClassesRoot.OpenSubKey(@"ChromeHTML\shell\open\command", true); + //if (key != null) + //{ + // var value = key.GetValue(null).ToString(); + // if (install) + // { + // value = value.Replace("chrome.exe\" -- \"", "chrome.exe\" --disable-lcd-text -- \""); + // } + // else + // { + // value = value.Replace("chrome.exe\" --disable-lcd-text -- \"", "chrome.exe\" -- \""); + // } + // key.SetValue(null, value); + //} + + var argument = "--disable-lcd-text"; + + var roamingFolder = 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); + + var allUsersStartMenuFolder = Environment.GetFolderPath(Environment.SpecialFolder.CommonStartMenu); + UpdateShortcut(Path.Combine(allUsersStartMenuFolder, @"Programs\Google Chrome.lnk"), argument, !install); + + return true; + } + + internal static bool IsChromeInstalled() + { + var key = Registry.ClassesRoot.OpenSubKey(@"ChromeHTML\shell\open\command"); + return key != null; + } + + internal static bool UpdateShortcut(string path, string arguments, bool removeArguments = false) + { + if (File.Exists(path)) + { + IWshRuntimeLibrary.WshShell shell = new IWshRuntimeLibrary.WshShell(); + + // C:\Users\All Users\Microsoft\Windows\Start Menu\Programs + // C:\Users\vinni\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch + // C:\Users\vinni\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Google Chrome.lnk + + IWshRuntimeLibrary.IWshShortcut shortcut = (IWshRuntimeLibrary.IWshShortcut)shell.CreateShortcut(path); + + shortcut.Arguments = shortcut.Arguments.Replace(arguments, ""); + if (!removeArguments) { - //Debug.WriteLine(dev.Name); - //foreach (var key in dev.Properties.Keys) - //{ - // Debug.WriteLine($"* {key}: {dev.Properties[key]}"); - //} - - var guid = dev.Properties["System.Devices.DeviceInstanceId"]; - - var aqs = "System.Devices.DeviceInstanceId:=\"" + guid + "\""; - var list2 = await PnpObject.FindAllAsync(PnpObjectType.Device, reqs, aqs); - - foreach (var dev2 in list2) + if (!string.IsNullOrEmpty(shortcut.Arguments)) { - foreach (var key in dev2.Properties.Keys) - { - var obj = dev2.Properties[key]; - string newValue = null; - if (obj is string[]) - { - var arr = obj as string[]; - if (arr.Length > 0) - { - newValue = arr[0]; - } - } - else - { - newValue = dev2.Properties[key].ToString(); - } - if (newValue != value) - { - value = newValue; - Logger.Debug($"LG TV with name {dev.Name} found at {value}"); - } - //Debug.WriteLine($"* {key}: {value}"); - } + shortcut.Arguments = shortcut.Arguments + " "; } + shortcut.Arguments = shortcut.Arguments + arguments; + } + // save it / create + shortcut.Save(); + + return true; + } + return false; + } + + public static string GetDeviceProperty(PnpObject device, string propertyName) + { + object objValue; + string value = null; + + foreach (var key in device.Properties.Keys) + { + Debug.WriteLine(key); + } + + if (device.Properties.TryGetValue(propertyName, out objValue)) + { + if (objValue is string[]) + { + var arr = objValue as string[]; + if (arr.Length > 0) + { + value = arr[0]; + } + } + else if (objValue is byte[]) + { + value = BitConverter.ToString((byte[])objValue); + } + else + { + value = objValue.ToString(); } } + return value; } - public static async Task> GetPnpDevices(string deviceName, string propertyName) + public static async Task> GetPnpDevices(string deviceName) { var devices = new List(); var list = await DeviceInformation.FindAllAsync("", new List()); var reqs = new List(); - reqs.Add(propertyName); + reqs.Add(PKEY_PNPX_IpAddress); + reqs.Add(PKEY_PNPX_PhysicalAddress); foreach (var dev in list) { string name = dev.Name; - if (dev.IsEnabled && dev.Name.Contains(deviceName)) + if (/*dev.IsEnabled &&*/ dev.Name.Contains(deviceName)) { var guid = dev.Properties["System.Devices.DeviceInstanceId"]; @@ -199,27 +276,13 @@ namespace ColorControl foreach (var dev2 in list2) { - foreach (var key in dev2.Properties.Keys) + var ipAddress = GetDeviceProperty(dev2, "System.Devices.IpAddress"); + var macAddress = GetDeviceProperty(dev2, PKEY_PNPX_PhysicalAddress); + + if (!devices.Any(x => x.Name.Equals(name) && x.IpAddress.Equals(ipAddress))) { - var obj = dev2.Properties[key]; - string value = null; - if (obj is string[]) - { - var arr = obj as string[]; - if (arr.Length > 0) - { - value = arr[0]; - } - } - else - { - value = dev2.Properties[key].ToString(); - } - if (!devices.Any(x => x.name.Equals(name) && x.ipAddress.Equals(value))) - { - var device = new PnpDev(name, value); - devices.Add(device); - } + var device = new PnpDev(dev, dev2, name, ipAddress, macAddress); + devices.Add(device); } } @@ -227,5 +290,14 @@ namespace ColorControl } return devices; } + + public static void WaitForTask(Task task) + { + while (task != null && (task.Status < TaskStatus.WaitingForChildrenToComplete)) + { + Thread.Sleep(100); + Application.DoEvents(); + } + } } } diff --git a/ColorControl/WOL.cs b/ColorControl/WOL.cs new file mode 100644 index 0000000..e981f7e --- /dev/null +++ b/ColorControl/WOL.cs @@ -0,0 +1,73 @@ +using NLog; +using System; +using System.Globalization; +using PacketDotNet; +using System.Net.NetworkInformation; +using SharpPcap; +using System.Diagnostics; +using SharpPcap.Npcap; +using System.Linq; + +namespace ColorControl +{ + class WOL + { + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + //You need SharpPcap for this to work + + public static void WakeFunction(string macAddress) + { + /* Retrieve the device list */ + var devices = CaptureDeviceList.Instance; + + Logger.Debug("Waking device with MAC-address " + macAddress); + + /*If no device exists, print error */ + if (devices.Count < 1) + { + Logger.Debug("No network device found on this machine"); + return; + } + + foreach (var device in devices) + { + if (device is NpcapDevice npcapDevice) + { + if (!npcapDevice.Interface.GatewayAddresses.Any()) + { + continue; + } + } + + Logger.Debug("Opening network device: " + device.Name); + + //Open the device + device.Open(); + + //A magic packet is a broadcast frame containing anywhere within its payload: 6 bytes of ones + //(resulting in hexadecimal FF FF FF FF FF FF), followed by sixteen repetitions + + string response = macAddress.Replace(":", "-"); + + var address = PhysicalAddress.Parse("FFFFFFFFFFFF"); + EthernetPacket ethernet = new EthernetPacket(address, address, EthernetType.WakeOnLan); + ethernet.PayloadPacket = new WakeOnLanPacket(PhysicalAddress.Parse(response)); + + byte[] bytes = ethernet.Bytes; + + try + { + //Send the packet out the network device + device.SendPacket(bytes); + } + catch (Exception e) + { + Logger.Debug(e.Message); + } + + device.Close(); + } + } + } +} \ No newline at end of file diff --git a/ColorControl/packages.config b/ColorControl/packages.config index 5f53336..3f23c22 100644 --- a/ColorControl/packages.config +++ b/ColorControl/packages.config @@ -6,5 +6,11 @@ + + + + + + \ No newline at end of file