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()
|
||||
{
|
||||
// Check each display in this profile and make sure it's currently available
|
||||
int validDisplayCount = 0;
|
||||
|
||||
//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)
|
||||
// Check whether this profile is possible
|
||||
if (AMDLibrary.GetLibrary().IsPossibleConfig(_amdDisplayConfig))
|
||||
{
|
||||
|
||||
SharedLogger.logger.Debug($"ProfileRepository/IsPossibleRefresh: The profile {Name} is possible!");
|
||||
SharedLogger.logger.Debug($"ProfileRepository/IsPossibleRefresh: The AMD profile {Name} is possible!");
|
||||
_isPossible = true;
|
||||
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@ -304,11 +286,11 @@ namespace DisplayMagicianShared.AMD
|
||||
// Now we create the screens structure from the AMD profile information
|
||||
_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)
|
||||
{
|
||||
@ -515,26 +497,6 @@ namespace DisplayMagicianShared.AMD
|
||||
// Allows us to use 'Contains'
|
||||
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)
|
||||
{
|
||||
@ -585,21 +547,6 @@ namespace DisplayMagicianShared.AMD
|
||||
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
|
||||
public int GetHashCode(AMDProfileItem profile)
|
||||
{
|
||||
|
@ -68,10 +68,6 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
|
||||
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]
|
||||
public NVIDIA_DISPLAY_CONFIG NVIDIADisplayConfig
|
||||
{
|
||||
@ -225,35 +221,17 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
|
||||
public override void RefreshPossbility()
|
||||
{
|
||||
// Check each display in this profile and make sure it's currently available
|
||||
int validDisplayCount = 0;
|
||||
|
||||
//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)
|
||||
// Check whether this profile is possible
|
||||
if (NVIDIALibrary.GetLibrary().IsPossibleConfig(_nvidiaDisplayConfig))
|
||||
{
|
||||
|
||||
SharedLogger.logger.Debug($"ProfileRepository/IsPossibleRefresh: The profile {Name} is possible!");
|
||||
SharedLogger.logger.Debug($"ProfileRepository/IsPossibleRefresh: The NVIDIA profile {Name} is possible!");
|
||||
_isPossible = true;
|
||||
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@ -294,7 +272,7 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
// Now we create the screens structure from the AMD profile information
|
||||
_screens = new List<ScreenPosition>();
|
||||
|
||||
if (_displayConfig. .Count > 0)
|
||||
if (_displayConfig.Count > 0)
|
||||
{
|
||||
foreach (var adapter in _displayConfig.AdapterConfigs)
|
||||
{
|
||||
@ -390,7 +368,12 @@ namespace DisplayMagicianShared.NVIDIA
|
||||
if (this.GetType() != other.GetType())
|
||||
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;
|
||||
|
||||
// Check if the profile identifiers are not the same, then return false
|
||||
|
@ -13,7 +13,16 @@ using DisplayMagicianShared.Windows;
|
||||
|
||||
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
|
||||
{
|
||||
@ -26,9 +35,11 @@ namespace DisplayMagicianShared
|
||||
private static ProfileItem _currentProfile;
|
||||
private static List<string> _connectedDisplayIdentifiers = new List<string>();
|
||||
private static bool notifiedEDIDErrorToUser = false;
|
||||
private static AMDLibrary AMDLibrary;
|
||||
private static NVIDIALibrary NVIDIALibrary;
|
||||
//private static bool _isLoading = false;
|
||||
private static AMDLibrary amdLibrary;
|
||||
private static NVIDIALibrary nvidiaLibrary;
|
||||
private static WinLibrary winLibrary;
|
||||
// Make th default video mode Windows
|
||||
public static VIDEO_MODE _videoMode = VIDEO_MODE.WINDOWS;
|
||||
|
||||
// Other constants that are useful
|
||||
public static string AppDataPath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "DisplayMagician");
|
||||
@ -43,29 +54,41 @@ namespace DisplayMagicianShared
|
||||
#region Class Constructors
|
||||
static ProfileRepository()
|
||||
{
|
||||
|
||||
// Initialise the the NVIDIA NvAPIWrapper
|
||||
try
|
||||
// Figure out the Video Cards and see what mode we want
|
||||
// Get a list of all the PCI Vendor IDs
|
||||
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.");
|
||||
NVIDIALibrary = new NVIDIALibrary();
|
||||
// Initialise the the NVIDIA NvAPI Library
|
||||
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
|
||||
{
|
||||
// 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
|
||||
{
|
||||
@ -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.");
|
||||
}
|
||||
|
||||
// Populate the Current Profile now so we have stuff to compare against
|
||||
ProfileItem myCurrentProfile = new NVIDIAProfileItem
|
||||
{
|
||||
Name = "Current Display Profile",
|
||||
Paths = PathInfo.GetActivePaths().Select(info => new DisplayMagicianShared.Topology.Path(info)).ToArray()
|
||||
};
|
||||
|
||||
myCurrentProfile.CreateProfileFromCurrentDisplaySettings();
|
||||
_currentProfile = myCurrentProfile;
|
||||
|
||||
SharedLogger.logger.Debug($"ProfileRepository/LoadProfiles: Finding the current profile in the Profile Repository");
|
||||
@ -683,14 +718,28 @@ namespace DisplayMagicianShared
|
||||
{
|
||||
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;
|
||||
amdLoadedProfile.PerformPostLoadingTasks();
|
||||
if (ProfileRepository.IsActiveProfile(amdLoadedProfile))
|
||||
_currentProfile = amdLoadedProfile;
|
||||
}
|
||||
|
||||
|
||||
if (ProfileRepository.IsActiveProfile(loadedProfile))
|
||||
_currentProfile = loadedProfile;
|
||||
|
||||
else
|
||||
{
|
||||
// Windows CCD config!
|
||||
WinProfileItem winLoadedProfile = (WinProfileItem)loadedProfile;
|
||||
winLoadedProfile.PerformPostLoadingTasks();
|
||||
if (ProfileRepository.IsActiveProfile(winLoadedProfile))
|
||||
_currentProfile = winLoadedProfile;
|
||||
}
|
||||
}
|
||||
|
||||
// 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