2021-06-22 09:05:24 +00:00
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.Linq ;
using System.Windows.Forms ;
using DisplayMagicianShared.Resources ;
using Newtonsoft.Json ;
using System.Drawing ;
2021-08-22 00:54:39 +00:00
using DisplayMagicianShared.Windows ;
2021-08-22 09:45:51 +00:00
using System.Drawing.Imaging ;
2021-06-22 09:05:24 +00:00
namespace DisplayMagicianShared.AMD
{
2021-06-27 01:53:00 +00:00
2021-09-04 08:58:08 +00:00
public class AMDProfileItem : ProfileItem
2021-06-22 09:05:24 +00:00
{
private static List < AMDProfileItem > _allSavedProfiles = new List < AMDProfileItem > ( ) ;
private ProfileIcon _profileIcon ;
private Bitmap _profileBitmap , _profileShortcutBitmap ;
private List < string > _profileDisplayIdentifiers = new List < string > ( ) ;
2021-06-24 10:14:39 +00:00
private List < ScreenPosition > _screens ;
2021-08-22 00:54:39 +00:00
private AMD_DISPLAY_CONFIG _amdDisplayConfig = new AMD_DISPLAY_CONFIG ( ) ;
private WINDOWS_DISPLAY_CONFIG _windowsDisplayConfig = new WINDOWS_DISPLAY_CONFIG ( ) ;
2021-06-22 09:05:24 +00:00
private static readonly string uuidV4Regex = @"(?im)^[{(]?[0-9A-F]{8}[-]?(?:[0-9A-F]{4}[-]?){3}[0-9A-F]{12}[)}]?$" ;
private string _uuid = "" ;
private bool _isPossible = false ;
private Keys _hotkey = Keys . None ;
public AMDProfileItem ( )
{
}
public new static Version Version = new Version ( 2 , 1 ) ;
#region Instance Properties
[JsonIgnore]
public override bool IsPossible
{
get
{
// Return the cached answer
return _isPossible ;
}
set
{
_isPossible = value ;
}
}
[JsonIgnore]
public override bool IsActive
{
get
{
if ( this . Equals ( ProfileRepository . CurrentProfile ) )
return true ;
else
return false ;
}
}
2021-08-22 06:58:08 +00:00
public override VIDEO_MODE VideoMode { get ; } = VIDEO_MODE . AMD ;
2021-06-22 09:05:24 +00:00
public override string Name { get ; set ; }
2021-06-27 01:53:00 +00:00
[JsonRequired]
2021-08-22 00:54:39 +00:00
public AMD_DISPLAY_CONFIG AMDDisplayConfig
2021-06-25 09:52:02 +00:00
{
get
{
2021-08-22 00:54:39 +00:00
return _amdDisplayConfig ;
2021-06-25 09:52:02 +00:00
}
set
{
2021-08-22 00:54:39 +00:00
_amdDisplayConfig = value ;
}
}
[JsonRequired]
public WINDOWS_DISPLAY_CONFIG WindowsDisplayConfig
{
get
{
return _windowsDisplayConfig ;
}
set
{
_windowsDisplayConfig = value ;
2021-06-25 09:52:02 +00:00
}
}
2021-08-22 00:54:39 +00:00
2021-06-22 09:05:24 +00:00
public override List < string > ProfileDisplayIdentifiers
{
get
{
if ( _profileDisplayIdentifiers . Count = = 0 )
{
2021-07-24 04:05:38 +00:00
_profileDisplayIdentifiers = AMDLibrary . GetLibrary ( ) . GetCurrentDisplayIdentifiers ( ) ;
2021-06-22 09:05:24 +00:00
}
return _profileDisplayIdentifiers ;
}
set
{
if ( value is List < string > )
_profileDisplayIdentifiers = value ;
}
}
#endregion
public override bool IsValid ( )
{
2021-08-22 04:49:38 +00:00
if ( AMDLibrary . GetLibrary ( ) . IsValidConfig ( _amdDisplayConfig ) & &
ProfileIcon is ProfileIcon & &
2021-06-22 09:05:24 +00:00
System . IO . File . Exists ( SavedProfileIconCacheFilename ) & &
ProfileBitmap is Bitmap & &
ProfileTightestBitmap is Bitmap & &
ProfileDisplayIdentifiers . Count > 0 )
{
2021-08-22 00:54:39 +00:00
if ( AMDDisplayConfig . AdapterConfigs . Count > 0 )
2021-06-22 09:05:24 +00:00
return true ;
else
return false ;
}
else
return false ;
}
public bool CopyTo ( AMDProfileItem profile , bool overwriteId = true )
{
if ( ! ( profile is AMDProfileItem ) )
return false ;
if ( overwriteId = = true )
profile . UUID = UUID ;
// Copy all our profile data over to the other profile
profile . Name = Name ;
2021-08-22 00:54:39 +00:00
profile . AMDDisplayConfig = AMDDisplayConfig ;
profile . WindowsDisplayConfig = WindowsDisplayConfig ;
2021-06-22 09:05:24 +00:00
profile . ProfileIcon = ProfileIcon ;
profile . SavedProfileIconCacheFilename = SavedProfileIconCacheFilename ;
profile . ProfileBitmap = ProfileBitmap ;
profile . ProfileTightestBitmap = ProfileTightestBitmap ;
profile . ProfileDisplayIdentifiers = ProfileDisplayIdentifiers ;
2021-06-27 02:44:10 +00:00
//profile.Screens = Screens;
2021-06-22 09:05:24 +00:00
return true ;
}
public override bool PreSave ( )
{
// Prepare our profile data for saving
if ( _profileDisplayIdentifiers . Count = = 0 )
{
2021-07-24 04:05:38 +00:00
_profileDisplayIdentifiers = AMDLibrary . GetLibrary ( ) . GetCurrentDisplayIdentifiers ( ) ;
2021-06-22 09:05:24 +00:00
}
// Return if it is valid and we should continue
return IsValid ( ) ;
}
2021-06-27 02:44:10 +00:00
public override void RefreshPossbility ( )
{
2021-08-22 03:42:12 +00:00
// Check whether this profile is possible
if ( AMDLibrary . GetLibrary ( ) . IsPossibleConfig ( _amdDisplayConfig ) )
2021-06-27 02:44:10 +00:00
{
2021-08-22 03:42:12 +00:00
SharedLogger . logger . Debug ( $"ProfileRepository/IsPossibleRefresh: The AMD profile {Name} is possible!" ) ;
2021-06-27 02:44:10 +00:00
_isPossible = true ;
}
else
{
2021-08-22 03:42:12 +00:00
SharedLogger . logger . Debug ( $"ProfileRepository/IsPossibleRefresh: The AMD profile {Name} is NOT possible!" ) ;
2021-06-27 02:44:10 +00:00
_isPossible = false ;
}
}
2021-08-24 10:46:32 +00:00
// Actually set this profile active
public override bool SetActive ( )
{
AMDLibrary amdLibrary = AMDLibrary . GetLibrary ( ) ;
WinLibrary winLibrary = WinLibrary . GetLibrary ( ) ;
if ( amdLibrary . IsInstalled )
{
if ( ! amdLibrary . IsActiveConfig ( _amdDisplayConfig ) & & ! winLibrary . IsActiveConfig ( _windowsDisplayConfig ) )
{
if ( amdLibrary . IsPossibleConfig ( _amdDisplayConfig ) )
{
SharedLogger . logger . Trace ( $"ProfileRepository/SetActive: The AMD display settings within profile {Name} are possible to use right now, so we'll use attempt to use them." ) ;
bool itWorkedforAMD = amdLibrary . SetActiveConfig ( _amdDisplayConfig ) ;
if ( itWorkedforAMD )
{
SharedLogger . logger . Trace ( $"ProfileRepository/SetActive: The AMD display settings within profile {Name} were successfully applied." ) ;
// Then let's try to also apply the windows changes
// Note: we are unable to check if the Windows CCD display config is possible, as it won't match if either the current display config is a ADL config,
// or if the display config we want to change to is a ADL config. So we just have to assume that it will work!
bool itWorkedforWindows = winLibrary . SetActiveConfig ( _windowsDisplayConfig ) ;
if ( itWorkedforWindows )
{
SharedLogger . logger . Trace ( $"ProfileRepository/SetActive: The Windows CCD display settings within profile {Name} were successfully applied." ) ;
return true ;
}
else
{
SharedLogger . logger . Trace ( $"ProfileRepository/SetActive: The Windows CCD display settings within profile {Name} were NOT applied correctly." ) ;
}
}
else
{
SharedLogger . logger . Trace ( $"ProfileRepository/SetActive: The AMD display settings within profile {Name} were NOT applied correctly." ) ;
}
}
else
{
SharedLogger . logger . Error ( $"ProfileRepository/SetActive: ERROR - Cannot apply the AMD display config in profile {Name} as it is not currently possible to use it." ) ;
}
}
else
{
SharedLogger . logger . Info ( $"ProfileRepository/SetActive: The display settings in profile {Name} are already installed. No need to install them again. Exiting." ) ;
}
}
return false ;
}
2021-06-26 09:54:11 +00:00
public override bool CreateProfileFromCurrentDisplaySettings ( )
2021-06-24 10:14:39 +00:00
{
2021-06-26 09:54:11 +00:00
AMDLibrary amdLibrary = AMDLibrary . GetLibrary ( ) ;
if ( amdLibrary . IsInstalled )
{
// Create the profile data from the current config
2021-08-22 00:54:39 +00:00
_amdDisplayConfig = amdLibrary . GetActiveConfig ( ) ;
_windowsDisplayConfig = WinLibrary . GetLibrary ( ) . GetActiveConfig ( ) ;
2021-09-05 09:00:36 +00:00
_profileDisplayIdentifiers = amdLibrary . GetCurrentDisplayIdentifiers ( ) ;
2021-06-26 09:54:11 +00:00
// Now, since the ActiveProfile has changed, we need to regenerate screen positions
_screens = GetScreenPositions ( ) ;
return true ;
}
else
2021-06-25 09:52:02 +00:00
{
2021-06-26 09:54:11 +00:00
return false ;
}
}
2021-06-27 02:44:10 +00:00
public override bool PerformPostLoadingTasks ( )
2021-06-27 01:53:00 +00:00
{
// First thing we do is to set up the Screens
_screens = GetScreenPositions ( ) ;
return true ;
}
2021-06-26 09:54:11 +00:00
public override List < ScreenPosition > GetScreenPositions ( )
{
// Now we create the screens structure from the AMD profile information
_screens = new List < ScreenPosition > ( ) ;
2021-06-25 09:52:02 +00:00
2021-08-22 04:49:38 +00:00
int pathCount = _windowsDisplayConfig . DisplayConfigPaths . Length ;
// First of all we need to figure out how many display paths we have.
if ( pathCount < 1 )
2021-06-26 09:54:11 +00:00
{
2021-08-22 04:49:38 +00:00
// Return an empty screen if we have no Display Config Paths to use!
return _screens ;
}
foreach ( var path in _windowsDisplayConfig . DisplayConfigPaths )
{
// For each path we go through and get the relevant info we need.
if ( _windowsDisplayConfig . DisplayConfigPaths . Length > 0 )
2021-06-25 09:52:02 +00:00
{
2021-08-22 04:49:38 +00:00
// Set some basics about the screen
ScreenPosition screen = new ScreenPosition ( ) ;
screen . Library = "NVIDIA" ;
UInt32 targetId = path . TargetInfo . Id ;
foreach ( DISPLAYCONFIG_MODE_INFO displayMode in _windowsDisplayConfig . DisplayConfigModes )
2021-06-25 09:52:02 +00:00
{
2021-08-22 04:49:38 +00:00
// Find the matching Display Config Source Mode
if ( displayMode . InfoType ! = DISPLAYCONFIG_MODE_INFO_TYPE . DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE & & displayMode . Id = = targetId )
2021-06-25 09:52:02 +00:00
{
2021-08-22 04:49:38 +00:00
screen . Name = targetId . ToString ( ) ;
//screen.DisplayConnector = displayMode.DisplayConnector;
screen . ScreenX = displayMode . SourceMode . Position . X ;
screen . ScreenY = displayMode . SourceMode . Position . Y ;
screen . ScreenWidth = ( int ) displayMode . SourceMode . Width ;
screen . ScreenHeight = ( int ) displayMode . SourceMode . Height ;
2021-06-27 01:53:00 +00:00
2021-06-29 10:15:57 +00:00
// If we're at the 0,0 coordinate then we're the primary monitor
if ( screen . ScreenX = = 0 & & screen . ScreenY = = 0 )
{
screen . IsPrimary = true ;
}
2021-08-22 04:49:38 +00:00
}
}
2021-06-29 10:15:57 +00:00
2021-08-22 04:49:38 +00:00
foreach ( ADVANCED_HDR_INFO_PER_PATH hdrInfo in _windowsDisplayConfig . DisplayHDRStates )
{
// Find the matching HDR information
if ( hdrInfo . Id = = targetId )
{
2021-06-27 01:53:00 +00:00
// HDR information
2021-08-22 04:49:38 +00:00
if ( hdrInfo . AdvancedColorInfo . AdvancedColorSupported )
2021-06-27 01:53:00 +00:00
{
screen . HDRSupported = true ;
2021-08-22 04:49:38 +00:00
if ( hdrInfo . AdvancedColorInfo . AdvancedColorEnabled )
2021-06-27 01:53:00 +00:00
{
screen . HDREnabled = true ;
}
else
{
screen . HDREnabled = false ;
}
2021-08-22 04:49:38 +00:00
2021-06-27 01:53:00 +00:00
}
else
{
screen . HDRSupported = false ;
screen . HDREnabled = false ;
}
2021-08-22 04:49:38 +00:00
}
}
2021-06-27 01:53:00 +00:00
2021-06-26 09:54:11 +00:00
2021-08-22 04:49:38 +00:00
// Now we need to check for Spanned screens
/ * if ( _amdDisplayConfig )
{
screen . IsSpanned = true ;
2021-08-22 06:58:08 +00:00
screen . Colour = Color . FromArgb ( 221 , 0 , 49 ) ; // represents AMD Red
screen . SpannedName = "AMD Eyefinity" ;
2021-08-22 04:49:38 +00:00
}
else
{
screen . IsSpanned = false ;
screen . Colour = Color . FromArgb ( 195 , 195 , 195 ) ; // represents normal screen colour
} * /
2021-06-27 01:53:00 +00:00
2021-08-22 04:49:38 +00:00
screen . IsSpanned = false ;
screen . Colour = Color . FromArgb ( 195 , 195 , 195 ) ; // represents normal screen colour
2021-06-26 09:54:11 +00:00
2021-08-22 04:49:38 +00:00
_screens . Add ( screen ) ;
2021-06-25 09:52:02 +00:00
}
}
2021-08-22 04:49:38 +00:00
2021-06-25 09:52:02 +00:00
return _screens ;
2021-06-24 10:14:39 +00:00
}
2021-09-04 08:58:08 +00:00
/ * public override int CompareTo ( object obj )
2021-06-22 09:05:24 +00:00
{
2021-09-04 04:32:42 +00:00
if ( ! ( obj is AMDProfileItem ) ) throw new ArgumentException ( "Object to CompareTo is not a AMDProfileItem" ) ; ;
2021-09-02 02:44:35 +00:00
AMDProfileItem otherProfile = ( AMDProfileItem ) obj ;
return this . Name . CompareTo ( otherProfile . Name ) ;
2021-09-04 08:58:08 +00:00
} * /
2021-06-22 09:05:24 +00:00
2021-09-02 02:44:35 +00:00
// The public override for the Object.Equals
2021-09-04 04:32:42 +00:00
public override bool Equals ( object obj )
{
return EqualsDerived ( obj ) & &
obj . GetType ( ) = = typeof ( AMDProfileItem ) ;
}
2021-09-02 02:44:35 +00:00
2021-06-22 09:05:24 +00:00
// Profiles are equal if their Viewports are equal
2021-09-04 04:32:42 +00:00
public override bool EqualsDerived ( object obj )
2021-06-22 09:05:24 +00:00
{
2021-09-04 04:32:42 +00:00
return base . EqualsDerived ( obj ) & &
! object . ReferenceEquals ( obj , null ) & &
obj is AMDProfileItem & &
( ( AMDProfileItem ) obj ) . AMDDisplayConfig = = this . AMDDisplayConfig & &
( ( AMDProfileItem ) obj ) . WindowsDisplayConfig = = this . WindowsDisplayConfig ;
2021-06-22 09:05:24 +00:00
}
public override int GetHashCode ( )
{
// Calculate the hash code for the product.
2021-08-22 04:49:38 +00:00
return ( AMDDisplayConfig , WindowsDisplayConfig , ProfileDisplayIdentifiers ) . GetHashCode ( ) ;
2021-09-02 02:44:35 +00:00
}
2021-06-22 09:05:24 +00:00
2021-09-02 02:44:35 +00:00
public static bool operator = = ( AMDProfileItem lhs , AMDProfileItem rhs )
{
2021-09-04 04:32:42 +00:00
if ( object . ReferenceEquals ( lhs , rhs ) )
return true ;
2021-09-02 02:44:35 +00:00
2021-09-04 04:32:42 +00:00
if ( ! object . ReferenceEquals ( lhs , null ) & &
! object . ReferenceEquals ( rhs , null ) & &
lhs . Equals ( rhs ) )
return true ;
return false ;
2021-06-22 09:05:24 +00:00
}
2021-09-02 02:44:35 +00:00
public static bool operator ! = ( AMDProfileItem lhs , AMDProfileItem rhs ) = > ! ( lhs = = rhs ) ;
2021-06-22 09:05:24 +00:00
}
2021-08-22 04:49:38 +00:00
2021-06-22 09:05:24 +00:00
}