// Copyright (c) Microsoft Corporation // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Collections.Generic; using System.Globalization; using ManagedCommon; namespace PowerDisplay.Common.Utils { /// /// Unified helper class for parsing monitor feature support from VCP capabilities. /// This eliminates duplicate VCP parsing logic across PowerDisplay.exe and Settings.UI. /// public static class MonitorFeatureHelper { /// /// VCP code for Brightness (0x10) - Standard VESA MCCS brightness control /// public const int VcpCodeBrightness = 0x10; /// /// VCP code for Contrast (0x12) - Standard VESA MCCS contrast control /// public const int VcpCodeContrast = 0x12; /// /// VCP code for Select Color Preset (0x14) - Color temperature control /// public const int VcpCodeSelectColorPreset = 0x14; /// /// VCP code for Audio Speaker Volume (0x62) /// public const int VcpCodeVolume = 0x62; /// /// Result of parsing monitor feature support from VCP capabilities /// public readonly struct FeatureSupportResult { public bool SupportsBrightness { get; init; } public bool SupportsContrast { get; init; } public bool SupportsColorTemperature { get; init; } public bool SupportsVolume { get; init; } public string CapabilitiesStatus { get; init; } public static FeatureSupportResult Unavailable => new() { SupportsBrightness = false, SupportsContrast = false, SupportsColorTemperature = false, SupportsVolume = false, CapabilitiesStatus = "unavailable", }; } /// /// Parse feature support from a list of VCP code strings. /// This is the single source of truth for determining monitor capabilities. /// /// List of VCP codes as strings (e.g., "0x10", "10", "0x12") /// Raw capabilities string, used to determine availability status /// Feature support result public static FeatureSupportResult ParseFeatureSupport(IReadOnlyList? vcpCodes, string? capabilitiesRaw) { // Check capabilities availability if (string.IsNullOrEmpty(capabilitiesRaw)) { return FeatureSupportResult.Unavailable; } // Convert all VCP codes to integers for comparison var vcpCodeInts = ParseVcpCodesToIntegers(vcpCodes); // Determine feature support based on VCP codes return new FeatureSupportResult { SupportsBrightness = vcpCodeInts.Contains(VcpCodeBrightness), SupportsContrast = vcpCodeInts.Contains(VcpCodeContrast), SupportsColorTemperature = vcpCodeInts.Contains(VcpCodeSelectColorPreset), SupportsVolume = vcpCodeInts.Contains(VcpCodeVolume), CapabilitiesStatus = "available", }; } /// /// Parse VCP codes from string list to integer set /// Handles both hex formats: "0x10" and "10" /// public static HashSet ParseVcpCodesToIntegers(IReadOnlyList? vcpCodes) { var result = new HashSet(); if (vcpCodes == null) { return result; } foreach (var code in vcpCodes) { if (string.IsNullOrWhiteSpace(code)) { continue; } // Remove "0x" prefix if present and parse as hex var cleanCode = code.Trim(); if (cleanCode.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) { cleanCode = cleanCode.Substring(2); } if (int.TryParse(cleanCode, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out int codeInt)) { result.Add(codeInt); } } return result; } /// /// Check if a specific VCP code is supported /// public static bool SupportsVcpCode(IReadOnlyList? vcpCodes, int vcpCode) { var parsed = ParseVcpCodesToIntegers(vcpCodes); return parsed.Contains(vcpCode); } /// /// Format VCP code for display (e.g., 0x10 -> "0x10") /// public static string FormatVcpCode(int vcpCode) { return $"0x{vcpCode:X2}"; } } }