mirror of
https://github.com/Maassoft/ColorControl.git
synced 2026-10-23 09:02:19 -05:00
fix auto-start not working, add support for color profiles, add B3 as supported models for service menu unlock
This commit is contained in:
1 parent
db19a9ad68
commit
bc565abd38
17 files changed
+687
-92
No files matched your search
@@ -18,8 +18,8 @@
|
||||
<PublisherName>Maassoft</PublisherName>
|
||||
<Company>Maassoft</Company>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>9.7.0.0</ApplicationVersion>
|
||||
<Version>9.7.0.0</Version>
|
||||
<ApplicationVersion>9.7.1.0</ApplicationVersion>
|
||||
<Version>9.7.1.0</Version>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<PublishWizardCompleted>true</PublishWizardCompleted>
|
||||
<BootstrapperEnabled>false</BootstrapperEnabled>
|
||||
@@ -38,6 +38,7 @@
|
||||
<ApplicationManifest>Properties\app.manifest</ApplicationManifest>
|
||||
<SignManifests>true</SignManifests>
|
||||
<AssemblyOriginatorKeyFile>ColorControl_TemporaryKey.pfx</AssemblyOriginatorKeyFile>
|
||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
|
||||
@@ -266,8 +266,9 @@ namespace ColorControl
|
||||
Logger.Debug("Initializing NVIDIA...Done.");
|
||||
|
||||
var rpcService = _serviceProvider.GetRequiredService<RpcClientService>();
|
||||
var winAdminService = _serviceProvider.GetRequiredService<WinApiAdminService>();
|
||||
|
||||
_nvPanel = new NvPanel(_serviceManager.NvService, _trayIcon, Handle, appContextProvider, rpcService);
|
||||
_nvPanel = new NvPanel(_serviceManager.NvService, _trayIcon, Handle, appContextProvider, rpcService, winAdminService);
|
||||
_nvPanel.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
||||
|
||||
InitShortcut(NvPanel.SHORTCUTID_NVQA, _config.NvQuickAccessShortcut, _serviceManager.NvService.ToggleQuickAccessForm);
|
||||
|
||||
+3
-3
@@ -418,19 +418,19 @@
|
||||
mnuLgSetSvcMenuFlag.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { miLgFullServiceMenuEnable, miLgFullServiceMenuDisable });
|
||||
mnuLgSetSvcMenuFlag.Name = "mnuLgSetSvcMenuFlag";
|
||||
mnuLgSetSvcMenuFlag.Size = new System.Drawing.Size(320, 22);
|
||||
mnuLgSetSvcMenuFlag.Text = "Enable Full Service Menu (C3/G3 only)";
|
||||
mnuLgSetSvcMenuFlag.Text = "Enable Full Service Menu (B3/C3/G3 only)";
|
||||
//
|
||||
// miLgFullServiceMenuEnable
|
||||
//
|
||||
miLgFullServiceMenuEnable.Name = "miLgFullServiceMenuEnable";
|
||||
miLgFullServiceMenuEnable.Size = new System.Drawing.Size(112, 22);
|
||||
miLgFullServiceMenuEnable.Size = new System.Drawing.Size(180, 22);
|
||||
miLgFullServiceMenuEnable.Text = "Enable";
|
||||
miLgFullServiceMenuEnable.Click += miLgFullServiceMenuEnable_Click;
|
||||
//
|
||||
// miLgFullServiceMenuDisable
|
||||
//
|
||||
miLgFullServiceMenuDisable.Name = "miLgFullServiceMenuDisable";
|
||||
miLgFullServiceMenuDisable.Size = new System.Drawing.Size(112, 22);
|
||||
miLgFullServiceMenuDisable.Size = new System.Drawing.Size(180, 22);
|
||||
miLgFullServiceMenuDisable.Text = "Disable";
|
||||
miLgFullServiceMenuDisable.Click += miLgFullServiceMenuDisable_Click;
|
||||
//
|
||||
|
||||
@@ -829,7 +829,7 @@ Do you want to continue?"
|
||||
mnuLgOLEDMotionPro.Visible = visible;
|
||||
miLgEnableMotionPro.Visible = enableVisible;
|
||||
|
||||
var svcMenuFlagVisible = new[] { "C3", "G3" }.Any(m => device?.ModelName?.Contains(m) == true);
|
||||
var svcMenuFlagVisible = new[] { "B3", "C3", "G3" }.Any(m => device?.ModelName?.Contains(m) == true);
|
||||
|
||||
mnuLgSetSvcMenuFlag.Visible = svcMenuFlagVisible;
|
||||
|
||||
|
||||
@@ -1,4 +1,64 @@
|
||||
<root>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
|
||||
@@ -38,8 +38,9 @@ namespace ColorControl.Services.NVIDIA
|
||||
private string _lastDisplayRefreshRates = string.Empty;
|
||||
private NotifyIcon _trayIcon;
|
||||
private RpcClientService _rpcService;
|
||||
private readonly WinApiAdminService _winApiAdminService;
|
||||
|
||||
public NvPanel(NvService nvService, NotifyIcon trayIcon, IntPtr handle, AppContextProvider appContextProvider, RpcClientService rpcService)
|
||||
public NvPanel(NvService nvService, NotifyIcon trayIcon, IntPtr handle, AppContextProvider appContextProvider, RpcClientService rpcService, WinApiAdminService winApiAdminService)
|
||||
{
|
||||
_nvService = nvService;
|
||||
_trayIcon = trayIcon;
|
||||
@@ -47,7 +48,7 @@ namespace ColorControl.Services.NVIDIA
|
||||
_appContextProvider = appContextProvider;
|
||||
_config = appContextProvider.GetAppContext().Config;
|
||||
_rpcService = rpcService;
|
||||
|
||||
_winApiAdminService = winApiAdminService;
|
||||
_rpcService.Name = "NvService";
|
||||
|
||||
InitializeComponent();
|
||||
@@ -441,6 +442,13 @@ namespace ColorControl.Services.NVIDIA
|
||||
FormUtils.BuildDropDownMenu(mnuNvOtherSettings, "Scaling", typeof(Scaling), preset, "scaling", nvPresetScalingMenuItem_Click, unchanged: true, skipValues: new object[] { Scaling.Customized })
|
||||
.DropDownItems[0].Visible = !isCurrentDisplay;
|
||||
|
||||
var itemNameProfile = $"{mnuNvOtherSettings.Name}_Profile";
|
||||
var profileMenu = FormUtils.BuildMenuItem(mnuNvOtherSettings.DropDownItems, itemNameProfile, "Color Profile");
|
||||
|
||||
var subItemNameProfile = $"{itemNameProfile}_SubItem";
|
||||
var subItemProfile = FormUtils.BuildMenuItem(profileMenu.DropDownItems, subItemNameProfile, "", onClick: nvPresetColorProfileMenuItem_Click);
|
||||
subItemProfile.Text = (!preset.ColorProfileSettings.ProfileName.IsNullOrWhiteSpace() ? $"{preset.ColorProfileSettings.ProfileName}" : "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)
|
||||
@@ -847,6 +855,70 @@ namespace ColorControl.Services.NVIDIA
|
||||
AddOrUpdateItem();
|
||||
}
|
||||
|
||||
private void nvPresetColorProfileMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var preset = GetSelectedNvPreset(true);
|
||||
|
||||
_nvService.ResolveDisplay(preset);
|
||||
|
||||
if (preset.Display == null)
|
||||
{
|
||||
MessageForms.WarningOk($"Display {preset.displayName} not found");
|
||||
return;
|
||||
}
|
||||
|
||||
var display = preset.Display.Name;
|
||||
if (!CCD.GetUsePerUserDisplayProfiles(display))
|
||||
{
|
||||
if (MessageForms.QuestionYesNo("To be able to select a color profile, user specific settings have to be enabled. Do you want to enable this?") != DialogResult.Yes)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CCD.SetUsePerUserDisplayProfiles(display, true);
|
||||
}
|
||||
|
||||
var profiles = CCD.GetDisplayColorProfiles(display);
|
||||
|
||||
if (!profiles.Any())
|
||||
{
|
||||
if (MessageForms.QuestionYesNo("There are no profiles associated with this display. You have to manually add these through the Color Management app. Do you want to open this?") != DialogResult.Yes)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_winApiAdminService.StartProcess("colorcpl.exe");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
profiles.Insert(0, "None");
|
||||
|
||||
var value = SelectStringValue(preset.ColorProfileSettings.ProfileName, "Color Profile", profiles);
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (value == "None")
|
||||
{
|
||||
value = null;
|
||||
}
|
||||
|
||||
if (preset.IsDisplayPreset)
|
||||
{
|
||||
_nvService.SetColorProfile(preset.Display, value);
|
||||
|
||||
UpdateDisplayInfoItems();
|
||||
return;
|
||||
}
|
||||
|
||||
preset.ColorProfileSettings.ProfileName = value;
|
||||
|
||||
AddOrUpdateItem();
|
||||
}
|
||||
|
||||
private void refreshRateMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var refreshRate = (uint)((ToolStripItem)sender).Tag;
|
||||
@@ -1357,6 +1429,33 @@ namespace ColorControl.Services.NVIDIA
|
||||
return settingValue;
|
||||
}
|
||||
|
||||
private string SelectStringValue(string currentValue, string label, IEnumerable<string> values)
|
||||
{
|
||||
var field = new FieldDefinition
|
||||
{
|
||||
Label = label,
|
||||
FieldType = FieldType.DropDown,
|
||||
Values = values,
|
||||
Value = currentValue
|
||||
};
|
||||
|
||||
var resultFields = MessageForms.ShowDialog(field.Label, new[] { field });
|
||||
|
||||
if (!resultFields.Any())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var strValue = (string)resultFields.First().Value;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(strValue))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return strValue;
|
||||
}
|
||||
|
||||
private void miNvProfileInspector_Click(object sender, EventArgs e)
|
||||
{
|
||||
StartNvProfileInspector();
|
||||
|
||||
@@ -4,6 +4,7 @@ using ColorControl.Shared.Contracts;
|
||||
using ColorControl.Shared.Contracts.NVIDIA;
|
||||
using Newtonsoft.Json;
|
||||
using nspector.Common;
|
||||
using NStandard;
|
||||
using NvAPIWrapper.Display;
|
||||
using NvAPIWrapper.Native.Display;
|
||||
using System;
|
||||
@@ -43,9 +44,10 @@ namespace ColorControl.Services.NVIDIA
|
||||
|
||||
public bool applyHdmiSettings { get; set; }
|
||||
public NvHdmiInfoFrameSettings HdmiInfoFrameSettings { get; set; }
|
||||
public NvColorProfileSettings ColorProfileSettings { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsDisplayPreset => Display != null;
|
||||
public bool IsDisplayPreset { get; set; }
|
||||
[JsonIgnore]
|
||||
public Display Display { get; set; }
|
||||
[JsonIgnore]
|
||||
@@ -72,6 +74,7 @@ namespace ColorControl.Services.NVIDIA
|
||||
driverSettings = new Dictionary<uint, uint>();
|
||||
ocSettings = new List<NvGpuOcSettings>();
|
||||
HdmiInfoFrameSettings = new NvHdmiInfoFrameSettings();
|
||||
ColorProfileSettings = new NvColorProfileSettings();
|
||||
}
|
||||
|
||||
public NvPreset(ColorData colorData) : this()
|
||||
@@ -106,6 +109,7 @@ namespace ColorControl.Services.NVIDIA
|
||||
|
||||
SDRBrightness = preset.SDRBrightness;
|
||||
scaling = preset.scaling;
|
||||
ColorProfileSettings = new NvColorProfileSettings(preset.ColorProfileSettings);
|
||||
applyOther = preset.applyOther;
|
||||
|
||||
HdmiInfoFrameSettings = new NvHdmiInfoFrameSettings(preset.HdmiInfoFrameSettings);
|
||||
@@ -279,6 +283,10 @@ namespace ColorControl.Services.NVIDIA
|
||||
{
|
||||
values.Add($"Scaling: {scaling.Value.GetDescription()}");
|
||||
}
|
||||
if (!ColorProfileSettings.ProfileName.IsNullOrWhiteSpace())
|
||||
{
|
||||
values.Add($"Color profile: {ColorProfileSettings.ProfileName}");
|
||||
}
|
||||
|
||||
if (!values.Any())
|
||||
{
|
||||
|
||||
@@ -28,6 +28,7 @@ using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using static ColorControl.Shared.Native.CCD;
|
||||
|
||||
namespace ColorControl.Services.NVIDIA
|
||||
{
|
||||
@@ -241,15 +242,18 @@ namespace ColorControl.Services.NVIDIA
|
||||
}
|
||||
|
||||
private void SetCurrentDisplay(NvPreset preset)
|
||||
{
|
||||
_currentDisplay = GetPresetDisplay(preset);
|
||||
}
|
||||
|
||||
private Display GetPresetDisplay(NvPreset preset)
|
||||
{
|
||||
if (preset.primaryDisplay)
|
||||
{
|
||||
_currentDisplay = GetPrimaryDisplay();
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentDisplay = Display.GetDisplays().FirstOrDefault(x => x.Name.Equals(preset.displayName));
|
||||
return GetPrimaryDisplay();
|
||||
}
|
||||
|
||||
return Display.GetDisplays().FirstOrDefault(x => x.Name.Equals(preset.displayName));
|
||||
}
|
||||
|
||||
public Display GetPrimaryDisplay()
|
||||
@@ -346,6 +350,11 @@ namespace ColorControl.Services.NVIDIA
|
||||
{
|
||||
SetSDRBrightness(display, preset.SDRBrightness.Value);
|
||||
}
|
||||
|
||||
if (preset.ColorProfileSettings.ProfileName != null)
|
||||
{
|
||||
CCD.SetDisplayDefaultColorProfile(display.Name, preset.ColorProfileSettings.ProfileName);
|
||||
}
|
||||
}
|
||||
|
||||
if (preset.applyHdmiSettings)
|
||||
@@ -903,9 +912,25 @@ namespace ColorControl.Services.NVIDIA
|
||||
return pathInfos.FirstOrDefault(c => c.TargetsInfo.Any(ti => ti.DisplayId == display.DisplayDevice.DisplayId));
|
||||
}
|
||||
|
||||
public void SetColorProfile(Display display, string name)
|
||||
{
|
||||
CCD.SetDisplayDefaultColorProfile(display.Name, name);
|
||||
}
|
||||
|
||||
public void TestResolution()
|
||||
{
|
||||
//var display = GetCurrentDisplay();
|
||||
|
||||
//CCD.GetUsePerUserDisplayProfiles(display.Name);
|
||||
|
||||
//CCD.GetDisplayColorProfiles(display.Name);
|
||||
|
||||
//CCD.InstallColorProfile(@"H:\srgb2000.icm");
|
||||
|
||||
//CCD.AddDisplayColorProfile(display.Name, "srgb2000.icm");
|
||||
|
||||
//CCD.SetDisplayDefaultColorProfile(display.Name, "srgb2000.icm");
|
||||
|
||||
//var displayDevice = display.DisplayDevice;
|
||||
|
||||
//var config = DisplayApi.GetDisplayConfig();
|
||||
@@ -1071,13 +1096,16 @@ namespace ColorControl.Services.NVIDIA
|
||||
}
|
||||
|
||||
var isPrimaryDisplay = displayCount == 1 || display.DisplayDevice.DisplayId == DisplayDevice.GetGDIPrimaryDisplayDevice()?.DisplayId;
|
||||
var preset = new NvPreset { Display = display, applyColorData = false, primaryDisplay = isPrimaryDisplay };
|
||||
var preset = new NvPreset { Display = display, IsDisplayPreset = true, applyColorData = false, primaryDisplay = isPrimaryDisplay };
|
||||
|
||||
preset.HDREnabled = IsHDREnabled(display);
|
||||
|
||||
preset.displayName = FormUtils.ExtendedDisplayName(display.Name);
|
||||
preset.colorData = GetCurrentColorData(display);
|
||||
preset.HdmiInfoFrameSettings = GetHdmiSettings(display);
|
||||
preset.SDRBrightness = GetSDRBrightness(display);
|
||||
preset.scaling = GetScaling(display);
|
||||
preset.ColorProfileSettings.ProfileName = CCD.GetDisplayDefaultColorProfile(display.Name, preset.HDREnabled ? COLORPROFILESUBTYPE.CPST_EXTENDED_DISPLAY_COLOR_MODE : COLORPROFILESUBTYPE.CPST_STANDARD_DISPLAY_COLOR_MODE);
|
||||
|
||||
var mode = GetCurrentMode(display.Name);
|
||||
|
||||
@@ -1100,8 +1128,6 @@ namespace ColorControl.Services.NVIDIA
|
||||
preset.ditheringMode = (uint)ditherInfo.mode;
|
||||
}
|
||||
|
||||
preset.HDREnabled = IsHDREnabled(display);
|
||||
|
||||
if (Config.ShowOverclocking)
|
||||
{
|
||||
var gpus = GetGPUs();
|
||||
@@ -1311,5 +1337,15 @@ namespace ColorControl.Services.NVIDIA
|
||||
{
|
||||
Utils.WriteObject(_configFilename, Config);
|
||||
}
|
||||
|
||||
internal void ResolveDisplay(NvPreset preset)
|
||||
{
|
||||
if (preset.Display != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
preset.Display = GetPresetDisplay(preset);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ namespace ColorControl.Services.Samsung
|
||||
{
|
||||
public static SynchronizationContext SyncContext { get; set; }
|
||||
|
||||
public bool ConnectionClosed { get; private set; }
|
||||
public bool? ConnectionClosed { get; private set; }
|
||||
public bool ClosedByDispose { get; private set; }
|
||||
|
||||
private MessageWebSocket _connection;
|
||||
@@ -133,7 +133,7 @@ namespace ColorControl.Services.Samsung
|
||||
_tokens.TryAdd(id, taskSource);
|
||||
|
||||
await SendMessageAsync(message);
|
||||
if (ConnectionClosed)
|
||||
if (ConnectionClosed == true)
|
||||
{
|
||||
throw new Exception("Connection closed");
|
||||
}
|
||||
@@ -143,7 +143,7 @@ namespace ColorControl.Services.Samsung
|
||||
else
|
||||
{
|
||||
await SendMessageAsync(message);
|
||||
if (ConnectionClosed)
|
||||
if (ConnectionClosed == true)
|
||||
{
|
||||
throw new Exception("Connection closed");
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@ namespace ColorControl.Services.Samsung
|
||||
}
|
||||
else
|
||||
{
|
||||
var _ = SelectedDevice.ConnectAsync();
|
||||
//var _ = SelectedDevice.ConnectAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
namespace ColorControl.Shared.Contracts.NVIDIA
|
||||
{
|
||||
public class NvColorProfileSettings
|
||||
{
|
||||
public string ProfileName { get; set; }
|
||||
|
||||
public NvColorProfileSettings()
|
||||
{
|
||||
}
|
||||
|
||||
public NvColorProfileSettings(NvColorProfileSettings settings)
|
||||
{
|
||||
settings ??= new NvColorProfileSettings();
|
||||
|
||||
ProfileName = settings.ProfileName;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var value = string.Empty;
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
+378
-21
@@ -1,4 +1,5 @@
|
||||
using NWin32;
|
||||
using ColorControl.Shared.Forms;
|
||||
using NWin32;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
@@ -8,6 +9,7 @@ namespace ColorControl.Shared.Native
|
||||
public static class CCD
|
||||
{
|
||||
private static bool? IsHDRActive = null;
|
||||
delegate (T, bool) DisplayConfigModeInfoDelegate<T>(DisplayConfigModeInfo modeInfo);
|
||||
|
||||
public enum DisplayTopology
|
||||
{
|
||||
@@ -60,7 +62,7 @@ namespace ColorControl.Shared.Native
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetHDRState(bool enabled, string displayName = null, float? SDRWhiteLevelInNits = null)
|
||||
public static void SetHDRState(bool enabled, string displayName = null)
|
||||
{
|
||||
uint pathCount, modeCount;
|
||||
|
||||
@@ -120,7 +122,271 @@ namespace ColorControl.Shared.Native
|
||||
}
|
||||
}
|
||||
|
||||
public static LUID GetAdapterId(string displayName = null)
|
||||
{
|
||||
return ExecuteForModeConfig((modeInfo) =>
|
||||
{
|
||||
if (modeInfo.infoType == DisplayConfigModeInfoType.Target)
|
||||
{
|
||||
return (modeInfo.adapterId, false);
|
||||
}
|
||||
|
||||
return (default(LUID), true);
|
||||
}, displayName
|
||||
);
|
||||
}
|
||||
|
||||
public static uint GetSourceId(string displayName = null)
|
||||
{
|
||||
return ExecuteForModeConfig((modeInfo) =>
|
||||
{
|
||||
if (modeInfo.infoType == DisplayConfigModeInfoType.Source)
|
||||
{
|
||||
return (modeInfo.id, false);
|
||||
}
|
||||
|
||||
return (0u, true);
|
||||
}, displayName
|
||||
);
|
||||
}
|
||||
|
||||
public static bool InstallColorProfile(string profileName)
|
||||
{
|
||||
var result = NativeMethods.InstallColorProfileW(null, profileName);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
var err = NWin32.NativeMethods.GetLastError();
|
||||
|
||||
throw new Win32Exception((int)err);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool MinRequiredVersion = true;
|
||||
|
||||
public static bool AddDisplayColorProfile(string displayName, string profileName, bool setAsDefault = true)
|
||||
{
|
||||
var adapterId = GetAdapterId(displayName);
|
||||
var sourceId = GetSourceId(displayName);
|
||||
|
||||
var err = NativeMethods.ColorProfileAddDisplayAssociation(WCS_PROFILE_MANAGEMENT_SCOPE.WCS_PROFILE_MANAGEMENT_SCOPE_CURRENT_USER, profileName, adapterId, sourceId, setAsDefault, true);
|
||||
|
||||
if (err != NativeConstants.ERROR_SUCCESS)
|
||||
{
|
||||
throw new Win32Exception(err);
|
||||
}
|
||||
|
||||
return err == NativeConstants.ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
public static bool RemoveDisplayColorProfile(string displayName, string profileName)
|
||||
{
|
||||
var adapterId = GetAdapterId(displayName);
|
||||
var sourceId = GetSourceId(displayName);
|
||||
|
||||
var err = NativeMethods.ColorProfileRemoveDisplayAssociation(WCS_PROFILE_MANAGEMENT_SCOPE.WCS_PROFILE_MANAGEMENT_SCOPE_CURRENT_USER, profileName, adapterId, sourceId, true);
|
||||
|
||||
if (err != NativeConstants.ERROR_SUCCESS)
|
||||
{
|
||||
throw new Win32Exception(err);
|
||||
}
|
||||
|
||||
return err == NativeConstants.ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
public static bool SetDisplayDefaultColorProfile(string displayName, string profileName)
|
||||
{
|
||||
var adapterId = GetAdapterId(displayName);
|
||||
var sourceId = GetSourceId(displayName);
|
||||
|
||||
var subType = COLORPROFILESUBTYPE.CPST_PERCEPTUAL;
|
||||
|
||||
if (profileName == null)
|
||||
{
|
||||
profileName = GetDisplayDefaultColorProfile(displayName, COLORPROFILESUBTYPE.CPST_EXTENDED_DISPLAY_COLOR_MODE);
|
||||
|
||||
if (profileName == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return RemoveDisplayColorProfile(displayName, profileName) && AddDisplayColorProfile(displayName, profileName, false);
|
||||
}
|
||||
|
||||
var err = NativeMethods.ColorProfileSetDisplayDefaultAssociation(WCS_PROFILE_MANAGEMENT_SCOPE.WCS_PROFILE_MANAGEMENT_SCOPE_CURRENT_USER, profileName, COLORPROFILETYPE.CPT_ICC, subType, adapterId, sourceId);
|
||||
|
||||
if (err != NativeConstants.ERROR_SUCCESS)
|
||||
{
|
||||
throw new Win32Exception(err);
|
||||
}
|
||||
|
||||
return err == NativeConstants.ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
public static string GetDisplayDefaultColorProfile(string displayName, COLORPROFILESUBTYPE profileSubType = COLORPROFILESUBTYPE.CPST_STANDARD_DISPLAY_COLOR_MODE)
|
||||
{
|
||||
if (!MinRequiredVersion)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var adapterId = GetAdapterId(displayName);
|
||||
var sourceId = GetSourceId(displayName);
|
||||
|
||||
var scope = GetUsePerUserDisplayProfiles(displayName) ? WCS_PROFILE_MANAGEMENT_SCOPE.WCS_PROFILE_MANAGEMENT_SCOPE_CURRENT_USER : WCS_PROFILE_MANAGEMENT_SCOPE.WCS_PROFILE_MANAGEMENT_SCOPE_SYSTEM_WIDE;
|
||||
try
|
||||
{
|
||||
var pointer = new IntPtr();
|
||||
var err = NativeMethods.ColorProfileGetDisplayDefault(scope, adapterId, sourceId, COLORPROFILETYPE.CPT_ICC, profileSubType, pointer);
|
||||
|
||||
if (err != NativeConstants.ERROR_SUCCESS)
|
||||
{
|
||||
// No default profile set
|
||||
if (err == -2147024894)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
throw new Win32Exception(err);
|
||||
}
|
||||
var profileName = Marshal.PtrToStringUni(pointer);
|
||||
|
||||
return profileName;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
MinRequiredVersion = false;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct UnmanagedStruct
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
|
||||
public IntPtr[] listOfStrings;
|
||||
}
|
||||
|
||||
public static List<string> GetDisplayColorProfiles(string displayName)
|
||||
{
|
||||
var adapterId = GetAdapterId(displayName);
|
||||
var sourceId = GetSourceId(displayName);
|
||||
|
||||
var pointer = IntPtr.Zero;
|
||||
|
||||
var scope = GetUsePerUserDisplayProfiles(displayName) ? WCS_PROFILE_MANAGEMENT_SCOPE.WCS_PROFILE_MANAGEMENT_SCOPE_CURRENT_USER : WCS_PROFILE_MANAGEMENT_SCOPE.WCS_PROFILE_MANAGEMENT_SCOPE_SYSTEM_WIDE;
|
||||
|
||||
var err = NativeMethods.ColorProfileGetDisplayList(scope, adapterId, sourceId, pointer, out var profileCount);
|
||||
|
||||
if (err != NativeConstants.ERROR_SUCCESS)
|
||||
{
|
||||
throw new Win32Exception(err);
|
||||
}
|
||||
|
||||
// No items
|
||||
if (pointer == IntPtr.Zero)
|
||||
{
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
var data = Marshal.PtrToStructure<UnmanagedStruct>(pointer);
|
||||
var list = data.listOfStrings.Take((int)profileCount).Select(p => Marshal.PtrToStringUni(p)).ToList();
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public static bool GetUsePerUserDisplayProfiles(string displayName)
|
||||
{
|
||||
var deviceKey = GetDisplayDeviceKey(displayName);
|
||||
|
||||
if (deviceKey == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var result = NativeMethods.WcsGetUsePerUserProfiles(deviceKey, DeviceClassFlags.CLASS_MONITOR, out var usePerUserProfiles);
|
||||
|
||||
if (!result)
|
||||
{
|
||||
//if (err != NativeConstants.ERROR_SUCCESS)
|
||||
//{
|
||||
// throw new Win32Exception(err);
|
||||
//}
|
||||
}
|
||||
|
||||
return usePerUserProfiles;
|
||||
}
|
||||
|
||||
public static bool SetUsePerUserDisplayProfiles(string displayName, bool usePerUserProfiles)
|
||||
{
|
||||
var deviceKey = GetDisplayDeviceKey(displayName);
|
||||
|
||||
if (deviceKey == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var result = NativeMethods.WcsSetUsePerUserProfiles(deviceKey, DeviceClassFlags.CLASS_MONITOR, usePerUserProfiles);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string GetDisplayDeviceKey(string displayName)
|
||||
{
|
||||
var hMonitor = FormUtils.GetMonitorForDisplayName(displayName);
|
||||
|
||||
if (hMonitor == IntPtr.Zero)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var mInfo = new MONITORINFOEX();
|
||||
mInfo.cbSize = (uint)Marshal.SizeOf(mInfo);
|
||||
if (!NativeMethods.GetMonitorInfo(hMonitor, ref mInfo))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var dd = new DISPLAYDEVICE();
|
||||
dd.cb = (uint)Marshal.SizeOf(dd);
|
||||
if (!NativeMethods.EnumDisplayDevices(mInfo.szDevice, 0, ref dd, 0))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return dd.DeviceKey;
|
||||
}
|
||||
|
||||
public static uint GetSDRWhiteLevel(string displayName = null)
|
||||
{
|
||||
return ExecuteForModeConfig<uint>((modeInfo) =>
|
||||
{
|
||||
if (modeInfo.infoType == DisplayConfigModeInfoType.Target)
|
||||
{
|
||||
var requestpacket = new DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO();
|
||||
requestpacket.header = new DISPLAYCONFIG_DEVICE_INFO_HEADER();
|
||||
requestpacket.header.type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO;
|
||||
requestpacket.header.size = Marshal.SizeOf<DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO>();
|
||||
|
||||
requestpacket.header.adapterId = modeInfo.adapterId;
|
||||
requestpacket.header.id = modeInfo.id;
|
||||
|
||||
var err = NativeMethods.DisplayConfigGetDeviceInfo(ref requestpacket);
|
||||
|
||||
if (err == NativeConstants.ERROR_SUCCESS && requestpacket.advancedColorSupported)
|
||||
{
|
||||
return (GetSDRWhiteLevelForDisplayConfig(modeInfo), false);
|
||||
}
|
||||
}
|
||||
|
||||
return (0, true);
|
||||
}, displayName
|
||||
);
|
||||
}
|
||||
|
||||
private static T ExecuteForModeConfig<T>(DisplayConfigModeInfoDelegate<T> infoDelegate, string displayName = null)
|
||||
{
|
||||
uint pathCount, modeCount;
|
||||
|
||||
@@ -142,24 +408,13 @@ namespace ColorControl.Shared.Native
|
||||
continue;
|
||||
}
|
||||
|
||||
var requestpacket = new DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO();
|
||||
requestpacket.header = new DISPLAYCONFIG_DEVICE_INFO_HEADER();
|
||||
requestpacket.header.type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO;
|
||||
requestpacket.header.size = Marshal.SizeOf<DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO>();
|
||||
|
||||
for (int i = 0; i < modeCount; i++)
|
||||
{
|
||||
if (modesArray[i].infoType == DisplayConfigModeInfoType.Target)
|
||||
var result = infoDelegate(modesArray[i]);
|
||||
|
||||
if (!result.Item2)
|
||||
{
|
||||
requestpacket.header.adapterId = modesArray[i].adapterId;
|
||||
requestpacket.header.id = modesArray[i].id;
|
||||
|
||||
err = NativeMethods.DisplayConfigGetDeviceInfo(ref requestpacket);
|
||||
|
||||
if (err == NativeConstants.ERROR_SUCCESS && requestpacket.advancedColorSupported)
|
||||
{
|
||||
return GetSDRWhiteLevelForDisplayConfig(modesArray[i]);
|
||||
}
|
||||
return result.Item1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -171,7 +426,7 @@ namespace ColorControl.Shared.Native
|
||||
throw new Win32Exception(err);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return default;
|
||||
}
|
||||
|
||||
public static bool IsHDREnabled(string displayName = null)
|
||||
@@ -314,7 +569,7 @@ namespace ColorControl.Shared.Native
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct LUID
|
||||
public struct LUID
|
||||
{
|
||||
uint LowPart;
|
||||
uint HighPart;
|
||||
@@ -682,6 +937,87 @@ namespace ColorControl.Shared.Native
|
||||
public string viewGdiDeviceName;
|
||||
}
|
||||
|
||||
enum WCS_PROFILE_MANAGEMENT_SCOPE
|
||||
{
|
||||
WCS_PROFILE_MANAGEMENT_SCOPE_SYSTEM_WIDE,
|
||||
WCS_PROFILE_MANAGEMENT_SCOPE_CURRENT_USER
|
||||
};
|
||||
|
||||
enum COLORPROFILETYPE
|
||||
{
|
||||
CPT_ICC,
|
||||
CPT_DMP,
|
||||
CPT_CAMP,
|
||||
CPT_GMMP
|
||||
};
|
||||
|
||||
public enum COLORPROFILESUBTYPE
|
||||
{
|
||||
CPST_PERCEPTUAL,
|
||||
CPST_RELATIVE_COLORIMETRIC,
|
||||
CPST_SATURATION,
|
||||
CPST_ABSOLUTE_COLORIMETRIC,
|
||||
CPST_NONE,
|
||||
CPST_RGB_WORKING_SPACE,
|
||||
CPST_CUSTOM_WORKING_SPACE,
|
||||
CPST_STANDARD_DISPLAY_COLOR_MODE,
|
||||
CPST_EXTENDED_DISPLAY_COLOR_MODE
|
||||
};
|
||||
|
||||
enum DeviceClassFlags : UInt32
|
||||
{
|
||||
// from: c:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\um\Icm.h
|
||||
/// <summary>
|
||||
///#define CLASS_MONITOR 'mntr'
|
||||
/// </summary>
|
||||
CLASS_MONITOR = 0x6d6e7472,
|
||||
|
||||
/// <summary>
|
||||
/// #define CLASS_PRINTER 'prtr'
|
||||
/// </summary>
|
||||
CLASS_PRINTER = 0x70727472,
|
||||
|
||||
/// <summary>
|
||||
/// #define CLASS_SCANNER 'scnr'
|
||||
/// </summary>
|
||||
CLASS_SCANNER = 0x73636e72
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct RECT
|
||||
{
|
||||
public int Left;
|
||||
public int Top;
|
||||
public int Right;
|
||||
public int Bottom;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct MONITORINFOEX
|
||||
{
|
||||
public uint cbSize;
|
||||
public RECT rcMonitor;
|
||||
public RECT rcWork;
|
||||
public uint dwFlags;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
|
||||
public string szDevice;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
public struct DISPLAYDEVICE
|
||||
{
|
||||
public uint cb;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
|
||||
public string DeviceName;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
||||
public string DeviceString;
|
||||
public uint StateFlags;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
||||
public string DeviceID;
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
|
||||
public string DeviceKey;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
static class NativeMethods
|
||||
@@ -710,8 +1046,29 @@ namespace ColorControl.Shared.Native
|
||||
[DllImport("user32")]
|
||||
public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_SDR_WHITE_LEVEL requestPacket);
|
||||
|
||||
[DllImport("user32")]
|
||||
public static extern int DisplayConfigSetDeviceInfo(ref DISPLAYCONFIG_SDR_WHITE_LEVEL setPacket);
|
||||
[DllImport("mscms", CharSet = CharSet.Unicode)]
|
||||
public static extern bool InstallColorProfileW(string machineName, string profilename);
|
||||
|
||||
[DllImport("mscms", CharSet = CharSet.Unicode)]
|
||||
public static extern int ColorProfileSetDisplayDefaultAssociation(WCS_PROFILE_MANAGEMENT_SCOPE scope, string profilename, COLORPROFILETYPE profiletype, COLORPROFILESUBTYPE profilesubtype, LUID targetadapterid, uint sourceid);
|
||||
|
||||
[DllImport("mscms", CharSet = CharSet.Unicode)]
|
||||
public static extern int ColorProfileAddDisplayAssociation(WCS_PROFILE_MANAGEMENT_SCOPE scope, string profilename, LUID targetadapterid, uint sourceid, bool setAsDefault, bool associateAsAdvancedColor);
|
||||
|
||||
[DllImport("mscms", CharSet = CharSet.Unicode)]
|
||||
public static extern int ColorProfileRemoveDisplayAssociation(WCS_PROFILE_MANAGEMENT_SCOPE scope, string profilename, LUID targetadapterid, uint sourceid, bool associateAsAdvancedColor);
|
||||
[DllImport("mscms", CharSet = CharSet.Unicode)]
|
||||
public static extern int ColorProfileGetDisplayList(WCS_PROFILE_MANAGEMENT_SCOPE scope, LUID targetadapterid, uint sourceid, in IntPtr pointer, out uint profileCount);
|
||||
[DllImport("mscms", CharSet = CharSet.Unicode)]
|
||||
public static extern int ColorProfileGetDisplayDefault(WCS_PROFILE_MANAGEMENT_SCOPE scope, LUID targetadapterid, uint sourceid, COLORPROFILETYPE profiletype, COLORPROFILESUBTYPE profilesubtype, in IntPtr pointer);
|
||||
[DllImport("mscms", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern bool WcsGetUsePerUserProfiles(string deviceName, DeviceClassFlags deviceClass, out bool usePerUserProfiles);
|
||||
[DllImport("mscms", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern bool WcsSetUsePerUserProfiles(string deviceName, DeviceClassFlags deviceClass, bool usePerUserProfiles);
|
||||
[DllImport("user32.dll")]
|
||||
public extern static bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFOEX lpmi);
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||
public static extern bool EnumDisplayDevices(string lpDevice, uint iDevNum, ref DISPLAYDEVICE lpDisplayDevice, uint dwFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,8 +34,7 @@ public class RpcServerService
|
||||
var arg = message.Arguments[i];
|
||||
var methodParam = methodParams[i];
|
||||
|
||||
var convertedArg = ConvertArgument(arg, methodParam.ParameterType);
|
||||
convertedArgs.Add(arg);
|
||||
AddArgument(arg, methodParam.ParameterType, convertedArgs);
|
||||
}
|
||||
|
||||
Logger.Debug($"Executing RPC: {message.ServiceName}.{message.MethodName}({string.Join(", ", convertedArgs)})");
|
||||
@@ -54,21 +53,22 @@ public class RpcServerService
|
||||
}
|
||||
}
|
||||
|
||||
private object ConvertArgument(object arg, Type type)
|
||||
private void AddArgument(object arg, Type type, List<object> list)
|
||||
{
|
||||
if (arg.GetType() != type)
|
||||
{
|
||||
if (type.IsEnum)
|
||||
{
|
||||
return Enum.ToObject(type, arg);
|
||||
// Add enum directly to list and not return as 'object'
|
||||
list.Add(Enum.ToObject(type, arg));
|
||||
return;
|
||||
}
|
||||
|
||||
var convertedArg = Convert.ChangeType(arg, type);
|
||||
return convertedArg;
|
||||
list.Add(Convert.ChangeType(arg, type));
|
||||
return;
|
||||
}
|
||||
|
||||
return arg;
|
||||
|
||||
list.Add(arg);
|
||||
}
|
||||
|
||||
public async Task<SvcResultMessage> ExecuteRpcTypedAsync(SvcRpcMessageTyped message)
|
||||
@@ -92,8 +92,7 @@ public class RpcServerService
|
||||
var arg = prop.GetValue(message);
|
||||
var methodParam = methodParams[paramIndex];
|
||||
|
||||
var convertedArg = ConvertArgument(arg, methodParam.ParameterType);
|
||||
convertedArgs.Add(arg);
|
||||
AddArgument(arg, methodParam.ParameterType, convertedArgs);
|
||||
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace novideo_srgb
|
||||
@@ -15,7 +12,7 @@ namespace novideo_srgb
|
||||
private static extern int QueryDisplayConfig(QDC flags, ref int numPathArrayElements, [In, Out] DISPLAYCONFIG_PATH_INFO[] pathArray, ref int numModeInfoArrayElements, [In, Out] DISPLAYCONFIG_MODE_INFO[] modeInfoArray, out DISPLAYCONFIG_TOPOLOGY_ID currentTopologyId);
|
||||
|
||||
[DllImport("user32")]
|
||||
private static extern int QueryDisplayConfig(QDC flags, ref int numPathArrayElements, [In, Out] DISPLAYCONFIG_PATH_INFO[] pathArray, ref int numModeInfoArrayElements, [In, Out] DISPLAYCONFIG_MODE_INFO[] modeInfoArray, IntPtr currentTopologyId);
|
||||
private static extern int QueryDisplayConfig(QDC flags, ref int numPathArrayElements, [In, Out] DISPLAYCONFIG_PATH_INFO[] path4Array, ref int numModeInfoArrayElements, [In, Out] DISPLAYCONFIG_MODE_INFO[] modeInfoArray, IntPtr currentTopologyId);
|
||||
|
||||
[DllImport("user32")]
|
||||
private static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO requestPacket);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
|
||||
namespace novideo_srgb
|
||||
{
|
||||
|
||||
@@ -37,11 +37,15 @@ namespace novideo_srgb
|
||||
foreach (var display in Display.GetDisplays())
|
||||
{
|
||||
var displays = WindowsDisplayAPI.Display.GetDisplays();
|
||||
var path = displays.First(x => x.DisplayName == display.Name).DevicePath;
|
||||
var path = displays.FirstOrDefault(x => x.DisplayName == display.Name)?.DevicePath;
|
||||
if (path == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var hdrActive = hdrPaths.Contains(path);
|
||||
|
||||
var settings = config?.FirstOrDefault(x => (string)x.Attribute("path") == path);
|
||||
var settings = config?.FirstOrDefault(x => (string?)x.Attribute("path") == path);
|
||||
MonitorData monitor;
|
||||
if (settings != null)
|
||||
{
|
||||
|
||||
+38
-29
@@ -6,6 +6,7 @@ using NvAPIWrapper.Display;
|
||||
using NvAPIWrapper.GPU;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using static novideo_srgb.Colorimetry;
|
||||
|
||||
namespace novideo_srgb
|
||||
{
|
||||
@@ -87,49 +88,57 @@ namespace novideo_srgb
|
||||
_clamped = Novideo.IsColorSpaceConversionActive(_output);
|
||||
}
|
||||
|
||||
if (!doClamp) return;
|
||||
if (!doClamp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_clamped) Thread.Sleep(100);
|
||||
if (UseEdid)
|
||||
Novideo.SetColorSpaceConversion(_output, Colorimetry.RGBToRGB(TargetColorSpace, EdidColorSpace));
|
||||
else if (UseIcc)
|
||||
{
|
||||
var profile = ICCMatrixProfile.FromFile(ProfilePath);
|
||||
if (CalibrateGamma)
|
||||
SetICCProfile(ProfilePath, SelectedGamma, TargetColorSpace);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetICCProfile(string fileName, int selectedGamma, ColorSpace colorSpace)
|
||||
{
|
||||
var profile = ICCMatrixProfile.FromFile(fileName);
|
||||
if (CalibrateGamma)
|
||||
{
|
||||
var trcBlack = Matrix.FromValues(new[,]
|
||||
{
|
||||
var trcBlack = Matrix.FromValues(new[,]
|
||||
{
|
||||
{ profile.trcs[0].SampleAt(0) },
|
||||
{ profile.trcs[1].SampleAt(0) },
|
||||
{ profile.trcs[2].SampleAt(0) }
|
||||
});
|
||||
var black = (profile.matrix * trcBlack)[1];
|
||||
var black = (profile.matrix * trcBlack)[1];
|
||||
|
||||
ToneCurve gamma;
|
||||
switch (SelectedGamma)
|
||||
{
|
||||
case 0:
|
||||
gamma = new SrgbEOTF(black);
|
||||
break;
|
||||
case 1:
|
||||
gamma = new GammaToneCurve(2.4, black, 0);
|
||||
break;
|
||||
case 2:
|
||||
gamma = new GammaToneCurve(CustomGamma, black, CustomPercentage / 100);
|
||||
break;
|
||||
case 3:
|
||||
gamma = new GammaToneCurve(CustomGamma, black, CustomPercentage / 100, true);
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException("Unsupported gamma type " + SelectedGamma);
|
||||
}
|
||||
|
||||
Novideo.SetColorSpaceConversion(_output, profile, TargetColorSpace, gamma, DisableOptimization);
|
||||
}
|
||||
else
|
||||
ToneCurve gamma;
|
||||
switch (selectedGamma)
|
||||
{
|
||||
Novideo.SetColorSpaceConversion(_output, profile, TargetColorSpace);
|
||||
case 0:
|
||||
gamma = new SrgbEOTF(black);
|
||||
break;
|
||||
case 1:
|
||||
gamma = new GammaToneCurve(2.4, black, 0);
|
||||
break;
|
||||
case 2:
|
||||
gamma = new GammaToneCurve(CustomGamma, black, CustomPercentage / 100);
|
||||
break;
|
||||
case 3:
|
||||
gamma = new GammaToneCurve(CustomGamma, black, CustomPercentage / 100, true);
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException("Unsupported gamma type " + selectedGamma);
|
||||
}
|
||||
|
||||
Novideo.SetColorSpaceConversion(_output, profile, colorSpace, gamma, DisableOptimization);
|
||||
}
|
||||
else
|
||||
{
|
||||
Novideo.SetColorSpaceConversion(_output, profile, colorSpace);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user