Added DisplayIdentifiers to Profile storage

DisplayIdentifiers are the minimum GPU/Display
that will allow us to identify whether a profile
will actually work. We look for the same DisplayIdentifiers
or a subset of them to determine whether a profile
will be valid to show. This is different from the data
stored under DisplayTarget, as that is used for detailed
compatibility....
This commit is contained in:
Terry MacDonald 2020-08-19 18:55:50 +12:00
parent 32ad405904
commit 0912ee5896
5 changed files with 198 additions and 32 deletions

View File

@ -0,0 +1,125 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WindowsDisplayAPI;
using EDIDParser;
using NvAPIWrapper.GPU;
using NvAPIWrapper.Native.GPU;
using Microsoft.Win32;
namespace HeliosPlus.Shared.DisplayIdentification
{
class DisplayIdentifier
{
public static List<string> GetDisplayIdentification()
{
List<string> DisplayIdentificationData = new List<string>();
List<Display> ConnectedDisplays = Display.GetDisplays().ToList<Display>();
foreach (Display ConnectedDisplay in ConnectedDisplays)
{
byte[] edidData;
using (RegistryKey key = ConnectedDisplay.OpenDevicePnPKey())
{
using (RegistryKey subkey = key.OpenSubKey("Device Parameters"))
{
// ReSharper disable once PossibleNullReferenceException
edidData = (byte[])subkey.GetValue("EDID", null);
}
}
EDID edid = new EDID(edidData);
Console.WriteLine($"EDID-ManufacturerID:{edid.ManufacturerId}");
Console.WriteLine($"EDID-ManufacturerCode:{edid.ManufacturerCode}");
Console.WriteLine($"EDID-ManufacturerYear:{edid.ManufactureYear}");
Console.WriteLine($"EDID-ManufacturerWeek:{edid.ManufactureWeek}");
Console.WriteLine($"EDID-ManufacturerDate:{edid.ManufactureDate}");
Console.WriteLine($"EDID-ProductCode:{edid.ProductCode}");
Console.WriteLine($"EDID-ProductYear:{edid.ProductYear}");
Console.WriteLine($"EDID-SerialNumber:{edid.SerialNumber}");
Console.WriteLine($"EDID-Timings:{edid.Timings}");
Console.WriteLine($"EDID-AdapterDeviceKey:{ConnectedDisplay.Adapter.DeviceName}");
Console.WriteLine($"EDID-AdapterDeviceName:{ConnectedDisplay.Adapter.DeviceName}");
Console.WriteLine($"EDID-AdapterDevicePath:{ConnectedDisplay.Adapter.DevicePath}");
Console.WriteLine($"EDID-{ConnectedDisplay.Adapter.DevicePath}-{edid.ManufacturerId}-{edid.ProductCode}-{edid.SerialNumber}");
string DisplayIdentificationHash = $"EDID-{ConnectedDisplay.Adapter.DevicePath}-{edid.ManufacturerId}-{edid.ProductCode}-{edid.SerialNumber}";
DisplayIdentificationData.Add(DisplayIdentificationHash);
}
return DisplayIdentificationData;
}
public static string GetDisplayIdentification(Display display)
{
byte[] edidData;
using (RegistryKey key = display.OpenDevicePnPKey())
{
using (RegistryKey subkey = key.OpenSubKey("Device Parameters"))
{
// ReSharper disable once PossibleNullReferenceException
edidData = (byte[])subkey.GetValue("EDID", null);
}
}
EDID edid = new EDID(edidData);
Console.WriteLine($"EDID-ManufacturerID:{edid.ManufacturerId}");
Console.WriteLine($"EDID-ManufacturerCode:{edid.ManufacturerCode}");
Console.WriteLine($"EDID-ManufacturerYear:{edid.ManufactureYear}");
Console.WriteLine($"EDID-ManufacturerWeek:{edid.ManufactureWeek}");
Console.WriteLine($"EDID-ManufacturerDate:{edid.ManufactureDate}");
Console.WriteLine($"EDID-ProductCode:{edid.ProductCode}");
Console.WriteLine($"EDID-ProductYear:{edid.ProductYear}");
Console.WriteLine($"EDID-SerialNumber:{edid.SerialNumber}");
Console.WriteLine($"EDID-Timings:{edid.Timings}");
Console.WriteLine($"EDID-AdapterDeviceKey:{display.Adapter.DeviceName}");
Console.WriteLine($"EDID-AdapterDeviceName:{display.Adapter.DeviceName}");
Console.WriteLine($"EDID-AdapterDevicePath:{display.Adapter.DevicePath}");
Console.WriteLine($"EDID-{display.Adapter.DevicePath}-{edid.ManufacturerId}-{edid.ProductCode}-{edid.SerialNumber}");
return $"EDID-{display.Adapter.DevicePath}-{edid.ManufacturerId}-{edid.ProductCode}-{edid.SerialNumber}";
}
public static bool IsDisplayHere(string DisplayIdentificationHash, Display display)
{
byte[] edidData;
using (RegistryKey key = display.OpenDevicePnPKey())
{
using (RegistryKey subkey = key.OpenSubKey("Device Parameters"))
{
// ReSharper disable once PossibleNullReferenceException
edidData = (byte[])subkey.GetValue("EDID", null);
}
}
// Parse the EDID data into a useful structure
EDID edid = new EDID(edidData);
string thisDisplayIdentificationHash = $"EDID-{display.Adapter.DevicePath}-{edid.ManufacturerId}-{edid.ProductCode}-{edid.SerialNumber}";
// Compare the supplied hash with the
if (DisplayIdentificationHash == thisDisplayIdentificationHash)
return true;
return false;
}
public static bool IsDisplayHere(string DisplayIdentificationHash)
{
List<Display> ConnectedDisplays = Display.GetDisplays().ToList<Display>();
foreach (Display ConnectedDisplay in ConnectedDisplays)
{
byte[] edidData;
using (RegistryKey key = ConnectedDisplay.OpenDevicePnPKey())
{
using (RegistryKey subkey = key.OpenSubKey("Device Parameters"))
{
// ReSharper disable once PossibleNullReferenceException
edidData = (byte[])subkey.GetValue("EDID", null);
}
}
// Parse the EDID data into a useful structure
EDID edid = new EDID(edidData);
string thisDisplayIdentificationHash = $"EDID-{ConnectedDisplay.Adapter.DevicePath}-{edid.ManufacturerId}-{edid.ProductCode}-{edid.SerialNumber}";
// Compare the supplied hash with the
if (DisplayIdentificationHash == thisDisplayIdentificationHash)
return true;
}
return false;
}
}
}

View File

@ -41,6 +41,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="DisplayIdentification\DisplayIdentifier.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
@ -112,6 +113,7 @@
<Version>1.3.0.13</Version>
</PackageReference>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@ -16,6 +16,7 @@ using System.Drawing;
using System.Drawing.Imaging;
using WindowsDisplayAPI;
using System.Text.RegularExpressions;
using HeliosPlus.Shared.DisplayIdentification;
namespace HeliosPlus.Shared
{
@ -24,6 +25,7 @@ namespace HeliosPlus.Shared
private static List<ProfileItem> _allSavedProfiles = new List<ProfileItem>();
private ProfileIcon _profileIcon;
private Bitmap _profileBitmap, _profileShortcutBitmap;
private List<string> _profileDisplayIdentifiers = new List<string>();
private static List<Display> _availableDisplays;
private static List<UnAttachedDisplay> _unavailableDisplays;
@ -98,7 +100,8 @@ namespace HeliosPlus.Shared
{
/*try
{
NvAPIWrapper.NVIDIA.Initialize();
// Generate the DeviceIdentifiers ready to be used
ProfileDisplayIdentifiers = DisplayIdentifier.GetDisplayIdentification();
}
catch (Exception ex)
{
@ -134,7 +137,9 @@ namespace HeliosPlus.Shared
{
get
{
IEnumerable<Display> currentDisplays = WindowsDisplayAPI.Display.GetDisplays();
//List<string> DisplayInfo = DisplayIdentifier.GetDisplayIdentification();
IEnumerable<Display> currentDisplays = Display.GetDisplays();
foreach (Display availableDisplay in currentDisplays)
{
Console.WriteLine($"DsiplayName: {availableDisplay.DisplayName}");
@ -216,6 +221,23 @@ namespace HeliosPlus.Shared
public string SavedProfileIconCacheFilename { get; set; }
public List<string> ProfileDisplayIdentifiers
{
get
{
if (_profileDisplayIdentifiers.Count == 0)
{
_profileDisplayIdentifiers = DisplayIdentifier.GetDisplayIdentification();
}
return _profileDisplayIdentifiers;
}
set
{
if (value is List<string>)
_profileDisplayIdentifiers = value;
}
}
[JsonConverter(typeof(CustomBitmapConverter))]
public Bitmap ProfileBitmap
{
@ -281,6 +303,19 @@ namespace HeliosPlus.Shared
return false;
}
public bool IsValid()
{
if (Viewports != null &&
ProfileIcon is Bitmap &&
File.Exists(SavedProfileIconCacheFilename) &&
ProfileBitmap is Bitmap &&
ProfileTightestBitmap is Bitmap &&
ProfileDisplayIdentifiers.Count > 0)
return true;
else
return false;
}
public bool CopyTo(ProfileItem profile, bool overwriteId = true)
{
@ -297,9 +332,22 @@ namespace HeliosPlus.Shared
profile.SavedProfileIconCacheFilename = SavedProfileIconCacheFilename;
profile.ProfileBitmap = ProfileBitmap;
profile.ProfileTightestBitmap = ProfileTightestBitmap;
profile.ProfileDisplayIdentifiers = ProfileDisplayIdentifiers;
return true;
}
public bool PreSave()
{
// Prepare our profile data for saving
if (_profileDisplayIdentifiers.Count == 0)
{
_profileDisplayIdentifiers = DisplayIdentifier.GetDisplayIdentification();
}
// Return if it is valid and we should continue
return IsValid();
}
// The public override for the Object.Equals
public override bool Equals(object obj)

View File

@ -24,6 +24,7 @@ using System.Resources;
using System.Net.NetworkInformation;
using NvAPIWrapper.Mosaic;
using NvAPIWrapper.Native.Mosaic;
using HeliosPlus.Shared.DisplayIdentification;
namespace HeliosPlus.Shared
{
@ -121,43 +122,30 @@ namespace HeliosPlus.Shared
#endregion
#region Class Methods
public static bool AddProfile(ProfileItem Profile)
public static bool AddProfile(ProfileItem profile)
{
if (!(Profile is ProfileItem))
if (!(profile is ProfileItem))
return false;
// Doublecheck if it already exists
// Because then we just update the one that already exists
if (!ContainsProfile(Profile))
if (!ContainsProfile(profile))
{
// Add the Profile to the list of Profiles
_allProfiles.Add(Profile);
}
_allProfiles.Add(profile);
/* // Doublecheck if it already exists
// Because then we just update the one that already exists
if (ContainsProfile(Profile))
{
// We update the existing Profile with the data over
ProfileItem ProfileToUpdate = GetProfile(Profile.UUID);
Profile.CopyTo(ProfileToUpdate);
}
else
{
// Add the Profile to the list of Profiles
_allProfiles.Add(Profile);
}
*/
//Doublecheck it's been added
if (ContainsProfile(Profile))
{
// Generate the Profile Icon ready to be used
SaveProfileIconToCache(Profile);
SaveProfileIconToCache(profile);
profile.PreSave();
// Save the Profiles JSON as it's different
SaveProfiles();
}
//Doublecheck it's been added
if (ContainsProfile(profile))
{
return true;
}
else
@ -370,10 +358,11 @@ namespace HeliosPlus.Shared
Name = "Current Display Profile",
Viewports = PathInfo.GetActivePaths().Select(info => new ProfileViewport(info)).ToArray(),
ProfileIcon = new ProfileIcon(_currentProfile),
ProfileBitmap = _currentProfile.ProfileIcon.ToBitmap(256, 256)
ProfileBitmap = _currentProfile.ProfileIcon.ToBitmap(256, 256),
ProfileDisplayIdentifiers = DisplayIdentifier.GetDisplayIdentification()
};
if (ProfileRepository.ProfileCount > 0)
if (_profilesLoaded && _allProfiles.Count > 0)
{
foreach (ProfileItem loadedProfile in ProfileRepository.AllProfiles)
{
@ -548,14 +537,14 @@ namespace HeliosPlus.Shared
}
}
public static void UpdateCurrentProfile()
/*public static void UpdateCurrentProfile()
{
_currentProfile = new ProfileItem
{
Name = "Current Display Profile",
Viewports = PathInfo.GetActivePaths().Select(info => new ProfileViewport(info)).ToArray()
};
}
}*/
public static bool IsValidFilename(string testName)
{

View File

@ -156,7 +156,8 @@ namespace HeliosPlus.UIForms
// Load all the profiles to prepare things
//_savedProfiles = ProfileRepository.AllProfiles;
// Update the Current Profile
ProfileRepository.UpdateCurrentProfile();
//ProfileRepository.UpdateCurrentProfile();
ProfileRepository.GetActiveProfile();
// Change to the current selected Profile
ChangeSelectedProfile(ProfileRepository.GetActiveProfile());
// Refresh the Profile UI
@ -322,7 +323,8 @@ namespace HeliosPlus.UIForms
private void btn_view_current_Click(object sender, EventArgs e)
{
// Reload the profiles in case we swapped to another program to change it
ProfileRepository.UpdateCurrentProfile();
//ProfileRepository.UpdateCurrentProfile();
ProfileRepository.GetActiveProfile();
// Change to the current selected Profile
ChangeSelectedProfile(ProfileRepository.GetActiveProfile());
// Refresh the Profile UI