From 6eae7db4599ab3ab66afb3da94917868711c30ed Mon Sep 17 00:00:00 2001 From: Vincent Maas Date: Sat, 26 Aug 2023 13:33:14 +0200 Subject: [PATCH] fix Nvidia error, add HDMI settings, add LG action --- ColorControl/ColorControl.csproj | 4 +- ColorControl/MainForm.cs | 14 +- ColorControl/Program.cs | 1 + ColorControl/Services/Common/ServiceBase.cs | 13 +- .../Services/GameLauncher/GamePanel.cs | 16 +- ColorControl/Services/LG/LgDevice.cs | 1 + ColorControl/Services/LG/LgPanel.cs | 52 ++-- ColorControl/Services/NVIDIA/NvGpuInfo.cs | 46 +-- .../Services/NVIDIA/NvPanel.Designer.cs | 48 ++- ColorControl/Services/NVIDIA/NvPanel.cs | 242 ++++++++++++--- ColorControl/Services/NVIDIA/NvPreset.cs | 98 ++++-- ColorControl/Services/NVIDIA/NvService.cs | 284 ++++++++++-------- .../Services/Samsung/ISamsungService.cs | 20 ++ .../Services/Samsung/SamsungDevice.cs | 26 +- ColorControl/Services/Samsung/SamsungPanel.cs | 69 ++--- .../Services/Samsung/SamsungService.cs | 22 +- .../Svc/ColorControlBackgroundService.cs | 14 + .../InfoFrameVideoExtendedColorimetry.cs | 2 +- Shared/Common/PipeUtils.cs | 18 ++ Shared/Common/Utils.cs | 35 ++- .../NVIDIA/NvHdmiInfoFrameSettings.cs | 46 +++ Shared/Contracts/Svc/SvcMessage.cs | 13 + Shared/Forms/FormUtils.cs | 4 +- Shared/Forms/MessageForms.cs | 185 +++++++----- Shared/Services/RpcService.cs | 23 ++ Shared/Shared.csproj | 4 + 26 files changed, 874 insertions(+), 426 deletions(-) create mode 100644 ColorControl/Services/Samsung/ISamsungService.cs create mode 100644 Shared/Contracts/NVIDIA/NvHdmiInfoFrameSettings.cs create mode 100644 Shared/Services/RpcService.cs diff --git a/ColorControl/ColorControl.csproj b/ColorControl/ColorControl.csproj index 031b21d..ce06623 100644 --- a/ColorControl/ColorControl.csproj +++ b/ColorControl/ColorControl.csproj @@ -18,8 +18,8 @@ Maassoft Maassoft 0 - 9.6.3.0 - 9.6.3.0 + 9.6.4.0 + 9.6.4.0 false true false diff --git a/ColorControl/MainForm.cs b/ColorControl/MainForm.cs index b2ce3c0..36f94d4 100644 --- a/ColorControl/MainForm.cs +++ b/ColorControl/MainForm.cs @@ -260,7 +260,9 @@ namespace ColorControl _serviceManager.NvService = new NvService(appContextProvider); Logger.Debug("Initializing NVIDIA...Done."); - _nvPanel = new NvPanel(_serviceManager.NvService, _trayIcon, Handle, appContextProvider); + var rpcService = Program.ServiceProvider.GetRequiredService(); + + _nvPanel = new NvPanel(_serviceManager.NvService, _trayIcon, Handle, appContextProvider, rpcService); _nvPanel.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; InitShortcut(NvPanel.SHORTCUTID_NVQA, _config.NvQuickAccessShortcut, _serviceManager.NvService.ToggleQuickAccessForm); @@ -1322,7 +1324,7 @@ Currently ColorControl is {(Utils.IsAdministrator() ? "" : "not ")}running as ad //InstallUpdate(""); //await Test(); - //_serviceManager.NvService.TestResolution(); + _serviceManager.NvService.TestResolution(); } private async Task Test() @@ -1414,18 +1416,18 @@ Currently ColorControl is {(Utils.IsAdministrator() ? "" : "not ")}running as ad private void btnOptionsAdvanced_Click(object sender, EventArgs e) { - var processPollingIntervalField = new MessageForms.FieldDefinition + var processPollingIntervalField = new FieldDefinition { - FieldType = MessageForms.FieldType.Numeric, + FieldType = FieldType.Numeric, Label = "Polling interval of process monitor (milliseconds).", SubLabel = "Decreasing this delay may execute triggered presets sooner but can cause a higher CPU load", MinValue = 50, MaxValue = 5000, Value = _config.ProcessMonitorPollingInterval }; - var useRawInputField = new MessageForms.FieldDefinition + var useRawInputField = new FieldDefinition { - FieldType = MessageForms.FieldType.CheckBox, + FieldType = FieldType.CheckBox, Label = "Use Raw Input for shortcuts (hot keys)", SubLabel = "This enables shortcuts to work during applications/games that block certain keys (like WinKey or Control). NOTE: if the application in the foreground runs with higher privileges than ColorControl, Raw Input does not work and normal hot keys are used", Value = _config.UseRawInput diff --git a/ColorControl/Program.cs b/ColorControl/Program.cs index cb90627..e0e16fd 100644 --- a/ColorControl/Program.cs +++ b/ColorControl/Program.cs @@ -247,6 +247,7 @@ namespace ColorControl services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddTransient(); }); } private static async Task RunService(string[] args) diff --git a/ColorControl/Services/Common/ServiceBase.cs b/ColorControl/Services/Common/ServiceBase.cs index d7db094..5c96f33 100644 --- a/ColorControl/Services/Common/ServiceBase.cs +++ b/ColorControl/Services/Common/ServiceBase.cs @@ -72,6 +72,13 @@ namespace ColorControl.Services.Common public virtual T CreateNewPreset() { var preset = new T(); + preset.name = CreateNewPresetName(); + + return preset; + } + + public string CreateNewPresetName() + { var name = "New preset"; string fullname; var number = 1; @@ -79,11 +86,9 @@ namespace ColorControl.Services.Common { fullname = $"{name} ({number})"; number++; - } while (_presets.Any(x => x.name.Equals(fullname))); + } while (_presets.Any(x => x.name?.Equals(fullname) == true)); - preset.name = fullname; - - return preset; + return fullname; } protected virtual void Initialize() diff --git a/ColorControl/Services/GameLauncher/GamePanel.cs b/ColorControl/Services/GameLauncher/GamePanel.cs index 7b6cc5d..c8b9742 100644 --- a/ColorControl/Services/GameLauncher/GamePanel.cs +++ b/ColorControl/Services/GameLauncher/GamePanel.cs @@ -397,10 +397,10 @@ namespace ColorControl.Services.GameLauncher var options = Enumerable.Range(0, numberOfProcessors).Select(i => $"CPU #{i}"); var values = MessageForms.ShowDialog("Set processor affinity", new[] { - new MessageForms.FieldDefinition + new FieldDefinition { Label = "Set desired processors which are allowed to run program", - FieldType = MessageForms.FieldType.Flags, + FieldType = FieldType.Flags, Values = options, Value = preset.ProcessAffinityMask } @@ -433,10 +433,10 @@ namespace ColorControl.Services.GameLauncher var dropDownValues = Utils.GetDescriptions(); var values = MessageForms.ShowDialog("Set process priority", new[] { - new MessageForms.FieldDefinition + new FieldDefinition { Label = "Set desired process priority", - FieldType = MessageForms.FieldType.DropDown, + FieldType = FieldType.DropDown, Values = dropDownValues, Value = preset.ProcessPriorityClass > 0 ? ((GamePriorityClass)preset.ProcessPriorityClass).GetDescription() : GamePriorityClass.Normal.GetDescription() } @@ -448,13 +448,7 @@ namespace ColorControl.Services.GameLauncher } var value = values.First().Value.ToString(); - var enumName = Utils.GetEnumNameByDescription(typeof(GamePriorityClass), value); - if (enumName != null) - { - value = enumName; - } - - var enumValue = Enum.Parse(typeof(GamePriorityClass), value); + var enumValue = Utils.GetEnumValueByDescription(value); preset.ProcessPriorityClass = (uint)(int)enumValue; } diff --git a/ColorControl/Services/LG/LgDevice.cs b/ColorControl/Services/LG/LgDevice.cs index aee2ac9..6a8f18d 100644 --- a/ColorControl/Services/LG/LgDevice.cs +++ b/ColorControl/Services/LG/LgDevice.cs @@ -184,6 +184,7 @@ namespace ColorControl.Services.LG //AddGenericPictureAction("dynamicRange", typeof(DynamicRange), category: "dimensionInfo", title: "Dynamic Range"); AddGenericPictureAction("colorGamut", typeof(ColorGamut), title: "Color Gamut"); AddGenericPictureAction("dynamicContrast", typeof(OffToHigh), title: "Dynamic Contrast"); + AddGenericPictureAction("superResolution", typeof(OffToHigh), title: "Super Resolution"); AddGenericPictureAction("gamma", typeof(GammaExp)); AddGenericPictureAction("colorTemperature", minValue: -50, maxValue: 50, title: "Color Temperature"); AddGenericPictureAction("whiteBalanceColorTemperature", typeof(WhiteBalanceColorTemperature), title: "White Balance Color Temperature"); diff --git a/ColorControl/Services/LG/LgPanel.cs b/ColorControl/Services/LG/LgPanel.cs index 31f05a1..295d908 100644 --- a/ColorControl/Services/LG/LgPanel.cs +++ b/ColorControl/Services/LG/LgPanel.cs @@ -551,14 +551,14 @@ namespace ColorControl.Services.LG { if (action.MinValue != action.MaxValue) { - List fields = new(); + List fields = new(); if (action.NumberOfValues == 1) { - fields.Add(new MessageForms.FieldDefinition + fields.Add(new FieldDefinition { Label = "Enter desired " + title, - FieldType = MessageForms.FieldType.Numeric, + FieldType = FieldType.Numeric, MinValue = action.MinValue, MaxValue = action.MaxValue, }); @@ -567,10 +567,10 @@ namespace ColorControl.Services.LG { var array = Enumerable.Range(0, action.NumberOfValues); - fields.AddRange(array.Select(i => new MessageForms.FieldDefinition + fields.AddRange(array.Select(i => new FieldDefinition { Label = "Value for " + (action.ValueLabels != null ? action.ValueLabels[i] : i.ToString()), - FieldType = MessageForms.FieldType.Numeric, + FieldType = FieldType.Numeric, MinValue = action.MinValue, MaxValue = action.MaxValue, })); @@ -603,10 +603,10 @@ namespace ColorControl.Services.LG } var values = MessageForms.ShowDialog("Choose value", new[] { - new MessageForms.FieldDefinition + new FieldDefinition { Label = "Choose desired " + title, - FieldType = MessageForms.FieldType.DropDown, + FieldType = FieldType.DropDown, Values = dropDownValues } }); @@ -750,7 +750,7 @@ You can also activate this option by using the Expert-button and selecting Wake- } } - private string ValidateAddDevice(IEnumerable values) + private string ValidateAddDevice(IEnumerable values) { if (values.Any(v => string.IsNullOrEmpty(v.Value?.ToString()))) { @@ -1025,10 +1025,10 @@ Do you want to continue?" var dropDownValues = Utils.GetDescriptions(fromValue: 1); var values = MessageForms.ShowDialog("Set trigger conditions", new[] { - new MessageForms.FieldDefinition + new FieldDefinition { Label = "Set desired trigger conditions", - FieldType = MessageForms.FieldType.Flags, + FieldType = FieldType.Flags, Values = dropDownValues, Value = edtLgPresetTriggerConditions.Tag ?? 0 } @@ -1155,11 +1155,11 @@ Do you want to continue?"; { var advancedWasEnabled = _lgService.Config.ShowAdvancedActions; - var fields = new MessageForms.FieldDefinition[] + var fields = new FieldDefinition[] { new() { - FieldType = MessageForms.FieldType.Numeric, + FieldType = FieldType.Numeric, Label = "Maximum number of retries powering on after startup/resume.", SubLabel = "Retries are necessary to wait for the network link of your pc to be established.", MinValue = 1, @@ -1168,7 +1168,7 @@ Do you want to continue?"; }, new() { - FieldType = MessageForms.FieldType.Numeric, + FieldType = FieldType.Numeric, Label = "Delay when shutting down/restarting PC (milliseconds).", SubLabel = "This delay may prevent the tv from powering off when restarting the pc.", MinValue = 0, @@ -1177,31 +1177,31 @@ Do you want to continue?"; }, new() { - FieldType = MessageForms.FieldType.Shortcut, + FieldType = FieldType.Shortcut, Label = "Quick Access shortcut", Value = _lgService.Config.QuickAccessShortcut }, new() { - FieldType = MessageForms.FieldType.Shortcut, + FieldType = FieldType.Shortcut, Label = "Game Bar shortcut", Value = _lgService.Config.GameBarShortcut }, new() { - FieldType = MessageForms.FieldType.CheckBox, + FieldType = FieldType.CheckBox, Label = "Show advanced actions under the Expert-button (InStart, EzAdjust, Software Update)", Value = _lgService.Config.ShowAdvancedActions }, new() { - FieldType = MessageForms.FieldType.CheckBox, + FieldType = FieldType.CheckBox, Label = "Automatically set selected device to last powered on", Value = _lgService.Config.SetSelectedDeviceByPowerOn }, new() { - FieldType = MessageForms.FieldType.Numeric, + FieldType = FieldType.Numeric, Label = "Default delay between remote control button presses (milliseconds).", SubLabel = "Increasing this delay may prevent skipped button presses.", MinValue = 100, @@ -1276,30 +1276,30 @@ The InStart, EzAdjust and Software Update items are now visible under the Expert var device = _lgService.SelectedDevice; var selectedItem = clbLgPower.SelectedItem; - var durationField = new MessageForms.FieldDefinition + var durationField = new FieldDefinition { Label = "Enter the minimal duration the screen saver must be running (in seconds)", - FieldType = MessageForms.FieldType.Numeric, + FieldType = FieldType.Numeric, MinValue = 0, MaxValue = 3600, Value = device.ScreenSaverMinimalDuration }; - var turnOffField = new MessageForms.FieldDefinition + var turnOffField = new FieldDefinition { Label = "Turn screen off instead of power off", - FieldType = MessageForms.FieldType.CheckBox, + FieldType = FieldType.CheckBox, Value = device.TurnScreenOffOnScreenSaver }; - var turnOnField = new MessageForms.FieldDefinition + var turnOnField = new FieldDefinition { Label = "Turn screen on instead of power on", - FieldType = MessageForms.FieldType.CheckBox, + FieldType = FieldType.CheckBox, Value = device.TurnScreenOnAfterScreenSaver }; - var manualField = new MessageForms.FieldDefinition + var manualField = new FieldDefinition { Label = "Perform action even on manually executed screen saver", - FieldType = MessageForms.FieldType.CheckBox, + FieldType = FieldType.CheckBox, Value = device.HandleManualScreenSaver }; diff --git a/ColorControl/Services/NVIDIA/NvGpuInfo.cs b/ColorControl/Services/NVIDIA/NvGpuInfo.cs index ecd2eb1..fb153d7 100644 --- a/ColorControl/Services/NVIDIA/NvGpuInfo.cs +++ b/ColorControl/Services/NVIDIA/NvGpuInfo.cs @@ -711,23 +711,23 @@ namespace ColorControl.Services.NVIDIA return string.Empty; } - internal MessageForms.FieldDefinition GetCoreOffsetField(NvGpuOcSettings settings) + internal FieldDefinition GetCoreOffsetField(NvGpuOcSettings settings) { var graphicsDelta = GetDeltaClockMinMax(PublicClockDomain.Graphics); - //var field = new MessageForms.FieldDefinition + //var field = new FieldDefinition //{ // Label = $"Core offset in MHz ({graphicsDelta.Item1.ToUnitString()} to {graphicsDelta.Item2.ToUnitString()})", - // FieldType = MessageForms.FieldType.Numeric, + // FieldType = FieldType.Numeric, // MinValue = graphicsDelta.Item1 / 1000, // MaxValue = graphicsDelta.Item2 / 1000, // Value = settings.GraphicsOffsetKHz / 1000 //}; - var field = new MessageForms.FieldDefinition + var field = new FieldDefinition { Label = $"Core offset in MHz ({graphicsDelta.Item1.ToUnitString()} to {graphicsDelta.Item2.ToUnitString()})", - FieldType = MessageForms.FieldType.TrackBar, + FieldType = FieldType.TrackBar, MinValue = graphicsDelta.Item1 / 1000, MaxValue = graphicsDelta.Item2 / 1000, Value = settings.GraphicsOffsetKHz / 1000, @@ -737,23 +737,23 @@ namespace ColorControl.Services.NVIDIA return field; } - internal MessageForms.FieldDefinition GetMemoryOffsetField(NvGpuOcSettings settings) + internal FieldDefinition GetMemoryOffsetField(NvGpuOcSettings settings) { var memoryDelta = GetDeltaClockMinMax(PublicClockDomain.Memory); - //var field = new MessageForms.FieldDefinition + //var field = new FieldDefinition //{ // Label = $"Memory offset in MHz ({memoryDelta.Item1.ToUnitString()} to {memoryDelta.Item2.ToUnitString()})", - // FieldType = MessageForms.FieldType.Numeric, + // FieldType = FieldType.Numeric, // MinValue = memoryDelta.Item1 / 1000, // MaxValue = memoryDelta.Item2 / 1000, // Value = settings.MemoryOffsetKHz / 1000 //}; - var field = new MessageForms.FieldDefinition + var field = new FieldDefinition { Label = $"Memory offset in MHz ({memoryDelta.Item1.ToUnitString()} to {memoryDelta.Item2.ToUnitString()})", - FieldType = MessageForms.FieldType.TrackBar, + FieldType = FieldType.TrackBar, MinValue = memoryDelta.Item1 / 1000, MaxValue = memoryDelta.Item2 / 1000, Value = settings.MemoryOffsetKHz / 1000, @@ -763,7 +763,7 @@ namespace ColorControl.Services.NVIDIA return field; } - internal MessageForms.FieldDefinition GetPowerField(NvGpuOcSettings settings) + internal FieldDefinition GetPowerField(NvGpuOcSettings settings) { var powerLimits = GetPowerLimits(); @@ -779,18 +779,18 @@ namespace ColorControl.Services.NVIDIA } var powerField = defaultPowerLimitMw > 0 ? - new MessageForms.FieldDefinition + new FieldDefinition { Label = $"Power limit in watts. Min: {MinPowerInMilliWatts / 1000}, max: {MaxPowerInMilliWatts / 1000}", - FieldType = MessageForms.FieldType.TrackBar, + FieldType = FieldType.TrackBar, Value = (int)Math.Round((decimal)defaultPowerLimitMw / 100000000 * settings.PowerPCM), MinValue = MinPowerInMilliWatts / 1000, MaxValue = MaxPowerInMilliWatts / 1000 } - : new MessageForms.FieldDefinition + : new FieldDefinition { Label = $"Power limit in PCM (per cent mille). Min: {powerLimits.Item1}, max: {powerLimits.Item2}", - FieldType = MessageForms.FieldType.TrackBar, + FieldType = FieldType.TrackBar, Value = settings.PowerPCM, MinValue = powerLimits.Item1, MaxValue = powerLimits.Item2 @@ -799,12 +799,12 @@ namespace ColorControl.Services.NVIDIA return powerField; } - internal MessageForms.FieldDefinition GetVoltageBoostField(NvGpuOcSettings settings) + internal FieldDefinition GetVoltageBoostField(NvGpuOcSettings settings) { - var field = new MessageForms.FieldDefinition + var field = new FieldDefinition { Label = "Voltage boost in %", - FieldType = MessageForms.FieldType.TrackBar, + FieldType = FieldType.TrackBar, Value = settings.VoltageBoostPercent, MinValue = 0, MaxValue = 100 @@ -813,7 +813,7 @@ namespace ColorControl.Services.NVIDIA return field; } - internal (MessageForms.FieldDefinition, MessageForms.FieldDefinition) GetCurveVoltFreqFields(NvGpuOcSettings settings) + internal (FieldDefinition, FieldDefinition) GetCurveVoltFreqFields(NvGpuOcSettings settings) { var curveEntries = CurveV3.GPUCurveEntries; @@ -832,18 +832,18 @@ namespace ColorControl.Services.NVIDIA .Distinct() .ToList(); - var voltField = new MessageForms.FieldDefinition + var voltField = new FieldDefinition { Label = "Optional undervolt: maximum voltage in millivolt (0 = disabled)", SubLabel = "If both UV voltage and UV frequency are set, frequency is derived from voltage.", - FieldType = MessageForms.FieldType.DropDown, + FieldType = FieldType.DropDown, Value = settings.FrequencyPreferred ? 0 : settings.MaximumVoltageUv / 1000, Values = voltValues, }; - var freqField = new MessageForms.FieldDefinition + var freqField = new FieldDefinition { Label = "Optional undervolt: maximum core frequency in MHz (0 = disabled)", - FieldType = MessageForms.FieldType.DropDown, + FieldType = FieldType.DropDown, Value = !settings.FrequencyPreferred ? 0 : settings.MaximumFrequencyKHz / 1000, Values = freqValues, }; diff --git a/ColorControl/Services/NVIDIA/NvPanel.Designer.cs b/ColorControl/Services/NVIDIA/NvPanel.Designer.cs index 964b46f..0a7c5e3 100644 --- a/ColorControl/Services/NVIDIA/NvPanel.Designer.cs +++ b/ColorControl/Services/NVIDIA/NvPanel.Designer.cs @@ -80,6 +80,8 @@ namespace ColorControl.Services.NVIDIA miHDREnabled = new System.Windows.Forms.ToolStripMenuItem(); mnuNvDriverSettings = new System.Windows.Forms.ToolStripMenuItem(); miNvDriverSettingsIncluded = new System.Windows.Forms.ToolStripMenuItem(); + mnuNvOtherSettings = new System.Windows.Forms.ToolStripMenuItem(); + miNvOtherIncluded = new System.Windows.Forms.ToolStripMenuItem(); mnuNvOverclocking = new System.Windows.Forms.ToolStripMenuItem(); miNvOverclockingIncluded = new System.Windows.Forms.ToolStripMenuItem(); miNvCopyId = new System.Windows.Forms.ToolStripMenuItem(); @@ -90,8 +92,8 @@ namespace ColorControl.Services.NVIDIA miNvNovideo = new System.Windows.Forms.ToolStripMenuItem(); miNvSettings = new System.Windows.Forms.ToolStripMenuItem(); lvNvPresetsToolTip = new System.Windows.Forms.ToolTip(components); - mnuNvOtherSettings = new System.Windows.Forms.ToolStripMenuItem(); - miNvOtherIncluded = new System.Windows.Forms.ToolStripMenuItem(); + mnuNvHdmiSettings = new System.Windows.Forms.ToolStripMenuItem(); + miNvHdmiIncluded = new System.Windows.Forms.ToolStripMenuItem(); mnuNvPresets.SuspendLayout(); mnuNvSettings.SuspendLayout(); SuspendLayout(); @@ -227,7 +229,7 @@ namespace ColorControl.Services.NVIDIA btnAddModesNv.Name = "btnAddModesNv"; btnAddModesNv.Size = new System.Drawing.Size(88, 27); btnAddModesNv.TabIndex = 9; - btnAddModesNv.Text = "Add modes"; + btnAddModesNv.Text = "Add..."; btnAddModesNv.UseVisualStyleBackColor = true; btnAddModesNv.Click += btnAddModesNv_Click; // @@ -322,9 +324,9 @@ namespace ColorControl.Services.NVIDIA // mnuNvPresets // mnuNvPresets.ImageScalingSize = new System.Drawing.Size(20, 20); - mnuNvPresets.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { miNvApply, miNvPresetApplyOnStartup, tssNvPresetMenu, mnuNvDisplay, mnuNvPresetsColorSettings, mnuRefreshRate, mnuNvResolution, miNvPresetDithering, miNvHDR, mnuNvDriverSettings, mnuNvOtherSettings, mnuNvOverclocking, miNvCopyId }); + mnuNvPresets.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { miNvApply, miNvPresetApplyOnStartup, tssNvPresetMenu, mnuNvDisplay, mnuNvPresetsColorSettings, mnuRefreshRate, mnuNvResolution, miNvPresetDithering, miNvHDR, mnuNvDriverSettings, mnuNvOtherSettings, mnuNvHdmiSettings, mnuNvOverclocking, miNvCopyId }); mnuNvPresets.Name = "mnuNvPresets"; - mnuNvPresets.Size = new System.Drawing.Size(185, 296); + mnuNvPresets.Size = new System.Drawing.Size(185, 318); mnuNvPresets.Opening += mnuNvPresets_Opening; // // miNvApply @@ -545,6 +547,20 @@ namespace ColorControl.Services.NVIDIA miNvDriverSettingsIncluded.Text = "Included"; miNvDriverSettingsIncluded.Click += miNvDriverSettingsIncluded_Click; // + // mnuNvOtherSettings + // + mnuNvOtherSettings.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { miNvOtherIncluded }); + mnuNvOtherSettings.Name = "mnuNvOtherSettings"; + mnuNvOtherSettings.Size = new System.Drawing.Size(184, 22); + mnuNvOtherSettings.Text = "Other"; + // + // miNvOtherIncluded + // + miNvOtherIncluded.Name = "miNvOtherIncluded"; + miNvOtherIncluded.Size = new System.Drawing.Size(180, 22); + miNvOtherIncluded.Text = "Included"; + miNvOtherIncluded.Click += miNvOtherIncluded_Click; + // // mnuNvOverclocking // mnuNvOverclocking.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { miNvOverclockingIncluded }); @@ -629,19 +645,19 @@ namespace ColorControl.Services.NVIDIA miNvSettings.Text = "Settings"; miNvSettings.Click += miNvSettings_Click; // - // mnuNvOtherSettings + // mnuNvHdmiSettings // - mnuNvOtherSettings.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { miNvOtherIncluded }); - mnuNvOtherSettings.Name = "mnuNvOtherSettings"; - mnuNvOtherSettings.Size = new System.Drawing.Size(184, 22); - mnuNvOtherSettings.Text = "Other"; + mnuNvHdmiSettings.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { miNvHdmiIncluded }); + mnuNvHdmiSettings.Name = "mnuNvHdmiSettings"; + mnuNvHdmiSettings.Size = new System.Drawing.Size(184, 22); + mnuNvHdmiSettings.Text = "HDMI Settings"; // - // miNvOtherIncluded + // miNvHdmiIncluded // - miNvOtherIncluded.Name = "miNvOtherIncluded"; - miNvOtherIncluded.Size = new System.Drawing.Size(180, 22); - miNvOtherIncluded.Text = "Included"; - miNvOtherIncluded.Click += miNvOtherIncluded_Click; + miNvHdmiIncluded.Name = "miNvHdmiIncluded"; + miNvHdmiIncluded.Size = new System.Drawing.Size(180, 22); + miNvHdmiIncluded.Text = "Included"; + miNvHdmiIncluded.Click += miNvHdmiIncluded_Click; // // NvPanel // @@ -742,5 +758,7 @@ namespace ColorControl.Services.NVIDIA private System.Windows.Forms.ToolStripMenuItem miNvNovideo; private System.Windows.Forms.ToolStripMenuItem mnuNvOtherSettings; private System.Windows.Forms.ToolStripMenuItem miNvOtherIncluded; + private System.Windows.Forms.ToolStripMenuItem mnuNvHdmiSettings; + private System.Windows.Forms.ToolStripMenuItem miNvHdmiIncluded; } } diff --git a/ColorControl/Services/NVIDIA/NvPanel.cs b/ColorControl/Services/NVIDIA/NvPanel.cs index 7a88f60..7731bac 100644 --- a/ColorControl/Services/NVIDIA/NvPanel.cs +++ b/ColorControl/Services/NVIDIA/NvPanel.cs @@ -9,6 +9,7 @@ using novideo_srgb; using nspector; using nspector.Common; using nspector.Common.Meta; +using NStandard; using NvAPIWrapper.Display; using NvAPIWrapper.GPU; using NvAPIWrapper.Native.Display; @@ -36,14 +37,18 @@ namespace ColorControl.Services.NVIDIA private readonly AppContextProvider _appContextProvider; private string _lastDisplayRefreshRates = string.Empty; private NotifyIcon _trayIcon; + private RpcService _rpcService; - public NvPanel(NvService nvService, NotifyIcon trayIcon, IntPtr handle, AppContextProvider appContextProvider) + public NvPanel(NvService nvService, NotifyIcon trayIcon, IntPtr handle, AppContextProvider appContextProvider, RpcService rpcService) { _nvService = nvService; _trayIcon = trayIcon; _mainHandle = handle; _appContextProvider = appContextProvider; _config = appContextProvider.GetAppContext().Config; + _rpcService = rpcService; + + _rpcService.Name = "NvService"; InitializeComponent(); @@ -338,6 +343,8 @@ namespace ColorControl.Services.NVIDIA mnuNvOverclocking.Visible = preset != null && _nvService.Config.ShowOverclocking; mnuNvOtherSettings.Enabled = preset != null; miNvOtherIncluded.Visible = presetItemsVisible; + mnuNvHdmiSettings.Enabled = preset != null; + miNvHdmiIncluded.Visible = presetItemsVisible; if (preset == null) { @@ -409,6 +416,7 @@ namespace ColorControl.Services.NVIDIA miHDREnabled.Checked = preset.HDREnabled; miToggleHDR.Checked = preset.toggleHDR; miNvOtherIncluded.Checked = preset.applyOther; + miNvHdmiIncluded.Checked = preset.applyHdmiSettings; miNvDriverSettingsIncluded.Checked = preset.applyDriverSettings; mnuNvPresetsColorSettings.Font = _menuItemFonts[preset.applyColorData]; @@ -418,9 +426,7 @@ namespace ColorControl.Services.NVIDIA miNvHDR.Font = _menuItemFonts[preset.applyHDR]; mnuNvOverclocking.Font = _menuItemFonts[preset.applyOverclocking]; mnuNvOtherSettings.Font = _menuItemFonts[preset.applyOther]; - - var contentTypeItem = FormUtils.BuildDropDownMenu(mnuNvOtherSettings, "Content type", typeof(InfoFrameVideoContentType), preset, "contentType", nvPresetContentTypeMenuItem_Click, unchanged: true); - contentTypeItem.DropDownItems[0].Visible = !isCurrentDisplay; + mnuNvHdmiSettings.Font = _menuItemFonts[preset.applyHdmiSettings]; var itemName = $"{mnuNvOtherSettings.Name}_SDRBrightness"; var brightnessMenu = FormUtils.BuildMenuItem(mnuNvOtherSettings.DropDownItems, itemName, "SDR brightness"); @@ -429,6 +435,13 @@ namespace ColorControl.Services.NVIDIA var subItem = FormUtils.BuildMenuItem(brightnessMenu.DropDownItems, subItemName, "", onClick: nvPresetBrightnessMenuItem_Click); subItem.Text = (preset.SDRBrightness.HasValue ? $"{preset.SDRBrightness.Value}%" : "Unset") + " (click to change)"; + FormUtils.BuildDropDownMenu(mnuNvHdmiSettings, "Content type", typeof(InfoFrameVideoContentType), preset.HdmiInfoFrameSettings, "ContentType", nvPresetHdmiContentTypeMenuItem_Click, unchanged: true) + .DropDownItems[0].Visible = !isCurrentDisplay; + FormUtils.BuildDropDownMenu(mnuNvHdmiSettings, "Colorimetry", typeof(InfoFrameVideoColorimetry), preset.HdmiInfoFrameSettings, "Colorimetry", nvPresetHdmiColorimetryMenuItem_Click, unchanged: true) + .DropDownItems[0].Visible = !isCurrentDisplay; + FormUtils.BuildDropDownMenu(mnuNvHdmiSettings, "Extended colorimetry", typeof(InfoFrameVideoExtendedColorimetry), preset.HdmiInfoFrameSettings, "ExtendedColorimetry", nvPresetHdmiExtendedColorimetryMenuItem_Click, unchanged: true) + .DropDownItems[0].Visible = !isCurrentDisplay; + BuildNvOverclockingMenu(preset); UpdateNvPresetMenuFont(); @@ -733,29 +746,41 @@ namespace ColorControl.Services.NVIDIA AddOrUpdateItem(); } - private void nvPresetContentTypeMenuItem_Click(object sender, EventArgs e) + private void nvPresetHdmiContentTypeMenuItem_Click(object sender, EventArgs e) + { + UpdateHdmiSettings(sender); + } + + private void nvPresetHdmiColorimetryMenuItem_Click(object sender, EventArgs e) + { + UpdateHdmiSettings(sender); + } + + private void nvPresetHdmiExtendedColorimetryMenuItem_Click(object sender, EventArgs e) + { + UpdateHdmiSettings(sender); + } + + private void UpdateHdmiSettings(object sender) where T : struct { var menuItem = (ToolStripMenuItem)sender; - - var value = (InfoFrameVideoContentType?)menuItem.Tag; + var propName = ((PropertyInfo)menuItem.OwnerItem.Tag).Name; + var value = (T)menuItem.Tag; var preset = GetSelectedNvPreset(true); + var settings = preset.IsDisplayPreset ? new NvHdmiInfoFrameSettings() : preset.HdmiInfoFrameSettings; + var propInfo = settings.GetType().GetDeclaredProperty(propName); + propInfo.SetValue(settings, value); + if (preset.IsDisplayPreset) { - if (!value.HasValue) - { - return; - } - - _nvService.SetHDMIContentType(preset.Display, value.Value); + _nvService.SetHdmiSettings(preset.Display, settings); UpdateDisplayInfoItems(); return; } - preset.contentType = value; - AddOrUpdateItem(); } @@ -854,29 +879,149 @@ namespace ColorControl.Services.NVIDIA AddOrUpdateItem(); } - private void btnAddModesNv_Click(object sender, EventArgs e) { - var presets = NvPreset.GetDefaultPresets(); - var added = false; - - foreach (var preset in presets) + var nameField = new FieldDefinition { - if (!_nvService.GetPresets().Any(x => x.colorData.Equals(preset.colorData))) - { - AddOrUpdateItem(preset); - added = true; - } + Label = "Preset name", + Value = _nvService.CreateNewPresetName() + }; + + + var displays = _nvService.GetSimpleDisplayInfos(); + //var primaryDisplay = _nvService.GetPrimaryDisplay(); + displays.Insert(0, new NvDisplayInfo(null, null, null, "Primary display")); + + var displayField = FieldDefinition.CreateDropDownField("Display", displays.Select(d => d.Name).ToList()); + + var sectionLabel = new FieldDefinition + { + Label = "Check the sections below you want to configure", + FieldType = FieldType.Label + }; + + var colorSelectField = FieldDefinition.CreateCheckField("Color settings"); + var resolutionSelectField = FieldDefinition.CreateCheckField("Resolution"); + var refreshRateSelectField = FieldDefinition.CreateCheckField("Refresh rate"); + + var result = MessageForms.ShowDialog("Create new NVIDIA preset", new[] { nameField, displayField, sectionLabel, colorSelectField, resolutionSelectField, refreshRateSelectField }); + + if (!result.Any()) + { + return; } - if (added) + var preset = new NvPreset(); + preset.name = nameField.Value.ToString(); + preset.primaryDisplay = displayField.Value.ToString() == "Primary display"; + preset.displayName = !preset.primaryDisplay ? displays.FirstOrDefault(d => d.ToString() == displayField.Value.ToString())?.Display?.Name : null; + + AskColorData(preset, colorSelectField.ValueAsBool); + AskResolution(preset, resolutionSelectField.ValueAsBool); + AskRefreshRate(preset, refreshRateSelectField.ValueAsBool); + + AddOrUpdateItem(preset); + + //var presets = NvPreset.GetDefaultPresets(); + //var added = false; + + //foreach (var preset in presets) + //{ + // if (!_nvService.GetPresets().Any(x => x.colorData.Equals(preset.colorData))) + // { + // AddOrUpdateItem(preset); + // added = true; + // } + //} + + //if (added) + //{ + // MessageForms.InfoOk("Missing presets added."); + //} + //else + //{ + // MessageForms.InfoOk("All presets for every color setting already exist."); + //} + } + + private void AskColorData(NvPreset preset, bool ask = true) + { + preset.colorData = NvPreset.DefaultColorData; + + if (!ask) { - MessageForms.InfoOk("Missing presets added."); + return; } - else + + var bitDepthField = FieldDefinition.CreateEnumField("Bit depth", ColorDataDepth.Default); + var colorFormatField = FieldDefinition.CreateEnumField("Color format", ColorDataFormat.Auto); + var dynamicRangeField = FieldDefinition.CreateEnumField("Dynamic range", ColorDataDynamicRange.Auto); + var colorimetryField = FieldDefinition.CreateEnumField("Color space", ColorDataColorimetry.Auto); + + var result = MessageForms.ShowDialog("Color settings", new[] { bitDepthField, colorFormatField, dynamicRangeField, colorimetryField }); + + if (!result.Any()) { - MessageForms.InfoOk("All presets for every color setting already exist."); + return; } + + preset.colorData = new ColorData( + colorFormatField.ValueAsEnum(), + colorimetryField.ValueAsEnum(), + dynamicRange: dynamicRangeField.ValueAsEnum(), + colorDepth: bitDepthField.ValueAsEnum()); + + preset.applyColorData = true; + } + + private void AskResolution(NvPreset preset, bool ask = true) + { + if (!ask) + { + return; + } + + var modes = _nvService.GetAvailableResolutions(preset).Select(d => $"{d.dmPelsWidth}x{d.dmPelsHeight}").ToList(); + + var modesField = FieldDefinition.CreateDropDownField("Resolution", modes); + + var result = MessageForms.ShowDialog("Resolution", new[] { modesField }); + + if (!result.Any()) + { + return; + } + + var values = modesField.Value.ToString().Split('x').Select(s => Utils.ParseUInt(s)).ToArray(); + + preset.resolutionWidth = values[0]; + preset.resolutionHeight = values[1]; + + preset.applyResolution = true; + } + + private void AskRefreshRate(NvPreset preset, bool ask = true) + { + if (!ask) + { + return; + } + + var modes = _nvService.GetAvailableRefreshRates(preset).Select(d => d.ToString()).ToList(); + + var modesField = FieldDefinition.CreateDropDownField("Refresh rate", modes); + + var result = MessageForms.ShowDialog("Refresh rate", new[] { modesField }); + + if (!result.Any()) + { + return; + } + + var value = modesField.ValueAsUInt; + + preset.refreshRate = value; + preset.applyRefreshRate = true; } private void miHDRIncluded_Click(object sender, EventArgs e) @@ -1132,12 +1277,12 @@ namespace ColorControl.Services.NVIDIA private uint SelectNvDriverValue(SettingMeta settingMeta, uint currentValue) { - var field = new MessageForms.FieldDefinition + var field = new FieldDefinition { MinValue = settingMeta.DwordValues.First().Value, MaxValue = settingMeta.DwordValues.Last().Value, Label = settingMeta.SettingName, - FieldType = MessageForms.FieldType.Numeric, + FieldType = FieldType.Numeric, Value = currentValue }; @@ -1155,12 +1300,12 @@ namespace ColorControl.Services.NVIDIA private int? SelectValue(int min, int max, int? currentValue, string label) { - var field = new MessageForms.FieldDefinition + var field = new FieldDefinition { MinValue = min, MaxValue = max, Label = label, - FieldType = MessageForms.FieldType.Numeric, + FieldType = FieldType.Numeric, Value = currentValue }; @@ -1201,24 +1346,24 @@ namespace ColorControl.Services.NVIDIA private void EditNvSettings() { - var quickAccessField = new MessageForms.FieldDefinition + var quickAccessField = new FieldDefinition { Label = "Quick Access shortcut", - FieldType = MessageForms.FieldType.Shortcut, + FieldType = FieldType.Shortcut, Value = _config.NvQuickAccessShortcut }; - var enableOcField = new MessageForms.FieldDefinition + var enableOcField = new FieldDefinition { Label = "Enable overclocking", - FieldType = MessageForms.FieldType.CheckBox, + FieldType = FieldType.CheckBox, Value = _nvService.Config.ShowOverclocking }; - var enableNovideoField = new MessageForms.FieldDefinition + var enableNovideoField = new FieldDefinition { Label = "Apply Novideo sRGB settings on startup", - FieldType = MessageForms.FieldType.CheckBox, + FieldType = FieldType.CheckBox, Value = _nvService.Config.ApplyNovideoOnStartup }; @@ -1331,10 +1476,10 @@ namespace ColorControl.Services.NVIDIA var overclockTypes = gpuInfo.SupportedOcTypes.Select(t => Utils.GetDescription(t)); var values = MessageForms.ShowDialog($"Overclock settings - {gpuInfo.GPU.FullName}", new[] { - new MessageForms.FieldDefinition + new FieldDefinition { Label = "Overclock method", - FieldType = MessageForms.FieldType.DropDown, + FieldType = FieldType.DropDown, Values = overclockTypes, Value = currentSettings.Type } }, okButtonText: "Next >"); @@ -1400,7 +1545,7 @@ namespace ColorControl.Services.NVIDIA nvOverclockSettings.MaximumFrequencyKHz = freqField.ValueAsUInt * 1000; nvOverclockSettings.MemoryOffsetKHz = memoryOffsetField.ValueAsInt * 1000; nvOverclockSettings.VoltageBoostPercent = voltageBoostField.ValueAsUInt; - nvOverclockSettings.PowerPCM = gpuInfo.PowerToPCM(powerField.ValueAsUInt, powerField.FieldType == MessageForms.FieldType.TrackBar); + nvOverclockSettings.PowerPCM = gpuInfo.PowerToPCM(powerField.ValueAsUInt, powerField.FieldType == FieldType.TrackBar); nvOverclockSettings.FrequencyPreferred = nvOverclockSettings.MaximumFrequencyKHz > 0 && nvOverclockSettings.MaximumVoltageUv == 0; return nvOverclockSettings; @@ -1434,7 +1579,7 @@ namespace ColorControl.Services.NVIDIA nvOverclockSettings.GraphicsOffsetKHz = coreOffsetField.ValueAsInt * 1000; nvOverclockSettings.MemoryOffsetKHz = memoryOffsetField.ValueAsInt * 1000; nvOverclockSettings.VoltageBoostPercent = voltageBoostField.ValueAsUInt; - nvOverclockSettings.PowerPCM = gpuInfo.PowerToPCM(powerField.ValueAsUInt, powerField.FieldType == MessageForms.FieldType.TrackBar); + nvOverclockSettings.PowerPCM = gpuInfo.PowerToPCM(powerField.ValueAsUInt, powerField.FieldType == FieldType.TrackBar); nvOverclockSettings.FrequencyPreferred = nvOverclockSettings.MaximumFrequencyKHz > 0 && nvOverclockSettings.MaximumVoltageUv == 0; return nvOverclockSettings; @@ -1487,7 +1632,7 @@ namespace ColorControl.Services.NVIDIA nvOverclockSettings.MaximumVoltageUv = newVolt; nvOverclockSettings.MemoryOffsetKHz = memoryOffsetField.ValueAsInt * 1000; nvOverclockSettings.VoltageBoostPercent = voltageBoostField.ValueAsUInt; - nvOverclockSettings.PowerPCM = gpuInfo.PowerToPCM(powerField.ValueAsUInt, powerField.FieldType == MessageForms.FieldType.TrackBar); + nvOverclockSettings.PowerPCM = gpuInfo.PowerToPCM(powerField.ValueAsUInt, powerField.FieldType == FieldType.TrackBar); return nvOverclockSettings; } @@ -1643,5 +1788,14 @@ namespace ColorControl.Services.NVIDIA AddOrUpdateItem(); } + + private void miNvHdmiIncluded_Click(object sender, EventArgs e) + { + var preset = GetSelectedNvPreset(); + + preset.applyHdmiSettings = !preset.applyHdmiSettings; + + AddOrUpdateItem(); + } } } diff --git a/ColorControl/Services/NVIDIA/NvPreset.cs b/ColorControl/Services/NVIDIA/NvPreset.cs index a58340a..95c5c01 100644 --- a/ColorControl/Services/NVIDIA/NvPreset.cs +++ b/ColorControl/Services/NVIDIA/NvPreset.cs @@ -34,16 +34,21 @@ namespace ColorControl.Services.NVIDIA public uint ditheringBits { get; set; } public uint ditheringMode { get; set; } public bool applyOther { get; set; } - public InfoFrameVideoContentType? contentType { get; set; } public int? SDRBrightness { get; set; } public bool applyDriverSettings { get; set; } public Dictionary driverSettings { get; set; } public bool applyOverclocking { get; set; } public List ocSettings { get; set; } + public bool applyHdmiSettings { get; set; } + public NvHdmiInfoFrameSettings HdmiInfoFrameSettings { get; set; } + [JsonIgnore] public bool IsDisplayPreset => Display != null; + [JsonIgnore] public Display Display { get; set; } + [JsonIgnore] + public string InfoLine { get; set; } public NvPreset() : base() { @@ -61,10 +66,10 @@ namespace ColorControl.Services.NVIDIA primaryDisplay = true; ditheringBits = 1; ditheringMode = 4; - contentType = InfoFrameVideoContentType.Auto; applyDriverSettings = false; driverSettings = new Dictionary(); ocSettings = new List(); + HdmiInfoFrameSettings = new NvHdmiInfoFrameSettings(); } public NvPreset(ColorData colorData) : this() @@ -97,9 +102,11 @@ namespace ColorControl.Services.NVIDIA applyDriverSettings = preset.applyDriverSettings; driverSettings = new Dictionary(preset.driverSettings); - contentType = preset.contentType; SDRBrightness = preset.SDRBrightness; applyOther = preset.applyOther; + + HdmiInfoFrameSettings = new NvHdmiInfoFrameSettings(preset.HdmiInfoFrameSettings); + applyHdmiSettings = preset.applyHdmiSettings; } public NvPreset Clone() @@ -111,50 +118,65 @@ namespace ColorControl.Services.NVIDIA public static string[] GetColumnNames() { - return new[] { "Name", "Display|140", "Color settings (BPC, format, dyn. range, color space)|260", "Refresh rate|100", "Resolution|120", "Dithering", "HDR", "Driver settings|300", "Other|200", "Overclocking|300", "Shortcut", "Apply on startup" }; + return new[] { "Name", "Display|140", "Color settings (BPC, format, dyn. range, color space)|260", "Refresh rate|100", "Resolution|120", "Dithering", "HDR", "Driver settings|300", "HDMI settings|200", "Other|200", "Overclocking|300", "Shortcut", "Apply on startup" }; } public override List GetDisplayValues(Config config = null) { - var values = new List(); + var isCurrent = IsDisplayPreset; - values.Add(name); + var values = new List + { + isCurrent ? "Current settings" : name + }; - var display = string.Format("{0}", primaryDisplay ? "Primary" : displayName); + var display = isCurrent ? displayName : string.Format("{0}", primaryDisplay ? "Primary" : displayName); values.Add(display); - var colorSettings = string.Format("{0}: {1}, {2}, {3}, {4}", applyColorData ? "Included" : "Excluded", colorData.ColorDepth, colorData.ColorFormat, colorData.DynamicRange, colorData.Colorimetry); + var colorSettings = FormatDisplaySetting(string.Format("{0}, {1}, {2}, {3}", colorData.ColorDepth, colorData.ColorFormat, colorData.DynamicRange, colorData.Colorimetry), isCurrent, applyColorData); values.Add(colorSettings); - values.Add(string.Format("{0}: {1}Hz", applyRefreshRate ? "Included" : "Excluded", refreshRate)); + values.Add(FormatDisplaySetting(string.Format("{0}Hz", refreshRate), isCurrent, applyRefreshRate)); if (applyResolution || resolutionWidth > 0) { - values.Add(string.Format("{0}: {1}x{2}", applyResolution ? "Included" : "Excluded", resolutionWidth, resolutionHeight)); + values.Add(FormatDisplaySetting(string.Format("{0}x{1}", resolutionWidth, resolutionHeight), isCurrent, applyResolution)); } else { - values.Add(string.Format("Excluded")); + values.Add(isCurrent ? "" : "Excluded"); } var dithering = GetDitheringDescription(); - values.Add(string.Format("{0}: {1}", applyDithering ? "Included" : "Excluded", dithering)); - values.Add(string.Format("{0}: {1}", applyHDR ? "Included" : "Excluded", toggleHDR ? "Toggle" : HDREnabled ? "Enabled" : "Disabled")); + values.Add(FormatDisplaySetting(dithering, isCurrent, applyDithering)); + values.Add(FormatDisplaySetting(toggleHDR ? "Toggle" : HDREnabled ? "Enabled" : "Disabled", isCurrent, applyHDR)); - values.Add(string.Format("{0}: {1}", applyDriverSettings ? "Included" : "Excluded", GetDriverSettingsDescription())); + values.Add(FormatDisplaySetting(GetDriverSettingsDescription(), isCurrent, applyDriverSettings)); - values.Add(string.Format("{0}: {1}", applyOther ? "Included" : "Excluded", GetOtherDescription())); + values.Add(FormatDisplaySetting(GetHdmiSettingsDescription(), isCurrent, applyHdmiSettings)); - values.Add(string.Format("{0}: {1}", applyOverclocking ? "Included" : "Excluded", GetOverclockingSettingsDescription())); + values.Add(FormatDisplaySetting(GetOtherDescription(), isCurrent, applyOther)); - values.Add(shortcut); + values.Add(FormatDisplaySetting(GetOverclockingSettingsDescription(), isCurrent, applyOverclocking)); - values.Add(string.Format("{0}", config?.NvPresetId_ApplyOnStartup == id ? "Yes" : string.Empty)); + values.Add(isCurrent ? "" : shortcut); + + values.Add(isCurrent ? "" : string.Format("{0}", config?.NvPresetId_ApplyOnStartup == id ? "Yes" : string.Empty)); + + if (isCurrent) + { + InfoLine = string.Format("{0}: {1}, {2}Hz, HDR: {3}", displayName, colorSettings, refreshRate, HDREnabled ? "Yes" : "No"); + } return values; } + private static string FormatDisplaySetting(string values, bool isCurrent, bool isEnabled) + { + return string.Format("{0}{1}", isCurrent ? "" : isEnabled ? "Included: " : "Excluded: ", values); + } + public string GetOverclockingSettingsDescription(bool useNewLines = false) { if (ocSettings.Count == 0) @@ -212,15 +234,36 @@ namespace ColorControl.Services.NVIDIA return dithering; } + public string GetHdmiSettingsDescription() + { + var values = new List(); + + if (HdmiInfoFrameSettings.Colorimetry.HasValue) + { + values.Add($"Colorimetry: {HdmiInfoFrameSettings.Colorimetry.Value}"); + } + if (HdmiInfoFrameSettings.ExtendedColorimetry.HasValue) + { + values.Add($"Ext. colorimetry: {HdmiInfoFrameSettings.ExtendedColorimetry.Value}"); + } + if (HdmiInfoFrameSettings.ContentType.HasValue) + { + values.Add($"Content type: {HdmiInfoFrameSettings.ContentType.Value}"); + } + + if (!values.Any()) + { + values.Add("None"); + } + + return string.Join(", ", values); + } + public string GetOtherDescription() { var values = new List(); - if (contentType.HasValue) - { - values.Add($"Content type: {contentType.Value}"); - } - if (SDRBrightness.HasValue) + if (SDRBrightness.HasValue && (HDREnabled || !IsDisplayPreset)) { values.Add($"SDR brightness: {SDRBrightness.Value}%"); } @@ -233,11 +276,14 @@ namespace ColorControl.Services.NVIDIA return string.Join(", ", values); } + public static ColorData DefaultColorData => new ColorData(ColorDataFormat.Auto, dynamicRange: ColorDataDynamicRange.Auto, colorDepth: ColorDataDepth.Default, colorSelectionPolicy: ColorDataSelectionPolicy.BestQuality); + public static List GetDefaultPresets() { - var presets = new List(); - - presets.Add(new NvPreset(new ColorData(ColorDataFormat.Auto, dynamicRange: ColorDataDynamicRange.Auto, colorDepth: ColorDataDepth.Default, colorSelectionPolicy: ColorDataSelectionPolicy.BestQuality))); + var presets = new List + { + new NvPreset(DefaultColorData) + }; for (var dynamicRange = ColorDataDynamicRange.VESA; dynamicRange <= ColorDataDynamicRange.CEA; dynamicRange++) { diff --git a/ColorControl/Services/NVIDIA/NvService.cs b/ColorControl/Services/NVIDIA/NvService.cs index 787cc89..de1fc11 100644 --- a/ColorControl/Services/NVIDIA/NvService.cs +++ b/ColorControl/Services/NVIDIA/NvService.cs @@ -14,6 +14,7 @@ using NvAPIWrapper.GPU; using NvAPIWrapper.Native; using NvAPIWrapper.Native.Display; using NvAPIWrapper.Native.Display.Structures; +using NvAPIWrapper.Native.General.Structures; using NvAPIWrapper.Native.GPU.Structures; using NWin32; using NWin32.NativeTypes; @@ -275,13 +276,13 @@ namespace ColorControl.Services.NVIDIA } } - public override async Task ApplyPreset(NvPreset preset) + public override Task ApplyPreset(NvPreset preset) { var result = true; if (!HasDisplaysAttached()) { - return false; + return Task.FromResult(false); } SetCurrentDisplay(preset); @@ -290,7 +291,7 @@ namespace ColorControl.Services.NVIDIA if (display == null) { - return false; + return Task.FromResult(false); } var hdrEnabled = IsHDREnabled(); @@ -327,17 +328,17 @@ namespace ColorControl.Services.NVIDIA if (preset.applyOther) { - if (preset.contentType.HasValue) - { - SetHDMIContentType(display, preset.contentType.Value); - } - if (preset.SDRBrightness.HasValue) { SetSDRBrightness(display, preset.SDRBrightness.Value); } } + if (preset.applyHdmiSettings) + { + SetHdmiSettings(display, preset.HdmiInfoFrameSettings); + } + if (preset.applyDithering) { if (!SetDithering(preset.ditheringEnabled ? NvDitherState.Enabled : NvDitherState.Disabled, preset: preset)) @@ -360,7 +361,7 @@ namespace ColorControl.Services.NVIDIA PresetApplied(); - return result; + return Task.FromResult(result); } public bool ApplyOverclocking(NvGpuOcSettings setting) @@ -663,7 +664,7 @@ namespace ColorControl.Services.NVIDIA return false; } - var desktopRect = display.DisplayDevice.ScanOutInformation.SourceDesktopRectangle; + var desktopRect = GetDesktopRect(display); if (refreshRate == 0) { @@ -696,11 +697,25 @@ namespace ColorControl.Services.NVIDIA } var portrait = IsDisplayInPortraitMode(display); - var desktopRect = display.DisplayDevice.ScanOutInformation.SourceDesktopRectangle; + var desktopRect = GetDesktopRect(display); return GetAvailableRefreshRatesInternal(display.Name, portrait, desktopRect.Width, desktopRect.Height); } + private Rectangle GetDesktopRect(Display display) + { + try + { + return display.DisplayDevice.ScanOutInformation.SourceDesktopRectangle; + } + catch (Exception) + { + var timing = display.DisplayDevice.CurrentTiming; + + return new Rectangle(0, 0, timing.HorizontalActive, timing.VerticalActive); + } + } + private bool IsDisplayInPortraitMode(Display display) { try @@ -726,7 +741,7 @@ namespace ColorControl.Services.NVIDIA return new List(); } - var portrait = new[] { Rotate.Degree90, Rotate.Degree270 }.Contains(display.DisplayDevice.ScanOutInformation.SourceToTargetRotation); + var portrait = IsDisplayInPortraitMode(display); var timing = display.DisplayDevice.CurrentTiming; return GetAvailableResolutionsInternal(display.Name, portrait, (uint)(timing.Extra.RefreshRate)); @@ -745,6 +760,44 @@ namespace ColorControl.Services.NVIDIA return hdr?.HDRMode == ColorDataHDRMode.UHDA; } + public void SetHdmiSettings(Display display, NvHdmiInfoFrameSettings settings) + { + var displayDevice = display.DisplayDevice; + + var info = displayDevice.HDMIVideoFrameOverrideInformation ?? displayDevice.HDMIVideoFrameCurrentInformation; + + if (!info.HasValue) + { + return; + } + + var infoValue = info.Value; + + var newInfo = new InfoFrameVideo( + infoValue.VideoIdentificationCode.Value, + InfoFrameVideoPixelRepetition.None, + settings.ColorFormat ?? infoValue.ColorFormat, + settings.Colorimetry ?? infoValue.Colorimetry, + settings.ExtendedColorimetry ?? infoValue.ExtendedColorimetry ?? InfoFrameVideoExtendedColorimetry.Auto, + settings.RGBQuantization ?? infoValue.RGBQuantization, + settings.YCCQuantization ?? infoValue.YCCQuantization, + settings.ContentMode ?? infoValue.ContentMode, + settings.ContentType ?? infoValue.ContentType, + InfoFrameVideoScanInfo.NoData, + InfoFrameBoolean.Auto, + InfoFrameVideoAspectRatioActivePortion.Auto, + InfoFrameVideoAspectRatioCodedFrame.Auto, + InfoFrameVideoNonUniformPictureScaling.NoData, + InfoFrameVideoBarData.NotPresent, + null, + null, + null, + null + ); + + displayDevice.SetHDMIVideoFrameInformation(newInfo, true); + } + public void SetHDMIContentType(Display display, InfoFrameVideoContentType contentType) { var displayDevice = display.DisplayDevice; @@ -770,10 +823,50 @@ namespace ColorControl.Services.NVIDIA return info.HasValue ? info.Value.ContentType : InfoFrameVideoContentType.Auto; } + public NvHdmiInfoFrameSettings GetHdmiSettings(Display display) + { + var displayDevice = display.DisplayDevice; + + var info = displayDevice.HDMIVideoFrameOverrideInformation ?? displayDevice.HDMIVideoFrameCurrentInformation; + + if (!info.HasValue) + { + return new NvHdmiInfoFrameSettings(); + } + + var infoValue = info.Value; + + return new NvHdmiInfoFrameSettings + { + ColorFormat = infoValue.ColorFormat, + Colorimetry = infoValue.Colorimetry, + ExtendedColorimetry = infoValue.ExtendedColorimetry, + RGBQuantization = infoValue.RGBQuantization, + YCCQuantization = infoValue.YCCQuantization, + ContentMode = infoValue.ContentMode, + ContentType = infoValue.ContentType + }; + } + public void TestResolution() { - var display = GetCurrentDisplay(); - var displayDevice = display.DisplayDevice; + //var display = GetCurrentDisplay(); + //var displayDevice = display.DisplayDevice; + + //var info = DisplayApi.GetScanOutConfiguration(displayDevice.DisplayId); + + //var vertices = new float[] { + // 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + // 0.0f, 2160.0f, 0.0f, 2160.0f, 0.0f, 0.0f, + // 3840.0f, 0.0f, 3840.0f, 0.0f, 0.0f, 0.0f, + // 3840.0f, 2160.0f, 3840.0f, 2160.0f, 0.0f, 0.0f, + //}; + + //var warp = new ScanOutWarpingV1(WarpingVerticeFormat.TriangleStripXYUVRQ, vertices, info.TargetViewPortRectangle); + //var verticesCount = 4; + //var isSticky = false; + + //DisplayApi.SetScanOutWarping(displayDevice.DisplayId, warp, ref verticesCount, out isSticky); //var timing = displayDevice.CurrentTiming; @@ -781,36 +874,53 @@ namespace ColorControl.Services.NVIDIA //displayDevice.TrialCustomResolution(res); - var info = displayDevice.HDMIVideoFrameOverrideInformation ?? displayDevice.HDMIVideoFrameCurrentInformation; + //var hdrColorData = displayDevice.HDRColorData; + //var mastering = hdrColorData.MasteringDisplayData; - if (info.HasValue) - { - var infoValue = info.Value; + //var newMastering = new MasteringDisplayColorData( + // new ColorDataColorCoordinate(0.2f, 0.2f), + // mastering.SecondColorCoordinate, + // mastering.ThirdColorCoordinate, + // mastering.WhiteColorCoordinate, + // 120, + // mastering.MinimumMasteringLuminance, + // mastering.MaximumContentLightLevel, + // mastering.MaximumFrameAverageLightLevel); - var newInfo = new InfoFrameVideo( - infoValue.VideoIdentificationCode.Value, - InfoFrameVideoPixelRepetition.None, - infoValue.ColorFormat, - InfoFrameVideoColorimetry.UseExtendedColorimetry, - InfoFrameVideoExtendedColorimetry.BT2020, - infoValue.RGBQuantization, - infoValue.YCCQuantization, - InfoFrameVideoITC.ITContent, - infoValue.ContentType, - InfoFrameVideoScanInfo.NoData, - InfoFrameBoolean.Auto, - InfoFrameVideoAspectRatioActivePortion.Auto, - InfoFrameVideoAspectRatioCodedFrame.Auto, - InfoFrameVideoNonUniformPictureScaling.NoData, - InfoFrameVideoBarData.NotPresent, - null, - null, - null, - null - ); + //var newHdrColorData = new HDRColorData(hdrColorData.HDRMode, newMastering); - displayDevice.SetHDMIVideoFrameInformation(newInfo, true); - } + //displayDevice.SetHDRColorData(newHdrColorData); + + //var info = displayDevice.HDMIVideoFrameOverrideInformation ?? displayDevice.HDMIVideoFrameCurrentInformation; + + //if (info.HasValue) + //{ + // var infoValue = info.Value; + + // var newInfo = new InfoFrameVideo( + // infoValue.VideoIdentificationCode.Value, + // InfoFrameVideoPixelRepetition.None, + // InfoFrameVideoColorFormat.RGB, + // InfoFrameVideoColorimetry.UseExtendedColorimetry, + // InfoFrameVideoExtendedColorimetry.BT2020, + // infoValue.RGBQuantization, + // infoValue.YCCQuantization, + // InfoFrameVideoITC.ITContent, + // infoValue.ContentType, + // InfoFrameVideoScanInfo.NoData, + // InfoFrameBoolean.Auto, + // InfoFrameVideoAspectRatioActivePortion.Auto, + // InfoFrameVideoAspectRatioCodedFrame.Auto, + // InfoFrameVideoNonUniformPictureScaling.NoData, + // InfoFrameVideoBarData.NotPresent, + // null, + // null, + // null, + // null + // ); + + // displayDevice.SetHDMIVideoFrameInformation(newInfo, true); + //} } public Display[] GetDisplays() @@ -856,87 +966,10 @@ namespace ColorControl.Services.NVIDIA foreach (var display in displays) { - var values = new List - { - "Current settings" - }; + var preset = GetPresetForDisplay(display, true, displays.Count()); - var name = FormUtils.ExtendedDisplayName(display.Name); - values.Add(name); - - var colorData = GetCurrentColorData(display); - var colorSettings = string.Format("{0}, {1}, {2}, {3}", colorData.ColorDepth, colorData.ColorFormat, colorData.DynamicRange, colorData.Colorimetry); - values.Add(colorSettings); - - var refreshRate = display.DisplayDevice.CurrentTiming.Extra.RefreshRate; - values.Add($"{refreshRate}Hz"); - - var mode = GetCurrentMode(display.Name); - values.Add($"{mode.dmPelsWidth}x{mode.dmPelsHeight}"); - - var ditherInfo = GetDithering(display); - string dithering; - if (ditherInfo.state == -1) - { - dithering = "Error"; - } - else - { - var state = (NvDitherState)ditherInfo.state; - dithering = state switch { NvDitherState.Disabled => "Disabled", NvDitherState.Auto => "Auto: ", _ => string.Empty }; - if (state is NvDitherState.Enabled or NvDitherState.Auto) - { - var ditherBitsDescription = ((NvDitherBits)ditherInfo.bits).GetDescription(); - var ditherModeDescription = ((NvDitherMode)ditherInfo.mode).GetDescription(); - dithering = string.Format("{0}{1} {2}", dithering, ditherBitsDescription, ditherModeDescription); - } - } - - values.Add(dithering); - - var hdrEnabled = IsHDREnabled(display); - values.Add(hdrEnabled ? "Yes" : "No"); - - var drsValues = new List(); - - foreach (var setting in settings) - { - var settingMeta = GetSettingMeta(setting.SettingId); - - if (settingMeta == null) - { - continue; - } - - var value = settingMeta.ToFriendlyName(setting.ValueText); - - if (value == null) - { - continue; - } - - drsValues.Add($"{settingMeta.SettingName}: {value}"); - } - - values.Add(string.Join(", ", drsValues)); - - var otherValues = new List - { - $"Content type: {GetHDMIContentType(display)}" - }; - - if (hdrEnabled) - { - var sdrBrightness = GetSDRBrightness(display); - - otherValues.Add($"SDR brightness: {sdrBrightness}%"); - } - - values.Add(string.Join(", ", otherValues)); - - var infoLine = string.Format("{0}: {1}, {2}Hz, HDR: {3}", name, colorSettings, refreshRate, hdrEnabled ? "Yes" : "No"); - - var displayInfo = new NvDisplayInfo(display, values, infoLine, name); + var values = preset.GetDisplayValues(_appContextProvider.GetAppContext().Config); + var displayInfo = new NvDisplayInfo(display, values, preset.InfoLine, preset.displayName); list.Add(displayInfo); } @@ -956,17 +989,22 @@ namespace ColorControl.Services.NVIDIA var display = displays.FirstOrDefault(d => displayName.StartsWith(d.Name)); + return GetPresetForDisplay(display, driverSettings, displays.Count()); + } + + public NvPreset GetPresetForDisplay(Display display, bool driverSettings = false, int displayCount = 1) + { if (display == null) { return null; } - var isPrimaryDisplay = displays.Count() == 1 || display.DisplayDevice.DisplayId == DisplayDevice.GetGDIPrimaryDisplayDevice()?.DisplayId; + var isPrimaryDisplay = displayCount == 1 || display.DisplayDevice.DisplayId == DisplayDevice.GetGDIPrimaryDisplayDevice()?.DisplayId; var preset = new NvPreset { Display = display, applyColorData = false, primaryDisplay = isPrimaryDisplay }; preset.displayName = FormUtils.ExtendedDisplayName(display.Name); preset.colorData = GetCurrentColorData(display); - preset.contentType = GetHDMIContentType(display); + preset.HdmiInfoFrameSettings = GetHdmiSettings(display); preset.SDRBrightness = GetSDRBrightness(display); var mode = GetCurrentMode(display.Name); diff --git a/ColorControl/Services/Samsung/ISamsungService.cs b/ColorControl/Services/Samsung/ISamsungService.cs new file mode 100644 index 0000000..7fdb502 --- /dev/null +++ b/ColorControl/Services/Samsung/ISamsungService.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace ColorControl.Services.Samsung +{ + internal interface ISamsungService + { + SamsungServiceConfig Config { get; } + List Devices { get; } + SamsungDevice SelectedDevice { get; set; } + string ServiceName { get; } + + Task ApplyPreset(SamsungPreset preset); + Task ApplyPreset(string idOrName); + SamsungDevice GetPresetDevice(SamsungPreset preset); + void GlobalSave(); + void InstallEventHandlers(); + Task RefreshDevices(bool connect = true, bool afterStartUp = false); + } +} \ No newline at end of file diff --git a/ColorControl/Services/Samsung/SamsungDevice.cs b/ColorControl/Services/Samsung/SamsungDevice.cs index b454c33..382d495 100644 --- a/ColorControl/Services/Samsung/SamsungDevice.cs +++ b/ColorControl/Services/Samsung/SamsungDevice.cs @@ -42,7 +42,7 @@ namespace ColorControl.Services.Samsung public enum ServiceMenuType { - Default, + HospitalityMenu, } public delegate void GenericDelegate(object sender); @@ -703,16 +703,16 @@ namespace ColorControl.Services.Samsung var preset3 = new SamsungPreset("ServiceMenuStep3", null, new[] { "KEY_VOLUP:5100:Press", "KEY_VOLUP:500:Release" }); var rebootPreset = new SamsungPreset("ServiceMenuStep4", null, new[] { "KEY_POWER:5000", "WOL" }); - var serviceMenuTypes = new[] { ServiceMenuType.Default }.Select(t => Utils.GetDescription(t)); + var serviceMenuTypes = new[] { ServiceMenuType.HospitalityMenu }.Select(t => Utils.GetDescription(t)); if (!MessageForms.ShowDialog($"Access Service Menu", new[] { - new MessageForms.FieldDefinition + new FieldDefinition { - Label = "Service Menu Type", - SubLabel = "'Default' will not reset your settings. Click 'Next >' to continue or 'X' to stop", - FieldType = MessageForms.FieldType.DropDown, + Label = "Service Menu Access Type", + SubLabel = "'Hospitality Menu' will not reset your settings. Click 'Next >' to continue or 'X' to stop", + FieldType = FieldType.DropDown, Values = serviceMenuTypes, - Value = ServiceMenuType.Default + Value = ServiceMenuType.HospitalityMenu } }, okButtonText: "Next >").Any()) { return true; @@ -721,11 +721,11 @@ namespace ColorControl.Services.Samsung await ExecutePresetWithProgressAsync(preset1, "Step 1: opening Service Menu. It is normal to see messages like 'Not Available'."); if (!MessageForms.ShowDialog($"Access Service Menu - Step 2", new[] { - new MessageForms.FieldDefinition + new FieldDefinition { Label = "Service Menu opened?", SubLabel = "If the menu is opened with the 'Hospitality Mode' item highlighted and the rest disabled, click 'Next >' to continue or 'X' to stop", - FieldType = MessageForms.FieldType.Label + FieldType = FieldType.Label } }, okButtonText: "Next >").Any()) { return true; @@ -734,11 +734,11 @@ namespace ColorControl.Services.Samsung await ExecutePresetWithProgressAsync(preset2, "Step 2: accessing Service Menu..."); var values = MessageForms.ShowDialog($"Access Service Menu - Step 3", new[] { - new MessageForms.FieldDefinition + new FieldDefinition { Label = "Service Menu - Advanced", SubLabel = "If the 'Advanced' item is highlighted and you want to access these settings, click 'Next >' or click 'X' to skip", - FieldType = MessageForms.FieldType.Label + FieldType = FieldType.Label } }, okButtonText: "Next >"); if (values.Any()) @@ -747,11 +747,11 @@ namespace ColorControl.Services.Samsung } if (!MessageForms.ShowDialog($"Reboot TV - Final Step", new[] { - new MessageForms.FieldDefinition + new FieldDefinition { Label = "Reboot TV", SubLabel = "After you have made the necessary changes, click 'Reboot TV' to reboot the TV or click 'X' to close. If the TV turns not back on automatically, power it on manually.", - FieldType = MessageForms.FieldType.Label + FieldType = FieldType.Label } }, okButtonText: "Reboot TV").Any()) { return true; diff --git a/ColorControl/Services/Samsung/SamsungPanel.cs b/ColorControl/Services/Samsung/SamsungPanel.cs index 4bdfe46..9c20836 100644 --- a/ColorControl/Services/Samsung/SamsungPanel.cs +++ b/ColorControl/Services/Samsung/SamsungPanel.cs @@ -547,14 +547,14 @@ namespace ColorControl.Services.Samsung { if (action.MinValue != action.MaxValue) { - List fields = new(); + List fields = new(); if (action.NumberOfValues == 1) { - fields.Add(new MessageForms.FieldDefinition + fields.Add(new FieldDefinition { Label = "Enter desired " + title, - FieldType = MessageForms.FieldType.Numeric, + FieldType = FieldType.Numeric, MinValue = action.MinValue, MaxValue = action.MaxValue, }); @@ -563,10 +563,10 @@ namespace ColorControl.Services.Samsung { var array = Enumerable.Range(0, action.NumberOfValues); - fields.AddRange(array.Select(i => new MessageForms.FieldDefinition + fields.AddRange(array.Select(i => new FieldDefinition { Label = "Value for " + (action.ValueLabels != null ? action.ValueLabels[i] : i.ToString()), - FieldType = MessageForms.FieldType.Numeric, + FieldType = FieldType.Numeric, MinValue = action.MinValue, MaxValue = action.MaxValue, })); @@ -591,19 +591,12 @@ namespace ColorControl.Services.Samsung } else { - var dropDownValues = new List(); - foreach (var enumValue in Enum.GetValues(action.EnumType)) - { - var description = Utils.GetDescription(action.EnumType, enumValue as IConvertible) ?? enumValue.ToString().Replace("_", ""); - dropDownValues.Add(description); - } - var values = MessageForms.ShowDialog("Choose value", new[] { - new MessageForms.FieldDefinition + new FieldDefinition { Label = "Choose desired " + title, - FieldType = MessageForms.FieldType.DropDown, - Values = dropDownValues + FieldType = FieldType.DropDown, + Values = Utils.GetDescriptions(action.EnumType, replaceUnderscore: true), } }); @@ -747,7 +740,7 @@ Use 'Settings > Test power off/on' to test this functionality." } } - private string ValidateAddDevice(IEnumerable values) + private string ValidateAddDevice(IEnumerable values) { if (values.Any(v => string.IsNullOrEmpty(v.Value?.ToString()))) { @@ -855,10 +848,10 @@ Do you want to continue?" var dropDownValues = Utils.GetDescriptions(fromValue: 1); var values = MessageForms.ShowDialog("Set trigger conditions", new[] { - new MessageForms.FieldDefinition + new FieldDefinition { Label = "Set desired trigger conditions", - FieldType = MessageForms.FieldType.Flags, + FieldType = FieldType.Flags, Values = dropDownValues, Value = edtSamsungPresetTriggerConditions.Tag ?? 0 } @@ -963,9 +956,9 @@ Do you want to continue?"; private void miNvSettings_Click(object sender, EventArgs e) { - var powerRetries = new MessageForms.FieldDefinition + var powerRetries = new FieldDefinition { - FieldType = MessageForms.FieldType.Numeric, + FieldType = FieldType.Numeric, Label = "Maximum number of retries powering on after startup/resume.", SubLabel = "Retries are necessary to wait for the network link of your pc to be established.", MinValue = 1, @@ -973,9 +966,9 @@ Do you want to continue?"; Value = _samsungService.Config.PowerOnRetries }; - var shutDownDelayField = new MessageForms.FieldDefinition + var shutDownDelayField = new FieldDefinition { - FieldType = MessageForms.FieldType.Numeric, + FieldType = FieldType.Numeric, Label = "Delay when shutting down/restarting PC (milliseconds).", SubLabel = "This delay may prevent the tv from powering off when restarting the pc.", MinValue = 0, @@ -983,9 +976,9 @@ Do you want to continue?"; Value = _samsungService.Config.ShutdownDelay }; - var buttonDelayField = new MessageForms.FieldDefinition + var buttonDelayField = new FieldDefinition { - FieldType = MessageForms.FieldType.Numeric, + FieldType = FieldType.Numeric, Label = "Default delay between remote control button presses (milliseconds).", SubLabel = "Increasing this delay may prevent skipped button presses.", MinValue = 100, @@ -993,23 +986,23 @@ Do you want to continue?"; Value = _samsungService.Config.DefaultButtonDelay }; - var quickAccessShortcutField = new MessageForms.FieldDefinition + var quickAccessShortcutField = new FieldDefinition { - FieldType = MessageForms.FieldType.Shortcut, + FieldType = FieldType.Shortcut, Label = "Quick Access shortcut", Value = _samsungService.Config.QuickAccessShortcut }; - var setDeviceField = new MessageForms.FieldDefinition + var setDeviceField = new FieldDefinition { - FieldType = MessageForms.FieldType.CheckBox, + FieldType = FieldType.CheckBox, Label = "Automatically set selected device to last powered on", Value = _samsungService.Config.SetSelectedDeviceByPowerOn }; - var showAdvancedField = new MessageForms.FieldDefinition + var showAdvancedField = new FieldDefinition { - FieldType = MessageForms.FieldType.CheckBox, + FieldType = FieldType.CheckBox, Label = "Show advanced actions under the Expert-button (Service Menu)", SubLabel = "WARNING: entering the Service Menu is not recommended. This app and its creator are in no way accountable for any damages it may cause to your tv.", Value = _samsungService.Config.ShowAdvancedActions @@ -1046,31 +1039,31 @@ Do you want to continue?"; var device = _samsungService.SelectedDevice; var selectedItem = clbLgPower.SelectedItem; - var durationField = new MessageForms.FieldDefinition + var durationField = new FieldDefinition { Label = "Enter the minimal duration the screen saver must be running (in seconds)", - FieldType = MessageForms.FieldType.Numeric, + FieldType = FieldType.Numeric, MinValue = 0, MaxValue = 3600, Value = device.Options.ScreenSaverMinimalDuration }; - var turnOffField = new MessageForms.FieldDefinition + var turnOffField = new FieldDefinition { Label = "Turn screen off instead of power off", SubLabel = "NOTE: turning the screen off might not work correctly on all models", - FieldType = MessageForms.FieldType.CheckBox, + FieldType = FieldType.CheckBox, Value = device.Options.TurnScreenOffOnScreenSaver }; - var turnOnField = new MessageForms.FieldDefinition + var turnOnField = new FieldDefinition { Label = "Turn screen on instead of power on", - FieldType = MessageForms.FieldType.CheckBox, + FieldType = FieldType.CheckBox, Value = device.Options.TurnScreenOnAfterScreenSaver }; - var manualField = new MessageForms.FieldDefinition + var manualField = new FieldDefinition { Label = "Perform action even on manually executed screen saver", - FieldType = MessageForms.FieldType.CheckBox, + FieldType = FieldType.CheckBox, Value = device.Options.HandleManualScreenSaver }; diff --git a/ColorControl/Services/Samsung/SamsungService.cs b/ColorControl/Services/Samsung/SamsungService.cs index f936a39..9d127e7 100644 --- a/ColorControl/Services/Samsung/SamsungService.cs +++ b/ColorControl/Services/Samsung/SamsungService.cs @@ -16,7 +16,7 @@ using System.Threading.Tasks; namespace ColorControl.Services.Samsung { - class SamsungService : ServiceBase + class SamsungService : ServiceBase, ISamsungService { private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); @@ -81,12 +81,6 @@ namespace ColorControl.Services.Samsung } } - public void Init() - { - var _ = RefreshDevices(afterStartUp: true); - InstallEventHandlers(); - } - public void InstallEventHandlers() { _powerEventDispatcher.RegisterEventHandler(PowerEventDispatcher.Event_MonitorOn, PowerModeChanged); @@ -273,7 +267,7 @@ namespace ColorControl.Services.Samsung return await ApplyPreset(preset, _appContext); } - public async Task ApplyPreset(SamsungPreset preset, Shared.Common.AppContext appContext) + private async Task ApplyPreset(SamsungPreset preset, Shared.Common.AppContext appContext) { var result = true; @@ -312,7 +306,7 @@ namespace ColorControl.Services.Samsung } } - internal void WakeAfterStartupOrResume(PowerOnOffState state = PowerOnOffState.StartUp, bool checkUserSession = true) + private void WakeAfterStartupOrResume(PowerOnOffState state = PowerOnOffState.StartUp, bool checkUserSession = true) { Devices.ForEach(d => d.ClearPowerOffTask()); @@ -323,7 +317,7 @@ namespace ColorControl.Services.Samsung PowerOnDevicesTask(wakeDevices, state, checkUserSession); } - public void PowerOffDevices(IEnumerable devices, PowerOnOffState state = PowerOnOffState.ShutDown) + private void PowerOffDevices(IEnumerable devices, PowerOnOffState state = PowerOnOffState.ShutDown) { if (!devices.Any()) { @@ -390,12 +384,12 @@ namespace ColorControl.Services.Samsung } } - public void PowerOnDevicesTask(IEnumerable devices, PowerOnOffState state = PowerOnOffState.StartUp, bool checkUserSession = true) + private void PowerOnDevicesTask(IEnumerable devices, PowerOnOffState state = PowerOnOffState.StartUp, bool checkUserSession = true) { Task.Run(async () => await PowerOnDevices(devices, state, checkUserSession)); } - public async Task PowerOnDevices(IEnumerable devices, PowerOnOffState state = PowerOnOffState.StartUp, bool checkUserSession = true) + private async Task PowerOnDevices(IEnumerable devices, PowerOnOffState state = PowerOnOffState.StartUp, bool checkUserSession = true) { if (!devices.Any()) { @@ -438,7 +432,7 @@ namespace ColorControl.Services.Samsung } } - public async Task RefreshAppsAsync(bool force = false) + private async Task RefreshAppsAsync(bool force = false) { if (SelectedDevice == null) { @@ -460,7 +454,7 @@ namespace ColorControl.Services.Samsung return _samsungApps; } - public async Task ProcessChanged(object sender, ProcessChangedEventArgs args, CancellationToken token) + private async Task ProcessChanged(object sender, ProcessChangedEventArgs args, CancellationToken token) { try { diff --git a/ColorControl/Svc/ColorControlBackgroundService.cs b/ColorControl/Svc/ColorControlBackgroundService.cs index 415bccd..b4f0fd9 100644 --- a/ColorControl/Svc/ColorControlBackgroundService.cs +++ b/ColorControl/Svc/ColorControlBackgroundService.cs @@ -114,6 +114,7 @@ namespace ColorControl.Svc SvcMessageType.GetLog => HandleGetLogMessage(message), SvcMessageType.ClearLog => HandleClearLogMessage(message), SvcMessageType.ExecuteRpc => await HandleExecuteRpcCommand(message), + SvcMessageType.ExecuteRpcGeneric => await HandleExecuteRpcGenericCommand(JsonConvert.DeserializeObject(json)), SvcMessageType.ExecuteUpdate => await HandleExecuteUpdateCommandAsync(JsonConvert.DeserializeObject(json)), SvcMessageType.RestartAfterUpdate => HandleRestartAfterUpdateMessage(), SvcMessageType.ApplyNvidiaDriverSettings => HandleNvDriverSettingsMessage(JsonConvert.DeserializeObject(json)), @@ -134,6 +135,19 @@ namespace ColorControl.Svc return SvcResultMessage.FromResult(await CommandLineHandler.HandleStartupParams(startUpParams, null)); } + private async Task HandleExecuteRpcGenericCommand(SvcRpcMessage message) + { + var service = NvService.CheckServiceInstance(); + + var method = service.GetType().GetMethod(message.MethodName); + + var result = method.Invoke(service, message.Arguments); + + var data = JsonConvert.SerializeObject(result); + + return SvcResultMessage.FromResult(data); + } + private SvcResultMessage HandleSetLgConfigMessage(SvcMessage message) { var data = message.Data; diff --git a/NvAPIWrapper/Native/Display/InfoFrameVideoExtendedColorimetry.cs b/NvAPIWrapper/Native/Display/InfoFrameVideoExtendedColorimetry.cs index 066ae76..5dec053 100644 --- a/NvAPIWrapper/Native/Display/InfoFrameVideoExtendedColorimetry.cs +++ b/NvAPIWrapper/Native/Display/InfoFrameVideoExtendedColorimetry.cs @@ -33,7 +33,7 @@ /// AdobeRGB, - Unknown1, + UnknownColorimetry, BT2020, diff --git a/Shared/Common/PipeUtils.cs b/Shared/Common/PipeUtils.cs index 9cd0917..7a59201 100644 --- a/Shared/Common/PipeUtils.cs +++ b/Shared/Common/PipeUtils.cs @@ -78,5 +78,23 @@ namespace ColorControl.Shared.Common return resultMessage.Result; } + + public static T SendRpcMessage(SvcRpcMessage message, int timeout = 2000) where T : class + { + var messageJson = JsonConvert.SerializeObject(message); + + var resultJson = SendMessage(messageJson, timeout); + + if (resultJson == null) + { + return null; + } + + var resultMessage = JsonConvert.DeserializeObject(resultJson); + + var result = JsonConvert.DeserializeObject(resultMessage.Data); + + return result; + } } } diff --git a/Shared/Common/Utils.cs b/Shared/Common/Utils.cs index 4b00489..1de6909 100644 --- a/Shared/Common/Utils.cs +++ b/Shared/Common/Utils.cs @@ -422,6 +422,17 @@ The best and suggested method to provide this is via a Windows Service. Only whe return null; // could also return string.Empty } + public static T GetEnumValueByDescription(string value) where T : struct + { + var enumName = GetEnumNameByDescription(typeof(T), value); + if (enumName != null) + { + value = enumName; + } + + return Enum.Parse(value); + } + public static string RemoveFirstUnderscore(this string text) { if (string.IsNullOrEmpty(text)) @@ -458,16 +469,22 @@ The best and suggested method to provide this is via a Windows Service. Only whe return GetDescriptions(typeof(T), value, fromValue); } - public static List GetDescriptions(Type enumType, int value = -1, int fromValue = 0) + public static List GetDescriptions(Type enumType, int value = -1, int fromValue = 0, bool replaceUnderscore = false) { var list = new List(); foreach (var enumValue in Enum.GetValues(enumType)) { - if ((int)enumValue < fromValue || value >= 0 && ((int)enumValue & value) == 0) + if (value > -1 || fromValue > 0) { - continue; + var enumIntValue = Convert.ToInt32(enumValue); + + if (enumIntValue < fromValue || value >= 0 && (enumIntValue & value) == 0) + { + continue; + } } - list.Add(GetDescription(enumType, enumValue as IConvertible)); + + list.Add(GetDescription(enumType, enumValue as IConvertible) ?? (replaceUnderscore ? enumValue.ToString().Replace("_", "") : enumValue.ToString())); } return list; } @@ -703,6 +720,16 @@ The best and suggested method to provide this is via a Windows Service. Only whe return def; } + public static uint ParseUInt(string value, uint def = 0) + { + if (uint.TryParse(value, out var result)) + { + return result; + } + + return def; + } + public static int ParseDynamicAsInt(dynamic value, int def = 0) { if (value.Type == JTokenType.Integer) diff --git a/Shared/Contracts/NVIDIA/NvHdmiInfoFrameSettings.cs b/Shared/Contracts/NVIDIA/NvHdmiInfoFrameSettings.cs new file mode 100644 index 0000000..8a18f54 --- /dev/null +++ b/Shared/Contracts/NVIDIA/NvHdmiInfoFrameSettings.cs @@ -0,0 +1,46 @@ +using NvAPIWrapper.Native.Display; + +namespace ColorControl.Shared.Contracts.NVIDIA +{ + public class NvHdmiInfoFrameSettings + { + public InfoFrameVideoColorFormat? ColorFormat { get; set; } + public InfoFrameVideoColorimetry? Colorimetry { get; set; } + public InfoFrameVideoExtendedColorimetry? ExtendedColorimetry { get; set; } + public InfoFrameVideoRGBQuantization? RGBQuantization { get; set; } + public InfoFrameVideoYCCQuantization? YCCQuantization { get; set; } + public InfoFrameVideoITC? ContentMode { get; set; } + public InfoFrameVideoContentType? ContentType { get; set; } + + public NvHdmiInfoFrameSettings() + { + //ColorFormat = InfoFrameVideoColorFormat.Auto; + //Colorimetry = InfoFrameVideoColorimetry.Auto; + //ExtendedColorimetry = InfoFrameVideoExtendedColorimetry.Auto; + //RGBQuantization = InfoFrameVideoRGBQuantization.Auto; + //YCCQuantization = InfoFrameVideoYCCQuantization.Auto; + //ContentMode = InfoFrameVideoITC.Auto; + //ContentType = InfoFrameVideoContentType.Auto; + } + + public NvHdmiInfoFrameSettings(NvHdmiInfoFrameSettings settings) + { + settings ??= new NvHdmiInfoFrameSettings(); + + ColorFormat = settings.ColorFormat; + Colorimetry = settings.Colorimetry; + ExtendedColorimetry = settings.ExtendedColorimetry; + RGBQuantization = settings.RGBQuantization; + YCCQuantization = settings.YCCQuantization; + ContentMode = settings.ContentMode; + ContentType = settings.ContentType; + } + + public override string ToString() + { + var value = string.Empty; + + return value; + } + } +} diff --git a/Shared/Contracts/Svc/SvcMessage.cs b/Shared/Contracts/Svc/SvcMessage.cs index 2c42b04..6242494 100644 --- a/Shared/Contracts/Svc/SvcMessage.cs +++ b/Shared/Contracts/Svc/SvcMessage.cs @@ -8,6 +8,7 @@ namespace ColorControl.Shared.Contracts GetLog = 2, ClearLog = 3, ExecuteRpc = 10, + ExecuteRpcGeneric = 11, ExecuteUpdate = 20, RestartAfterUpdate = 21, ApplyNvidiaDriverSettings = 101, @@ -54,4 +55,16 @@ namespace ColorControl.Shared.Contracts public List OverclockingSettings { get; set; } } + + public class SvcRpcMessage : SvcMessage + { + public SvcRpcMessage() + { + MessageType = SvcMessageType.ExecuteRpcGeneric; + } + + public string ServiceName { get; set; } + public string MethodName { get; set; } + public object[] Arguments { get; set; } + } } diff --git a/Shared/Forms/FormUtils.cs b/Shared/Forms/FormUtils.cs index c082487..6da5888 100644 --- a/Shared/Forms/FormUtils.cs +++ b/Shared/Forms/FormUtils.cs @@ -519,10 +519,10 @@ namespace ColorControl.Shared.Forms public static string EditShortcut(string shortcut, string label = "Shortcut", string title = null) { - var field = new MessageForms.FieldDefinition + var field = new FieldDefinition { Label = label, - FieldType = MessageForms.FieldType.Shortcut, + FieldType = FieldType.Shortcut, Value = shortcut }; var values = MessageForms.ShowDialog(title ?? "Set shortcut", new[] { field }); diff --git a/Shared/Forms/MessageForms.cs b/Shared/Forms/MessageForms.cs index 2cb298e..9c6db94 100644 --- a/Shared/Forms/MessageForms.cs +++ b/Shared/Forms/MessageForms.cs @@ -4,81 +4,114 @@ using System.Globalization; namespace ColorControl.Shared.Forms { + public enum FieldType + { + Text, + Numeric, + DropDown, + Flags, + Shortcut, + CheckBox, + TrackBar, + Label + } + + public class FieldDefinition + { + public string Label { get; set; } + public string SubLabel { 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 int NumberOfValues { get; set; } + public int StepSize { get; set; } + public object Value { get; set; } + + public int ValueAsInt => int.Parse(Value.ToString()); + public uint ValueAsUInt => uint.Parse(Value.ToString()); + public bool ValueAsBool => bool.Parse(Value.ToString()); + public T ValueAsEnum() where T : struct => Utils.GetEnumValueByDescription(Value.ToString()); + + public static FieldDefinition CreateEnumField(string label, T value) where T : struct, IConvertible + { + return new FieldDefinition + { + Label = label, + FieldType = FieldType.DropDown, + Values = Utils.GetDescriptions(typeof(T), replaceUnderscore: true), + Value = value.GetDescription() + }; + } + + public static FieldDefinition CreateDropDownField(string label, IList values) + { + return new FieldDefinition + { + Label = label, + FieldType = FieldType.DropDown, + Values = values, + Value = values.FirstOrDefault() + }; + } + + public static FieldDefinition CreateCheckField(string label, bool value = true) + { + return new FieldDefinition + { + Label = label, + FieldType = FieldType.CheckBox, + Value = value + }; + } + } + + public class MessageForm : Form + { + private ToolTip _toolTip; + public Dictionary _controls = new(); + + public void edtShortcut_KeyDown(object sender, KeyEventArgs e) + { + ((TextBox)sender).Text = KeyboardShortcutManager.FormatKeyboardShortcut(e); + } + + public void edtShortcut_KeyUp(object sender, KeyEventArgs e) + { + KeyboardShortcutManager.HandleKeyboardShortcutUp(e); + } + + public void TrackBar_Scroll(object sender, EventArgs e) + { + var trackBar = sender as TrackBar; + var edit = (NumericUpDown)_controls[trackBar]; + + var indexDbl = (trackBar.Value * 1.0) / trackBar.TickFrequency; + var index = Convert.ToInt32(Math.Round(indexDbl)); + + var newValue = trackBar.Value < trackBar.Maximum ? trackBar.TickFrequency * index : trackBar.Value; + newValue = Math.Max(newValue, trackBar.Minimum); + newValue = Math.Min(newValue, trackBar.Maximum); + + trackBar.Value = newValue; + + edit.Value = trackBar.Value; + + _toolTip ??= new ToolTip(); + _toolTip.Show(trackBar.Value.ToString(), trackBar, 50, 10, 1500); + } + + public void TrackBarEdit_ValueChanged(object sender, EventArgs e) + { + var edit = (NumericUpDown)sender; + var trackBar = (TrackBar)_controls.First(c => c.Value == edit).Key; + + trackBar.Value = (int)edit.Value; + } + } + public class MessageForms { - public enum FieldType - { - Text, - Numeric, - DropDown, - Flags, - Shortcut, - CheckBox, - TrackBar, - Label - } - - public class FieldDefinition - { - public string Label { get; set; } - public string SubLabel { 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 int NumberOfValues { get; set; } - public int StepSize { get; set; } - public object Value { get; set; } - - public int ValueAsInt => int.Parse(Value.ToString()); - public uint ValueAsUInt => uint.Parse(Value.ToString()); - public bool ValueAsBool => bool.Parse(Value.ToString()); - } - - public class MessageForm : Form - { - private ToolTip _toolTip; - public Dictionary _controls = new(); - - public void edtShortcut_KeyDown(object sender, KeyEventArgs e) - { - ((TextBox)sender).Text = KeyboardShortcutManager.FormatKeyboardShortcut(e); - } - - public void edtShortcut_KeyUp(object sender, KeyEventArgs e) - { - KeyboardShortcutManager.HandleKeyboardShortcutUp(e); - } - - public void TrackBar_Scroll(object sender, EventArgs e) - { - var trackBar = sender as TrackBar; - var edit = (NumericUpDown)_controls[trackBar]; - - var indexDbl = (trackBar.Value * 1.0) / trackBar.TickFrequency; - var index = Convert.ToInt32(Math.Round(indexDbl)); - - var newValue = trackBar.Value < trackBar.Maximum ? trackBar.TickFrequency * index : trackBar.Value; - newValue = Math.Max(newValue, trackBar.Minimum); - newValue = Math.Min(newValue, trackBar.Maximum); - - trackBar.Value = newValue; - - edit.Value = trackBar.Value; - - _toolTip ??= new ToolTip(); - _toolTip.Show(trackBar.Value.ToString(), trackBar, 50, 10, 1500); - } - - public void TrackBarEdit_ValueChanged(object sender, EventArgs e) - { - var edit = (NumericUpDown)sender; - var trackBar = (TrackBar)_controls.First(c => c.Value == edit).Key; - - trackBar.Value = (int)edit.Value; - } - } - public static Form MainForm; public static void WarningOk(string text) @@ -196,6 +229,10 @@ namespace ColorControl.Shared.Forms textBox.Mask = "AA-AA-AA-AA-AA-AA"; textBox.Culture = CultureInfo.InvariantCulture; } + else if (field.Value != null) + { + textBox.Text = field.Value.ToString(); + } control = textBox; break; @@ -362,7 +399,7 @@ namespace ColorControl.Shared.Forms case FieldType.Label: control = textLabel; - top += 20; + top -= 20; break; diff --git a/Shared/Services/RpcService.cs b/Shared/Services/RpcService.cs new file mode 100644 index 0000000..7e12b72 --- /dev/null +++ b/Shared/Services/RpcService.cs @@ -0,0 +1,23 @@ +using ColorControl.Shared.Common; +using ColorControl.Shared.Contracts; + +namespace ColorControl.Shared.Services +{ + public class RpcService + { + public string Name { get; set; } + + public T Call(string method, params object[] arguments) where T : class + { + var rpcMessage = new SvcRpcMessage + { + ServiceName = Name, + MethodName = method, + Arguments = arguments + }; + + return PipeUtils.SendRpcMessage(rpcMessage); + } + + } +} diff --git a/Shared/Shared.csproj b/Shared/Shared.csproj index ff84db2..bc10159 100644 --- a/Shared/Shared.csproj +++ b/Shared/Shared.csproj @@ -40,6 +40,10 @@ + + + + Never