// 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}";
}
}
}