diff --git a/ColorControl.sln b/ColorControl.sln index c62f64f..2b1aff5 100644 --- a/ColorControl.sln +++ b/ColorControl.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.30128.74 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ColorControl", "ColorControl\ColorControl.csproj", "{A6005D08-70F0-44CB-A384-9219EBA84F21}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0373E1EF-1DE6-4BCB-BC95-2D7961DBA194}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/ColorControl/ADL.cs b/ColorControl/ADL.cs new file mode 100644 index 0000000..3ecc89e --- /dev/null +++ b/ColorControl/ADL.cs @@ -0,0 +1,529 @@ +#region Copyright + +/******************************************************************************* + Copyright(c) 2008 - 2009 Advanced Micro Devices, Inc. All Rights Reserved. + Copyright (c) 2002 - 2006 ATI Technologies Inc. All Rights Reserved. + + THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF + ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDED BUT NOT LIMITED TO + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A + PARTICULAR PURPOSE. + + File: ADL.cs + + Purpose: Implements ADL interface + + Description: Implements some of the methods defined in ADL interface. + + ********************************************************************************/ + +#endregion Copyright + +#region Using + +using System; +using System.Collections.Generic; +using System.Text; +using System.Runtime.InteropServices; +using System.Diagnostics; +using System.Threading; +using FARPROC = System.IntPtr; +using HMODULE = System.IntPtr; + +#endregion Using + +#region ATI.ADL + +namespace ATI.ADL +{ + #region Export Delegates + /// ADL Memory allocation function allows ADL to callback for memory allocation + /// input size + /// retrun ADL Error Code + internal delegate IntPtr ADL_Main_Memory_Alloc (int size); + + // ///// ADL Create Function to create ADL Data + /// Call back functin pointer which is ised to allocate memeory + /// If it is 1, then ADL will only retuen the physical exist adapters + ///// retrun ADL Error Code + internal delegate int ADL_Main_Control_Create(ADL_Main_Memory_Alloc callback, int enumConnectedAdapters); + + /// ADL Destroy Function to free up ADL Data + /// retrun ADL Error Code + internal delegate int ADL_Main_Control_Destroy (); + + /// ADL Function to get the number of adapters + /// return number of adapters + /// retrun ADL Error Code + internal delegate int ADL_Adapter_NumberOfAdapters_Get (ref int numAdapters); + + /// ADL Function to get the GPU adapter information + /// return GPU adapter information + /// the size of the GPU adapter struct + /// retrun ADL Error Code + internal delegate int ADL_Adapter_AdapterInfo_Get (IntPtr info, int inputSize); + + /// Function to determine if the adapter is active or not. + /// The function is used to check if the adapter associated with iAdapterIndex is active + /// Adapter Index. + /// Status of the adapter. True: Active; False: Dsiabled + /// Non zero is successfull + internal delegate int ADL_Adapter_Active_Get(int adapterIndex, ref int status); + + /// Get display information based on adapter index + /// Adapter Index + /// return the total number of supported displays + /// return ADLDisplayInfo Array for supported displays' information + /// force detect or not + /// return ADL Error Code + internal delegate int ADL_Display_DisplayInfo_Get(int adapterIndex, ref int numDisplays, out IntPtr displayInfoArray, int forceDetect); + + internal delegate int ADL_Display_Size_Get(int adapterIndex, int displayIndex, ref int lpWidth, ref int lpHeight, ref int lpDefaultWidth, ref int lpDefaultHeight, ref int lpMinWidth, ref int lpMinHeight, ref int lpMaxWidth, ref int lpMaxHeight, ref int lpStepWidth, ref int lpStepHeight); + + #endregion Export Delegates + + #region Export Struct + + #region ADLAdapterInfo + /// ADLAdapterInfo Structure + [StructLayout(LayoutKind.Sequential)] + internal struct ADLAdapterInfo + { + /// The size of the structure + int Size; + /// Adapter Index + internal int AdapterIndex; + /// Adapter UDID + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)ADL.ADL_MAX_PATH)] + internal string UDID; + /// Adapter Bus Number + internal int BusNumber; + /// Adapter Driver Number + internal int DriverNumber; + /// Adapter Function Number + internal int FunctionNumber; + /// Adapter Vendor ID + internal int VendorID; + /// Adapter Adapter name + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)ADL.ADL_MAX_PATH)] + internal string AdapterName; + /// Adapter Display name + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)ADL.ADL_MAX_PATH)] + internal string DisplayName; + /// Adapter Present status + internal int Present; + /// Adapter Exist status + internal int Exist; + /// Adapter Driver Path + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)ADL.ADL_MAX_PATH)] + internal string DriverPath; + /// Adapter Driver Ext Path + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)ADL.ADL_MAX_PATH)] + internal string DriverPathExt; + /// Adapter PNP String + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)ADL.ADL_MAX_PATH)] + internal string PNPString; + /// OS Display Index + internal int OSDisplayIndex; + } + + + /// ADLAdapterInfo Array + [StructLayout(LayoutKind.Sequential)] + internal struct ADLAdapterInfoArray + { + /// ADLAdapterInfo Array + [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)ADL.ADL_MAX_ADAPTERS)] + internal ADLAdapterInfo[] ADLAdapterInfo; + } + #endregion ADLAdapterInfo + + + #region ADLDisplayInfo + /// ADLDisplayID Structure + [StructLayout(LayoutKind.Sequential)] + internal struct ADLDisplayID + { + /// Display Logical Index + internal int DisplayLogicalIndex; + /// Display Physical Index + internal int DisplayPhysicalIndex; + /// Adapter Logical Index + internal int DisplayLogicalAdapterIndex; + /// Adapter Physical Index + internal int DisplayPhysicalAdapterIndex; + } + + /// ADLDisplayInfo Structure + [StructLayout(LayoutKind.Sequential)] + internal struct ADLDisplayInfo + { + /// Display Index + internal ADLDisplayID DisplayID; + /// Display Controller Index + internal int DisplayControllerIndex; + /// Display Name + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)ADL.ADL_MAX_PATH)] + internal string DisplayName; + /// Display Manufacturer Name + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = (int)ADL.ADL_MAX_PATH)] + internal string DisplayManufacturerName; + /// Display Type : < The Display type. CRT, TV,CV,DFP are some of display types, + internal int DisplayType; + /// Display output type + internal int DisplayOutputType; + /// Connector type + internal int DisplayConnector; + /// Indicating the display info bits' mask. + internal int DisplayInfoMask; + /// Indicating the display info value. + internal int DisplayInfoValue; + } + #endregion ADLDisplayInfo + + #endregion Export Struct + + #region ADL Class + /// ADL Class + internal static class ADL + { + #region Internal Constant + /// Define the maximum path + internal const int ADL_MAX_PATH = 256; + /// Define the maximum adapters + internal const int ADL_MAX_ADAPTERS = 40 /* 150 */; + /// Define the maximum displays + internal const int ADL_MAX_DISPLAYS = 40 /* 150 */; + /// Define the maximum device name length + internal const int ADL_MAX_DEVICENAME = 32; + /// Define the successful + internal const int ADL_SUCCESS = 0; + /// Define the failure + internal const int ADL_FAIL = -1; + /// Define the driver ok + internal const int ADL_DRIVER_OK = 0; + /// Maximum number of GL-Sync ports on the GL-Sync module + internal const int ADL_MAX_GLSYNC_PORTS = 8; + /// Maximum number of GL-Sync ports on the GL-Sync module + internal const int ADL_MAX_GLSYNC_PORT_LEDS = 8; + /// Maximum number of ADLMOdes for the adapter + internal const int ADL_MAX_NUM_DISPLAYMODES = 1024; + + #endregion Internal Constant + + #region Class ADLImport + /// ADLImport class + private static class ADLImport + { + #region Internal Constant + /// Atiadlxx_FileName + internal const string Atiadlxx_FileName = "atiadlxx.dll"; + /// Kernel32_FileName + internal const string Kernel32_FileName = "kernel32.dll"; + #endregion Internal Constant + + #region DLLImport + [DllImport(Kernel32_FileName)] + internal static extern HMODULE GetModuleHandle (string moduleName); + + [DllImport(Atiadlxx_FileName)] + internal static extern int ADL_Main_Control_Create (ADL_Main_Memory_Alloc callback, int enumConnectedAdapters); + + [DllImport(Atiadlxx_FileName)] + internal static extern int ADL_Main_Control_Destroy (); + + [DllImport(Atiadlxx_FileName)] + internal static extern int ADL_Main_Control_IsFunctionValid (HMODULE module, string procName); + + [DllImport(Atiadlxx_FileName)] + internal static extern FARPROC ADL_Main_Control_GetProcAddress (HMODULE module, string procName); + + [DllImport(Atiadlxx_FileName)] + internal static extern int ADL_Adapter_NumberOfAdapters_Get (ref int numAdapters); + + [DllImport(Atiadlxx_FileName)] + internal static extern int ADL_Adapter_AdapterInfo_Get (IntPtr info, int inputSize); + + [DllImport(Atiadlxx_FileName)] + internal static extern int ADL_Adapter_Active_Get(int adapterIndex, ref int status); + + [DllImport(Atiadlxx_FileName)] + internal static extern int ADL_Display_DisplayInfo_Get(int adapterIndex, ref int numDisplays, out IntPtr displayInfoArray, int forceDetect); + + [DllImport(Atiadlxx_FileName)] + internal static extern int ADL_Display_Size_Get(int iAdapterIndex, int iDisplayIndex, ref int lpWidth, ref int lpHeight, ref int lpDefaultWidth, ref int lpDefaultHeight, ref int lpMinWidth, ref int lpMinHeight, ref int lpMaxWidth, ref int lpMaxHeight, ref int lpStepWidth, ref int lpStepHeight); + + #endregion DLLImport + } + #endregion Class ADLImport + + #region Class ADLCheckLibrary + /// ADLCheckLibrary class + private class ADLCheckLibrary + { + #region Private Members + private HMODULE ADLLibrary = System.IntPtr.Zero; + #endregion Private Members + + #region Static Members + /// new a private instance + private static ADLCheckLibrary ADLCheckLibrary_ = new ADLCheckLibrary(); + #endregion Static Members + + #region Constructor + /// Constructor + private ADLCheckLibrary () + { + try + { + if (1 == ADLImport.ADL_Main_Control_IsFunctionValid(IntPtr.Zero, "ADL_Main_Control_Create")) + { + ADLLibrary = ADLImport.GetModuleHandle(ADLImport.Atiadlxx_FileName); + } + } + catch (DllNotFoundException) { } + catch (EntryPointNotFoundException) { } + catch (Exception) { } + } + #endregion Constructor + + #region Destructor + /// Destructor to force calling ADL Destroy function before free up the ADL library + ~ADLCheckLibrary () + { + if (System.IntPtr.Zero != ADLCheckLibrary_.ADLLibrary) + { + ADLImport.ADL_Main_Control_Destroy(); + } + } + #endregion Destructor + + #region Static IsFunctionValid + /// Check the import function to see it exists or not + /// function name + /// return true, if function exists + internal static bool IsFunctionValid (string functionName) + { + bool result = false; + if (System.IntPtr.Zero != ADLCheckLibrary_.ADLLibrary) + { + if (1 == ADLImport.ADL_Main_Control_IsFunctionValid(ADLCheckLibrary_.ADLLibrary, functionName)) + { + result = true; + } + } + return result; + } + #endregion Static IsFunctionValid + + #region Static GetProcAddress + /// Get the unmanaged function pointer + /// function name + /// return function pointer, if function exists + internal static FARPROC GetProcAddress (string functionName) + { + FARPROC result = System.IntPtr.Zero; + if (System.IntPtr.Zero != ADLCheckLibrary_.ADLLibrary) + { + result = ADLImport.ADL_Main_Control_GetProcAddress(ADLCheckLibrary_.ADLLibrary, functionName); + } + return result; + } + #endregion Static GetProcAddress + } + #endregion Class ADLCheckLibrary + + #region Export Functions + + #region ADL_Main_Memory_Alloc + /// Build in memory allocation function + internal static ADL_Main_Memory_Alloc ADL_Main_Memory_Alloc = ADL_Main_Memory_Alloc_; + /// Build in memory allocation function + /// input size + /// return the memory buffer + private static IntPtr ADL_Main_Memory_Alloc_ (int size) + { + IntPtr result = Marshal.AllocCoTaskMem(size); + return result; + } + #endregion ADL_Main_Memory_Alloc + + #region ADL_Main_Memory_Free + /// Build in memory free function + /// input buffer + internal static void ADL_Main_Memory_Free (IntPtr buffer) + { + if (IntPtr.Zero != buffer) + { + Marshal.FreeCoTaskMem(buffer); + } + } + #endregion ADL_Main_Memory_Free + + #region ADL_Main_Control_Create + /// ADL_Main_Control_Create Delegates + internal static ADL_Main_Control_Create ADL_Main_Control_Create + { + get + { + if (!ADL_Main_Control_Create_Check && null == ADL_Main_Control_Create_) + { + ADL_Main_Control_Create_Check = true; + if (ADLCheckLibrary.IsFunctionValid("ADL_Main_Control_Create")) + { + ADL_Main_Control_Create_ = ADLImport.ADL_Main_Control_Create; + } + } + return ADL_Main_Control_Create_; + } + } + /// Private Delegate + private static ADL_Main_Control_Create ADL_Main_Control_Create_ = null; + /// check flag to indicate the delegate has been checked + private static bool ADL_Main_Control_Create_Check = false; + #endregion ADL_Main_Control_Create + + #region ADL_Main_Control_Destroy + /// ADL_Main_Control_Destroy Delegates + internal static ADL_Main_Control_Destroy ADL_Main_Control_Destroy + { + get + { + if (!ADL_Main_Control_Destroy_Check && null == ADL_Main_Control_Destroy_) + { + ADL_Main_Control_Destroy_Check = true; + if (ADLCheckLibrary.IsFunctionValid("ADL_Main_Control_Destroy")) + { + ADL_Main_Control_Destroy_ = ADLImport.ADL_Main_Control_Destroy; + } + } + return ADL_Main_Control_Destroy_; + } + } + /// Private Delegate + private static ADL_Main_Control_Destroy ADL_Main_Control_Destroy_ = null; + /// check flag to indicate the delegate has been checked + private static bool ADL_Main_Control_Destroy_Check = false; + #endregion ADL_Main_Control_Destroy + + #region ADL_Adapter_NumberOfAdapters_Get + /// ADL_Adapter_NumberOfAdapters_Get Delegates + internal static ADL_Adapter_NumberOfAdapters_Get ADL_Adapter_NumberOfAdapters_Get + { + get + { + if (!ADL_Adapter_NumberOfAdapters_Get_Check && null == ADL_Adapter_NumberOfAdapters_Get_) + { + ADL_Adapter_NumberOfAdapters_Get_Check = true; + if (ADLCheckLibrary.IsFunctionValid("ADL_Adapter_NumberOfAdapters_Get")) + { + ADL_Adapter_NumberOfAdapters_Get_ = ADLImport.ADL_Adapter_NumberOfAdapters_Get; + } + } + return ADL_Adapter_NumberOfAdapters_Get_; + } + } + /// Private Delegate + private static ADL_Adapter_NumberOfAdapters_Get ADL_Adapter_NumberOfAdapters_Get_ = null; + /// check flag to indicate the delegate has been checked + private static bool ADL_Adapter_NumberOfAdapters_Get_Check = false; + #endregion ADL_Adapter_NumberOfAdapters_Get + + #region ADL_Adapter_AdapterInfo_Get + /// ADL_Adapter_AdapterInfo_Get Delegates + internal static ADL_Adapter_AdapterInfo_Get ADL_Adapter_AdapterInfo_Get + { + get + { + if (!ADL_Adapter_AdapterInfo_Get_Check && null == ADL_Adapter_AdapterInfo_Get_) + { + ADL_Adapter_AdapterInfo_Get_Check = true; + if (ADLCheckLibrary.IsFunctionValid("ADL_Adapter_AdapterInfo_Get")) + { + ADL_Adapter_AdapterInfo_Get_ = ADLImport.ADL_Adapter_AdapterInfo_Get; + } + } + return ADL_Adapter_AdapterInfo_Get_; + } + } + /// Private Delegate + private static ADL_Adapter_AdapterInfo_Get ADL_Adapter_AdapterInfo_Get_ = null; + /// check flag to indicate the delegate has been checked + private static bool ADL_Adapter_AdapterInfo_Get_Check = false; + #endregion ADL_Adapter_AdapterInfo_Get + + #region ADL_Adapter_Active_Get + /// ADL_Adapter_Active_Get Delegates + internal static ADL_Adapter_Active_Get ADL_Adapter_Active_Get + { + get + { + if (!ADL_Adapter_Active_Get_Check && null == ADL_Adapter_Active_Get_) + { + ADL_Adapter_Active_Get_Check = true; + if (ADLCheckLibrary.IsFunctionValid("ADL_Adapter_Active_Get")) + { + ADL_Adapter_Active_Get_ = ADLImport.ADL_Adapter_Active_Get; + } + } + return ADL_Adapter_Active_Get_; + } + } + /// Private Delegate + private static ADL_Adapter_Active_Get ADL_Adapter_Active_Get_ = null; + /// check flag to indicate the delegate has been checked + private static bool ADL_Adapter_Active_Get_Check = false; + #endregion ADL_Adapter_Active_Get + + #region ADL_Display_DisplayInfo_Get + /// ADL_Display_DisplayInfo_Get Delegates + internal static ADL_Display_DisplayInfo_Get ADL_Display_DisplayInfo_Get + { + get + { + if (!ADL_Display_DisplayInfo_Get_Check && null == ADL_Display_DisplayInfo_Get_) + { + ADL_Display_DisplayInfo_Get_Check = true; + if (ADLCheckLibrary.IsFunctionValid("ADL_Display_DisplayInfo_Get")) + { + ADL_Display_DisplayInfo_Get_ = ADLImport.ADL_Display_DisplayInfo_Get; + } + } + return ADL_Display_DisplayInfo_Get_; + } + } + /// Private Delegate + private static ADL_Display_DisplayInfo_Get ADL_Display_DisplayInfo_Get_ = null; + /// check flag to indicate the delegate has been checked + private static bool ADL_Display_DisplayInfo_Get_Check = false; + #endregion ADL_Display_DisplayInfo_Get + + #region ADL_Display_Size_Get + /// ADL_Display_Size_Get Delegates + internal static ADL_Display_Size_Get ADL_Display_Size_Get + { + get + { + if (!ADL_Display_Size_Get_Check && null == ADL_Display_Size_Get) + { + ADL_Display_Size_Get_Check = true; + if (ADLCheckLibrary.IsFunctionValid("ADL_Display_Size_Get")) + { + ADL_Display_Size_Get_ = ADLImport.ADL_Display_Size_Get; + } + } + return ADL_Display_Size_Get_; + } + } + /// Private Delegate + private static ADL_Display_Size_Get ADL_Display_Size_Get_ = null; + /// check flag to indicate the delegate has been checked + private static bool ADL_Display_Size_Get_Check = false; + #endregion ADL_Display_Size_Get + + #endregion Export Functions + } + #endregion ADL Class +} + +#endregion ATI.ADL \ No newline at end of file diff --git a/ColorControl/ADLWrapper.cs b/ColorControl/ADLWrapper.cs new file mode 100644 index 0000000..61e7652 --- /dev/null +++ b/ColorControl/ADLWrapper.cs @@ -0,0 +1,172 @@ +using ATI.ADL; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace ColorControl +{ + class ADLWrapper + { + public static bool Initialize() + { + int ADLRet = -1; + + if (null != ADL.ADL_Main_Control_Create) + { + // Second parameter is 1: Get only the present adapters + ADLRet = ADL.ADL_Main_Control_Create(ADL.ADL_Main_Memory_Alloc, 1); + } + return (ADL.ADL_SUCCESS == ADLRet); + } + + public static void Uninitialze() + { + if (null != ADL.ADL_Main_Control_Destroy) + { + ADL.ADL_Main_Control_Destroy(); + } + } + + public static ADLAdapterInfoArray? GetAdapters() + { + int ADLRet = -1; + int NumberOfAdapters = 0; + + if (null != ADL.ADL_Adapter_NumberOfAdapters_Get) + { + ADL.ADL_Adapter_NumberOfAdapters_Get(ref NumberOfAdapters); + } + Console.WriteLine("Number Of Adapters: " + NumberOfAdapters.ToString() + "\n"); + + if (NumberOfAdapters > 0) + { + // Get OS adpater info from ADL + ADLAdapterInfoArray OSAdapterInfoData; + OSAdapterInfoData = new ADLAdapterInfoArray(); + + if (null != ADL.ADL_Adapter_AdapterInfo_Get) + { + IntPtr AdapterBuffer = IntPtr.Zero; + int size = Marshal.SizeOf(OSAdapterInfoData); + AdapterBuffer = Marshal.AllocCoTaskMem((int)size); + Marshal.StructureToPtr(OSAdapterInfoData, AdapterBuffer, false); + + if (null != ADL.ADL_Adapter_AdapterInfo_Get) + { + ADLRet = ADL.ADL_Adapter_AdapterInfo_Get(AdapterBuffer, size); + if (ADL.ADL_SUCCESS == ADLRet) + { + OSAdapterInfoData = (ADLAdapterInfoArray)Marshal.PtrToStructure(AdapterBuffer, OSAdapterInfoData.GetType()); + int IsActive = 0; + + for (int i = 0; i < NumberOfAdapters; i++) + { + // Check if the adapter is active + if (null != ADL.ADL_Adapter_Active_Get) + ADLRet = ADL.ADL_Adapter_Active_Get(OSAdapterInfoData.ADLAdapterInfo[i].AdapterIndex, ref IsActive); + + if (ADL.ADL_SUCCESS == ADLRet) + { + + } + } + } + else + { + Console.WriteLine("ADL_Adapter_AdapterInfo_Get() returned error code " + ADLRet.ToString()); + } + } + // Release the memory for the AdapterInfo structure + if (IntPtr.Zero != AdapterBuffer) + { + Marshal.FreeCoTaskMem(AdapterBuffer); + } + } + return OSAdapterInfoData; + } + return null; + } + + public static List GetAllDisplays() + { + int ADLRet; + int NumberOfDisplays = 0; + + var DisplayInfoData = new List(); + + var OSAdapterInfoData = GetAdapters(); + if (OSAdapterInfoData == null || !OSAdapterInfoData.Value.ADLAdapterInfo.Any()) + { + return DisplayInfoData; + } + var primaryAdapter = OSAdapterInfoData.Value.ADLAdapterInfo.First(); + + ADLDisplayInfo oneDisplayInfo = new ADLDisplayInfo(); + + if (null != ADL.ADL_Display_DisplayInfo_Get) + { + IntPtr DisplayBuffer = IntPtr.Zero; + int j = 0; + + // Force the display detection and get the Display Info. Use 0 as last parameter to NOT force detection + ADLRet = ADL.ADL_Display_DisplayInfo_Get(primaryAdapter.AdapterIndex, ref NumberOfDisplays, out DisplayBuffer, 1); + if (ADL.ADL_SUCCESS == ADLRet) + { + for (j = 0; j < NumberOfDisplays; j++) + { + oneDisplayInfo = (ADLDisplayInfo)Marshal.PtrToStructure(new IntPtr(DisplayBuffer.ToInt32() + j * Marshal.SizeOf(oneDisplayInfo)), oneDisplayInfo.GetType()); + DisplayInfoData.Add(oneDisplayInfo); + } + Console.WriteLine("\nTotal Number of Displays supported: " + NumberOfDisplays.ToString()); + Console.WriteLine("\nDispID AdpID Type OutType CnctType Connected Mapped InfoValue DisplayName "); + + for (j = 0; j < NumberOfDisplays; j++) + { + int InfoValue = DisplayInfoData[j].DisplayInfoValue; + string StrConnected = (1 == (InfoValue & 1)) ? "Yes" : "No "; + string StrMapped = (2 == (InfoValue & 2)) ? "Yes" : "No "; + int AdpID = DisplayInfoData[j].DisplayID.DisplayLogicalAdapterIndex; + string StrAdpID = (AdpID < 0) ? "--" : AdpID.ToString("d2"); + + Console.WriteLine(DisplayInfoData[j].DisplayID.DisplayLogicalIndex.ToString() + " " + + StrAdpID + " " + + DisplayInfoData[j].DisplayType.ToString() + " " + + DisplayInfoData[j].DisplayOutputType.ToString() + " " + + DisplayInfoData[j].DisplayConnector.ToString() + " " + + StrConnected + " " + + StrMapped + " " + + InfoValue.ToString("x4") + " " + + DisplayInfoData[j].DisplayName.ToString()); + } + Console.WriteLine(); + } + else + { + Console.WriteLine("ADL_Display_DisplayInfo_Get() returned error code " + ADLRet.ToString()); + } + // Release the memory for the DisplayInfo structure + if (IntPtr.Zero != DisplayBuffer) + Marshal.FreeCoTaskMem(DisplayBuffer); + } + return DisplayInfoData; + } + + public static bool GetDisplayResolution(string displayName, ref int horizontal, ref int vertical) + { + var displays = GetAllDisplays(); + var display = displays.FirstOrDefault(d => d.DisplayName.Equals(displayName, StringComparison.OrdinalIgnoreCase)); + if (display.DisplayID.DisplayPhysicalIndex >= 0 && ADL.ADL_Display_Size_Get != null) + { + int lpDefaultWidth, lpDefaultHeight, lpMinWidth, lpMinHeight, lpMaxWidth, lpMaxHeight, lpStepWidth, lpStepHeight; + lpDefaultWidth = lpDefaultHeight = lpMinWidth = lpMinHeight = lpMaxWidth = lpMaxHeight = lpStepWidth = lpStepHeight = 0; + var ADLRet = ADL.ADL_Display_Size_Get(display.DisplayID.DisplayPhysicalAdapterIndex, display.DisplayID.DisplayPhysicalIndex, ref horizontal, ref vertical, ref lpDefaultWidth, ref lpDefaultHeight, ref lpMinWidth, ref lpMinHeight, ref lpMaxWidth, ref lpMaxHeight, ref lpStepWidth, ref lpStepHeight); + + return ADLRet == ADL.ADL_SUCCESS; + } + return false; + } + } +} diff --git a/ColorControl/AmdPreset.cs b/ColorControl/AmdPreset.cs new file mode 100644 index 0000000..3459c0c --- /dev/null +++ b/ColorControl/AmdPreset.cs @@ -0,0 +1,186 @@ +using NvAPIWrapper.Display; +using NvAPIWrapper.Native.Display; +using System; +using System.Collections.Generic; +using System.Text; + +namespace ColorControl +{ + class AmdPreset : PresetBase + { + public bool applyColorData { get; set; } + public ColorData colorData { get; set; } + public bool applyHDR { get; set; } + public bool HDREnabled { get; set; } + public bool toggleHDR { get; set; } + public bool applyDithering { get; set; } + public bool ditheringEnabled { get; set; } + public bool applyRefreshRate { get; set; } + public uint refreshRate { get; set; } + public bool primaryDisplay { get; set; } + public string displayName { get; set; } + + public AmdPreset() + { + applyColorData = true; + applyDithering = false; + ditheringEnabled = true; + applyHDR = false; + HDREnabled = false; + toggleHDR = false; + applyRefreshRate = false; + refreshRate = 60; + primaryDisplay = true; + } + + public AmdPreset(ColorData colorData) : this() + { + id = GetNewId(); + this.colorData = colorData; + } + + public AmdPreset(AmdPreset preset): this() + { + id = GetNewId(); + + primaryDisplay = preset.primaryDisplay; + displayName = preset.displayName; + + var colorData = preset.colorData; + this.colorData = new ColorData(colorData.ColorFormat, dynamicRange: colorData.DynamicRange, colorDepth: colorData.ColorDepth, colorSelectionPolicy: colorData.SelectionPolicy); + applyColorData = preset.applyColorData; + + applyHDR = preset.applyHDR; + HDREnabled = preset.HDREnabled; + toggleHDR = preset.toggleHDR; + applyDithering = preset.applyDithering; + ditheringEnabled = preset.ditheringEnabled; + applyRefreshRate = preset.applyRefreshRate; + refreshRate = preset.refreshRate; + } + + public AmdPreset Clone() + { + var preset = new AmdPreset(this); + + return preset; + } + + public static string[] GetColumnNames() + { + //return new[] { "BPC", "Format", "Dynamic range", "Toggle HDR", "Shortcut" }; + return new[] { "Display|140", "Color settings (BPC, format, dyn. range, color space)|260", "Refresh rate|100", "Dithering", "HDR", "Shortcut" }; + } + + public List GetDisplayValues() + { + var values = new List(); + + var display = 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); + + values.Add(colorSettings); + values.Add(string.Format("{0}: {1}Hz", applyRefreshRate ? "Included" : "Excluded", refreshRate)); + values.Add(string.Format("{0}: {1}", applyDithering ? "Included" : "Excluded", ditheringEnabled ? "Enabled" : "Disabled")); + values.Add(string.Format("{0}: {1}", applyHDR ? "Included" : "Excluded", toggleHDR ? "Toggle" : HDREnabled ? "Enabled" : "Disabled")); + + //values.Add(colorData.ColorDepth.ToString()); + //values.Add(colorData.ColorFormat.ToString()); + //values.Add(colorData.DynamicRange.ToString()); + //values.Add(toggleHDR.ToString()); + values.Add(shortcut); + + return values; + } + + public static List GetDefaultPresets() + { + var presets = new List(); + + presets.Add(new AmdPreset(new ColorData(ColorDataFormat.Auto, dynamicRange: ColorDataDynamicRange.Auto, colorDepth: ColorDataDepth.Default, colorSelectionPolicy: ColorDataSelectionPolicy.BestQuality))); + + for (var dynamicRange = ColorDataDynamicRange.VESA; dynamicRange <= ColorDataDynamicRange.CEA; dynamicRange++) + { + presets.Add(new AmdPreset(new ColorData(ColorDataFormat.RGB, dynamicRange: dynamicRange, colorDepth: ColorDataDepth.BPC8, colorSelectionPolicy: ColorDataSelectionPolicy.User))); + presets.Add(new AmdPreset(new ColorData(ColorDataFormat.RGB, dynamicRange: dynamicRange, colorDepth: ColorDataDepth.BPC10, colorSelectionPolicy: ColorDataSelectionPolicy.User))); + presets.Add(new AmdPreset(new ColorData(ColorDataFormat.RGB, dynamicRange: dynamicRange, colorDepth: ColorDataDepth.BPC12, colorSelectionPolicy: ColorDataSelectionPolicy.User))); + } + + for (var format = ColorDataFormat.YUV422; format <= ColorDataFormat.YUV420; format++) + { + presets.Add(new AmdPreset(new ColorData(format, dynamicRange: ColorDataDynamicRange.Auto, colorDepth: ColorDataDepth.BPC8, colorSelectionPolicy: ColorDataSelectionPolicy.User))); + presets.Add(new AmdPreset(new ColorData(format, dynamicRange: ColorDataDynamicRange.Auto, colorDepth: ColorDataDepth.BPC10, colorSelectionPolicy: ColorDataSelectionPolicy.User))); + presets.Add(new AmdPreset(new ColorData(format, dynamicRange: ColorDataDynamicRange.Auto, colorDepth: ColorDataDepth.BPC12, colorSelectionPolicy: ColorDataSelectionPolicy.User))); + } + + return presets; + } + + public string GetTextForMenuItem() + { + var sb = new StringBuilder(); + if (displayName != null) + { + sb.AppendFormat("Display: {0} / ", displayName); + } + if (applyColorData) + { + var colorSettings = string.Format("Format: {0}, {1}, {2}", colorData.ColorDepth, colorData.ColorFormat, colorData.DynamicRange); + sb.Append(colorSettings); + sb.Append(" / "); + } + if (applyRefreshRate) + { + sb.AppendFormat("{0}Hz", refreshRate); + sb.Append(" / "); + } + if (applyDithering) + { + sb.AppendFormat("Dithering: {0}", ditheringEnabled ? "Yes" : "No"); + sb.Append(" / "); + } + if (applyHDR) + { + sb.AppendFormat("HDR: {0}", toggleHDR ? "Toggle" : HDREnabled ? "Enabled" : "Disabled"); + sb.Append(" / "); + } + + return sb.ToString(0, Math.Max(0, sb.Length - 3)); + } + + public static ColorData GenerateColorData(IDictionary dictionary) + { + var format = ColorDataFormat.RGB; + var dynamicRange = ColorDataDynamicRange.VESA; + var colorDepth = ColorDataDepth.BPC8; + var colorimetry = ColorDataColorimetry.Auto; + var selectionPolicy = ColorDataSelectionPolicy.User; + object value; + if (dictionary.TryGetValue("ColorFormat", out value)) + { + format = (ColorDataFormat)Enum.ToObject(typeof(ColorDataFormat), value); + } + if (dictionary.TryGetValue("ColorDepth", out value)) + { + colorDepth = (ColorDataDepth)Enum.ToObject(typeof(ColorDataDepth), value); + } + if (dictionary.TryGetValue("Colorimetry", out value)) + { + colorimetry = (ColorDataColorimetry)Enum.ToObject(typeof(ColorDataColorimetry), value); + } + if (dictionary.TryGetValue("DynamicRange", out value)) + { + dynamicRange = (ColorDataDynamicRange)Enum.ToObject(typeof(ColorDataDynamicRange), value); + } + if (dictionary.TryGetValue("SelectionPolicy", out value)) + { + selectionPolicy = (ColorDataSelectionPolicy)Enum.ToObject(typeof(ColorDataSelectionPolicy), value); + } + return new ColorData(format, dynamicRange: dynamicRange, colorimetry: colorimetry, colorDepth: colorDepth, colorSelectionPolicy: selectionPolicy); + } + + } +} + diff --git a/ColorControl/AmdService.cs b/ColorControl/AmdService.cs new file mode 100644 index 0000000..906e6fe --- /dev/null +++ b/ColorControl/AmdService.cs @@ -0,0 +1,133 @@ +using ATI.ADL; +using NvAPIWrapper.Display; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; + +namespace ColorControl +{ + class AmdService : GraphicsService + { + private string CurrentDisplay; + + public AmdService() + { + } + + public void SetCurrentDisplay(AmdPreset preset) + { + CurrentDisplay = preset.displayName; + } + + public string GetCurrentDisplay() + { + return CurrentDisplay; + } + + public bool ApplyPreset(AmdPreset preset, Config config) + { + SetCurrentDisplay(preset); + + if (preset.applyHDR) + { + if (preset.toggleHDR || preset.HDREnabled != IsHDREnabled()) + { + ToggleHDR(config.DisplaySettingsDelay); + } + } + + if (preset.applyRefreshRate) + { + SetRefreshRate(preset.refreshRate); + } + + if (preset.applyColorData) + { + var display = GetCurrentDisplay(); + // TODO: ADL call to set color format, depth, space + // ADL_Display_PixelFormat_Set + // ADL_Display_ColorDepth_Set + + //var data = new ColorData(ColorDataFormat.YUV444, ColorDataColorimetry.YCC709, ColorDataDynamicRange.Auto, ColorDataDepth.BPC8, preset.colorData.SelectionPolicy, ColorDataDesktopDepth.Default); + //display.DisplayDevice.SetColorData(preset.colorData); + } + + if (preset.applyDithering) + { + SetDithering(preset.ditheringEnabled); + } + + return true; + } + + public void SetDithering(bool enabled) + { + // TODO: ADL call to set dithering state + // ADL_Display_DitherState_Get + } + + public bool GetDithering() + { + // TODO: ADL call to get dithering state + // ADL_Display_DitherState_Set + return false; + } + + public bool SetRefreshRate(uint refreshRate) + { + var portrait = false; + var horizontal = 3840; + var vertical = 2160; + var display = GetCurrentDisplay(); + + ADLWrapper.GetDisplayResolution(display, ref horizontal, ref vertical); + + return SetRefreshRateInternal(display, refreshRate, portrait, horizontal, vertical); + } + + public List GetAvailableRefreshRates(AmdPreset preset = null) + { + if (preset != null) + { + SetCurrentDisplay(preset); + } + + var portrait = false; + var horizontal = 3840; + var vertical = 2160; + var display = GetCurrentDisplay(); + + ADLWrapper.GetDisplayResolution(display, ref horizontal, ref vertical); + + return GetAvailableRefreshRatesInternal(display, portrait, horizontal, vertical); + } + + public bool IsHDREnabled() + { + // TODO: ADL call to get HDR state + //var displayDevice = GetCurrentDisplay().DisplayDevice; + //var hdr = displayDevice.HDRColorData; + //return hdr?.HDRMode == ColorDataHDRMode.UHDA; + return false; + } + + public List GetDisplays() + { + return ADLWrapper.GetAllDisplays(); + } + + protected override void Initialize() + { + if (!ADLWrapper.Initialize()) + { + throw new InvalidOperationException("Cannot load AMD API"); + } + } + + protected override void Uninitialize() + { + ADLWrapper.Uninitialze(); + } + } +} diff --git a/ColorControl/ColorControl.csproj b/ColorControl/ColorControl.csproj index df4d882..2852b58 100644 --- a/ColorControl/ColorControl.csproj +++ b/ColorControl/ColorControl.csproj @@ -27,7 +27,7 @@ ColorControl Maassoft 0 - 1.2.0.0 + 1.3.0.0 false true true @@ -172,6 +172,11 @@ + + + + + diff --git a/ColorControl/GraphicsService.cs b/ColorControl/GraphicsService.cs new file mode 100644 index 0000000..0c73b12 --- /dev/null +++ b/ColorControl/GraphicsService.cs @@ -0,0 +1,97 @@ +using NWin32; +using NWin32.NativeTypes; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading; + +namespace ColorControl +{ + class GraphicsService + { + protected static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); + + public GraphicsService() + { + Initialize(); + } + + ~GraphicsService() + { + Uninitialize(); + } + + protected virtual void Initialize() + { + + } + + protected virtual void Uninitialize() + { + + } + + protected void ToggleHDR(int delay = 1000) + { + Process.Start("ms-settings:display"); + Thread.Sleep(delay); + + var process = Process.GetProcessesByName("SystemSettings").FirstOrDefault(); + if (process != null) + { + System.Windows.Forms.SendKeys.SendWait("{TAB}"); + System.Windows.Forms.SendKeys.SendWait("{TAB}"); + System.Windows.Forms.SendKeys.SendWait(" "); + System.Windows.Forms.SendKeys.SendWait("%{F4}"); + } + } + + protected bool SetRefreshRateInternal(string displayName, uint refreshRate, bool portrait, int horizontal, int vertical) + { + uint i = 0; + DEVMODEA devMode; + while (NativeMethods.EnumDisplaySettingsA(displayName, i, out devMode)) + { + // Also compare width with vertical and height with horizontal in case of portrait mode + if (((!portrait && devMode.dmPelsWidth == horizontal && devMode.dmPelsHeight == vertical) || + (portrait && devMode.dmPelsWidth == vertical && devMode.dmPelsHeight == horizontal)) + && devMode.dmBitsPerPel == 32 && devMode.dmDisplayFrequency == refreshRate) + { + IntPtr bla = Marshal.AllocHGlobal(Marshal.SizeOf(devMode)); + Marshal.StructureToPtr(devMode, bla, false); + var result = NativeMethods.ChangeDisplaySettingsExA(displayName, bla, IntPtr.Zero, 0, IntPtr.Zero); + if (result != NativeConstants.DISP_CHANGE_SUCCESSFUL) + { + Logger.Error($"Could not set refreshrate {refreshRate} on display {displayName} because ChangeDisplaySettingsExA returned a non-zero return code: {result}"); + } + return result == NativeConstants.DISP_CHANGE_SUCCESSFUL; + } + i++; + } + Logger.Info($"Could not set refreshrate {refreshRate} on display {displayName} because EnumDisplaySettings did not report it as a valid refreshrate"); + + return false; + } + + protected List GetAvailableRefreshRatesInternal(string displayName, bool portrait, int horizontal, int vertical) + { + var list = new List(); + + uint i = 0; + DEVMODEA devMode; + while (NativeMethods.EnumDisplaySettingsA(displayName, i, out devMode)) + { + if ((!portrait && devMode.dmPelsWidth == horizontal && devMode.dmPelsHeight == vertical) || + (portrait && devMode.dmPelsWidth == vertical && devMode.dmPelsHeight == horizontal)) + { + list.Add(devMode.dmDisplayFrequency); + } + i++; + } + return list; + } + + } +} diff --git a/ColorControl/LgService.cs b/ColorControl/LgService.cs index f5e2afc..4761325 100644 --- a/ColorControl/LgService.cs +++ b/ColorControl/LgService.cs @@ -16,7 +16,6 @@ namespace ColorControl { class LgService { - public static string LgControllerExe = "LgController.exe"; public static string LgListAppsJson = "listApps.json"; public static string LgDeviceSearchKey = "[LG]"; @@ -26,7 +25,15 @@ namespace ColorControl public string FriendlyScreenName { get; private set; } public List Devices { get; private set; } - public PnpDev SelectedDevice { get; set; } + public PnpDev SelectedDevice + { + get { return _selectedDevice; } + set + { + _selectedDevice = value; + Config.PreferredMacAddress = _selectedDevice != null ? _selectedDevice.MacAddress : null; + } + } public LgServiceConfig Config { get; private set; } @@ -35,6 +42,7 @@ namespace ColorControl private string _configFilename; private bool _allowPowerOn; private bool _justWokeUp; + private PnpDev _selectedDevice; public LgService(string dataDir, bool allowPowerOn) { @@ -104,7 +112,9 @@ namespace ColorControl Devices = task.Result; if (Devices?.Count > 0) { - SelectedDevice = Devices[0]; + var preferredDevice = Devices.FirstOrDefault(x => x.MacAddress.Equals(Config.PreferredMacAddress)) ?? Devices[0]; + + SelectedDevice = preferredDevice; } } diff --git a/ColorControl/LgServiceConfig.cs b/ColorControl/LgServiceConfig.cs index 833c4f5..9433524 100644 --- a/ColorControl/LgServiceConfig.cs +++ b/ColorControl/LgServiceConfig.cs @@ -12,6 +12,8 @@ public int PowerOnDelayAfterResume { get; set; } + public string PreferredMacAddress { get; set; } + public LgServiceConfig() { PowerOnDelayAfterResume = 5000; diff --git a/ColorControl/MainForm.Designer.cs b/ColorControl/MainForm.Designer.cs index c0c7df1..1e1e4d6 100644 --- a/ColorControl/MainForm.Designer.cs +++ b/ColorControl/MainForm.Designer.cs @@ -58,6 +58,8 @@ this.miHDREnabled = new System.Windows.Forms.ToolStripMenuItem(); this.btnApply = new System.Windows.Forms.Button(); this.lvNvPresets = new System.Windows.Forms.ListView(); + this.tabAMD = new System.Windows.Forms.TabPage(); + this.lblErrorAMD = new System.Windows.Forms.Label(); this.tabLG = new System.Windows.Forms.TabPage(); this.clbLgPower = new System.Windows.Forms.CheckedListBox(); this.btnLgAddButton = new System.Windows.Forms.Button(); @@ -111,9 +113,11 @@ this.lbPlugins = new System.Windows.Forms.ListBox(); this.label7 = new System.Windows.Forms.Label(); this.lblInfo = new System.Windows.Forms.Label(); + this.btnClearLog = new System.Windows.Forms.Button(); this.tcMain.SuspendLayout(); this.tabNVIDIA.SuspendLayout(); this.mnuNvPresets.SuspendLayout(); + this.tabAMD.SuspendLayout(); this.tabLG.SuspendLayout(); this.tabOptions.SuspendLayout(); this.grpMiscellaneousOptions.SuspendLayout(); @@ -134,6 +138,7 @@ | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.tcMain.Controls.Add(this.tabNVIDIA); + this.tcMain.Controls.Add(this.tabAMD); this.tcMain.Controls.Add(this.tabLG); this.tcMain.Controls.Add(this.tabOptions); this.tcMain.Controls.Add(this.tabLog); @@ -141,8 +146,8 @@ this.tcMain.Location = new System.Drawing.Point(12, 12); this.tcMain.Name = "tcMain"; this.tcMain.SelectedIndex = 0; - this.tcMain.Size = new System.Drawing.Size(849, 532); - this.tcMain.TabIndex = 3; + this.tcMain.Size = new System.Drawing.Size(849, 472); + this.tcMain.TabIndex = 1; this.tcMain.SelectedIndexChanged += new System.EventHandler(this.tabControl1_SelectedIndexChanged); // // tabNVIDIA @@ -160,7 +165,7 @@ this.tabNVIDIA.Location = new System.Drawing.Point(4, 22); this.tabNVIDIA.Name = "tabNVIDIA"; this.tabNVIDIA.Padding = new System.Windows.Forms.Padding(3); - this.tabNVIDIA.Size = new System.Drawing.Size(841, 506); + this.tabNVIDIA.Size = new System.Drawing.Size(841, 446); this.tabNVIDIA.TabIndex = 0; this.tabNVIDIA.Text = "NVIDIA controller"; this.tabNVIDIA.UseVisualStyleBackColor = true; @@ -168,7 +173,7 @@ // btnAddModesNv // this.btnAddModesNv.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.btnAddModesNv.Location = new System.Drawing.Point(574, 477); + this.btnAddModesNv.Location = new System.Drawing.Point(574, 417); this.btnAddModesNv.Name = "btnAddModesNv"; this.btnAddModesNv.Size = new System.Drawing.Size(75, 23); this.btnAddModesNv.TabIndex = 9; @@ -180,7 +185,7 @@ // this.btnNvPresetDelete.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.btnNvPresetDelete.Enabled = false; - this.btnNvPresetDelete.Location = new System.Drawing.Point(493, 477); + this.btnNvPresetDelete.Location = new System.Drawing.Point(493, 417); this.btnNvPresetDelete.Name = "btnNvPresetDelete"; this.btnNvPresetDelete.Size = new System.Drawing.Size(75, 23); this.btnNvPresetDelete.TabIndex = 8; @@ -202,7 +207,7 @@ // this.btnClone.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.btnClone.Enabled = false; - this.btnClone.Location = new System.Drawing.Point(412, 477); + this.btnClone.Location = new System.Drawing.Point(412, 417); this.btnClone.Name = "btnClone"; this.btnClone.Size = new System.Drawing.Size(75, 23); this.btnClone.TabIndex = 6; @@ -214,7 +219,7 @@ // this.btnSetShortcut.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.btnSetShortcut.Enabled = false; - this.btnSetShortcut.Location = new System.Drawing.Point(372, 477); + this.btnSetShortcut.Location = new System.Drawing.Point(372, 417); this.btnSetShortcut.Name = "btnSetShortcut"; this.btnSetShortcut.Size = new System.Drawing.Size(34, 23); this.btnSetShortcut.TabIndex = 5; @@ -226,7 +231,7 @@ // this.lblShortcut.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.lblShortcut.AutoSize = true; - this.lblShortcut.Location = new System.Drawing.Point(168, 482); + this.lblShortcut.Location = new System.Drawing.Point(168, 422); this.lblShortcut.Name = "lblShortcut"; this.lblShortcut.Size = new System.Drawing.Size(50, 13); this.lblShortcut.TabIndex = 4; @@ -236,7 +241,7 @@ // this.edtShortcut.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.edtShortcut.Enabled = false; - this.edtShortcut.Location = new System.Drawing.Point(224, 479); + this.edtShortcut.Location = new System.Drawing.Point(224, 419); this.edtShortcut.Name = "edtShortcut"; this.edtShortcut.ReadOnly = true; this.edtShortcut.Size = new System.Drawing.Size(142, 20); @@ -250,7 +255,7 @@ this.btnChange.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.btnChange.ContextMenuStrip = this.mnuNvPresets; this.btnChange.Enabled = false; - this.btnChange.Location = new System.Drawing.Point(87, 477); + this.btnChange.Location = new System.Drawing.Point(87, 417); this.btnChange.Name = "btnChange"; this.btnChange.Size = new System.Drawing.Size(75, 23); this.btnChange.TabIndex = 2; @@ -388,7 +393,7 @@ // this.btnApply.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.btnApply.Enabled = false; - this.btnApply.Location = new System.Drawing.Point(6, 477); + this.btnApply.Location = new System.Drawing.Point(6, 417); this.btnApply.Name = "btnApply"; this.btnApply.Size = new System.Drawing.Size(75, 23); this.btnApply.TabIndex = 1; @@ -407,13 +412,34 @@ this.lvNvPresets.Location = new System.Drawing.Point(6, 6); this.lvNvPresets.MultiSelect = false; this.lvNvPresets.Name = "lvNvPresets"; - this.lvNvPresets.Size = new System.Drawing.Size(829, 465); + this.lvNvPresets.Size = new System.Drawing.Size(829, 405); this.lvNvPresets.TabIndex = 0; this.lvNvPresets.UseCompatibleStateImageBehavior = false; this.lvNvPresets.View = System.Windows.Forms.View.Details; this.lvNvPresets.SelectedIndexChanged += new System.EventHandler(this.lvNvPresets_SelectedIndexChanged); this.lvNvPresets.DoubleClick += new System.EventHandler(this.lvNvPresets_DoubleClick); // + // tabAMD + // + this.tabAMD.Controls.Add(this.lblErrorAMD); + this.tabAMD.Location = new System.Drawing.Point(4, 22); + this.tabAMD.Name = "tabAMD"; + this.tabAMD.Padding = new System.Windows.Forms.Padding(3); + this.tabAMD.Size = new System.Drawing.Size(841, 446); + this.tabAMD.TabIndex = 5; + this.tabAMD.Text = "AMD controller"; + this.tabAMD.UseVisualStyleBackColor = true; + // + // lblErrorAMD + // + this.lblErrorAMD.AutoSize = true; + this.lblErrorAMD.Location = new System.Drawing.Point(6, 3); + this.lblErrorAMD.Name = "lblErrorAMD"; + this.lblErrorAMD.Size = new System.Drawing.Size(50, 13); + this.lblErrorAMD.TabIndex = 8; + this.lblErrorAMD.Text = "ErrorText"; + this.lblErrorAMD.Visible = false; + // // tabLG // this.tabLG.Controls.Add(this.clbLgPower); @@ -441,7 +467,7 @@ this.tabLG.Location = new System.Drawing.Point(4, 22); this.tabLG.Name = "tabLG"; this.tabLG.Padding = new System.Windows.Forms.Padding(3); - this.tabLG.Size = new System.Drawing.Size(841, 506); + this.tabLG.Size = new System.Drawing.Size(841, 446); this.tabLG.TabIndex = 1; this.tabLG.Text = "LG controller"; this.tabLG.UseVisualStyleBackColor = true; @@ -458,8 +484,8 @@ "Automatically power on after resume from standby. Needs a system dependent delay " + "before waking TV, see Options.", "Automatically power off on shutdown. Because this app cannot detect a restart, re" + - "starting could also trigger this. Hold down SHIFT on restart to prevent power of" + - "f.", + "starting could also trigger this. Hold down Ctrl on restart to prevent power off" + + ".", "Automatically power off on standby"}); this.clbLgPower.Location = new System.Drawing.Point(6, 33); this.clbLgPower.Name = "clbLgPower"; @@ -472,7 +498,7 @@ this.btnLgAddButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.btnLgAddButton.ContextMenuStrip = this.mnuLgButtons; this.btnLgAddButton.Enabled = false; - this.btnLgAddButton.Location = new System.Drawing.Point(760, 460); + this.btnLgAddButton.Location = new System.Drawing.Point(760, 400); this.btnLgAddButton.Name = "btnLgAddButton"; this.btnLgAddButton.Size = new System.Drawing.Size(75, 23); this.btnLgAddButton.TabIndex = 32; @@ -508,7 +534,7 @@ // btnLgRefreshApps // this.btnLgRefreshApps.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.btnLgRefreshApps.Location = new System.Drawing.Point(293, 407); + this.btnLgRefreshApps.Location = new System.Drawing.Point(293, 347); this.btnLgRefreshApps.Name = "btnLgRefreshApps"; this.btnLgRefreshApps.Size = new System.Drawing.Size(75, 23); this.btnLgRefreshApps.TabIndex = 29; @@ -519,7 +545,7 @@ // btnAddLg // this.btnAddLg.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.btnAddLg.Location = new System.Drawing.Point(168, 354); + this.btnAddLg.Location = new System.Drawing.Point(168, 294); this.btnAddLg.Name = "btnAddLg"; this.btnAddLg.Size = new System.Drawing.Size(75, 23); this.btnAddLg.TabIndex = 28; @@ -531,7 +557,7 @@ // this.btnDeleteLg.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.btnDeleteLg.Enabled = false; - this.btnDeleteLg.Location = new System.Drawing.Point(249, 354); + this.btnDeleteLg.Location = new System.Drawing.Point(249, 294); this.btnDeleteLg.Name = "btnDeleteLg"; this.btnDeleteLg.Size = new System.Drawing.Size(75, 23); this.btnDeleteLg.TabIndex = 27; @@ -545,7 +571,7 @@ this.cbxLgApps.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.cbxLgApps.Enabled = false; this.cbxLgApps.FormattingEnabled = true; - this.cbxLgApps.Location = new System.Drawing.Point(87, 409); + this.cbxLgApps.Location = new System.Drawing.Point(87, 349); this.cbxLgApps.Name = "cbxLgApps"; this.cbxLgApps.Size = new System.Drawing.Size(200, 21); this.cbxLgApps.TabIndex = 26; @@ -554,7 +580,7 @@ // this.label5.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.label5.AutoSize = true; - this.label5.Location = new System.Drawing.Point(6, 412); + this.label5.Location = new System.Drawing.Point(6, 352); this.label5.Name = "label5"; this.label5.Size = new System.Drawing.Size(29, 13); this.label5.TabIndex = 25; @@ -581,7 +607,7 @@ // this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(6, 386); + this.label1.Location = new System.Drawing.Point(6, 326); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(38, 13); this.label1.TabIndex = 20; @@ -591,7 +617,7 @@ // this.edtNameLg.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.edtNameLg.Enabled = false; - this.edtNameLg.Location = new System.Drawing.Point(87, 383); + this.edtNameLg.Location = new System.Drawing.Point(87, 323); this.edtNameLg.Name = "edtNameLg"; this.edtNameLg.Size = new System.Drawing.Size(200, 20); this.edtNameLg.TabIndex = 19; @@ -601,7 +627,7 @@ this.edtStepsLg.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.edtStepsLg.Enabled = false; - this.edtStepsLg.Location = new System.Drawing.Point(87, 462); + this.edtStepsLg.Location = new System.Drawing.Point(87, 402); this.edtStepsLg.Multiline = true; this.edtStepsLg.Name = "edtStepsLg"; this.edtStepsLg.Size = new System.Drawing.Size(667, 37); @@ -611,7 +637,7 @@ // this.lblStepsLg.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.lblStepsLg.AutoSize = true; - this.lblStepsLg.Location = new System.Drawing.Point(6, 465); + this.lblStepsLg.Location = new System.Drawing.Point(6, 405); this.lblStepsLg.Name = "lblStepsLg"; this.lblStepsLg.Size = new System.Drawing.Size(37, 13); this.lblStepsLg.TabIndex = 16; @@ -631,7 +657,7 @@ // this.btnCloneLg.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.btnCloneLg.Enabled = false; - this.btnCloneLg.Location = new System.Drawing.Point(87, 354); + this.btnCloneLg.Location = new System.Drawing.Point(87, 294); this.btnCloneLg.Name = "btnCloneLg"; this.btnCloneLg.Size = new System.Drawing.Size(75, 23); this.btnCloneLg.TabIndex = 14; @@ -643,7 +669,7 @@ // this.btnSetShortcutLg.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.btnSetShortcutLg.Enabled = false; - this.btnSetShortcutLg.Location = new System.Drawing.Point(330, 354); + this.btnSetShortcutLg.Location = new System.Drawing.Point(330, 294); this.btnSetShortcutLg.Name = "btnSetShortcutLg"; this.btnSetShortcutLg.Size = new System.Drawing.Size(75, 23); this.btnSetShortcutLg.TabIndex = 13; @@ -655,7 +681,7 @@ // this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(6, 439); + this.label2.Location = new System.Drawing.Point(6, 379); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(50, 13); this.label2.TabIndex = 12; @@ -665,7 +691,7 @@ // this.edtShortcutLg.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.edtShortcutLg.Enabled = false; - this.edtShortcutLg.Location = new System.Drawing.Point(87, 436); + this.edtShortcutLg.Location = new System.Drawing.Point(87, 376); this.edtShortcutLg.Name = "edtShortcutLg"; this.edtShortcutLg.ReadOnly = true; this.edtShortcutLg.Size = new System.Drawing.Size(200, 20); @@ -677,7 +703,7 @@ // this.btnApplyLg.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.btnApplyLg.Enabled = false; - this.btnApplyLg.Location = new System.Drawing.Point(6, 354); + this.btnApplyLg.Location = new System.Drawing.Point(6, 294); this.btnApplyLg.Name = "btnApplyLg"; this.btnApplyLg.Size = new System.Drawing.Size(75, 23); this.btnApplyLg.TabIndex = 9; @@ -695,7 +721,7 @@ this.lvLgPresets.Location = new System.Drawing.Point(6, 103); this.lvLgPresets.MultiSelect = false; this.lvLgPresets.Name = "lvLgPresets"; - this.lvLgPresets.Size = new System.Drawing.Size(829, 245); + this.lvLgPresets.Size = new System.Drawing.Size(829, 185); this.lvLgPresets.TabIndex = 8; this.lvLgPresets.UseCompatibleStateImageBehavior = false; this.lvLgPresets.View = System.Windows.Forms.View.Details; @@ -711,7 +737,7 @@ this.tabOptions.Location = new System.Drawing.Point(4, 22); this.tabOptions.Name = "tabOptions"; this.tabOptions.Padding = new System.Windows.Forms.Padding(3); - this.tabOptions.Size = new System.Drawing.Size(841, 506); + this.tabOptions.Size = new System.Drawing.Size(841, 446); this.tabOptions.TabIndex = 2; this.tabOptions.Text = "Options"; this.tabOptions.UseVisualStyleBackColor = true; @@ -926,11 +952,12 @@ // // tabLog // + this.tabLog.Controls.Add(this.btnClearLog); this.tabLog.Controls.Add(this.edtLog); this.tabLog.Location = new System.Drawing.Point(4, 22); this.tabLog.Name = "tabLog"; this.tabLog.Padding = new System.Windows.Forms.Padding(3); - this.tabLog.Size = new System.Drawing.Size(841, 506); + this.tabLog.Size = new System.Drawing.Size(841, 446); this.tabLog.TabIndex = 3; this.tabLog.Text = "Log"; this.tabLog.UseVisualStyleBackColor = true; @@ -940,12 +967,12 @@ this.edtLog.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.edtLog.Location = new System.Drawing.Point(6, 6); + this.edtLog.Location = new System.Drawing.Point(6, 35); this.edtLog.Multiline = true; this.edtLog.Name = "edtLog"; this.edtLog.ReadOnly = true; this.edtLog.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; - this.edtLog.Size = new System.Drawing.Size(832, 497); + this.edtLog.Size = new System.Drawing.Size(832, 408); this.edtLog.TabIndex = 0; // // tabInfo @@ -955,7 +982,7 @@ this.tabInfo.Location = new System.Drawing.Point(4, 22); this.tabInfo.Name = "tabInfo"; this.tabInfo.Padding = new System.Windows.Forms.Padding(3); - this.tabInfo.Size = new System.Drawing.Size(841, 506); + this.tabInfo.Size = new System.Drawing.Size(841, 446); this.tabInfo.TabIndex = 4; this.tabInfo.Text = "Info"; this.tabInfo.UseVisualStyleBackColor = true; @@ -969,7 +996,7 @@ this.grpNVIDIAInfo.Controls.Add(this.tvNVIDIAInfo); this.grpNVIDIAInfo.Location = new System.Drawing.Point(397, 6); this.grpNVIDIAInfo.Name = "grpNVIDIAInfo"; - this.grpNVIDIAInfo.Size = new System.Drawing.Size(440, 496); + this.grpNVIDIAInfo.Size = new System.Drawing.Size(440, 436); this.grpNVIDIAInfo.TabIndex = 4; this.grpNVIDIAInfo.TabStop = false; this.grpNVIDIAInfo.Text = "NVIDIA info"; @@ -977,7 +1004,7 @@ // btnRefreshNVIDIAInfo // this.btnRefreshNVIDIAInfo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.btnRefreshNVIDIAInfo.Location = new System.Drawing.Point(6, 467); + this.btnRefreshNVIDIAInfo.Location = new System.Drawing.Point(6, 407); this.btnRefreshNVIDIAInfo.Name = "btnRefreshNVIDIAInfo"; this.btnRefreshNVIDIAInfo.Size = new System.Drawing.Size(75, 23); this.btnRefreshNVIDIAInfo.TabIndex = 1; @@ -992,7 +1019,7 @@ | System.Windows.Forms.AnchorStyles.Right))); this.tvNVIDIAInfo.Location = new System.Drawing.Point(6, 19); this.tvNVIDIAInfo.Name = "tvNVIDIAInfo"; - this.tvNVIDIAInfo.Size = new System.Drawing.Size(428, 442); + this.tvNVIDIAInfo.Size = new System.Drawing.Size(428, 382); this.tvNVIDIAInfo.TabIndex = 0; // // groupBox3 @@ -1034,15 +1061,25 @@ this.lblInfo.TabIndex = 1; this.lblInfo.Text = "Info"; // + // btnClearLog + // + this.btnClearLog.Location = new System.Drawing.Point(6, 6); + this.btnClearLog.Name = "btnClearLog"; + this.btnClearLog.Size = new System.Drawing.Size(75, 23); + this.btnClearLog.TabIndex = 2; + this.btnClearLog.Text = "Clear log"; + this.btnClearLog.UseVisualStyleBackColor = true; + this.btnClearLog.Click += new System.EventHandler(this.btnClearLog_Click); + // // MainForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.BackColor = System.Drawing.SystemColors.Control; - this.ClientSize = new System.Drawing.Size(873, 556); + this.ClientSize = new System.Drawing.Size(873, 496); this.Controls.Add(this.tcMain); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.MinimumSize = new System.Drawing.Size(800, 398); + this.MinimumSize = new System.Drawing.Size(800, 535); this.Name = "MainForm"; this.Text = "ColorControl"; this.Activated += new System.EventHandler(this.MainForm_Activated); @@ -1055,6 +1092,8 @@ this.tabNVIDIA.ResumeLayout(false); this.tabNVIDIA.PerformLayout(); this.mnuNvPresets.ResumeLayout(false); + this.tabAMD.ResumeLayout(false); + this.tabAMD.PerformLayout(); this.tabLG.ResumeLayout(false); this.tabLG.PerformLayout(); this.tabOptions.ResumeLayout(false); @@ -1081,7 +1120,6 @@ #endregion private System.Windows.Forms.TabControl tcMain; - private System.Windows.Forms.TabPage tabNVIDIA; private System.Windows.Forms.TabPage tabLG; private System.Windows.Forms.ListView lvNvPresets; private System.Windows.Forms.Button btnApply; @@ -1161,6 +1199,10 @@ private System.Windows.Forms.Label label11; private System.Windows.Forms.TextBox edtBlankScreenSaverShortcut; private System.Windows.Forms.CheckBox chkMinimizeOnClose; + private System.Windows.Forms.TabPage tabNVIDIA; + private System.Windows.Forms.TabPage tabAMD; + private System.Windows.Forms.Label lblErrorAMD; + private System.Windows.Forms.Button btnClearLog; } } diff --git a/ColorControl/MainForm.cs b/ColorControl/MainForm.cs index c922e3e..587e60a 100644 --- a/ColorControl/MainForm.cs +++ b/ColorControl/MainForm.cs @@ -79,6 +79,8 @@ namespace ColorControl private StartUpParams StartUpParams { get; } + private AmdService _amdService; + public MainForm(StartUpParams startUpParams) { InitializeComponent(); @@ -132,6 +134,16 @@ namespace ColorControl _nvPresetsFilename = Path.Combine(_dataDir, "NvPresets.json"); FillNvPresets(); + try + { + _amdService = new AmdService(); + lblErrorAMD.Text = "If you see this message, it means you have AMD graphics drivers installed. Unfortunately, this feature is not completed yet. If I get an AMD card I might finish it."; + } + catch (Exception) + { + tcMain.TabPages.Remove(tabAMD); + } + _lgPresetsFilename = Path.Combine(_dataDir, "LgPresets.json"); var toCopy = Path.Combine(Directory.GetCurrentDirectory(), "LgPresets.json"); if (!File.Exists(_lgPresetsFilename) && File.Exists(toCopy)) @@ -351,6 +363,8 @@ namespace ColorControl return; } + var text = "ColorControl"; + var displays = _nvService.GetDisplays(); foreach (var display in displays) { @@ -414,7 +428,11 @@ namespace ColorControl item.SubItems.Add(values[i]); } } + + text += "\n" + string.Format("{0}: {1}, {2}Hz, HDR: {3}", name, colorSettings, refreshRate, _nvService.IsHDREnabled() ? "Yes" : "No"); } + + Utils.SetNotifyIconText(trayIcon, text); } private void RegisterShortcut(int id, string shortcut, bool clear = false) @@ -483,7 +501,7 @@ namespace ColorControl SaveLgPresets(); SaveConfig(); - + if (SystemShutdown && _lgService.Config.PowerOffOnShutdown) { Logger.Debug($"MainForm_FormClosing: SystemShutdown"); @@ -492,14 +510,16 @@ namespace ColorControl { Logger.Debug("Not powering off because of a restart"); } - else if (NativeMethods.GetAsyncKeyState(NativeConstants.VK_LSHIFT) < 0 || NativeMethods.GetAsyncKeyState(NativeConstants.VK_RSHIFT) < 0) + else if (NativeMethods.GetAsyncKeyState(NativeConstants.VK_CONTROL) < 0 || NativeMethods.GetAsyncKeyState(NativeConstants.VK_RCONTROL) < 0) { - Logger.Debug("Not powering off because SHIFT-key is down"); + Logger.Debug("Not powering off because CONTROL-key is down"); } else { + Logger.Debug("Powering off tv..."); var task = _lgService.PowerOff(); Utils.WaitForTask(task); + Logger.Debug("Done powering off tv"); //ExecPowerOffPreset(true); } } @@ -654,6 +674,11 @@ namespace ColorControl { Hide(); } + else if (WindowState == FormWindowState.Normal) + { + _config.FormWidth = Width; + _config.FormHeight = Height; + } } private void chkStartAfterLogin_CheckedChanged(object sender, EventArgs e) @@ -755,8 +780,11 @@ namespace ColorControl private void SaveConfig() { _config.StartMinimized = chkStartMinimized.Checked; - _config.FormWidth = Width; - _config.FormHeight = Height; + if (WindowState != FormWindowState.Minimized) + { + _config.FormWidth = Width; + _config.FormHeight = Height; + } try { @@ -795,6 +823,14 @@ namespace ColorControl lblError.Visible = true; } + if (_amdService == null) + { + ShowControls(tabAMD, false, lblErrorAMD); + + lblErrorAMD.Text = "Error while initializing the ADL-wrapper. You either don't have a AMD GPU or it is disabled. AMD controls will not be available."; + lblErrorAMD.Visible = true; + } + if (_lgService == null) { ShowControls(tabLG, false, lblLgError); @@ -1843,5 +1879,15 @@ Do you want to continue?"; { UpdateDisplayInfoItems(); } + + private void btnClearLog_Click(object sender, EventArgs e) + { + var filename = Path.Combine(_dataDir, "LogFile.txt"); + if (File.Exists(filename)) + { + File.Delete(filename); + edtLog.Clear(); + } + } } } \ No newline at end of file diff --git a/ColorControl/NvService.cs b/ColorControl/NvService.cs index ad9551e..017d7aa 100644 --- a/ColorControl/NvService.cs +++ b/ColorControl/NvService.cs @@ -2,32 +2,19 @@ using NvAPIWrapper.Display; using NvAPIWrapper.Native.Display; using NvAPIWrapper.Native.GPU.Structures; -using NWin32; -using NWin32.NativeTypes; using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; -using System.Threading; namespace ColorControl { - class NvService + class NvService : GraphicsService { - const UInt32 WM_KEYDOWN = 0x0100; - const UInt32 WM_KEYUP = 0x0101; - const int VK_TAB = 0x09; - const int VK_SPACE = 0x20; - - [DllImport("user32.dll")] - static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam); - [DllImport(@"nvapi64", EntryPoint = @"nvapi_QueryInterface", CallingConvention = CallingConvention.Cdecl, PreserveSig = true)] private static extern IntPtr NvAPI64_QueryInterface(uint interfaceId); - public delegate long NvAPI_Disp_SetDitherControl( [In] PhysicalGPUHandle physicalGpu, [In] uint OutputId, @@ -38,10 +25,10 @@ namespace ColorControl public delegate long NvAPI_Disp_GetDitherControl( [In] PhysicalGPUHandle physicalGpu, - [Out] uint OutputId, - [In] [Out] IntPtr ditherControl); + [In] uint OutputId, + [In][Out] IntPtr ditherControl); - [StructLayout(LayoutKind.Sequential, Pack = 4)] + [StructLayout(LayoutKind.Sequential, Pack = 8)] public struct NV_GPU_DITHER_CONTROL_V1 { public int version; @@ -50,18 +37,10 @@ namespace ColorControl public uint mode; }; - private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); - private Display _currentDisplay; public NvService() { - NVIDIA.Initialize(); - } - - ~NvService() - { - NVIDIA.Unload(); } public Display GetCurrentDisplay() @@ -125,21 +104,6 @@ namespace ColorControl return true; } - public void ToggleHDR(int delay = 1000) - { - Process.Start("ms-settings:display"); - Thread.Sleep(delay); - - var process = Process.GetProcessesByName("SystemSettings").FirstOrDefault(); - if (process != null) - { - System.Windows.Forms.SendKeys.SendWait("{TAB}"); - System.Windows.Forms.SendKeys.SendWait("{TAB}"); - System.Windows.Forms.SendKeys.SendWait(" "); - System.Windows.Forms.SendKeys.SendWait("%{F4}"); - } - } - public void SetDithering(bool enabled) { var ptr = NvAPI64_QueryInterface(0xDF0DFCDD); @@ -174,16 +138,16 @@ namespace ColorControl NV_GPU_DITHER_CONTROL_V1 info = new NV_GPU_DITHER_CONTROL_V1(); info.version = 1; - IntPtr bla = Marshal.AllocHGlobal(Marshal.SizeOf(info)); + IntPtr bla = Marshal.AllocHGlobal(Marshal.SizeOf(info.GetType())); Marshal.StructureToPtr(info, bla, false); // Does not work yet...What is the exact interface of NvAPI_Disp_GetDitherControl? - //var result = delegateValue(gpuHandle, displayId, bla); - //if (result != 0) - //{ - // Logger.Error($"Could not get dithering because NvAPI_Disp_GetDitherControl returned a non-zero return code: {result}"); - //} + var result = delegateValue(gpuHandle, displayId, bla); + if (result != 0) + { + Logger.Error($"Could not get dithering because NvAPI_Disp_GetDitherControl returned a non-zero return code: {result}"); + } return info.state == 1; } @@ -197,34 +161,11 @@ namespace ColorControl var portrait = new[] { Rotate.Degree90, Rotate.Degree270 }.Contains(display.DisplayDevice.ScanOutInformation.SourceToTargetRotation); var timing = display.DisplayDevice.CurrentTiming; - uint i = 0; - DEVMODEA devMode; - while (NativeMethods.EnumDisplaySettingsA(display.Name, i, out devMode)) - { - // Also compare width with vertical and height with horizontal in case of portrait mode - if (((!portrait && devMode.dmPelsWidth == timing.HorizontalVisible && devMode.dmPelsHeight == timing.VerticalVisible) || - (portrait && devMode.dmPelsWidth == timing.VerticalVisible && devMode.dmPelsHeight == timing.HorizontalVisible)) - && devMode.dmBitsPerPel == 32 && devMode.dmDisplayFrequency == refreshRate) - { - IntPtr bla = Marshal.AllocHGlobal(Marshal.SizeOf(devMode)); - Marshal.StructureToPtr(devMode, bla, false); - var result = NativeMethods.ChangeDisplaySettingsExA(display.Name, bla, IntPtr.Zero, 0, IntPtr.Zero); - if (result != NativeConstants.DISP_CHANGE_SUCCESSFUL) - { - Logger.Error($"Could not set refreshrate {refreshRate} on display {display.Name} because ChangeDisplaySettingsExA returned a non-zero return code: {result}"); - } - return result == NativeConstants.DISP_CHANGE_SUCCESSFUL; - } - i++; - } - Logger.Info($"Could not set refreshrate {refreshRate} on display {display.Name} because EnumDisplaySettings did not report it as a valid refreshrate"); - return false; + return SetRefreshRateInternal(display.Name, refreshRate, portrait, timing.HorizontalVisible, timing.VerticalVisible); } public List GetAvailableRefreshRates(NvPreset preset = null) { - var list = new List(); - if (preset != null) { SetCurrentDisplay(preset); @@ -234,18 +175,7 @@ namespace ColorControl var portrait = new[] { Rotate.Degree90, Rotate.Degree270 }.Contains(display.DisplayDevice.ScanOutInformation.SourceToTargetRotation); var timing = display.DisplayDevice.CurrentTiming; - uint i = 0; - DEVMODEA devMode; - while (NativeMethods.EnumDisplaySettingsA(display.Name, i, out devMode)) - { - if ((!portrait && devMode.dmPelsWidth == timing.HorizontalVisible && devMode.dmPelsHeight == timing.VerticalVisible) || - (portrait && devMode.dmPelsWidth == timing.VerticalVisible && devMode.dmPelsHeight == timing.HorizontalVisible)) - { - list.Add(devMode.dmDisplayFrequency); - } - i++; - } - return list; + return GetAvailableRefreshRatesInternal(display.Name, portrait, timing.HorizontalVisible, timing.VerticalVisible); } public bool IsHDREnabled() @@ -259,5 +189,15 @@ namespace ColorControl { return Display.GetDisplays(); } + + protected override void Initialize() + { + NVIDIA.Initialize(); + } + + protected override void Uninitialize() + { + NVIDIA.Unload(); + } } } diff --git a/ColorControl/Properties/AssemblyInfo.cs b/ColorControl/Properties/AssemblyInfo.cs index 7f2619d..33de681 100644 --- a/ColorControl/Properties/AssemblyInfo.cs +++ b/ColorControl/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.2.0.0")] -[assembly: AssemblyFileVersion("1.2.0.0")] +[assembly: AssemblyVersion("1.3.0.0")] +[assembly: AssemblyFileVersion("1.3.0.0")] diff --git a/ColorControl/Utils.cs b/ColorControl/Utils.cs index eea6057..946cf0f 100644 --- a/ColorControl/Utils.cs +++ b/ColorControl/Utils.cs @@ -163,13 +163,10 @@ namespace ColorControl if (key != null) { var value = key.GetValue(null).ToString(); + value = value.Replace("chrome.exe\" " + argument + " --", "chrome.exe\" --"); if (install) { - value = value.Replace("chrome.exe\" -- \"", "chrome.exe\" " + argument + " -- \""); - } - else - { - value = value.Replace("chrome.exe\" " + argument + " -- \"", "chrome.exe\" -- \""); + value = value.Replace("chrome.exe\" --", "chrome.exe\" " + argument + " --"); } key.SetValue(null, value); } @@ -295,5 +292,15 @@ namespace ColorControl Application.DoEvents(); } } + + public static void SetNotifyIconText(NotifyIcon ni, string text) + { + text = text.Substring(0, Math.Min(text.Length, 127)); + Type t = typeof(NotifyIcon); + BindingFlags hidden = BindingFlags.NonPublic | BindingFlags.Instance; + t.GetField("text", hidden).SetValue(ni, text); + if ((bool)t.GetField("added", hidden).GetValue(ni)) + t.GetMethod("UpdateIcon", hidden).Invoke(ni, new object[] { true }); + } } }