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-06-22 09:05:24 +00:00
public class AMDProfileItem : ProfileItem , IComparable
{
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-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-06-22 09:05:24 +00:00
// The public override for the Object.Equals
public override bool Equals ( object obj )
{
return this . Equals ( obj as AMDProfileItem ) ;
}
// Profiles are equal if their Viewports are equal
public bool Equals ( AMDProfileItem other )
{
// If parameter is null, return false.
if ( other is 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 ;
2021-08-22 04:49:38 +00:00
// If AMD Display Config is different then return false.
2021-08-22 00:54:39 +00:00
if ( ! AMDDisplayConfig . Equals ( other . AMDDisplayConfig ) )
return false ;
2021-08-22 04:49:38 +00:00
// If Windows Display Config is different then return false.
2021-08-22 00:54:39 +00:00
if ( ! WindowsDisplayConfig . Equals ( other . WindowsDisplayConfig ) )
2021-06-22 09:05:24 +00:00
return false ;
2021-08-22 04:49:38 +00:00
// If Display Identifiers are different then return false.
if ( ! ProfileDisplayIdentifiers . SequenceEqual ( other . ProfileDisplayIdentifiers ) )
2021-06-22 09:05:24 +00:00
return false ;
2021-08-22 04:49:38 +00:00
// Otherwise if all the tests work, then we're good!
return true ;
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-06-22 09:05:24 +00:00
}
}
2021-08-22 04:49:38 +00:00
2021-06-22 09:05:24 +00:00
}