[WIP] Fixed error loading JSON after save

There was a problem with the unused display config containing null values on save, which meant that the JSON would be invalid when loaded in the next time. The fix was to ensure that both NVIDIA and AMD both were filled with a default config when a new profiles was created. This means that the real config would overwrite whichever config was needed, and the JSON file would work as all objects were populated correctly!
This commit is contained in:
Terry MacDonald 2021-09-19 20:56:58 +12:00
parent 1591fd534e
commit cd71725617
4 changed files with 68 additions and 19 deletions

View File

@ -276,7 +276,22 @@ namespace DisplayMagicianShared.AMD
return _instance; return _instance;
} }
public AMD_DISPLAY_CONFIG CreateDefaultConfig()
{
AMD_DISPLAY_CONFIG myDefaultConfig = new AMD_DISPLAY_CONFIG();
// Fill in the minimal amount we need to avoid null references
// so that we won't break json.net when we save a default config
myDefaultConfig.AdapterConfigs = new List<AMD_ADAPTER_CONFIG>();
myDefaultConfig.SlsConfig.SLSMapConfigs = new List<AMD_SLSMAP_CONFIG>();
myDefaultConfig.SlsConfig.SLSEnabledDisplayTargets = new List<ADL_MODE>();
myDefaultConfig.DisplayTargets = new List<ADL_DISPLAY_TARGET>();
myDefaultConfig.HdrConfigs = new Dictionary<int, AMD_HDR_CONFIG>();
myDefaultConfig.DisplayIdentifiers = new List<string>();
return myDefaultConfig;
}
public AMD_DISPLAY_CONFIG GetActiveConfig() public AMD_DISPLAY_CONFIG GetActiveConfig()
{ {

View File

@ -286,7 +286,22 @@ namespace DisplayMagicianShared.NVIDIA
return _instance; return _instance;
} }
public NVIDIA_DISPLAY_CONFIG CreateDefaultConfig()
{
NVIDIA_DISPLAY_CONFIG myDefaultConfig = new NVIDIA_DISPLAY_CONFIG();
// Fill in the minimal amount we need to avoid null references
// so that we won't break json.net when we save a default config
myDefaultConfig.MosaicConfig.MosaicGridTopos = new NV_MOSAIC_GRID_TOPO_V2[0];
myDefaultConfig.MosaicConfig.MosaicViewports = new List<NV_RECT[]>();
myDefaultConfig.HdrConfig.HdrCapabilities = new Dictionary<uint, NV_HDR_CAPABILITIES_V2>();
myDefaultConfig.HdrConfig.HdrColorData = new Dictionary<uint, NV_HDR_COLOR_DATA_V2>();
myDefaultConfig.DisplayNames = new Dictionary<uint, string>();
myDefaultConfig.DisplayIdentifiers = new List<string>();
return myDefaultConfig;
}
public NVIDIA_DISPLAY_CONFIG GetActiveConfig() public NVIDIA_DISPLAY_CONFIG GetActiveConfig()
{ {

View File

@ -58,9 +58,9 @@ namespace DisplayMagicianShared
private Bitmap _profileBitmap, _profileShortcutBitmap; private Bitmap _profileBitmap, _profileShortcutBitmap;
private List<string> _profileDisplayIdentifiers = new List<string>(); private List<string> _profileDisplayIdentifiers = new List<string>();
private List<ScreenPosition> _screens = new List<ScreenPosition>(); private List<ScreenPosition> _screens = new List<ScreenPosition>();
private NVIDIA_DISPLAY_CONFIG _nvidiaDisplayConfig = new NVIDIA_DISPLAY_CONFIG(); private NVIDIA_DISPLAY_CONFIG _nvidiaDisplayConfig;
private AMD_DISPLAY_CONFIG _amdDisplayConfig = new AMD_DISPLAY_CONFIG(); private AMD_DISPLAY_CONFIG _amdDisplayConfig;
private WINDOWS_DISPLAY_CONFIG _windowsDisplayConfig = new WINDOWS_DISPLAY_CONFIG(); private WINDOWS_DISPLAY_CONFIG _windowsDisplayConfig;
internal static string AppDataPath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "DisplayMagician"); internal static string AppDataPath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "DisplayMagician");
private static string AppWallpaperPath = Path.Combine(AppDataPath, $"Wallpaper"); private static string AppWallpaperPath = Path.Combine(AppDataPath, $"Wallpaper");
@ -135,6 +135,14 @@ namespace DisplayMagicianShared
#endregion #endregion
public ProfileItem() public ProfileItem()
{ {
// Fill out a new NVIDIA and AMD object when a profile is being created
// so that it will save correctly. Json.NET will save null references by default
// unless we fill them up first, and that in turn causes NullReference errors when
// loading the DisplayProfiles_2.0.json into DisplayMagician next time.
// We cannot make the structs themselves create the default entry, so instead, we
// make each library create the default.
_nvidiaDisplayConfig = NVIDIALibrary.GetLibrary().CreateDefaultConfig();
_amdDisplayConfig = AMDLibrary.GetLibrary().CreateDefaultConfig();
} }
public static Version Version = new Version(2, 1); public static Version Version = new Version(2, 1);
@ -456,7 +464,10 @@ namespace DisplayMagicianShared
public bool CreateProfileFromCurrentDisplaySettings() public bool CreateProfileFromCurrentDisplaySettings()
{ {
if (VideoMode == VIDEO_MODE.NVIDIA) // Create defaults for NVIDIA and AMD so that the JSON file can save properly
// (C# Structs populate with default values which mean that arrays start with null)
if (VideoMode == VIDEO_MODE.NVIDIA && NVIDIALibrary.GetLibrary().IsInstalled)
{ {
NVIDIALibrary nvidiaLibrary = NVIDIALibrary.GetLibrary(); NVIDIALibrary nvidiaLibrary = NVIDIALibrary.GetLibrary();
if (nvidiaLibrary.IsInstalled) if (nvidiaLibrary.IsInstalled)
@ -476,7 +487,7 @@ namespace DisplayMagicianShared
return false; return false;
} }
} }
else if(VideoMode == VIDEO_MODE.AMD) else if(VideoMode == VIDEO_MODE.AMD && AMDLibrary.GetLibrary().IsInstalled)
{ {
AMDLibrary amdLibrary = AMDLibrary.GetLibrary(); AMDLibrary amdLibrary = AMDLibrary.GetLibrary();
if (amdLibrary.IsInstalled) if (amdLibrary.IsInstalled)
@ -664,7 +675,7 @@ namespace DisplayMagicianShared
// Actually set this profile active // Actually set this profile active
public bool SetActive() public bool SetActive()
{ {
if (VideoMode == VIDEO_MODE.NVIDIA) if (VideoMode == VIDEO_MODE.NVIDIA && NVIDIALibrary.GetLibrary().IsInstalled)
{ {
NVIDIALibrary nvidiaLibrary = NVIDIALibrary.GetLibrary(); NVIDIALibrary nvidiaLibrary = NVIDIALibrary.GetLibrary();
WinLibrary winLibrary = WinLibrary.GetLibrary(); WinLibrary winLibrary = WinLibrary.GetLibrary();
@ -716,7 +727,7 @@ namespace DisplayMagicianShared
} }
} }
} }
else if (VideoMode == VIDEO_MODE.AMD) else if (VideoMode == VIDEO_MODE.AMD && AMDLibrary.GetLibrary().IsInstalled)
{ {
AMDLibrary amdLibrary = AMDLibrary.GetLibrary(); AMDLibrary amdLibrary = AMDLibrary.GetLibrary();
WinLibrary winLibrary = WinLibrary.GetLibrary(); WinLibrary winLibrary = WinLibrary.GetLibrary();
@ -1511,7 +1522,7 @@ namespace DisplayMagicianShared
// ProfileDisplayIdentifiers may be the same but in different order within the array, so we need to handle // ProfileDisplayIdentifiers may be the same but in different order within the array, so we need to handle
// that fact. // that fact.
return NVIDIADisplayConfig.Equals(other.NVIDIADisplayConfig) && return NVIDIADisplayConfig.Equals(other.NVIDIADisplayConfig) &&
//AMDDisplayConfig.Equals(other.AMDDisplayConfig) && AMDDisplayConfig.Equals(other.AMDDisplayConfig) &&
WindowsDisplayConfig.Equals(other.WindowsDisplayConfig) && WindowsDisplayConfig.Equals(other.WindowsDisplayConfig) &&
ProfileDisplayIdentifiers.SequenceEqual (other.ProfileDisplayIdentifiers); ProfileDisplayIdentifiers.SequenceEqual (other.ProfileDisplayIdentifiers);
} }

View File

@ -226,10 +226,13 @@ namespace DisplayMagicianShared
return false; return false;
} }
if (!_profilesLoaded)
{
if (!LoadProfiles()) if (!LoadProfiles())
{ {
return false; return false;
} }
}
return true; return true;
} }
@ -692,11 +695,13 @@ namespace DisplayMagicianShared
{ {
_allProfiles = JsonConvert.DeserializeObject<List<ProfileItem>>(json, new JsonSerializerSettings _allProfiles = JsonConvert.DeserializeObject<List<ProfileItem>>(json, new JsonSerializerSettings
{ {
MissingMemberHandling = MissingMemberHandling.Ignore, MissingMemberHandling = MissingMemberHandling.Error,
NullValueHandling = NullValueHandling.Ignore, NullValueHandling = NullValueHandling.Include,
//NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Include, DefaultValueHandling = DefaultValueHandling.Include,
//DefaultValueHandling = DefaultValueHandling.Ignore,
TypeNameHandling = TypeNameHandling.Auto, TypeNameHandling = TypeNameHandling.Auto,
ObjectCreationHandling = ObjectCreationHandling.Replace ObjectCreationHandling = ObjectCreationHandling.Auto,
}); });
} }
catch (Exception ex) catch (Exception ex)
@ -780,9 +785,12 @@ namespace DisplayMagicianShared
var json = JsonConvert.SerializeObject(_allProfiles, Formatting.Indented, new JsonSerializerSettings var json = JsonConvert.SerializeObject(_allProfiles, Formatting.Indented, new JsonSerializerSettings
{ {
NullValueHandling = NullValueHandling.Include, NullValueHandling = NullValueHandling.Include,
DefaultValueHandling = DefaultValueHandling.Populate, //NullValueHandling = NullValueHandling.Ignore,
TypeNameHandling = TypeNameHandling.Auto DefaultValueHandling = DefaultValueHandling.Include,
//DefaultValueHandling = DefaultValueHandling.Ignore,
TypeNameHandling = TypeNameHandling.Auto,
MissingMemberHandling = MissingMemberHandling.Error,
ObjectCreationHandling = ObjectCreationHandling.Replace,
}); });