diff --git a/DisplayMagicianShared/AMD/AMDProfileItem.cs b/DisplayMagicianShared/AMD/AMDProfileItem.cs index 9a5e168..ca9ff0a 100644 --- a/DisplayMagicianShared/AMD/AMDProfileItem.cs +++ b/DisplayMagicianShared/AMD/AMDProfileItem.cs @@ -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(); - 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 { - // 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) { diff --git a/DisplayMagicianShared/NVIDIA/NVIDIAProfileItem.cs b/DisplayMagicianShared/NVIDIA/NVIDIAProfileItem.cs index 4b71e63..ad3d150 100644 --- a/DisplayMagicianShared/NVIDIA/NVIDIAProfileItem.cs +++ b/DisplayMagicianShared/NVIDIA/NVIDIAProfileItem.cs @@ -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(); - 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 diff --git a/DisplayMagicianShared/ProfileRepository.cs b/DisplayMagicianShared/ProfileRepository.cs index bbf9d7a..59ec64e 100644 --- a/DisplayMagicianShared/ProfileRepository.cs +++ b/DisplayMagicianShared/ProfileRepository.cs @@ -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 _connectedDisplayIdentifiers = new List(); 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 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 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 diff --git a/DisplayMagicianShared/Topology/Path.cs b/DisplayMagicianShared/Topology/Path.cs deleted file mode 100644 index c3867b0..0000000 --- a/DisplayMagicianShared/Topology/Path.cs +++ /dev/null @@ -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 - { - // 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; - } - - } -} \ No newline at end of file diff --git a/DisplayMagicianShared/Topology/PathHelper.cs b/DisplayMagicianShared/Topology/PathHelper.cs deleted file mode 100644 index 3df3146..0000000 --- a/DisplayMagicianShared/Topology/PathHelper.cs +++ /dev/null @@ -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; - } - } - } -} \ No newline at end of file diff --git a/DisplayMagicianShared/Topology/PathTarget.cs b/DisplayMagicianShared/Topology/PathTarget.cs deleted file mode 100644 index 819b22a..0000000 --- a/DisplayMagicianShared/Topology/PathTarget.cs +++ /dev/null @@ -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 - { - 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; } - - /// - 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 - { - // 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; - } - - } -} \ No newline at end of file