diff --git a/HeliosPlus.Shared/ProfileItem.cs b/HeliosPlus.Shared/ProfileItem.cs index 8878e8b..46d7398 100644 --- a/HeliosPlus.Shared/ProfileItem.cs +++ b/HeliosPlus.Shared/ProfileItem.cs @@ -138,12 +138,15 @@ namespace HeliosPlus.Shared get { + // Get the list of connected devices + List connectedDisplayIdentifiers = ProfileRepository.GenerateAllDisplayIdentifiers(); + // Check each display in this profile and make sure it's currently available int validDisplayCount = 0; 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.CurrentProfile.ProfileDisplayIdentifiers.Contains(profileDisplayIdentifier)) + if (connectedDisplayIdentifiers.Contains(profileDisplayIdentifier)) validDisplayCount++; } @@ -187,7 +190,7 @@ namespace HeliosPlus.Shared { if (_profileDisplayIdentifiers.Count == 0) { - _profileDisplayIdentifiers = this.GenerateDisplayIdentifiers(); + _profileDisplayIdentifiers = ProfileRepository.GenerateProfileDisplayIdentifiers(); } return _profileDisplayIdentifiers; } @@ -277,98 +280,7 @@ namespace HeliosPlus.Shared return false; } - public List GenerateDisplayIdentifiers() - { - List displayIdentifiers = new List(); - - // If the Video Card is an NVidia, then we should generate specific NVidia displayIdentifiers - NvAPIWrapper.GPU.LogicalGPU[] myLogicalGPUs = NvAPIWrapper.GPU.LogicalGPU.GetLogicalGPUs(); - if (myLogicalGPUs.Length > 0) - { - - foreach (NvAPIWrapper.GPU.LogicalGPU myLogicalGPU in myLogicalGPUs) - { - NvAPIWrapper.GPU.PhysicalGPU[] myPhysicalGPUs = myLogicalGPU.CorrespondingPhysicalGPUs; - foreach (NvAPIWrapper.GPU.PhysicalGPU myPhysicalGPU in myPhysicalGPUs) - { - // get a list of all physical outputs attached to the GPUs - NvAPIWrapper.GPU.GPUOutput[] myGPUOutputs = myPhysicalGPU.ActiveOutputs; - foreach (NvAPIWrapper.GPU.GPUOutput aGPUOutput in myGPUOutputs) - { - // Figure out the displaydevice attached to the output - NvAPIWrapper.Display.DisplayDevice aConnectedDisplayDevice = myPhysicalGPU.GetDisplayDeviceByOutput(aGPUOutput); - - // Create an array of all the important display info we need to record - string[] displayInfo = { - "NVIDIA", - myLogicalGPU.ToString(), - myPhysicalGPU.ToString(), - myPhysicalGPU.ArchitectInformation.ShortName.ToString(), - myPhysicalGPU.ArchitectInformation.Revision.ToString(), - myPhysicalGPU.Board.ToString(), - myPhysicalGPU.Foundry.ToString(), - myPhysicalGPU.GPUId.ToString(), - myPhysicalGPU.GPUType.ToString(), - aGPUOutput.OutputId.ToString(), - aConnectedDisplayDevice.ConnectionType.ToString(), - aConnectedDisplayDevice.DisplayId.ToString(), - }; - - // Create a display identifier out of it - string displayIdentifier = String.Join("|", displayInfo); - // Add it to the list of display identifiers so we can return it - displayIdentifiers.Add(displayIdentifier); - } - - } - } - } - // else videocard is not NVIdia so we just use the WindowsAPI access method - // Note: This won't support any special AMD EyeFinity profiles unfortunately..... - // TODO: Add the detection and generation of the device ids using an AMD library - // so that we can match valid AMD Eyefinity profiles with valid AMD standard profiles. - else - { - - // Then go through the displays in the profile and check they are made of displays - // that currently are available. - foreach (ProfileViewport profileViewport in Viewports) - { - // For each profile, we want to make sure all TargetDisplays.DevicePath are in the list of - // availableDevicePaths - //foreach (WindowsDisplayAPI.DisplayConfig.PathTargetInfo profilePathTargetInfo in profileViewport.ToPathInfo().TargetsInfo) - foreach (ProfileViewportTargetDisplay profileTargetDisplay in profileViewport.TargetDisplays) - { - - - WindowsDisplayAPI.DisplayConfig.PathTargetInfo profilePathTargetInfo = profileTargetDisplay.ToPathTargetInfo(); - - // Create an array of all the important display info we need to record - string[] displayInfo = { - "WINAPI", - profileViewport.SourceId.ToString(), - profilePathTargetInfo.DisplayTarget.Adapter.AdapterId.HighPart.ToString(), - profilePathTargetInfo.DisplayTarget.Adapter.AdapterId.LowPart.ToString(), - profilePathTargetInfo.OutputTechnology.ToString(), - profilePathTargetInfo.DisplayTarget.EDIDManufactureCode.ToString(), - profilePathTargetInfo.DisplayTarget.FriendlyName, - profilePathTargetInfo.DisplayTarget.EDIDManufactureId.ToString(), - profilePathTargetInfo.DisplayTarget.EDIDProductCode.ToString(), - profilePathTargetInfo.DisplayTarget.ConnectorInstance.ToString(), - profileTargetDisplay.DevicePath, - }; - - // Create a display identifier out of it - string displayIdentifier = String.Join("|", displayInfo); - // Add it to the list of display identifiers so we can return it - displayIdentifiers.Add(displayIdentifier); - } - } - - } - - return displayIdentifiers; - } + public bool CopyTo(ProfileItem profile, bool overwriteId = true) { @@ -394,7 +306,7 @@ namespace HeliosPlus.Shared // Prepare our profile data for saving if (_profileDisplayIdentifiers.Count == 0) { - _profileDisplayIdentifiers = GenerateDisplayIdentifiers(); + _profileDisplayIdentifiers = ProfileRepository.GenerateProfileDisplayIdentifiers(); } // Return if it is valid and we should continue diff --git a/HeliosPlus.Shared/ProfileRepository.cs b/HeliosPlus.Shared/ProfileRepository.cs index 59859ac..35c0e19 100644 --- a/HeliosPlus.Shared/ProfileRepository.cs +++ b/HeliosPlus.Shared/ProfileRepository.cs @@ -562,41 +562,272 @@ namespace HeliosPlus.Shared } } - public static bool ApplyProfile(ProfileItem profile) + public static List GenerateProfileDisplayIdentifiers() { - // If we're already on the wanted profile then no need to change! - if (ProfileRepository.IsActiveProfile(profile)) - return true; + List displayIdentifiers = new List(); - // We need to check if the profile is valid - if (!profile.IsPossible) - return false; - - try + // If the Video Card is an NVidia, then we should generate specific NVidia displayIdentifiers + NvAPIWrapper.GPU.LogicalGPU[] myLogicalGPUs = NvAPIWrapper.GPU.LogicalGPU.GetLogicalGPUs(); + if (myLogicalGPUs.Length > 0) { - // Now lets start by changing the display topology - Task applyProfileTopologyTask = Task.Run(() => - { - Console.WriteLine("ProfileRepository/SaveShortcutIconToCache : Applying Profile Topology " + profile.Name); - ApplyTopology(profile); - }); - applyProfileTopologyTask.Wait(); - // And then change the path information - Task applyProfilePathInfoTask = Task.Run(() => + foreach (NvAPIWrapper.GPU.LogicalGPU myLogicalGPU in myLogicalGPUs) { - Console.WriteLine("ProfileRepository/SaveShortcutIconToCache : Applying Profile Path " + profile.Name); - ApplyPathInfo(profile); - }); - applyProfilePathInfoTask.Wait(); + NvAPIWrapper.GPU.PhysicalGPU[] myPhysicalGPUs = myLogicalGPU.CorrespondingPhysicalGPUs; + foreach (NvAPIWrapper.GPU.PhysicalGPU myPhysicalGPU in myPhysicalGPUs) + { + // get a list of all physical outputs attached to the GPUs + NvAPIWrapper.GPU.GPUOutput[] myGPUOutputs = myPhysicalGPU.ActiveOutputs; + foreach (NvAPIWrapper.GPU.GPUOutput aGPUOutput in myGPUOutputs) + { + // Figure out the displaydevice attached to the output + NvAPIWrapper.Display.DisplayDevice aConnectedDisplayDevice = myPhysicalGPU.GetDisplayDeviceByOutput(aGPUOutput); - return true; + // Create an array of all the important display info we need to record + string[] displayInfo = { + "NVIDIA", + myLogicalGPU.ToString(), + myPhysicalGPU.ToString(), + myPhysicalGPU.ArchitectInformation.ShortName.ToString(), + myPhysicalGPU.ArchitectInformation.Revision.ToString(), + myPhysicalGPU.Board.ToString(), + myPhysicalGPU.Foundry.ToString(), + myPhysicalGPU.GPUId.ToString(), + myPhysicalGPU.GPUType.ToString(), + aGPUOutput.OutputId.ToString(), + aConnectedDisplayDevice.ConnectionType.ToString(), + aConnectedDisplayDevice.DisplayId.ToString() + }; + + // Create a display identifier out of it + string displayIdentifier = String.Join("|", displayInfo); + // Add it to the list of display identifiers so we can return it + displayIdentifiers.Add(displayIdentifier); + } + + } + } } - catch (Exception ex) + // else videocard is not NVIdia so we just use the WindowsAPI access method + // Note: This won't support any special AMD EyeFinity profiles unfortunately..... + // TODO: Add the detection and generation of the device ids using an AMD library + // so that we can match valid AMD Eyefinity profiles with valid AMD standard profiles. + else { - Console.WriteLine($"ProfileRepository/ApplyTopology exception: {ex.Message}: {ex.StackTrace} - {ex.InnerException}"); - return false; + + // Then go through the adapters we have running using the WindowsDisplayAPI + List allDisplayAdapters = DisplayAdapter.GetDisplayAdapters().ToList(); + foreach (DisplayAdapter displayAdapter in allDisplayAdapters) + { + Console.WriteLine($"DP : {displayAdapter.DevicePath}"); + Console.WriteLine($"DK : {displayAdapter.DeviceKey}"); + Console.WriteLine($"DN : {displayAdapter.DeviceName}"); + Console.WriteLine($"DK : {displayAdapter.DeviceKey}"); + PathDisplayAdapter pathDisplayAdapter = displayAdapter.ToPathDisplayAdapter(); + Console.WriteLine($"AI : {pathDisplayAdapter.AdapterId}"); + Console.WriteLine($"AIDP : {pathDisplayAdapter.DevicePath}"); + Console.WriteLine($"AIII : {pathDisplayAdapter.IsInvalid}"); + List displayDevices = displayAdapter.GetDisplayDevices().ToList(); + foreach (DisplayDevice displayDevice in displayDevices) + { + Console.WriteLine($"DDA : {displayDevice.Adapter}"); + Console.WriteLine($"DDDK : {displayDevice.DeviceKey}"); + Console.WriteLine($"DDDN : {displayDevice.DeviceName}"); + Console.WriteLine($"DDDP : {displayDevice.DevicePath}"); + Console.WriteLine($"DDDiFN : {displayDevice.DisplayFullName}"); + Console.WriteLine($"DDDiN : {displayDevice.DisplayName}"); + Console.WriteLine($"DDDiIA : {displayDevice.IsAvailable}"); + Console.WriteLine($"DDDiIV : {displayDevice.IsValid}"); + PathDisplaySource pathDisplaySource = displayDevice.ToPathDisplaySource(); + Console.WriteLine($"PDSA : {pathDisplaySource.Adapter}"); + Console.WriteLine($"PDSCDS : {pathDisplaySource.CurrentDPIScale}"); + Console.WriteLine($"PDSDN : {pathDisplaySource.DisplayName}"); + Console.WriteLine($"PDSMDS : {pathDisplaySource.MaximumDPIScale}"); + Console.WriteLine($"PDSRDS : {pathDisplaySource.RecommendedDPIScale}"); + Console.WriteLine($"PDSSI : {pathDisplaySource.SourceId}"); + PathDisplayTarget pathDisplayTarget = displayDevice.ToPathDisplayTarget(); + Console.WriteLine($"PDTA : {pathDisplayTarget.Adapter}"); + //Console.WriteLine($"PDTBP : {pathDisplayTarget.BootPersistence}"); + Console.WriteLine($"PDTCI : {pathDisplayTarget.ConnectorInstance}"); + Console.WriteLine($"PDTDP : {pathDisplayTarget.DevicePath}"); + Console.WriteLine($"PDTEMC : {pathDisplayTarget.EDIDManufactureCode}"); + Console.WriteLine($"PDTEMI : {pathDisplayTarget.EDIDManufactureId}"); + Console.WriteLine($"PDTEPC : {pathDisplayTarget.EDIDProductCode}"); + Console.WriteLine($"PDTFN : {pathDisplayTarget.FriendlyName}"); + Console.WriteLine($"PDTIA : {pathDisplayTarget.IsAvailable}"); + Console.WriteLine($"PDTPR : {pathDisplayTarget.PreferredResolution}"); + Console.WriteLine($"PDTPSM : {pathDisplayTarget.PreferredSignalMode}"); + Console.WriteLine($"PDTTI : {pathDisplayTarget.TargetId}"); + Console.WriteLine($"PDTVRS : {pathDisplayTarget.VirtualResolutionSupport}"); + } + + // For each profile, we want to make sure all TargetDisplays.DevicePath are in the list of + // availableDevicePaths + //foreach (WindowsDisplayAPI.DisplayConfig.PathTargetInfo profilePathTargetInfo in profileViewport.ToPathInfo().TargetsInfo) + /* foreach (ProfileViewportTargetDisplay profileTargetDisplay in profileViewport.TargetDisplays) + { + + + WindowsDisplayAPI.DisplayConfig.PathTargetInfo profilePathTargetInfo = profileTargetDisplay.ToPathTargetInfo(); + + // Create an array of all the important display info we need to record + string[] displayInfo = { + "WINAPI", + profileViewport.SourceId.ToString(), + profilePathTargetInfo.DisplayTarget.Adapter.AdapterId.HighPart.ToString(), + profilePathTargetInfo.DisplayTarget.Adapter.AdapterId.LowPart.ToString(), + profilePathTargetInfo.OutputTechnology.ToString(), + profilePathTargetInfo.DisplayTarget.EDIDManufactureCode.ToString(), + profilePathTargetInfo.DisplayTarget.FriendlyName, + profilePathTargetInfo.DisplayTarget.EDIDManufactureId.ToString(), + profilePathTargetInfo.DisplayTarget.EDIDProductCode.ToString(), + profilePathTargetInfo.DisplayTarget.ConnectorInstance.ToString(), + profileTargetDisplay.DevicePath, + }; + + // Create a display identifier out of it + string displayIdentifier = String.Join("|", displayInfo); + // Add it to the list of display identifiers so we can return it + displayIdentifiers.Add(displayIdentifier); + }*/ + } + } + + return displayIdentifiers; + } + + public static List GenerateAllDisplayIdentifiers() + { + List displayIdentifiers = new List(); + + // If the Video Card is an NVidia, then we should generate specific NVidia displayIdentifiers + NvAPIWrapper.GPU.LogicalGPU[] myLogicalGPUs = NvAPIWrapper.GPU.LogicalGPU.GetLogicalGPUs(); + if (myLogicalGPUs.Length > 0) + { + + foreach (NvAPIWrapper.GPU.LogicalGPU myLogicalGPU in myLogicalGPUs) + { + NvAPIWrapper.GPU.PhysicalGPU[] myPhysicalGPUs = myLogicalGPU.CorrespondingPhysicalGPUs; + foreach (NvAPIWrapper.GPU.PhysicalGPU myPhysicalGPU in myPhysicalGPUs) + { + // get a list of all physical outputs attached to the GPUs + NvAPIWrapper.Display.DisplayDevice[] allDisplayDevices = myPhysicalGPU.GetDisplayDevices(); + foreach (NvAPIWrapper.Display.DisplayDevice aDisplayDevice in allDisplayDevices) + { + + // Create an array of all the important display info we need to record + string[] displayInfo = { + "NVIDIA", + myLogicalGPU.ToString(), + myPhysicalGPU.ToString(), + myPhysicalGPU.ArchitectInformation.ShortName.ToString(), + myPhysicalGPU.ArchitectInformation.Revision.ToString(), + myPhysicalGPU.Board.ToString(), + myPhysicalGPU.Foundry.ToString(), + myPhysicalGPU.GPUId.ToString(), + myPhysicalGPU.GPUType.ToString(), + aDisplayDevice.Output.OutputId.ToString(), + aDisplayDevice.ConnectionType.ToString(), + aDisplayDevice.DisplayId.ToString(), + }; + + // Create a display identifier out of it + string displayIdentifier = String.Join("|", displayInfo); + // Add it to the list of display identifiers so we can return it + displayIdentifiers.Add(displayIdentifier); + } + + } + } + } + // else videocard is not NVIdia so we just use the WindowsAPI access method + // Note: This won't support any special AMD EyeFinity profiles unfortunately..... + // TODO: Add the detection and generation of the device ids using an AMD library + // so that we can match valid AMD Eyefinity profiles with valid AMD standard profiles. + else + { + + // Then go through the adapters we have running using the WindowsDisplayAPI + List allDisplayAdapters = DisplayAdapter.GetDisplayAdapters().ToList(); + foreach (DisplayAdapter displayAdapter in allDisplayAdapters) + { + Console.WriteLine($"DP : {displayAdapter.DevicePath}"); + Console.WriteLine($"DK : {displayAdapter.DeviceKey}"); + Console.WriteLine($"DN : {displayAdapter.DeviceName}"); + Console.WriteLine($"DK : {displayAdapter.DeviceKey}"); + PathDisplayAdapter pathDisplayAdapter = displayAdapter.ToPathDisplayAdapter(); + Console.WriteLine($"AI : {pathDisplayAdapter.AdapterId}"); + Console.WriteLine($"AIDP : {pathDisplayAdapter.DevicePath}"); + Console.WriteLine($"AIII : {pathDisplayAdapter.IsInvalid}"); + List displayDevices = displayAdapter.GetDisplayDevices().ToList(); + foreach (DisplayDevice displayDevice in displayDevices) + { + Console.WriteLine($"DDA : {displayDevice.Adapter}"); + Console.WriteLine($"DDDK : {displayDevice.DeviceKey}"); + Console.WriteLine($"DDDN : {displayDevice.DeviceName}"); + Console.WriteLine($"DDDP : {displayDevice.DevicePath}"); + Console.WriteLine($"DDDiFN : {displayDevice.DisplayFullName}"); + Console.WriteLine($"DDDiN : {displayDevice.DisplayName}"); + Console.WriteLine($"DDDiIA : {displayDevice.IsAvailable}"); + Console.WriteLine($"DDDiIV : {displayDevice.IsValid}"); + PathDisplaySource pathDisplaySource = displayDevice.ToPathDisplaySource(); + Console.WriteLine($"PDSA : {pathDisplaySource.Adapter}"); + Console.WriteLine($"PDSCDS : {pathDisplaySource.CurrentDPIScale}"); + Console.WriteLine($"PDSDN : {pathDisplaySource.DisplayName}"); + Console.WriteLine($"PDSMDS : {pathDisplaySource.MaximumDPIScale}"); + Console.WriteLine($"PDSRDS : {pathDisplaySource.RecommendedDPIScale}"); + Console.WriteLine($"PDSSI : {pathDisplaySource.SourceId}"); + PathDisplayTarget pathDisplayTarget = displayDevice.ToPathDisplayTarget(); + Console.WriteLine($"PDTA : {pathDisplayTarget.Adapter}"); + //Console.WriteLine($"PDTBP : {pathDisplayTarget.BootPersistence}"); + Console.WriteLine($"PDTCI : {pathDisplayTarget.ConnectorInstance}"); + Console.WriteLine($"PDTDP : {pathDisplayTarget.DevicePath}"); + Console.WriteLine($"PDTEMC : {pathDisplayTarget.EDIDManufactureCode}"); + Console.WriteLine($"PDTEMI : {pathDisplayTarget.EDIDManufactureId}"); + Console.WriteLine($"PDTEPC : {pathDisplayTarget.EDIDProductCode}"); + Console.WriteLine($"PDTFN : {pathDisplayTarget.FriendlyName}"); + Console.WriteLine($"PDTIA : {pathDisplayTarget.IsAvailable}"); + Console.WriteLine($"PDTPR : {pathDisplayTarget.PreferredResolution}"); + Console.WriteLine($"PDTPSM : {pathDisplayTarget.PreferredSignalMode}"); + Console.WriteLine($"PDTTI : {pathDisplayTarget.TargetId}"); + Console.WriteLine($"PDTVRS : {pathDisplayTarget.VirtualResolutionSupport}"); + } + + // For each profile, we want to make sure all TargetDisplays.DevicePath are in the list of + // availableDevicePaths + //foreach (WindowsDisplayAPI.DisplayConfig.PathTargetInfo profilePathTargetInfo in profileViewport.ToPathInfo().TargetsInfo) + /* foreach (ProfileViewportTargetDisplay profileTargetDisplay in profileViewport.TargetDisplays) + { + + + WindowsDisplayAPI.DisplayConfig.PathTargetInfo profilePathTargetInfo = profileTargetDisplay.ToPathTargetInfo(); + + // Create an array of all the important display info we need to record + string[] displayInfo = { + "WINAPI", + profileViewport.SourceId.ToString(), + profilePathTargetInfo.DisplayTarget.Adapter.AdapterId.HighPart.ToString(), + profilePathTargetInfo.DisplayTarget.Adapter.AdapterId.LowPart.ToString(), + profilePathTargetInfo.OutputTechnology.ToString(), + profilePathTargetInfo.DisplayTarget.EDIDManufactureCode.ToString(), + profilePathTargetInfo.DisplayTarget.FriendlyName, + profilePathTargetInfo.DisplayTarget.EDIDManufactureId.ToString(), + profilePathTargetInfo.DisplayTarget.EDIDProductCode.ToString(), + profilePathTargetInfo.DisplayTarget.ConnectorInstance.ToString(), + profileTargetDisplay.DevicePath, + }; + + // Create a display identifier out of it + string displayIdentifier = String.Join("|", displayInfo); + // Add it to the list of display identifiers so we can return it + displayIdentifiers.Add(displayIdentifier); + }*/ + } + + } + + return displayIdentifiers; } public static bool ApplyTopology(ProfileItem profile) @@ -701,3 +932,4 @@ namespace HeliosPlus.Shared } +