From 3abf10649682cc1f350381fb98744f46822ac4fc Mon Sep 17 00:00:00 2001 From: Vincent Maas Date: Sun, 6 Jun 2021 15:58:21 +0200 Subject: [PATCH] extended expert-button, added new actions --- ColorControl/ColorControl.csproj | 2 +- ColorControl/ExceptionExtensions.cs | 13 ++- ColorControl/LgDevice.cs | 109 +++++++++++++++++++++++- ColorControl/LgService.cs | 17 ++++ ColorControl/MainForm.Designer.cs | 103 +++++++++++----------- ColorControl/MainForm.cs | 94 +++++++++++++++++++- ColorControl/MainForm.resx | 3 - ColorControl/MessageForms.cs | 103 ++++++++++++++++++---- ColorControl/Properties/AssemblyInfo.cs | 4 +- ColorControl/Utils.cs | 70 ++++++++++++++- ColorControl/lgtv/LgTvApi.cs | 71 ++++++++++++++- ColorControl/lgtv/LgTvConnection.cs | 2 +- 12 files changed, 502 insertions(+), 89 deletions(-) diff --git a/ColorControl/ColorControl.csproj b/ColorControl/ColorControl.csproj index 720f60f..bce4ff1 100644 --- a/ColorControl/ColorControl.csproj +++ b/ColorControl/ColorControl.csproj @@ -27,7 +27,7 @@ ColorControl Maassoft 0 - 3.1.1.0 + 3.2.0.0 false true true diff --git a/ColorControl/ExceptionExtensions.cs b/ColorControl/ExceptionExtensions.cs index ca1aa7d..a1f18e5 100644 --- a/ColorControl/ExceptionExtensions.cs +++ b/ColorControl/ExceptionExtensions.cs @@ -18,7 +18,7 @@ namespace ColorControl /// Environment stack trace, for pulling additional stack frames. public static string ToLogString(this Exception exception, string environmentStackTrace = "") { - List environmentStackTraceLines = ExceptionExtensions.GetUserStackTraceLines(environmentStackTrace); + List environmentStackTraceLines = GetUserStackTraceLines(environmentStackTrace); if (environmentStackTraceLines.Any()) { environmentStackTraceLines.RemoveAt(0); @@ -29,7 +29,14 @@ namespace ColorControl string fullStackTrace = String.Join(Environment.NewLine, stackTraceLines); - string logMessage = exception.Message + Environment.NewLine + fullStackTrace; + string logMessage = exception.Message + Environment.NewLine; + + if (exception.InnerException != null) + { + logMessage += $"Inner exception: {exception.InnerException.Message}{Environment.NewLine}"; + } + + logMessage += fullStackTrace; return logMessage; } @@ -51,7 +58,7 @@ namespace ColorControl List outputList = new List(); Regex regex = new Regex(@"([^\)]*\)) in (.*):([A-z]*) (\d)*$"); - List stackTraceLines = ExceptionExtensions.GetStackTraceLines(fullStackTrace); + List stackTraceLines = GetStackTraceLines(fullStackTrace); foreach (string stackTraceLine in stackTraceLines) { if (!regex.IsMatch(stackTraceLine)) diff --git a/ColorControl/LgDevice.cs b/ColorControl/LgDevice.cs index ecfcc66..0efcf98 100644 --- a/ColorControl/LgDevice.cs +++ b/ColorControl/LgDevice.cs @@ -11,6 +11,15 @@ namespace ColorControl { class LgDevice { + public class InvokableAction + { + public Func, bool> Function { get; set; } + public string Name { get; set; } + public Type EnumType { get; set; } + public decimal MinValue { get; set; } + public decimal MaxValue { get; set; } + } + protected static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); public string Name { get; private set; } @@ -32,7 +41,7 @@ namespace ColorControl private bool _justWokeUp; [JsonIgnore] - private Dictionary> _invokableActions = new Dictionary>(); + private List _invokableActions = new List(); [JsonIgnore] public string ModelName { get; private set; } @@ -46,7 +55,42 @@ namespace ColorControl IsCustom = isCustom; IsDummy = isDummy; - _invokableActions.Add("WOL", new Func(Wake)); + AddInvokableAction("WOL", new Func, bool>(WakeAction)); + AddGenericPictureAction("backlight", minValue: 0, maxValue: 100); + AddGenericPictureAction("brightness", minValue: 0, maxValue: 100); + AddGenericPictureAction("contrast", minValue: 0, maxValue: 100); + AddGenericPictureAction("color", minValue: 0, maxValue: 100); + AddGenericPictureAction("pictureMode", typeof(PictureMode)); + AddGenericPictureAction("colorGamut", typeof(ColorGamut)); + AddGenericPictureAction("dynamicContrast", typeof(OffToAuto)); + AddGenericPictureAction("peakBrightness", typeof(OffToAuto)); + AddGenericPictureAction("smoothGradation", typeof(OffToAuto)); + AddGenericPictureAction("energySaving", typeof(EnergySaving)); + //AddGenericPictureAction("truMotionMode", typeof(TruMotionMode)); + AddGenericPictureAction("motionProOLED", typeof(OffToHigh)); + } + + private void AddInvokableAction(string name, Func, bool> function) + { + var action = new InvokableAction + { + Name = name, + Function = function + }; + + _invokableActions.Add(action); + } + + private void AddGenericPictureAction(string name, Type type = null, decimal minValue = 0, decimal maxValue = 0) + { + var action = new InvokableAction + { + Name = name, + Function = new Func, bool>(GenericPictureAction), + EnumType = type + }; + + _invokableActions.Add(action); } public override string ToString() @@ -177,8 +221,22 @@ namespace ColorControl { var keySpec = step.Split(':'); var key = keySpec[0].ToUpper(); - if (_invokableActions.ContainsKey(key)) + var index = key.IndexOf("("); + string[] parameters = null; + if (index > -1) { + var keyValue = keySpec[0].Split('('); + key = keyValue[0]; + parameters = keyValue[1].Substring(0, keyValue[1].Length - 1).Split(','); + } + var action = _invokableActions.FirstOrDefault(a => a.Name.Equals(key, StringComparison.OrdinalIgnoreCase)); + if (action != null) + { + if (!key.Equals("WOL")) + { + ExecuteAction(action, parameters); + } + continue; } @@ -193,6 +251,24 @@ namespace ColorControl } } + private void ExecuteAction(InvokableAction action, string[] parameters) + { + var function = action.Function; + + if (parameters?.Length > 0) + { + var keyValues = new Dictionary { + { "name", action.Name }, + { "value", parameters[0] } + }; + + function(keyValues); + return; + } + + function(null); + } + private void SendKey(LgWebOsMouseService mouse, string key, int delay = 180) { if (key.Length == 1 && int.TryParse(key, out _)) @@ -335,7 +411,7 @@ namespace ColorControl return result; } - public Dictionary> GetInvokableActions() + public List GetInvokableActions() { return _invokableActions; } @@ -391,5 +467,30 @@ namespace ColorControl { await _lgTvApi.SetConfig(key, value); } + internal async Task SetSystemSettings(string name, string value) + { + await _lgTvApi.SetSystemSettings(name, value); + } + + internal async Task GetPictureSettings() + { + var keys = new[] { "backlight", "brightness", "contrast", "color", "pictureMode", "colorGamut", "dynamicContrast", "peakBrightness", "smoothGradation", "energySaving", "motionProOLED" }; + + return await _lgTvApi.GetSystemSettings("picture", keys); + } + + private bool WakeAction(Dictionary parameters) + { + return Wake(); + } + + private bool GenericPictureAction(Dictionary parameters) + { + var settingName = parameters["name"]; + var task = _lgTvApi.SetSystemSettings(settingName, parameters["value"]); + Utils.WaitForTask(task); + + return true; + } } } diff --git a/ColorControl/LgService.cs b/ColorControl/LgService.cs index 1eff85b..569d128 100644 --- a/ColorControl/LgService.cs +++ b/ColorControl/LgService.cs @@ -532,6 +532,9 @@ namespace ColorControl _monitorTaskCounter++; var validCounter = _monitorTaskCounter; var lastProcessId = 0; + //const int minBacklight = 30; + //const int maxBacklight = 50; + //var lastBacklight = minBacklight; while (Devices.Any(d => d.PowerSwitchOnScreenSaver) && validCounter == _monitorTaskCounter) { @@ -580,6 +583,20 @@ namespace ColorControl wasConnected = true; } + //if (Utils.IsForegroundFullScreen()) + //{ + // if (lastBacklight != maxBacklight) + // { + // SelectedDevice?.SetBacklight(maxBacklight); + // lastBacklight = maxBacklight; + // } + //} + //else if (lastBacklight != minBacklight) + //{ + // SelectedDevice?.SetBacklight(minBacklight); + // lastBacklight = minBacklight; + //} + var process = processes.FirstOrDefault(p => p.ProcessName.ToLowerInvariant().EndsWith(".scr")); if (process == null) diff --git a/ColorControl/MainForm.Designer.cs b/ColorControl/MainForm.Designer.cs index 046ab1f..e15d450 100644 --- a/ColorControl/MainForm.Designer.cs +++ b/ColorControl/MainForm.Designer.cs @@ -105,6 +105,12 @@ this.tabLG = new System.Windows.Forms.TabPage(); this.scLgController = new System.Windows.Forms.SplitContainer(); this.btnLgExpert = new System.Windows.Forms.Button(); + this.mnuLgExpert = new System.Windows.Forms.ContextMenuStrip(this.components); + this.mnuLgExpertBacklight = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuLgOLEDMotionPro = new System.Windows.Forms.ToolStripMenuItem(); + this.miLgEnableMotionPro = new System.Windows.Forms.ToolStripMenuItem(); + this.miLgDisableMotionPro = new System.Windows.Forms.ToolStripMenuItem(); + this.miLgExpertSeparator1 = new System.Windows.Forms.ToolStripSeparator(); this.chkLgRemoteControlShow = new System.Windows.Forms.CheckBox(); this.label3 = new System.Windows.Forms.Label(); this.cbxLgDevices = new System.Windows.Forms.ComboBox(); @@ -176,12 +182,6 @@ this.lbPlugins = new System.Windows.Forms.ListBox(); this.label7 = new System.Windows.Forms.Label(); this.lblInfo = new System.Windows.Forms.Label(); - this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker(); - this.mnuLgExpert = new System.Windows.Forms.ContextMenuStrip(this.components); - this.mnuLgExpertBacklight = new System.Windows.Forms.ToolStripMenuItem(); - this.mnuLgOLEDMotionPro = new System.Windows.Forms.ToolStripMenuItem(); - this.miLgEnableMotionPro = new System.Windows.Forms.ToolStripMenuItem(); - this.miLgDisableMotionPro = new System.Windows.Forms.ToolStripMenuItem(); this.tcMain.SuspendLayout(); this.tabNVIDIA.SuspendLayout(); this.mnuNvPresets.SuspendLayout(); @@ -191,6 +191,7 @@ ((System.ComponentModel.ISupportInitialize)(this.scLgController)).BeginInit(); this.scLgController.Panel1.SuspendLayout(); this.scLgController.SuspendLayout(); + this.mnuLgExpert.SuspendLayout(); this.mnuLgButtons.SuspendLayout(); this.tabOptions.SuspendLayout(); this.grpNvidiaOptions.SuspendLayout(); @@ -205,7 +206,6 @@ this.tabInfo.SuspendLayout(); this.grpNVIDIAInfo.SuspendLayout(); this.groupBox3.SuspendLayout(); - this.mnuLgExpert.SuspendLayout(); this.SuspendLayout(); // // tcMain @@ -986,6 +986,51 @@ this.btnLgExpert.UseVisualStyleBackColor = true; this.btnLgExpert.Click += new System.EventHandler(this.btnLgExpert_Click); // + // mnuLgExpert + // + this.mnuLgExpert.ImageScalingSize = new System.Drawing.Size(20, 20); + this.mnuLgExpert.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.mnuLgOLEDMotionPro, + this.miLgExpertSeparator1, + this.mnuLgExpertBacklight}); + this.mnuLgExpert.Name = "mnuLgButtons"; + this.mnuLgExpert.Size = new System.Drawing.Size(282, 76); + this.mnuLgExpert.Opening += new System.ComponentModel.CancelEventHandler(this.mnuLgExpert_Opening); + // + // mnuLgExpertBacklight + // + this.mnuLgExpertBacklight.Name = "mnuLgExpertBacklight"; + this.mnuLgExpertBacklight.Size = new System.Drawing.Size(281, 22); + this.mnuLgExpertBacklight.Text = "Backlight"; + // + // mnuLgOLEDMotionPro + // + this.mnuLgOLEDMotionPro.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.miLgEnableMotionPro, + this.miLgDisableMotionPro}); + this.mnuLgOLEDMotionPro.Name = "mnuLgOLEDMotionPro"; + this.mnuLgOLEDMotionPro.Size = new System.Drawing.Size(281, 22); + this.mnuLgOLEDMotionPro.Text = "Activate OLED Motion Pro (B9/C9 only)"; + // + // miLgEnableMotionPro + // + this.miLgEnableMotionPro.Name = "miLgEnableMotionPro"; + this.miLgEnableMotionPro.Size = new System.Drawing.Size(207, 22); + this.miLgEnableMotionPro.Text = "Enable OLED Motion Pro"; + this.miLgEnableMotionPro.Click += new System.EventHandler(this.miLgEnableMotionPro_Click); + // + // miLgDisableMotionPro + // + this.miLgDisableMotionPro.Name = "miLgDisableMotionPro"; + this.miLgDisableMotionPro.Size = new System.Drawing.Size(207, 22); + this.miLgDisableMotionPro.Text = "Disable OLED Motion Pro"; + this.miLgDisableMotionPro.Click += new System.EventHandler(this.miLgDisableMotionPro_Click); + // + // miLgExpertSeparator1 + // + this.miLgExpertSeparator1.Name = "miLgExpertSeparator1"; + this.miLgExpertSeparator1.Size = new System.Drawing.Size(278, 6); + // // chkLgRemoteControlShow // this.chkLgRemoteControlShow.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); @@ -1038,6 +1083,7 @@ this.cbxLgApps.Name = "cbxLgApps"; this.cbxLgApps.Size = new System.Drawing.Size(200, 21); this.cbxLgApps.TabIndex = 26; + this.cbxLgApps.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.cbxLgApps_KeyPress); // // lvLgPresets // @@ -1781,45 +1827,6 @@ this.lblInfo.TabIndex = 1; this.lblInfo.Text = "Info"; // - // mnuLgExpert - // - this.mnuLgExpert.ImageScalingSize = new System.Drawing.Size(20, 20); - this.mnuLgExpert.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.mnuLgExpertBacklight, - this.mnuLgOLEDMotionPro}); - this.mnuLgExpert.Name = "mnuLgButtons"; - this.mnuLgExpert.Size = new System.Drawing.Size(236, 70); - this.mnuLgExpert.Opening += new System.ComponentModel.CancelEventHandler(this.mnuLgExpert_Opening); - // - // mnuLgExpertBacklight - // - this.mnuLgExpertBacklight.Name = "mnuLgExpertBacklight"; - this.mnuLgExpertBacklight.Size = new System.Drawing.Size(235, 22); - this.mnuLgExpertBacklight.Text = "Backlight"; - // - // mnuLgOLEDMotionPro - // - this.mnuLgOLEDMotionPro.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.miLgEnableMotionPro, - this.miLgDisableMotionPro}); - this.mnuLgOLEDMotionPro.Name = "mnuLgOLEDMotionPro"; - this.mnuLgOLEDMotionPro.Size = new System.Drawing.Size(235, 22); - this.mnuLgOLEDMotionPro.Text = "OLED Motion Pro (B9/C9 only)"; - // - // miLgEnableMotionPro - // - this.miLgEnableMotionPro.Name = "miLgEnableMotionPro"; - this.miLgEnableMotionPro.Size = new System.Drawing.Size(207, 22); - this.miLgEnableMotionPro.Text = "Enable OLED Motion Pro"; - this.miLgEnableMotionPro.Click += new System.EventHandler(this.miLgEnableMotionPro_Click); - // - // miLgDisableMotionPro - // - this.miLgDisableMotionPro.Name = "miLgDisableMotionPro"; - this.miLgDisableMotionPro.Size = new System.Drawing.Size(207, 22); - this.miLgDisableMotionPro.Text = "Disable OLED Motion Pro"; - this.miLgDisableMotionPro.Click += new System.EventHandler(this.miLgDisableMotionPro_Click); - // // MainForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -1849,6 +1856,7 @@ this.scLgController.Panel1.PerformLayout(); ((System.ComponentModel.ISupportInitialize)(this.scLgController)).EndInit(); this.scLgController.ResumeLayout(false); + this.mnuLgExpert.ResumeLayout(false); this.mnuLgButtons.ResumeLayout(false); this.tabOptions.ResumeLayout(false); this.grpNvidiaOptions.ResumeLayout(false); @@ -1870,7 +1878,6 @@ this.grpNVIDIAInfo.ResumeLayout(false); this.groupBox3.ResumeLayout(false); this.groupBox3.PerformLayout(); - this.mnuLgExpert.ResumeLayout(false); this.ResumeLayout(false); } @@ -2022,13 +2029,13 @@ private System.Windows.Forms.CheckedListBox clbLgPower; private System.Windows.Forms.Label lblLgError; private System.Windows.Forms.CheckBox chkLgRemoteControlShow; - private System.ComponentModel.BackgroundWorker backgroundWorker1; private System.Windows.Forms.Button btnLgExpert; private System.Windows.Forms.ContextMenuStrip mnuLgExpert; private System.Windows.Forms.ToolStripMenuItem mnuLgExpertBacklight; private System.Windows.Forms.ToolStripMenuItem mnuLgOLEDMotionPro; private System.Windows.Forms.ToolStripMenuItem miLgEnableMotionPro; private System.Windows.Forms.ToolStripMenuItem miLgDisableMotionPro; + private System.Windows.Forms.ToolStripSeparator miLgExpertSeparator1; } } diff --git a/ColorControl/MainForm.cs b/ColorControl/MainForm.cs index 43bbe00..7967a5b 100644 --- a/ColorControl/MainForm.cs +++ b/ColorControl/MainForm.cs @@ -1645,8 +1645,62 @@ namespace ColorControl private void miLgAddAction_Click(object sender, EventArgs e) { var item = sender as ToolStripItem; + var action = item.Tag as LgDevice.InvokableAction; - AddToLgSteps(item.Text); + var text = item.Text; + + var value = string.Empty; + + if (action.EnumType == null) + { + var values = MessageForms.ShowDialog("Enter value", new[] { + new MessageForms.FieldDefinition + { + Label = "Enter desired " + text, + FieldType = MessageForms.FieldType.Numeric, + MinValue = action.MinValue, + MaxValue = action.MaxValue + } + }); + + if (!values.Any()) + { + return; + } + + value = values.First(); + } + else + { + var dropDownValues = new List(); + foreach (var enumValue in Enum.GetValues(action.EnumType)) + { + dropDownValues.Add(enumValue.ToString()); + } + + var values = MessageForms.ShowDialog("Choose value", new[] { + new MessageForms.FieldDefinition + { + Label = "Choose desired " + text, + FieldType = MessageForms.FieldType.DropDown, + Values = dropDownValues + } + }); + + if (!values.Any()) + { + return; + } + + value = values.First(); + } + + if (!string.IsNullOrEmpty(value)) + { + text += $"({value})"; + } + + AddToLgSteps(text); } private void AddToLgSteps(string step) @@ -2402,11 +2456,12 @@ Do you want to continue?"; var device = _lgService.GetPresetDevice(preset); var actions = device?.GetInvokableActions(); - foreach (var keyValuePair in actions) + foreach (var action in actions) { - var text = keyValuePair.Key; + var text = action.Name; var item = mnuLgActions.DropDownItems.Add(text); + item.Tag = action; item.Click += miLgAddAction_Click; } @@ -2441,7 +2496,9 @@ Do you want to continue?" private void mnuLgExpert_Opening(object sender, CancelEventArgs e) { var device = _lgService.SelectedDevice; - mnuLgOLEDMotionPro.Visible = device?.ModelName != null ? (device.ModelName.Contains("C9") || device.ModelName.Contains("B9")) : false; + var visible = device?.ModelName != null ? (device.ModelName.Contains("C9") || device.ModelName.Contains("B9")) : false; + mnuLgOLEDMotionPro.Visible = visible; + miLgExpertSeparator1.Visible = visible; if (mnuLgExpertBacklight.DropDownItems.Count == 0) { @@ -2453,6 +2510,18 @@ Do you want to continue?" item.Click += btnLgExpertBacklight_Click; } } + + // Does not work yet, getting a "401 no permissions" error + //var task = device?.GetPictureSettings(); + //var settings = Utils.WaitForTask(task); + + Utils.BuildDropDownMenuEx(mnuLgExpert, "Picture Mode", typeof(PictureMode), btnLgExpertColorGamut_Click, "pictureMode"); + Utils.BuildDropDownMenuEx(mnuLgExpert, "Color Gamut", typeof(ColorGamut), btnLgExpertColorGamut_Click, "colorGamut"); + Utils.BuildDropDownMenuEx(mnuLgExpert, "Dynamic Contrast", typeof(OffToAuto), btnLgExpertColorGamut_Click, "dynamicContrast"); + Utils.BuildDropDownMenuEx(mnuLgExpert, "Smooth Gradation", typeof(OffToAuto), btnLgExpertColorGamut_Click, "smoothGradation"); + Utils.BuildDropDownMenuEx(mnuLgExpert, "Peak Brightness", typeof(OffToAuto), btnLgExpertColorGamut_Click, "peakBrightness"); + Utils.BuildDropDownMenuEx(mnuLgExpert, "OLED Motion Pro", typeof(OffToHigh), btnLgExpertColorGamut_Click, "motionProOLED"); + Utils.BuildDropDownMenuEx(mnuLgExpert, "Energy Saving", typeof(EnergySaving), btnLgExpertColorGamut_Click, "energySaving"); } private void btnLgExpert_Click(object sender, EventArgs e) @@ -2468,6 +2537,15 @@ Do you want to continue?" _lgService.SelectedDevice?.SetBacklight(backlight); } + private void btnLgExpertColorGamut_Click(object sender, EventArgs e) + { + var item = sender as ToolStripItem; + var name = item.Tag.ToString(); + var value = item.Text; + + _lgService.SelectedDevice?.SetSystemSettings(name, value); + } + private void miLgEnableMotionPro_Click(object sender, EventArgs e) { if (MessageForms.QuestionYesNo("Are you sure you want to enable OLED Motion Pro? This app and its creator are in no way accountable for any damages it may cause to your tv.") == DialogResult.Yes) @@ -2484,5 +2562,13 @@ Do you want to continue?" MessageForms.InfoOk("Setting applied."); } + + private void cbxLgApps_KeyPress(object sender, KeyPressEventArgs e) + { + if (e.KeyChar == ((char)Keys.Back)) + { + cbxLgApps.SelectedIndex = -1; + } + } } } \ No newline at end of file diff --git a/ColorControl/MainForm.resx b/ColorControl/MainForm.resx index 69e375d..7229478 100644 --- a/ColorControl/MainForm.resx +++ b/ColorControl/MainForm.resx @@ -129,9 +129,6 @@ 147, 17 - - 419, 17 - diff --git a/ColorControl/MessageForms.cs b/ColorControl/MessageForms.cs index 7f176fc..4da01fd 100644 --- a/ColorControl/MessageForms.cs +++ b/ColorControl/MessageForms.cs @@ -8,6 +8,22 @@ namespace ColorControl { class MessageForms { + public enum FieldType + { + Text, + Numeric, + DropDown + } + + public class FieldDefinition + { + public string Label { get; set; } + public FieldType FieldType { get; set; } = FieldType.Text; + public IEnumerable Values { get; set; } + public decimal MinValue { get; set; } + public decimal MaxValue { get; set; } + } + public static Form MainForm; public static void WarningOk(string text) @@ -31,47 +47,100 @@ namespace ColorControl } public static List ShowDialog(string caption, IEnumerable labels, Func, string> validateFunc = null) + { + var fieldDefinitions = labels.Select(l => new FieldDefinition + { + Label = l + }); + + return ShowDialog(caption, fieldDefinitions, validateFunc); + } + + public static List ShowDialog(string caption, IEnumerable fields, Func, string> validateFunc = null) { var values = new List(); var prompt = new Form() { Width = 500, - Height = 90 + (labels.Count() * 55), + Height = 90 + (fields.Count() * 55), FormBorderStyle = FormBorderStyle.FixedDialog, Text = caption, StartPosition = FormStartPosition.CenterScreen }; var top = 10; - var boxes = new List(); + var boxes = new List(); - foreach (var label in labels) + foreach (var field in fields) { - var textLabel = new Label() { Left = 40, Top = top, Text = label }; + var label = field.Label; + var textLabel = new Label() { Left = 40, Top = top, Text = label, AutoSize = true }; top += 25; prompt.Controls.Add(textLabel); - var textBox = new MaskedTextBox() { Left = 40, Top = top, Width = 400 }; + Control control; - if (label.Contains("Ip-address")) + switch(field.FieldType) { - textBox.Mask = "###.###.###.###"; - textBox.ValidatingType = typeof(System.Net.IPAddress); - textBox.Culture = CultureInfo.InvariantCulture; - } - else if (label.Contains("MAC-address")) - { - textBox.Mask = "AA-AA-AA-AA-AA-AA"; - textBox.Culture = CultureInfo.InvariantCulture; + case FieldType.Text: + var textBox = new MaskedTextBox() { Left = 40, Top = top, Width = 400 }; + + if (label.Contains("Ip-address")) + { + textBox.Mask = "###.###.###.###"; + textBox.ValidatingType = typeof(System.Net.IPAddress); + textBox.Culture = CultureInfo.InvariantCulture; + } + else if (label.Contains("MAC-address")) + { + textBox.Mask = "AA-AA-AA-AA-AA-AA"; + textBox.Culture = CultureInfo.InvariantCulture; + } + + control = textBox; + break; + + case FieldType.Numeric: + var numericEdit = new NumericUpDown() { Left = 40, Top = top, Width = 400 }; + + if (field.MinValue != field.MaxValue) + { + numericEdit.Minimum = field.MinValue; + numericEdit.Maximum = field.MaxValue; + } + + control = numericEdit; + break; + + case FieldType.DropDown: + var comboBox = new ComboBox + { + Left = 40, + Top = top, + Width = 400, + DropDownStyle = ComboBoxStyle.DropDownList + }; + + if (field.Values != null && field.Values.Any()) + { + comboBox.Items.AddRange(field.Values.ToArray()); + comboBox.SelectedIndex = 0; + } + + control = comboBox; + break; + + default: + continue; } top += 30; - prompt.Controls.Add(textBox); - boxes.Add(textBox); + prompt.Controls.Add(control); + boxes.Add(control); } - var confirmation = new Button() { Text = "Add", Left = 365, Width = 75, Top = prompt.ClientRectangle.Height - 30 }; + var confirmation = new Button() { Text = "OK", Left = 365, Width = 75, Top = prompt.ClientRectangle.Height - 30 }; confirmation.Click += (sender, e) => { values.AddRange(boxes.Select(b => b.Text.Trim())); diff --git a/ColorControl/Properties/AssemblyInfo.cs b/ColorControl/Properties/AssemblyInfo.cs index 9ee6987..505e5e3 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("3.1.1.0")] -[assembly: AssemblyFileVersion("3.1.1.0")] +[assembly: AssemblyVersion("3.2.0.0")] +[assembly: AssemblyFileVersion("3.2.0.0")] diff --git a/ColorControl/Utils.cs b/ColorControl/Utils.cs index c0cb636..527fc4e 100644 --- a/ColorControl/Utils.cs +++ b/ColorControl/Utils.cs @@ -18,6 +18,7 @@ using System.Security.Principal; using System.Threading; using System.Threading.Tasks; using System.Web.Script.Serialization; +using System.Windows; using System.Windows.Forms; using Windows.Devices.Enumeration; using Windows.Devices.Enumeration.Pnp; @@ -511,9 +512,28 @@ namespace ColorControl } } - public static void BuildDropDownMenu(ToolStripMenuItem mnuParent, string name, Type enumType, object colorData, string propertyName, EventHandler clickEvent) + public static void BuildDropDownMenuEx(ContextMenuStrip mnuParent, string name, Type enumType, EventHandler clickEvent, object tag = null) { - PropertyInfo property; + var subMenuName = $"{mnuParent.Name}_{name}"; + var subMenuItems = mnuParent.Items.Find(subMenuName, false); + ToolStripMenuItem subMenuItem; + if (subMenuItems.Length == 0) + { + subMenuItem = (ToolStripMenuItem)mnuParent.Items.Add(name); + subMenuItem.Name = subMenuName; + + foreach (var enumValue in Enum.GetValues(enumType)) + { + var item = subMenuItem.DropDownItems.Add(enumValue.ToString()); + item.Tag = tag; + item.Click += clickEvent; + } + } + } + + public static void BuildDropDownMenu(ToolStripDropDownItem mnuParent, string name, Type enumType, object colorData, string propertyName, EventHandler clickEvent) + { + PropertyInfo property = null; var subMenuItems = mnuParent.DropDownItems.Find("miColorSettings_" + name, false); ToolStripMenuItem subMenuItem; if (subMenuItems.Length == 0) @@ -521,8 +541,11 @@ namespace ColorControl subMenuItem = (ToolStripMenuItem)mnuParent.DropDownItems.Add(name); subMenuItem.Name = "miColorSettings_" + name; - property = colorData.GetType().GetDeclaredProperty(propertyName); - subMenuItem.Tag = property; + if (colorData != null) + { + property = colorData.GetType().GetDeclaredProperty(propertyName); + subMenuItem.Tag = property; + } foreach (var enumValue in Enum.GetValues(enumType)) { @@ -537,6 +560,10 @@ namespace ColorControl property = (PropertyInfo)subMenuItem.Tag; } + if (colorData == null) + { + return; + } var value = property.GetValue(colorData); foreach (var item in subMenuItem.DropDownItems) @@ -715,6 +742,41 @@ namespace ColorControl return result; } } + + public static bool IsForegroundFullScreen(Screen screen = null) + { + + if (screen == null) + { + screen = Screen.PrimaryScreen; + } + tagRECT rect = new tagRECT(); + IntPtr hWnd = (IntPtr)NativeMethods.GetForegroundWindow(); + + + NativeMethods.GetWindowRect(hWnd, out rect); + + /* in case you want the process name: + uint procId = 0; + GetWindowThreadProcessId(hWnd, out procId); + var proc = System.Diagnostics.Process.GetProcessById((int)procId); + Console.WriteLine(proc.ProcessName); + */ + + + if (screen.Bounds.Width <= (rect.right - rect.left) && screen.Bounds.Height <= (rect.bottom - rect.top)) + { + Console.WriteLine("Fullscreen!"); + return true; + } + else + { + Console.WriteLine("Nope, :-("); + return false; + } + + + } } public static class ProcessExtensions diff --git a/ColorControl/lgtv/LgTvApi.cs b/ColorControl/lgtv/LgTvApi.cs index e198fea..136a2db 100644 --- a/ColorControl/lgtv/LgTvApi.cs +++ b/ColorControl/lgtv/LgTvApi.cs @@ -16,6 +16,57 @@ namespace LgTv OK, Exit } + + public enum PictureMode + { + cinema, eco, expert1, expert2, game, + normal, photo, sports, technicolor, vivid, hdrEffect, hdrCinema, + hdrCinemaBright, hdrExternal, hdrGame, hdrStandard, hdrTechnicolor, + hdrVivid, dolbyHdrCinema, dolbyHdrCinemaBright, dolbyHdrDarkAmazon, + dolbyHdrGame, dolbyHdrStandard, dolbyHdrVivid, dolbyStandard + } + + public enum OffToHigh + { + off, + low, + medium, + high + } + + public enum OffToAuto + { + off, + low, + medium, + high, + auto + } + + public enum ColorGamut + { + auto, + extended, + wide, + srgb + } + + public enum EnergySaving + { + auto, + off, + min, + med, + max, + screen_off + } + + public enum TruMotionMode + { + off, + user + } + public class LgTvApi:IDisposable { public bool ConnectionClosed { get => _connection?.ConnectionClosed ?? true; } @@ -365,11 +416,13 @@ namespace LgTv return (string)response.sessionId; } - public async Task SetSystemSettings(string key, string value) + public async Task SetSystemSettings(string key, string value, string category = "picture") { var lunauri = "luna://com.webos.settingsservice/setSystemSettings"; - var @params = JObject.Parse(@"{ ""category"": ""picture"", ""settings"": { """ + key + @""": """ + value + @""" } }"); + var json = @"{ ""category"": """ + category + @""", ""settings"": { """ + key + @""": """ + value + @""" } }"; + + var @params = JObject.Parse(json); await ExecuteRequest(lunauri, @params); } @@ -430,6 +483,20 @@ namespace LgTv return res; } + public async Task GetSystemSettings(string category, params string[] keys) + { + var payload = new + { + category = category, + keys = keys + }; + + var requestMessage = new RequestMessage("ssap://settings/getSystemSettings", payload); + var command = _connection.SendCommandAsync(requestMessage); + var res = await command; + return res; + } + public void Close() { _connection.Close(); diff --git a/ColorControl/lgtv/LgTvConnection.cs b/ColorControl/lgtv/LgTvConnection.cs index 5f7c192..3652877 100644 --- a/ColorControl/lgtv/LgTvConnection.cs +++ b/ColorControl/lgtv/LgTvConnection.cs @@ -170,7 +170,7 @@ namespace LgTv if (id == "register_0") return; if (obj.type == "error") { - taskCompletion.SetException(new Exception(obj.error)); + taskCompletion.SetException(new Exception(obj.error?.ToString())); } //else if (args.Cancelled) //{