From fa63d8dc4f935770f3a7fd8d557b1580fe82b8cd Mon Sep 17 00:00:00 2001 From: Vincent Maas Date: Sun, 20 Jun 2021 13:59:12 +0200 Subject: [PATCH] fixed some issues --- ColorControl/ColorControl.csproj | 2 +- ColorControl/ColorDataConverter.cs | 29 +--------- ColorControl/LgDevice.cs | 75 ++++++++++++++++++++++++- ColorControl/LgService.cs | 6 ++ ColorControl/MainForm.Designer.cs | 3 +- ColorControl/MainForm.cs | 18 +++++- ColorControl/NvPreset.cs | 13 +++-- ColorControl/Properties/AssemblyInfo.cs | 4 +- ColorControl/lgtv/LgTvApi.cs | 25 ++++++++- ColorControl/lgtv/LgTvConnection.cs | 20 +++++++ ColorControl/lgtv/RequestMessage.cs | 8 ++- 11 files changed, 160 insertions(+), 43 deletions(-) diff --git a/ColorControl/ColorControl.csproj b/ColorControl/ColorControl.csproj index 4902b35..02ca566 100644 --- a/ColorControl/ColorControl.csproj +++ b/ColorControl/ColorControl.csproj @@ -27,7 +27,7 @@ ColorControl Maassoft 0 - 3.2.1.0 + 3.2.2.0 false true true diff --git a/ColorControl/ColorDataConverter.cs b/ColorControl/ColorDataConverter.cs index de541a6..0872404 100644 --- a/ColorControl/ColorDataConverter.cs +++ b/ColorControl/ColorDataConverter.cs @@ -1,5 +1,4 @@ using NvAPIWrapper.Display; -using NvAPIWrapper.Native.Display; using System; using System.Collections.Generic; using System.Web.Script.Serialization; @@ -22,33 +21,7 @@ public override IDictionary Serialize(object obj, JavaScriptSeri public override object Deserialize(IDictionary dictionary, Type type, JavaScriptSerializer serializer) { - var format = ColorDataFormat.RGB; - var dynamicRange = ColorDataDynamicRange.VESA; - var colorDepth = ColorDataDepth.BPC8; - var colorimetry = ColorDataColorimetry.Auto; - var selectionPolicy = ColorDataSelectionPolicy.User; - object value; - if (dictionary.TryGetValue("ColorFormat", out value)) - { - format = (ColorDataFormat)Enum.ToObject(typeof(ColorDataFormat), value); - } - if (dictionary.TryGetValue("ColorDepth", out value)) - { - colorDepth = (ColorDataDepth)Enum.ToObject(typeof(ColorDataDepth), value); - } - if (dictionary.TryGetValue("Colorimetry", out value)) - { - colorimetry = (ColorDataColorimetry)Enum.ToObject(typeof(ColorDataColorimetry), value); - } - if (dictionary.TryGetValue("DynamicRange", out value)) - { - dynamicRange = (ColorDataDynamicRange)Enum.ToObject(typeof(ColorDataDynamicRange), value); - } - if (dictionary.TryGetValue("SelectionPolicy", out value)) - { - selectionPolicy = (ColorDataSelectionPolicy)Enum.ToObject(typeof(ColorDataSelectionPolicy), value); - } - return new ColorData(format, dynamicRange: dynamicRange, colorimetry: colorimetry, colorDepth: colorDepth, colorSelectionPolicy: selectionPolicy, desktopColorDepth: ColorDataDesktopDepth.Default); + return NvPreset.GenerateColorData(dictionary); } } } diff --git a/ColorControl/LgDevice.cs b/ColorControl/LgDevice.cs index 0efcf98..57a44c2 100644 --- a/ColorControl/LgDevice.cs +++ b/ColorControl/LgDevice.cs @@ -20,6 +20,22 @@ public class InvokableAction public decimal MaxValue { get; set; } } + public enum PowerState + { + Unknown, + Active, + Power_Off, + Suspend, + Active_Standby + } + + public enum PowerOffSource + { + Unknown, + App, + Manually + } + protected static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); public string Name { get; private set; } @@ -35,10 +51,17 @@ public class InvokableAction public bool PowerOffOnStandby { get; set; } public bool PowerSwitchOnScreenSaver { get; set; } + [JsonIgnore] + public PowerState CurrentState { get; set; } + [JsonIgnore] private LgTvApi _lgTvApi; [JsonIgnore] private bool _justWokeUp; + [JsonIgnore] + public PowerOffSource PoweredOffBy { get; private set; } + + public bool PoweredOffViaApp { get; private set; } [JsonIgnore] private List _invokableActions = new List(); @@ -87,7 +110,9 @@ private void AddGenericPictureAction(string name, Type type = null, decimal minV { Name = name, Function = new Func, bool>(GenericPictureAction), - EnumType = type + EnumType = type, + MinValue = minValue, + MaxValue = maxValue }; _invokableActions.Add(action); @@ -95,7 +120,8 @@ private void AddGenericPictureAction(string name, Type type = null, decimal minV public override string ToString() { - return (IsDummy ? string.Empty : (IsCustom ? "Custom: " : "Auto detect: ")) + $"{Name}" + (!string.IsNullOrEmpty(IpAddress) ? $" ({IpAddress})" : string.Empty); + //return (IsDummy ? string.Empty : (IsCustom ? "Custom: " : "Auto detect: ")) + $"{Name}" + (!string.IsNullOrEmpty(IpAddress) ? $" ({IpAddress})" : string.Empty); + return $"{(IsDummy ? string.Empty : (IsCustom ? "Custom: " : "Auto detect: "))}{Name}{(!string.IsNullOrEmpty(IpAddress) ? ", " + IpAddress : string.Empty)}"; } public async Task Connect(int retries = 3) @@ -114,6 +140,14 @@ public async Task Connect(int retries = 3) { ModelName = info.modelName; } + + //await _lgTvApi.SubscribeVolume(VolumeChanged); + await _lgTvApi.SubscribePowerState(PowerStateChanged); + + //await _lgTvApi.SetInput("HDMI_1"); + //await Task.Delay(2000); + //await _lgTvApi.SetConfig("com.palm.app.settings.enableHdmiPcLabel", true); + //await _lgTvApi.SetInput("HDMI_2"); } return _lgTvApi != null; } @@ -125,6 +159,40 @@ public async Task Connect(int retries = 3) } } + public bool VolumeChanged(dynamic payload) + { + return true; + } + public bool PowerStateChanged(dynamic payload) + { + Logger.Debug($"[{Name}] Power state change: " + JsonConvert.SerializeObject(payload)); + + var state = ((string)payload.state).Replace(' ', '_'); + + PowerState newState; + if (Enum.TryParse(state, out newState)) + { + CurrentState = newState; + + if (CurrentState == PowerState.Active) + { + if (payload.processing == null) + { + PoweredOffViaApp = false; + } + } + else { + PoweredOffBy = PoweredOffViaApp ? PowerOffSource.App : PowerOffSource.Manually; + } + } + else + { + CurrentState = PowerState.Unknown; + Logger.Warn($"Unknown power state: {state}"); + } + return true; + } + public bool IsConnected() { return !_lgTvApi?.ConnectionClosed ?? false; @@ -303,7 +371,10 @@ internal async Task PowerOff() return false; } + PoweredOffViaApp = true; + await _lgTvApi.TurnOff(); + return true; } diff --git a/ColorControl/LgService.cs b/ColorControl/LgService.cs index 569d128..206fa6c 100644 --- a/ColorControl/LgService.cs +++ b/ColorControl/LgService.cs @@ -429,6 +429,12 @@ internal void WakeAfterStartupOrResume(PowerOnOffState state = PowerOnOffState.S state == PowerOnOffState.ScreenSaver && d.PowerSwitchOnScreenSaver); foreach (var device in wakeDevices) { + if (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); } diff --git a/ColorControl/MainForm.Designer.cs b/ColorControl/MainForm.Designer.cs index 3469fea..b8ed7a1 100644 --- a/ColorControl/MainForm.Designer.cs +++ b/ColorControl/MainForm.Designer.cs @@ -994,7 +994,7 @@ private void InitializeComponent() this.miLgExpertSeparator1, this.mnuLgExpertBacklight}); this.mnuLgExpert.Name = "mnuLgButtons"; - this.mnuLgExpert.Size = new System.Drawing.Size(321, 76); + this.mnuLgExpert.Size = new System.Drawing.Size(321, 54); this.mnuLgExpert.Opening += new System.ComponentModel.CancelEventHandler(this.mnuLgExpert_Opening); // // mnuLgOLEDMotionPro @@ -1056,6 +1056,7 @@ private void InitializeComponent() // cbxLgDevices // this.cbxLgDevices.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cbxLgDevices.DropDownWidth = 400; this.cbxLgDevices.FormattingEnabled = true; this.cbxLgDevices.Location = new System.Drawing.Point(86, 8); this.cbxLgDevices.Name = "cbxLgDevices"; diff --git a/ColorControl/MainForm.cs b/ColorControl/MainForm.cs index cdca8c0..03b8eda 100644 --- a/ColorControl/MainForm.cs +++ b/ColorControl/MainForm.cs @@ -52,6 +52,7 @@ public partial class MainForm : Form private StartUpParams StartUpParams { get; } private AmdService _amdService; + private bool _skipResize; public MainForm(AppContext appContext) { @@ -541,6 +542,11 @@ private void MainForm_FormClosed(object sender, FormClosedEventArgs e) private void MainForm_Resize(object sender, EventArgs e) { + if (_skipResize) + { + return; + } + if (WindowState == FormWindowState.Minimized) { if (_config.MinimizeToTray) @@ -578,8 +584,16 @@ private void LoadConfig() Utils.RegisterShortcut(Handle, SHORTCUTID_SCREENSAVER, _config.ScreenSaverShortcut); } - Width = _config.FormWidth; - Height = _config.FormHeight; + _skipResize = true; + try + { + Width = _config.FormWidth; + Height = _config.FormHeight; + } + finally + { + _skipResize = false; + } } private void SaveConfig() diff --git a/ColorControl/NvPreset.cs b/ColorControl/NvPreset.cs index 2ca3e68..3a3dcbf 100644 --- a/ColorControl/NvPreset.cs +++ b/ColorControl/NvPreset.cs @@ -51,7 +51,7 @@ public NvPreset(NvPreset preset): this() displayName = preset.displayName; var colorData = preset.colorData; - this.colorData = new ColorData(colorData.ColorFormat, dynamicRange: colorData.DynamicRange, colorDepth: colorData.ColorDepth, colorSelectionPolicy: colorData.SelectionPolicy); + this.colorData = new ColorData(colorData.ColorFormat, dynamicRange: colorData.DynamicRange, colorDepth: colorData.ColorDepth, colorSelectionPolicy: ColorDataSelectionPolicy.User); applyColorData = preset.applyColorData; applyHDR = preset.applyHDR; @@ -206,11 +206,16 @@ public static ColorData GenerateColorData(IDictionary dictionary { dynamicRange = (ColorDataDynamicRange)Enum.ToObject(typeof(ColorDataDynamicRange), value); } - if (dictionary.TryGetValue("SelectionPolicy", out value)) + if (dictionary.TryGetValue("SelectionPolicy", out _)) { - selectionPolicy = (ColorDataSelectionPolicy)Enum.ToObject(typeof(ColorDataSelectionPolicy), value); + selectionPolicy = + colorDepth == ColorDataDepth.Default && + format >= ColorDataFormat.Default && + colorimetry >= ColorDataColorimetry.Default && + dynamicRange == ColorDataDynamicRange.Auto ? + ColorDataSelectionPolicy.BestQuality : selectionPolicy; } - return new ColorData(format, dynamicRange: dynamicRange, colorimetry: colorimetry, colorDepth: colorDepth, colorSelectionPolicy: selectionPolicy); + return new ColorData(format, dynamicRange: dynamicRange, colorimetry: colorimetry, colorDepth: colorDepth, colorSelectionPolicy: selectionPolicy, desktopColorDepth: ColorDataDesktopDepth.Default); } } diff --git a/ColorControl/Properties/AssemblyInfo.cs b/ColorControl/Properties/AssemblyInfo.cs index 5d35f19..710f786 100644 --- a/ColorControl/Properties/AssemblyInfo.cs +++ b/ColorControl/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ // 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.2.1.0")] -[assembly: AssemblyFileVersion("3.2.1.0")] +[assembly: AssemblyVersion("3.2.2.0")] +[assembly: AssemblyFileVersion("3.2.2.0")] diff --git a/ColorControl/lgtv/LgTvApi.cs b/ColorControl/lgtv/LgTvApi.cs index 136a2db..56a4b91 100644 --- a/ColorControl/lgtv/LgTvApi.cs +++ b/ColorControl/lgtv/LgTvApi.cs @@ -307,7 +307,7 @@ public async Task GetVolume() } public async Task> GetInputList() { - var requestMessage = new RequestMessage("input","ssap://tv/getExternalInputList"); + var requestMessage = new RequestMessage("input","ssap://tv/getExternalInputList"); var results = await _connection.SendCommandAsync(requestMessage); var l = new List(); foreach (var result in results) @@ -326,6 +326,20 @@ public async Task SetInput(string id) await _connection.SendCommandAsync(requestMessage); } + public async Task SubscribeVolume(Func callback, dynamic payload = null) + { + var requestMessage = new RequestMessage("ssap://audio/getVolume", null, "subscribe"); + + await _connection.SubscribeAsync(requestMessage, callback); + } + + public async Task SubscribePowerState(Func callback, dynamic payload = null) + { + var requestMessage = new RequestMessage("ssap://com.webos.service.tvpower/power/getPowerState", null, "subscribe"); + + await _connection.SubscribeAsync(requestMessage, callback); + } + public async Task> GetLaunchPoints() { _appList = new List(); @@ -436,6 +450,15 @@ public async Task SetConfig(string key, string value) await ExecuteRequest(lunauri, @params); } + public async Task SetConfig(string key, bool value) + { + var lunauri = "luna://com.webos.service.config/setConfigs"; + + var @params = JObject.Parse(@"{ ""configs"": { """ + key + @""": " + value.ToString().ToLowerInvariant() + @" } }"); + + await ExecuteRequest(lunauri, @params); + } + private async Task ExecuteRequest(string lunauri, object @params) { var buttons = new[] diff --git a/ColorControl/lgtv/LgTvConnection.cs b/ColorControl/lgtv/LgTvConnection.cs index 3652877..e662fd0 100644 --- a/ColorControl/lgtv/LgTvConnection.cs +++ b/ColorControl/lgtv/LgTvConnection.cs @@ -29,6 +29,7 @@ public class LgTvApiCore : IDisposable public event IsConnectedDelegate IsConnected; private readonly ConcurrentDictionary> _tokens = new ConcurrentDictionary>(); + private readonly ConcurrentDictionary> _callbacks = new ConcurrentDictionary>(); private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); @@ -135,6 +136,20 @@ public Task SendCommandAsync(RequestMessage message) return SendCommandAsync(rawMessage.Id, serialized); } + public Task SubscribeAsync(RequestMessage message, Func callback) + { + var rawMessage = new RawRequestMessage(message, ++_commandCount); + var serialized = JsonConvert.SerializeObject(rawMessage, new JsonSerializerSettings() + { + NullValueHandling = NullValueHandling.Ignore, + ContractResolver = new CamelCasePropertyNamesContractResolver() + }); + + _callbacks.TryAdd(rawMessage.Id, callback); + + return SendCommandAsync(rawMessage.Id, serialized); + } + private void Connection_Closed(IWebSocket sender, WebSocketClosedEventArgs args) { MessageWebSocket webSocket = Interlocked.Exchange(ref _connection, null); @@ -177,6 +192,11 @@ private void Connection_MessageReceived(MessageWebSocket sender, MessageWebSocke // taskSource.SetCanceled(); //} taskCompletion.TrySetResult(obj.payload); + + if (_callbacks.TryGetValue(id, out Func callback)) + { + callback(obj.payload); + } } } } diff --git a/ColorControl/lgtv/RequestMessage.cs b/ColorControl/lgtv/RequestMessage.cs index fb769db..0ddc6e0 100644 --- a/ColorControl/lgtv/RequestMessage.cs +++ b/ColorControl/lgtv/RequestMessage.cs @@ -9,10 +9,14 @@ public RequestMessage(string prefix, string uri) Prefix = prefix; Uri = uri; } - public RequestMessage(string uri,object payload) + public RequestMessage(string uri, object payload, string type = "request") { Uri = uri; - Payload = JsonConvert.SerializeObject(payload); + if (payload != null) + { + Payload = JsonConvert.SerializeObject(payload); + } + Type = type; } public string Prefix { get; set; }