diff --git a/DisplayMagicianShared/AMD/AMDLibrary.cs b/DisplayMagicianShared/AMD/AMDLibrary.cs index 52d5982..0c83117 100644 --- a/DisplayMagicianShared/AMD/AMDLibrary.cs +++ b/DisplayMagicianShared/AMD/AMDLibrary.cs @@ -276,7 +276,22 @@ namespace DisplayMagicianShared.AMD 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(); + myDefaultConfig.SlsConfig.SLSMapConfigs = new List(); + myDefaultConfig.SlsConfig.SLSEnabledDisplayTargets = new List(); + myDefaultConfig.DisplayTargets = new List(); + myDefaultConfig.HdrConfigs = new Dictionary(); + myDefaultConfig.DisplayIdentifiers = new List(); + + return myDefaultConfig; + } public AMD_DISPLAY_CONFIG GetActiveConfig() { diff --git a/DisplayMagicianShared/NVIDIA/NVIDIALibrary.cs b/DisplayMagicianShared/NVIDIA/NVIDIALibrary.cs index b39dbc0..bfaaef5 100644 --- a/DisplayMagicianShared/NVIDIA/NVIDIALibrary.cs +++ b/DisplayMagicianShared/NVIDIA/NVIDIALibrary.cs @@ -286,7 +286,22 @@ namespace DisplayMagicianShared.NVIDIA 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(); + myDefaultConfig.HdrConfig.HdrCapabilities = new Dictionary(); + myDefaultConfig.HdrConfig.HdrColorData = new Dictionary(); + myDefaultConfig.DisplayNames = new Dictionary(); + myDefaultConfig.DisplayIdentifiers = new List(); + + return myDefaultConfig; + } public NVIDIA_DISPLAY_CONFIG GetActiveConfig() { diff --git a/DisplayMagicianShared/ProfileItem.cs b/DisplayMagicianShared/ProfileItem.cs index 657d31d..33666a2 100644 --- a/DisplayMagicianShared/ProfileItem.cs +++ b/DisplayMagicianShared/ProfileItem.cs @@ -58,9 +58,9 @@ namespace DisplayMagicianShared private Bitmap _profileBitmap, _profileShortcutBitmap; private List _profileDisplayIdentifiers = new List(); private List _screens = new List(); - private NVIDIA_DISPLAY_CONFIG _nvidiaDisplayConfig = new NVIDIA_DISPLAY_CONFIG(); - private AMD_DISPLAY_CONFIG _amdDisplayConfig = new AMD_DISPLAY_CONFIG(); - private WINDOWS_DISPLAY_CONFIG _windowsDisplayConfig = new WINDOWS_DISPLAY_CONFIG(); + private NVIDIA_DISPLAY_CONFIG _nvidiaDisplayConfig; + private AMD_DISPLAY_CONFIG _amdDisplayConfig; + private WINDOWS_DISPLAY_CONFIG _windowsDisplayConfig; internal static string AppDataPath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "DisplayMagician"); private static string AppWallpaperPath = Path.Combine(AppDataPath, $"Wallpaper"); @@ -135,6 +135,14 @@ namespace DisplayMagicianShared #endregion 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); @@ -456,7 +464,10 @@ namespace DisplayMagicianShared 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(); if (nvidiaLibrary.IsInstalled) @@ -476,7 +487,7 @@ namespace DisplayMagicianShared return false; } } - else if(VideoMode == VIDEO_MODE.AMD) + else if(VideoMode == VIDEO_MODE.AMD && AMDLibrary.GetLibrary().IsInstalled) { AMDLibrary amdLibrary = AMDLibrary.GetLibrary(); if (amdLibrary.IsInstalled) @@ -664,7 +675,7 @@ namespace DisplayMagicianShared // Actually set this profile active public bool SetActive() { - if (VideoMode == VIDEO_MODE.NVIDIA) + if (VideoMode == VIDEO_MODE.NVIDIA && NVIDIALibrary.GetLibrary().IsInstalled) { NVIDIALibrary nvidiaLibrary = NVIDIALibrary.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(); WinLibrary winLibrary = WinLibrary.GetLibrary(); @@ -1509,9 +1520,9 @@ namespace DisplayMagicianShared // Check the object fields // 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) && - //AMDDisplayConfig.Equals(other.AMDDisplayConfig) && + AMDDisplayConfig.Equals(other.AMDDisplayConfig) && WindowsDisplayConfig.Equals(other.WindowsDisplayConfig) && ProfileDisplayIdentifiers.SequenceEqual (other.ProfileDisplayIdentifiers); } diff --git a/DisplayMagicianShared/ProfileRepository.cs b/DisplayMagicianShared/ProfileRepository.cs index 2ec1e54..f291e34 100644 --- a/DisplayMagicianShared/ProfileRepository.cs +++ b/DisplayMagicianShared/ProfileRepository.cs @@ -225,11 +225,14 @@ namespace DisplayMagicianShared { return false; } - - if (!LoadProfiles()) + + if (!_profilesLoaded) { - return false; - } + if (!LoadProfiles()) + { + return false; + } + } return true; } @@ -692,11 +695,13 @@ namespace DisplayMagicianShared { _allProfiles = JsonConvert.DeserializeObject>(json, new JsonSerializerSettings { - MissingMemberHandling = MissingMemberHandling.Ignore, - NullValueHandling = NullValueHandling.Ignore, + MissingMemberHandling = MissingMemberHandling.Error, + NullValueHandling = NullValueHandling.Include, + //NullValueHandling = NullValueHandling.Ignore, DefaultValueHandling = DefaultValueHandling.Include, + //DefaultValueHandling = DefaultValueHandling.Ignore, TypeNameHandling = TypeNameHandling.Auto, - ObjectCreationHandling = ObjectCreationHandling.Replace + ObjectCreationHandling = ObjectCreationHandling.Auto, }); } catch (Exception ex) @@ -780,9 +785,12 @@ namespace DisplayMagicianShared var json = JsonConvert.SerializeObject(_allProfiles, Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Include, - DefaultValueHandling = DefaultValueHandling.Populate, - TypeNameHandling = TypeNameHandling.Auto - + //NullValueHandling = NullValueHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Include, + //DefaultValueHandling = DefaultValueHandling.Ignore, + TypeNameHandling = TypeNameHandling.Auto, + MissingMemberHandling = MissingMemberHandling.Error, + ObjectCreationHandling = ObjectCreationHandling.Replace, });