mirror of
https://github.com/terrymacdonald/DisplayMagician.git
synced 2024-08-30 18:32:20 +00:00
[WIP] Added video card detection
Added ability for ProfileRepository to know what mode it is in when DisplayMagician starts.
This commit is contained in:
parent
01ffda8428
commit
40b8525dd8
@ -235,35 +235,17 @@ namespace DisplayMagicianShared.AMD
|
|||||||
|
|
||||||
public override void RefreshPossbility()
|
public override void RefreshPossbility()
|
||||||
{
|
{
|
||||||
// Check each display in this profile and make sure it's currently available
|
// Check whether this profile is possible
|
||||||
int validDisplayCount = 0;
|
if (AMDLibrary.GetLibrary().IsPossibleConfig(_amdDisplayConfig))
|
||||||
|
|
||||||
//validDisplayCount = (from connectedDisplay in ProfileRepository.ConnectedDisplayIdentifiers select connectedDisplay == profileDisplayIdentifier).Count();
|
|
||||||
|
|
||||||
foreach (string profileDisplayIdentifier in ProfileDisplayIdentifiers)
|
|
||||||
{
|
|
||||||
// If this profile has a display that isn't currently available then we need to say it's a no!
|
|
||||||
if (ProfileRepository.ConnectedDisplayIdentifiers.Any(s => profileDisplayIdentifier.Equals(s)))
|
|
||||||
{
|
|
||||||
SharedLogger.logger.Trace($"ProfileItem/RefreshPossbility: We found the display in the profile {Name} with profileDisplayIdentifier {profileDisplayIdentifier} is connected now.");
|
|
||||||
validDisplayCount++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SharedLogger.logger.Warn($"ProfileItem/RefreshPossbility: We found the display in the profile {Name} with profileDisplayIdentifier {profileDisplayIdentifier} is NOT currently connected, so this profile cannot be used.");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if (validDisplayCount == ProfileDisplayIdentifiers.Count)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
SharedLogger.logger.Debug($"ProfileRepository/IsPossibleRefresh: The profile {Name} is possible!");
|
SharedLogger.logger.Debug($"ProfileRepository/IsPossibleRefresh: The AMD profile {Name} is possible!");
|
||||||
_isPossible = true;
|
_isPossible = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SharedLogger.logger.Debug($"ProfileRepository/IsPossibleRefresh: The profile {Name} is NOT possible!");
|
SharedLogger.logger.Debug($"ProfileRepository/IsPossibleRefresh: The AMD profile {Name} is NOT possible!");
|
||||||
_isPossible = false;
|
_isPossible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,11 +286,11 @@ namespace DisplayMagicianShared.AMD
|
|||||||
// Now we create the screens structure from the AMD profile information
|
// Now we create the screens structure from the AMD profile information
|
||||||
_screens = new List<ScreenPosition>();
|
_screens = new List<ScreenPosition>();
|
||||||
|
|
||||||
if ( _displayConfig.W.Count > 0)
|
if ( _amdDisplayConfig.AdapterConfigs.Count > 0)
|
||||||
{
|
{
|
||||||
foreach ( var adapter in _displayConfig.AdapterConfigs)
|
foreach ( var adapter in _amdDisplayConfig.AdapterConfigs)
|
||||||
{
|
{
|
||||||
foreach (var display in adapter.SLSMapIndex)
|
foreach (var display in adapter)
|
||||||
{
|
{
|
||||||
foreach (var mode in display.DisplayModes)
|
foreach (var mode in display.DisplayModes)
|
||||||
{
|
{
|
||||||
@ -515,26 +497,6 @@ namespace DisplayMagicianShared.AMD
|
|||||||
// Allows us to use 'Contains'
|
// Allows us to use 'Contains'
|
||||||
class AMDProfileComparer : IEqualityComparer<AMDProfileItem>
|
class AMDProfileComparer : IEqualityComparer<AMDProfileItem>
|
||||||
{
|
{
|
||||||
// Products are equal if their names and product numbers are equal.
|
|
||||||
/*public bool Equals(AMDProfileItem x, AMDProfileItem y)
|
|
||||||
{
|
|
||||||
|
|
||||||
//Check whether the compared objects reference the same data.
|
|
||||||
if (Object.ReferenceEquals(x, y)) return true;
|
|
||||||
|
|
||||||
//Check whether any of the compared objects is null.
|
|
||||||
if (x is null || y is null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Check whether the profiles' properties are equal
|
|
||||||
// We need to exclude the name as the name is solely for saving to disk
|
|
||||||
// and displaying to the user.
|
|
||||||
// Two profiles are equal only when they have the same viewport data
|
|
||||||
if (x.Paths.SequenceEqual(y.Paths))
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
public bool Equals(AMDProfileItem x, AMDProfileItem y)
|
public bool Equals(AMDProfileItem x, AMDProfileItem y)
|
||||||
{
|
{
|
||||||
@ -585,21 +547,6 @@ namespace DisplayMagicianShared.AMD
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If Equals() returns true for a pair of objects
|
|
||||||
// then GetHashCode() must return the same value for these objects.
|
|
||||||
/*public int GetHashCode(AMDProfileItem profile)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Check whether the object is null
|
|
||||||
if (profile is null) return 0;
|
|
||||||
|
|
||||||
// Get hash code for the Viewports field if it is not null.
|
|
||||||
int hashPaths = profile.Paths == null ? 0 : profile.Paths.GetHashCode();
|
|
||||||
|
|
||||||
//Calculate the hash code for the product.
|
|
||||||
return hashPaths;
|
|
||||||
|
|
||||||
}*/
|
|
||||||
// Modified the GetHashCode to compare the displayidentifier
|
// Modified the GetHashCode to compare the displayidentifier
|
||||||
public int GetHashCode(AMDProfileItem profile)
|
public int GetHashCode(AMDProfileItem profile)
|
||||||
{
|
{
|
||||||
|
@ -68,10 +68,6 @@ namespace DisplayMagicianShared.NVIDIA
|
|||||||
|
|
||||||
public override string Name { get; set; }
|
public override string Name { get; set; }
|
||||||
|
|
||||||
//public Topology.Path[] Paths { get; set; } = new Topology.Path[0];
|
|
||||||
|
|
||||||
//public NVIDIALibrary.NVIDIAProfile ProfileData { get; set; } = new NVIDIALibrary.NVIDIAProfile();
|
|
||||||
|
|
||||||
[JsonRequired]
|
[JsonRequired]
|
||||||
public NVIDIA_DISPLAY_CONFIG NVIDIADisplayConfig
|
public NVIDIA_DISPLAY_CONFIG NVIDIADisplayConfig
|
||||||
{
|
{
|
||||||
@ -225,35 +221,17 @@ namespace DisplayMagicianShared.NVIDIA
|
|||||||
|
|
||||||
public override void RefreshPossbility()
|
public override void RefreshPossbility()
|
||||||
{
|
{
|
||||||
// Check each display in this profile and make sure it's currently available
|
// Check whether this profile is possible
|
||||||
int validDisplayCount = 0;
|
if (NVIDIALibrary.GetLibrary().IsPossibleConfig(_nvidiaDisplayConfig))
|
||||||
|
|
||||||
//validDisplayCount = (from connectedDisplay in ProfileRepository.ConnectedDisplayIdentifiers select connectedDisplay == profileDisplayIdentifier).Count();
|
|
||||||
|
|
||||||
foreach (string profileDisplayIdentifier in ProfileDisplayIdentifiers)
|
|
||||||
{
|
|
||||||
// If this profile has a display that isn't currently available then we need to say it's a no!
|
|
||||||
if (ProfileRepository.ConnectedDisplayIdentifiers.Any(s => profileDisplayIdentifier.Equals(s)))
|
|
||||||
{
|
|
||||||
SharedLogger.logger.Trace($"ProfileItem/RefreshPossbility: We found the display in the profile {Name} with profileDisplayIdentifier {profileDisplayIdentifier} is connected now.");
|
|
||||||
validDisplayCount++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SharedLogger.logger.Warn($"ProfileItem/RefreshPossbility: We found the display in the profile {Name} with profileDisplayIdentifier {profileDisplayIdentifier} is NOT currently connected, so this profile cannot be used.");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if (validDisplayCount == ProfileDisplayIdentifiers.Count)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
SharedLogger.logger.Debug($"ProfileRepository/IsPossibleRefresh: The profile {Name} is possible!");
|
SharedLogger.logger.Debug($"ProfileRepository/IsPossibleRefresh: The NVIDIA profile {Name} is possible!");
|
||||||
_isPossible = true;
|
_isPossible = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SharedLogger.logger.Debug($"ProfileRepository/IsPossibleRefresh: The profile {Name} is NOT possible!");
|
SharedLogger.logger.Debug($"ProfileRepository/IsPossibleRefresh: The NVIDIA profile {Name} is NOT possible!");
|
||||||
_isPossible = false;
|
_isPossible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,7 +272,7 @@ namespace DisplayMagicianShared.NVIDIA
|
|||||||
// Now we create the screens structure from the AMD profile information
|
// Now we create the screens structure from the AMD profile information
|
||||||
_screens = new List<ScreenPosition>();
|
_screens = new List<ScreenPosition>();
|
||||||
|
|
||||||
if (_displayConfig. .Count > 0)
|
if (_displayConfig.Count > 0)
|
||||||
{
|
{
|
||||||
foreach (var adapter in _displayConfig.AdapterConfigs)
|
foreach (var adapter in _displayConfig.AdapterConfigs)
|
||||||
{
|
{
|
||||||
@ -390,7 +368,12 @@ namespace DisplayMagicianShared.NVIDIA
|
|||||||
if (this.GetType() != other.GetType())
|
if (this.GetType() != other.GetType())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (Paths.Length != other.Paths.Length)
|
// If NVIDIA Display Config is different then return false.
|
||||||
|
if (!NVIDIADisplayConfig.Equals(other.NVIDIADisplayConfig))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// If Windows Display Config is different then return false.
|
||||||
|
if (!WindowsDisplayConfig.Equals(other.WindowsDisplayConfig))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Check if the profile identifiers are not the same, then return false
|
// Check if the profile identifiers are not the same, then return false
|
||||||
|
@ -13,7 +13,16 @@ using DisplayMagicianShared.Windows;
|
|||||||
|
|
||||||
namespace DisplayMagicianShared
|
namespace DisplayMagicianShared
|
||||||
{
|
{
|
||||||
|
// This enum sets the video card mode used within DisplayMagician
|
||||||
|
// It effectively controls what video card library is used to store profiles on the computer
|
||||||
|
// We look up the PCI vendor ID for the video cards, and then we look for them in the order from most commonly
|
||||||
|
// sold video card to the least, followed by the generic 'catch-all' windows mode.
|
||||||
|
public enum VIDEO_MODE : Int32
|
||||||
|
{
|
||||||
|
WINDOWS = 0,
|
||||||
|
NVIDIA = 1,
|
||||||
|
AMD = 2,
|
||||||
|
}
|
||||||
|
|
||||||
public static class ProfileRepository
|
public static class ProfileRepository
|
||||||
{
|
{
|
||||||
@ -26,9 +35,11 @@ namespace DisplayMagicianShared
|
|||||||
private static ProfileItem _currentProfile;
|
private static ProfileItem _currentProfile;
|
||||||
private static List<string> _connectedDisplayIdentifiers = new List<string>();
|
private static List<string> _connectedDisplayIdentifiers = new List<string>();
|
||||||
private static bool notifiedEDIDErrorToUser = false;
|
private static bool notifiedEDIDErrorToUser = false;
|
||||||
private static AMDLibrary AMDLibrary;
|
private static AMDLibrary amdLibrary;
|
||||||
private static NVIDIALibrary NVIDIALibrary;
|
private static NVIDIALibrary nvidiaLibrary;
|
||||||
//private static bool _isLoading = false;
|
private static WinLibrary winLibrary;
|
||||||
|
// Make th default video mode Windows
|
||||||
|
public static VIDEO_MODE _videoMode = VIDEO_MODE.WINDOWS;
|
||||||
|
|
||||||
// Other constants that are useful
|
// Other constants that are useful
|
||||||
public static string AppDataPath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "DisplayMagician");
|
public static string AppDataPath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "DisplayMagician");
|
||||||
@ -43,29 +54,41 @@ namespace DisplayMagicianShared
|
|||||||
#region Class Constructors
|
#region Class Constructors
|
||||||
static ProfileRepository()
|
static ProfileRepository()
|
||||||
{
|
{
|
||||||
|
// Figure out the Video Cards and see what mode we want
|
||||||
// Initialise the the NVIDIA NvAPIWrapper
|
// Get a list of all the PCI Vendor IDs
|
||||||
try
|
List<string> videoCardVendors = WinLibrary.GetLibrary().GetCurrentPCIVideoCardVendors();
|
||||||
|
// This sets the order in which the different modes have been chosen.
|
||||||
|
// NVIDIA Video cards are the most common, so go first
|
||||||
|
_videoMode = VIDEO_MODE.WINDOWS;
|
||||||
|
if (!NVIDIALibrary.GetLibrary().PCIVendorIDs.All(value => videoCardVendors.Contains(value)))
|
||||||
{
|
{
|
||||||
SharedLogger.logger.Debug($"ProfileRepository/ProfileRepository: Initialising the NVIDIA NVAPI library.");
|
// Initialise the the NVIDIA NvAPI Library
|
||||||
NVIDIALibrary = new NVIDIALibrary();
|
try
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Debug($"ProfileRepository/ProfileRepository: Initialising the NVIDIA NVAPI library.");
|
||||||
|
nvidiaLibrary = new NVIDIALibrary();
|
||||||
|
_videoMode = VIDEO_MODE.NVIDIA;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn(ex, $"ProfileRepository/ProfileRepository: Initialising NVIDIA NVAPI caused an exception.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
else if (!NVIDIALibrary.GetLibrary().PCIVendorIDs.All(value => videoCardVendors.Contains(value)))
|
||||||
{
|
{
|
||||||
SharedLogger.logger.Warn(ex, $"ProfileRepository/ProfileRepository: Initialising NVIDIA NVAPI caused an exception.");
|
// Initialise the the AMD ADL Library
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Debug($"ProfileRepository/ProfileRepository: Initialising the AMD ADL library.");
|
||||||
|
amdLibrary = new AMDLibrary();
|
||||||
|
_videoMode = VIDEO_MODE.AMD;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SharedLogger.logger.Warn(ex, $"ProfileRepository/ProfileRepository: Initialising AMD ADL caused an exception.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialise the the AMD ADLWrapper
|
|
||||||
try
|
|
||||||
{
|
|
||||||
SharedLogger.logger.Debug($"ProfileRepository/ProfileRepository: Initialising the AMD ADL library.");
|
|
||||||
AMDLibrary = new AMDLibrary();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
SharedLogger.logger.Warn(ex, $"ProfileRepository/ProfileRepository: Initialising AMD ADL caused an exception.");
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Create the Profile Storage Path if it doesn't exist so that it's avilable for all the program
|
// Create the Profile Storage Path if it doesn't exist so that it's avilable for all the program
|
||||||
@ -157,6 +180,18 @@ namespace DisplayMagicianShared
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static VIDEO_MODE VideoMode
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _videoMode;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_videoMode = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static List<string> ConnectedDisplayIdentifiers
|
public static List<string> ConnectedDisplayIdentifiers
|
||||||
{
|
{
|
||||||
@ -667,12 +702,12 @@ namespace DisplayMagicianShared
|
|||||||
SharedLogger.logger.Error(ex, $"ProfileRepository/LoadProfiles: Tried to parse the JSON in the {_profileStorageJsonFileName} but the JsonConvert threw an exception.");
|
SharedLogger.logger.Error(ex, $"ProfileRepository/LoadProfiles: Tried to parse the JSON in the {_profileStorageJsonFileName} but the JsonConvert threw an exception.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Populate the Current Profile now so we have stuff to compare against
|
||||||
ProfileItem myCurrentProfile = new NVIDIAProfileItem
|
ProfileItem myCurrentProfile = new NVIDIAProfileItem
|
||||||
{
|
{
|
||||||
Name = "Current Display Profile",
|
Name = "Current Display Profile",
|
||||||
Paths = PathInfo.GetActivePaths().Select(info => new DisplayMagicianShared.Topology.Path(info)).ToArray()
|
|
||||||
};
|
};
|
||||||
|
myCurrentProfile.CreateProfileFromCurrentDisplaySettings();
|
||||||
_currentProfile = myCurrentProfile;
|
_currentProfile = myCurrentProfile;
|
||||||
|
|
||||||
SharedLogger.logger.Debug($"ProfileRepository/LoadProfiles: Finding the current profile in the Profile Repository");
|
SharedLogger.logger.Debug($"ProfileRepository/LoadProfiles: Finding the current profile in the Profile Repository");
|
||||||
@ -683,14 +718,28 @@ namespace DisplayMagicianShared
|
|||||||
{
|
{
|
||||||
if (loadedProfile.Driver.Equals("AMD"))
|
if (loadedProfile.Driver.Equals("AMD"))
|
||||||
{
|
{
|
||||||
|
// NVIDIA config!
|
||||||
|
NVIDIAProfileItem nvidiaLoadedProfile = (NVIDIAProfileItem)loadedProfile;
|
||||||
|
nvidiaLoadedProfile.PerformPostLoadingTasks();
|
||||||
|
if (ProfileRepository.IsActiveProfile(nvidiaLoadedProfile))
|
||||||
|
_currentProfile = nvidiaLoadedProfile;
|
||||||
|
}
|
||||||
|
else if (loadedProfile.Driver.Equals("AMD"))
|
||||||
|
{
|
||||||
|
// AMD config!
|
||||||
AMDProfileItem amdLoadedProfile = (AMDProfileItem) loadedProfile;
|
AMDProfileItem amdLoadedProfile = (AMDProfileItem) loadedProfile;
|
||||||
amdLoadedProfile.PerformPostLoadingTasks();
|
amdLoadedProfile.PerformPostLoadingTasks();
|
||||||
|
if (ProfileRepository.IsActiveProfile(amdLoadedProfile))
|
||||||
|
_currentProfile = amdLoadedProfile;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (ProfileRepository.IsActiveProfile(loadedProfile))
|
// Windows CCD config!
|
||||||
_currentProfile = loadedProfile;
|
WinProfileItem winLoadedProfile = (WinProfileItem)loadedProfile;
|
||||||
|
winLoadedProfile.PerformPostLoadingTasks();
|
||||||
|
if (ProfileRepository.IsActiveProfile(winLoadedProfile))
|
||||||
|
_currentProfile = winLoadedProfile;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort the profiles alphabetically
|
// Sort the profiles alphabetically
|
||||||
|
@ -1,239 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Drawing;
|
|
||||||
using System.Linq;
|
|
||||||
using WindowsDisplayAPI.DisplayConfig;
|
|
||||||
using WindowsDisplayAPI.Native.DisplayConfig;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Converters;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace DisplayMagicianShared.Topology
|
|
||||||
{
|
|
||||||
public class Path
|
|
||||||
{
|
|
||||||
public Path(PathInfo pathInfo)
|
|
||||||
{
|
|
||||||
SourceId = pathInfo.DisplaySource.SourceId;
|
|
||||||
PixelFormat = pathInfo.PixelFormat;
|
|
||||||
Position = pathInfo.Position;
|
|
||||||
Resolution = pathInfo.Resolution;
|
|
||||||
TargetDisplays = pathInfo.TargetsInfo.Select(targetDisplay => new PathTarget(targetDisplay)).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Path()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonConverter(typeof(StringEnumConverter))]
|
|
||||||
public DisplayConfigPixelFormat PixelFormat { get; set; }
|
|
||||||
|
|
||||||
public Point Position { get; set; }
|
|
||||||
|
|
||||||
public Size Resolution { get; set; }
|
|
||||||
|
|
||||||
public uint SourceId { get; set; }
|
|
||||||
|
|
||||||
public PathTarget[] TargetDisplays { get; set; }
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"\\\\.\\DISPLAY{SourceId}";
|
|
||||||
}
|
|
||||||
|
|
||||||
public PathInfo ToPathInfo()
|
|
||||||
{
|
|
||||||
var targetDisplays = TargetDisplays.Select(target => target.ToPathTargetInfo()).Where(info => info != null).ToArray();
|
|
||||||
|
|
||||||
if (targetDisplays.Any())
|
|
||||||
{
|
|
||||||
return new PathInfo(new PathDisplaySource(targetDisplays.First().DisplayTarget.Adapter, SourceId), Position,
|
|
||||||
Resolution, PixelFormat, targetDisplays);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The public override for the Object.Equals
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
return this.Equals(obj as Path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Profiles are equal if their contents (except name) are equal
|
|
||||||
public bool Equals(Path other)
|
|
||||||
{
|
|
||||||
|
|
||||||
// If parameter is null, return false.
|
|
||||||
if (Object.ReferenceEquals(other, null))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Optimization for a common success case.
|
|
||||||
if (Object.ReferenceEquals(this, other))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// If run-time types are not exactly the same, return false.
|
|
||||||
if (this.GetType() != other.GetType())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Check whether the Profile Viewport properties are equal
|
|
||||||
// Two profiles are equal only when they have the same viewport data exactly
|
|
||||||
if (PixelFormat == other.PixelFormat &&
|
|
||||||
Position.Equals(other.Position) &&
|
|
||||||
Resolution.Equals(other.Resolution) &&
|
|
||||||
SourceId == other.SourceId)
|
|
||||||
{
|
|
||||||
// If the above all match, then we need to check the DisplayTargets
|
|
||||||
foreach (PathTarget myTargetDisplay in TargetDisplays)
|
|
||||||
{
|
|
||||||
if (!other.TargetDisplays.Contains(myTargetDisplay))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If Equals() returns true for this object compared to another
|
|
||||||
// then GetHashCode() must return the same value for these objects.
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
// Get hash code for the PixelFormat field if it is not null.
|
|
||||||
int hashPixelFormat = PixelFormat.GetHashCode();
|
|
||||||
|
|
||||||
// Get hash code for the Position field if it is not null.
|
|
||||||
int hashPosition = Position == null ? 0 : Position.GetHashCode();
|
|
||||||
|
|
||||||
// Get hash code for the Resolution field if it is not null.
|
|
||||||
int hashResolution = Resolution == null ? 0 : Resolution.GetHashCode();
|
|
||||||
|
|
||||||
// Get hash code for the SourceId field if it is not null.
|
|
||||||
int hashSourceId = SourceId.GetHashCode();
|
|
||||||
|
|
||||||
// Get hash code for the TargetDisplays field if it is not null.
|
|
||||||
int hashTargetDisplays = TargetDisplays == null ? 0 : TargetDisplays.GetHashCode();
|
|
||||||
|
|
||||||
//Calculate the hash code for the product.
|
|
||||||
return hashPixelFormat ^ hashPosition ^ hashResolution ^ hashSourceId ^ hashTargetDisplays;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsPossible(Path other)
|
|
||||||
{
|
|
||||||
|
|
||||||
// If parameter is null, return false.
|
|
||||||
if (Object.ReferenceEquals(other, null))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Optimization for a common success case.
|
|
||||||
if (Object.ReferenceEquals(this, other))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// If run-time types are not exactly the same, return false.
|
|
||||||
if (this.GetType() != other.GetType())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Check whether the Profile Viewport properties are equal
|
|
||||||
// Two profiles are equal only when they have the same viewport data exactly
|
|
||||||
/*if (PixelFormat == other.PixelFormat &&
|
|
||||||
Position.Equals(other.Position) &&
|
|
||||||
Resolution.Equals(other.Resolution) &&
|
|
||||||
SourceId == other.SourceId)*/
|
|
||||||
// Note: Removed the source ID as it changes on boot sometimes!
|
|
||||||
// It can change and the profiles can still be the same
|
|
||||||
if (PixelFormat == other.PixelFormat &&
|
|
||||||
Position.Equals(other.Position) &&
|
|
||||||
Resolution.Equals(other.Resolution))
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ContainsSurround()
|
|
||||||
{
|
|
||||||
foreach (PathTarget pathTarget in TargetDisplays)
|
|
||||||
{
|
|
||||||
if (pathTarget.SurroundTopology == null)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Custom comparer for the ProfileViewport class
|
|
||||||
class PathComparer : IEqualityComparer<Path>
|
|
||||||
{
|
|
||||||
// Products are equal if their names and product numbers are equal.
|
|
||||||
public bool Equals(Path x, Path y)
|
|
||||||
{
|
|
||||||
|
|
||||||
//Check whether the compared objects reference the same data.
|
|
||||||
if (Object.ReferenceEquals(x, y)) return true;
|
|
||||||
|
|
||||||
//Check whether any of the compared objects is null.
|
|
||||||
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Check whether the Profile Viewport properties are equal
|
|
||||||
// Two profiles are equal only when they have the same viewport data exactly
|
|
||||||
/*if (x.PixelFormat == y.PixelFormat &&
|
|
||||||
x.Position.Equals(y.Position) &&
|
|
||||||
x.Resolution.Equals(y.Resolution) &&
|
|
||||||
x.SourceId == y.SourceId)*/
|
|
||||||
// Note: Removed the source ID as it changes on boot sometimes!
|
|
||||||
// It can change and the profiles can still be the same
|
|
||||||
if (x.PixelFormat == y.PixelFormat &&
|
|
||||||
x.Position.Equals(y.Position) &&
|
|
||||||
x.Resolution.Equals(y.Resolution) &&
|
|
||||||
x.SourceId == y.SourceId)
|
|
||||||
{
|
|
||||||
// If the above all match, then we need to check the DisplayTargets
|
|
||||||
// If they aren't equal then we need to return false;
|
|
||||||
/*if (!x.TargetDisplays.SequenceEqual(y.TargetDisplays))
|
|
||||||
return false;
|
|
||||||
else
|
|
||||||
return true;*/
|
|
||||||
foreach (PathTarget xTargetDisplay in x.TargetDisplays)
|
|
||||||
{
|
|
||||||
if (!y.TargetDisplays.Contains(xTargetDisplay))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/*foreach (PathTarget yTargetDisplay in y.TargetDisplays)
|
|
||||||
{
|
|
||||||
if (!x.TargetDisplays.Contains(yTargetDisplay))
|
|
||||||
return false;
|
|
||||||
}*/
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If Equals() returns true for a pair of objects
|
|
||||||
// then GetHashCode() must return the same value for these objects.
|
|
||||||
public int GetHashCode(Path profileViewport)
|
|
||||||
{
|
|
||||||
// Check whether the object is null
|
|
||||||
if (Object.ReferenceEquals(profileViewport, null)) return 0;
|
|
||||||
|
|
||||||
// Get hash code for the PixelFormat field if it is not null.
|
|
||||||
int hashPixelFormat = profileViewport.PixelFormat.GetHashCode();
|
|
||||||
|
|
||||||
// Get hash code for the Position field if it is not null.
|
|
||||||
int hashPosition = profileViewport.Position == null ? 0 : profileViewport.Position.GetHashCode();
|
|
||||||
|
|
||||||
// Get hash code for the Resolution field if it is not null.
|
|
||||||
int hashResolution = profileViewport.Resolution == null ? 0 : profileViewport.Resolution.GetHashCode();
|
|
||||||
|
|
||||||
// Get hash code for the SourceId field if it is not null.
|
|
||||||
int hashSourceId = profileViewport.SourceId.GetHashCode();
|
|
||||||
|
|
||||||
// Get hash code for the TargetDisplays field if it is not null.
|
|
||||||
int hashTargetDisplays = profileViewport.TargetDisplays == null ? 0 : profileViewport.TargetDisplays.GetHashCode();
|
|
||||||
|
|
||||||
//Calculate the hash code for the product.
|
|
||||||
return hashPixelFormat ^ hashPosition ^ hashResolution ^ hashSourceId ^ hashTargetDisplays;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,147 +0,0 @@
|
|||||||
using WindowsDisplayAPI.Native.DisplayConfig;
|
|
||||||
|
|
||||||
namespace DisplayMagicianShared.Topology
|
|
||||||
{
|
|
||||||
internal static class PathHelper
|
|
||||||
{
|
|
||||||
public static DisplayConfigRotation ToDisplayConfigRotation(this Rotation rotation)
|
|
||||||
{
|
|
||||||
switch (rotation)
|
|
||||||
{
|
|
||||||
case Rotation.Identity:
|
|
||||||
|
|
||||||
return DisplayConfigRotation.Identity;
|
|
||||||
case Rotation.Rotate90:
|
|
||||||
|
|
||||||
return DisplayConfigRotation.Rotate90;
|
|
||||||
case Rotation.Rotate180:
|
|
||||||
|
|
||||||
return DisplayConfigRotation.Rotate180;
|
|
||||||
case Rotation.Rotate270:
|
|
||||||
|
|
||||||
return DisplayConfigRotation.Rotate270;
|
|
||||||
default:
|
|
||||||
|
|
||||||
return DisplayConfigRotation.NotSpecified;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static DisplayConfigScaling ToDisplayConfigScaling(this Scaling scaling)
|
|
||||||
{
|
|
||||||
switch (scaling)
|
|
||||||
{
|
|
||||||
case Scaling.Identity:
|
|
||||||
|
|
||||||
return DisplayConfigScaling.Identity;
|
|
||||||
case Scaling.Centered:
|
|
||||||
|
|
||||||
return DisplayConfigScaling.Centered;
|
|
||||||
case Scaling.Stretched:
|
|
||||||
|
|
||||||
return DisplayConfigScaling.Stretched;
|
|
||||||
case Scaling.AspectRatioCenteredMax:
|
|
||||||
|
|
||||||
return DisplayConfigScaling.AspectRatioCenteredMax;
|
|
||||||
case Scaling.Custom:
|
|
||||||
|
|
||||||
return DisplayConfigScaling.Custom;
|
|
||||||
case Scaling.Preferred:
|
|
||||||
|
|
||||||
return DisplayConfigScaling.Preferred;
|
|
||||||
default:
|
|
||||||
|
|
||||||
return DisplayConfigScaling.NotSpecified;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DisplayConfigScanLineOrdering ToDisplayConfigScanLineOrdering(
|
|
||||||
this ScanLineOrdering scanLineOrdering)
|
|
||||||
{
|
|
||||||
switch (scanLineOrdering)
|
|
||||||
{
|
|
||||||
case ScanLineOrdering.Progressive:
|
|
||||||
|
|
||||||
return DisplayConfigScanLineOrdering.Progressive;
|
|
||||||
case ScanLineOrdering.InterlacedWithUpperFieldFirst:
|
|
||||||
|
|
||||||
return DisplayConfigScanLineOrdering.InterlacedWithUpperFieldFirst;
|
|
||||||
case ScanLineOrdering.InterlacedWithLowerFieldFirst:
|
|
||||||
|
|
||||||
return DisplayConfigScanLineOrdering.InterlacedWithLowerFieldFirst;
|
|
||||||
default:
|
|
||||||
|
|
||||||
return DisplayConfigScanLineOrdering.NotSpecified;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Rotation ToRotation(this DisplayConfigRotation rotation)
|
|
||||||
{
|
|
||||||
switch (rotation)
|
|
||||||
{
|
|
||||||
case DisplayConfigRotation.Identity:
|
|
||||||
|
|
||||||
return Rotation.Identity;
|
|
||||||
case DisplayConfigRotation.Rotate90:
|
|
||||||
|
|
||||||
return Rotation.Rotate90;
|
|
||||||
case DisplayConfigRotation.Rotate180:
|
|
||||||
|
|
||||||
return Rotation.Rotate180;
|
|
||||||
case DisplayConfigRotation.Rotate270:
|
|
||||||
|
|
||||||
return Rotation.Rotate270;
|
|
||||||
default:
|
|
||||||
|
|
||||||
return Rotation.Unknown;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Scaling ToScaling(this DisplayConfigScaling scaling)
|
|
||||||
{
|
|
||||||
switch (scaling)
|
|
||||||
{
|
|
||||||
case DisplayConfigScaling.Identity:
|
|
||||||
|
|
||||||
return Scaling.Identity;
|
|
||||||
case DisplayConfigScaling.Centered:
|
|
||||||
|
|
||||||
return Scaling.Centered;
|
|
||||||
case DisplayConfigScaling.Stretched:
|
|
||||||
|
|
||||||
return Scaling.Stretched;
|
|
||||||
case DisplayConfigScaling.AspectRatioCenteredMax:
|
|
||||||
|
|
||||||
return Scaling.AspectRatioCenteredMax;
|
|
||||||
case DisplayConfigScaling.Custom:
|
|
||||||
|
|
||||||
return Scaling.Custom;
|
|
||||||
case DisplayConfigScaling.Preferred:
|
|
||||||
|
|
||||||
return Scaling.Preferred;
|
|
||||||
default:
|
|
||||||
|
|
||||||
return Scaling.NotSpecified;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ScanLineOrdering ToScanLineOrdering(this DisplayConfigScanLineOrdering scanLineOrdering)
|
|
||||||
{
|
|
||||||
switch (scanLineOrdering)
|
|
||||||
{
|
|
||||||
case DisplayConfigScanLineOrdering.Progressive:
|
|
||||||
|
|
||||||
return ScanLineOrdering.Progressive;
|
|
||||||
case DisplayConfigScanLineOrdering.InterlacedWithUpperFieldFirst:
|
|
||||||
|
|
||||||
return ScanLineOrdering.InterlacedWithUpperFieldFirst;
|
|
||||||
case DisplayConfigScanLineOrdering.InterlacedWithLowerFieldFirst:
|
|
||||||
|
|
||||||
return ScanLineOrdering.InterlacedWithLowerFieldFirst;
|
|
||||||
default:
|
|
||||||
|
|
||||||
return ScanLineOrdering.NotSpecified;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,273 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using WindowsDisplayAPI.DisplayConfig;
|
|
||||||
using DisplayMagicianShared.NVIDIA;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Converters;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace DisplayMagicianShared.Topology
|
|
||||||
{
|
|
||||||
public class PathTarget : IEquatable<PathTarget>
|
|
||||||
{
|
|
||||||
public PathTarget(PathTargetInfo targetInfo, SurroundTopology surround = null)
|
|
||||||
{
|
|
||||||
DevicePath = targetInfo.DisplayTarget.DevicePath;
|
|
||||||
var index = DevicePath.IndexOf("{", StringComparison.InvariantCultureIgnoreCase);
|
|
||||||
|
|
||||||
if (index > 0)
|
|
||||||
{
|
|
||||||
DevicePath = DevicePath.Substring(0, index).TrimEnd('#');
|
|
||||||
SharedLogger.logger.Trace($"PathTarget/PathTarget: Grabbed the DevicePath of {DevicePath}.");
|
|
||||||
}
|
|
||||||
|
|
||||||
FrequencyInMillihertz = targetInfo.FrequencyInMillihertz;
|
|
||||||
SharedLogger.logger.Trace($"PathTarget/PathTarget: Grabbed the FrequencyInMillihertz of {FrequencyInMillihertz}.");
|
|
||||||
Rotation = targetInfo.Rotation.ToRotation();
|
|
||||||
SharedLogger.logger.Trace($"PathTarget/PathTarget: Grabbed the Rotation of {Rotation}.");
|
|
||||||
Scaling = targetInfo.Scaling.ToScaling();
|
|
||||||
SharedLogger.logger.Trace($"PathTarget/PathTarget: Grabbed the Scaling of {Scaling}.");
|
|
||||||
ScanLineOrdering = targetInfo.ScanLineOrdering.ToScanLineOrdering();
|
|
||||||
SharedLogger.logger.Trace($"PathTarget/PathTarget: Grabbed the ScanLineOrdering of {ScanLineOrdering}.");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
DisplayName = targetInfo.DisplayTarget.FriendlyName;
|
|
||||||
SharedLogger.logger.Trace($"PathTarget/PathTarget: Grabbed the DisplayName of {DisplayName}.");
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
SharedLogger.logger.Warn(ex, $"PathTarget/PathTarget: Exception grabbing the DisplayName of {DisplayName} from the TargetInfo DisplayTarget.");
|
|
||||||
DisplayName = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (surround != null)
|
|
||||||
{
|
|
||||||
SharedLogger.logger.Trace($"PathTarget/PathTarget: This PathTarget supplied an NVIDIA surround object, so using the SurroundTopology supplied.");
|
|
||||||
SurroundTopology = surround;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
SurroundTopology = SurroundTopology.FromPathTargetInfo(targetInfo);
|
|
||||||
if (SurroundTopology != null)
|
|
||||||
{
|
|
||||||
SharedLogger.logger.Trace($"PathTarget/PathTarget: The SurroundTopology object supplied was null, so we created one ourselves. We found {SurroundTopology.Displays.Count()} displays involved in it {SurroundTopology.Columns}x{SurroundTopology.Rows}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SharedLogger.logger.Trace($"PathTarget/PathTarget: The SurroundTopology object supplied was null, so we tried to create one ourselves and failed. This is likely a non NVIDIA surround display profile.");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
SharedLogger.logger.Error(ex, $"PathTarget/PathTarget: A SurroundTopology object was not supplied, but we had an exception getting our own SurroundTopology from the PathTargetInfo object.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public PathTarget()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public string DevicePath { get; set; }
|
|
||||||
|
|
||||||
public string DisplayName { get; set; }
|
|
||||||
|
|
||||||
public ulong FrequencyInMillihertz { get; set; }
|
|
||||||
|
|
||||||
[JsonConverter(typeof(StringEnumConverter))]
|
|
||||||
public Rotation Rotation { get; set; }
|
|
||||||
|
|
||||||
[JsonConverter(typeof(StringEnumConverter))]
|
|
||||||
public Scaling Scaling { get; set; }
|
|
||||||
|
|
||||||
[JsonConverter(typeof(StringEnumConverter))]
|
|
||||||
public ScanLineOrdering ScanLineOrdering { get; set; }
|
|
||||||
|
|
||||||
public SurroundTopology SurroundTopology { get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return DisplayName ?? $"PathTarget {DevicePath}";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public PathTargetInfo ToPathTargetInfo()
|
|
||||||
{
|
|
||||||
var targetDevice =
|
|
||||||
PathDisplayTarget.GetDisplayTargets()
|
|
||||||
.FirstOrDefault(
|
|
||||||
target => target.DevicePath.StartsWith(DevicePath,
|
|
||||||
StringComparison.InvariantCultureIgnoreCase));
|
|
||||||
|
|
||||||
if (targetDevice == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new PathTargetInfo(new PathDisplayTarget(targetDevice.Adapter, targetDevice.TargetId),
|
|
||||||
FrequencyInMillihertz, ScanLineOrdering.ToDisplayConfigScanLineOrdering(),
|
|
||||||
Rotation.ToDisplayConfigRotation(), Scaling.ToDisplayConfigScaling());
|
|
||||||
}
|
|
||||||
|
|
||||||
// The public override for the Object.Equals
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
return this.Equals(obj as PathTarget);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Profiles are equal if their contents (except name) are equal
|
|
||||||
public bool Equals(PathTarget other)
|
|
||||||
{
|
|
||||||
|
|
||||||
// If parameter is null, return false.
|
|
||||||
if (Object.ReferenceEquals(other, null))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Optimization for a common success case.
|
|
||||||
if (Object.ReferenceEquals(this, other))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// If run-time types are not exactly the same, return false.
|
|
||||||
if (this.GetType() != other.GetType())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Check whether the Profile Viewport properties are equal
|
|
||||||
// Two profiles are equal only when they have the same viewport data exactly
|
|
||||||
if (FrequencyInMillihertz == other.FrequencyInMillihertz &&
|
|
||||||
Rotation.Equals(other.Rotation) &&
|
|
||||||
Scaling.Equals(other.Scaling) &&
|
|
||||||
ScanLineOrdering.Equals(other.ScanLineOrdering) &&
|
|
||||||
DisplayName.Equals(other.DisplayName) &&
|
|
||||||
DevicePath.Equals(other.DevicePath))
|
|
||||||
{
|
|
||||||
// If the above all match, then we need to check the SurroundTopology matches
|
|
||||||
if (SurroundTopology == null && other.SurroundTopology == null)
|
|
||||||
return true;
|
|
||||||
else if (SurroundTopology != null && other.SurroundTopology == null)
|
|
||||||
return false;
|
|
||||||
else if (SurroundTopology == null && other.SurroundTopology != null)
|
|
||||||
return false;
|
|
||||||
else if (SurroundTopology.Equals(other.SurroundTopology))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If Equals() returns true for this object compared to another
|
|
||||||
// then GetHashCode() must return the same value for these objects.
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
// Get hash code for the FrequencyInMillihertz field if it is not null.
|
|
||||||
int hashFrequencyInMillihertz = FrequencyInMillihertz.GetHashCode();
|
|
||||||
|
|
||||||
// Get hash code for the Position field if it is not null.
|
|
||||||
int hashRotation = Rotation.GetHashCode();
|
|
||||||
|
|
||||||
// Get hash code for the Scaling field if it is not null.
|
|
||||||
int hashScaling = Scaling.GetHashCode();
|
|
||||||
|
|
||||||
// Get hash code for the ScanLineOrdering field if it is not null.
|
|
||||||
int hashScanLineOrdering = ScanLineOrdering.GetHashCode();
|
|
||||||
|
|
||||||
// Get hash code for the hashDisplayName field if it is not null.
|
|
||||||
int hashDisplayName = DisplayName == null ? 0 : DisplayName.GetHashCode();
|
|
||||||
|
|
||||||
// Get hash code for the DevicePath field if it is not null.
|
|
||||||
int hashDevicePath = DevicePath == null ? 0 : DevicePath.GetHashCode();
|
|
||||||
|
|
||||||
// Get hash code for the SurroundTopology field if it is not null.
|
|
||||||
int hashSurroundTopology = SurroundTopology == null ? 0 : SurroundTopology.GetHashCode();
|
|
||||||
|
|
||||||
//Calculate the hash code for the product.
|
|
||||||
return hashFrequencyInMillihertz ^ hashRotation ^ hashScaling ^ hashScanLineOrdering ^
|
|
||||||
hashDisplayName ^ hashDevicePath ^ hashSurroundTopology;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom comparer for the ProfileViewportTargetDisplay class
|
|
||||||
class ProfileViewportTargetDisplayComparer : IEqualityComparer<PathTarget>
|
|
||||||
{
|
|
||||||
// Products are equal if their names and product numbers are equal.
|
|
||||||
public bool Equals(PathTarget x, PathTarget y)
|
|
||||||
{
|
|
||||||
|
|
||||||
//Check whether the compared objects reference the same data.
|
|
||||||
if (Object.ReferenceEquals(x, y)) return true;
|
|
||||||
|
|
||||||
//Check whether any of the compared objects is null.
|
|
||||||
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Check whether the Profile Viewport properties are equal
|
|
||||||
// Two profiles are equal only when they have the same viewport data exactly
|
|
||||||
if (x.FrequencyInMillihertz == y.FrequencyInMillihertz &&
|
|
||||||
x.Rotation.Equals(y.Rotation) &&
|
|
||||||
x.Scaling.Equals(y.Scaling) &&
|
|
||||||
x.ScanLineOrdering.Equals(y.ScanLineOrdering) &&
|
|
||||||
x.DisplayName.Equals(y.DisplayName) &&
|
|
||||||
x.DevicePath.Equals(y.DevicePath))
|
|
||||||
{
|
|
||||||
// If the above all match, then we need to check the SurroundTopology matches
|
|
||||||
if (x.SurroundTopology == null && y.SurroundTopology == null)
|
|
||||||
return true;
|
|
||||||
else if (x.SurroundTopology != null && y.SurroundTopology == null)
|
|
||||||
return false;
|
|
||||||
else if (x.SurroundTopology == null && y.SurroundTopology != null)
|
|
||||||
return false;
|
|
||||||
else if (x.SurroundTopology.Equals(y.SurroundTopology))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If Equals() returns true for a pair of objects
|
|
||||||
// then GetHashCode() must return the same value for these objects.
|
|
||||||
public int GetHashCode(PathTarget profileViewport)
|
|
||||||
{
|
|
||||||
// Check whether the object is null
|
|
||||||
if (Object.ReferenceEquals(profileViewport, null)) return 0;
|
|
||||||
|
|
||||||
// Get hash code for the FrequencyInMillihertz field if it is not null.
|
|
||||||
int hashFrequencyInMillihertz = profileViewport.FrequencyInMillihertz.GetHashCode();
|
|
||||||
|
|
||||||
// Get hash code for the Position field if it is not null.
|
|
||||||
int hashRotation = profileViewport.Rotation.GetHashCode();
|
|
||||||
|
|
||||||
// Get hash code for the Scaling field if it is not null.
|
|
||||||
int hashScaling = profileViewport.Scaling.GetHashCode();
|
|
||||||
|
|
||||||
// Get hash code for the ScanLineOrdering field if it is not null.
|
|
||||||
int hashScanLineOrdering = profileViewport.ScanLineOrdering.GetHashCode();
|
|
||||||
|
|
||||||
// Get hash code for the hashDisplayName field if it is not null.
|
|
||||||
int hashDisplayName = profileViewport.DisplayName == null ? 0 : profileViewport.DisplayName.GetHashCode();
|
|
||||||
|
|
||||||
// Get hash code for the DevicePath field if it is not null.
|
|
||||||
int hashDevicePath = profileViewport.DevicePath == null ? 0 : profileViewport.DevicePath.GetHashCode();
|
|
||||||
|
|
||||||
// Get hash code for the SurroundTopology field if it is not null.
|
|
||||||
int hashSurroundTopology = profileViewport.SurroundTopology == null ? 0 : profileViewport.SurroundTopology.GetHashCode();
|
|
||||||
|
|
||||||
//Calculate the hash code for the product.
|
|
||||||
return hashFrequencyInMillihertz ^ hashRotation ^ hashScaling ^ hashScanLineOrdering ^
|
|
||||||
hashDisplayName ^ hashDevicePath ^ hashSurroundTopology;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user