Refactor color temp init to be synchronous in DDC/CI

Simplifies color temperature initialization by moving it from async handling in MainViewModel to synchronous initialization during monitor enumeration in DdcCiController. Removes related async methods and UI update logic, reducing complexity and ensuring color temperature values are available immediately after enumeration.
This commit is contained in:
Yu Leng
2025-12-10 11:18:28 +08:00
parent 0a2b433697
commit 97560ea6c0
3 changed files with 21 additions and 140 deletions

View File

@@ -576,6 +576,12 @@ namespace PowerDisplay.Common.Drivers.DDC
{
InitializeInputSource(monitor, candidate.Handle);
}
// Initialize color temperature if supported
if (monitor.SupportsColorTemperature)
{
InitializeColorTemperature(monitor, candidate.Handle);
}
}
monitors.Add(monitor);
@@ -600,6 +606,18 @@ namespace PowerDisplay.Common.Drivers.DDC
}
}
/// <summary>
/// Initialize color temperature value for a monitor using VCP 0x14.
/// </summary>
private static void InitializeColorTemperature(Monitor monitor, IntPtr handle)
{
if (DdcCiNative.TryGetVCPFeature(handle, VcpCodeSelectColorPreset, out uint current, out uint _))
{
monitor.CurrentColorTemperature = (int)current;
Logger.LogDebug($"[{monitor.Id}] Color temperature: {VcpValueNames.GetFormattedName(VcpCodeSelectColorPreset, (int)current)}");
}
}
/// <summary>
/// Update monitor capability flags based on parsed VCP capabilities.
/// </summary>

View File

@@ -344,56 +344,6 @@ namespace PowerDisplay.Helpers
return Task.FromResult(result);
}
/// <summary>
/// Initialize input source for a monitor (async operation)
/// </summary>
public async Task InitializeInputSourceAsync(string monitorId, CancellationToken cancellationToken = default)
{
try
{
var sourceInfo = await GetInputSourceAsync(monitorId, cancellationToken);
if (sourceInfo.IsValid)
{
var monitor = GetMonitor(monitorId);
if (monitor != null)
{
// Store raw VCP 0x60 value (e.g., 0x11 for HDMI-1)
monitor.CurrentInputSource = sourceInfo.Current;
Logger.LogInfo($"[{monitorId}] Input source initialized: {monitor.InputSourceName}");
}
}
}
catch (Exception ex)
{
Logger.LogWarning($"Failed to initialize input source for {monitorId}: {ex.Message}");
}
}
/// <summary>
/// Initialize color temperature for a monitor (async operation)
/// </summary>
public async Task InitializeColorTemperatureAsync(string monitorId, CancellationToken cancellationToken = default)
{
try
{
var tempInfo = await GetColorTemperatureAsync(monitorId, cancellationToken);
if (tempInfo.IsValid)
{
var monitor = GetMonitor(monitorId);
if (monitor != null)
{
// Store raw VCP 0x14 preset value (e.g., 0x05 for 6500K)
// No Kelvin conversion - we use discrete presets
monitor.CurrentColorTemperature = tempInfo.Current;
}
}
}
catch (Exception ex)
{
Logger.LogWarning($"Failed to initialize color temperature for {monitorId}: {ex.Message}");
}
}
/// <summary>
/// Get monitor by ID. Uses dictionary lookup for O(1) performance.
/// </summary>

View File

@@ -95,7 +95,6 @@ public partial class MainViewModel
var settings = _settingsUtils.GetSettingsOrDefault<PowerDisplaySettings>(PowerDisplaySettings.ModuleName);
var hiddenMonitorIds = GetHiddenMonitorIds(settings);
var colorTempTasks = new List<Task>();
foreach (var monitor in monitors)
{
// Skip monitors that are marked as hidden in settings
@@ -107,69 +106,14 @@ public partial class MainViewModel
var vm = new MonitorViewModel(monitor, _monitorManager, this);
Monitors.Add(vm);
// Asynchronously initialize color temperature for DDC/CI monitors
if (monitor.SupportsColorTemperature && monitor.CommunicationMethod == "DDC/CI")
{
var task = InitializeColorTemperatureSafeAsync(monitor.Id, vm);
colorTempTasks.Add(task);
}
}
OnPropertyChanged(nameof(HasMonitors));
OnPropertyChanged(nameof(ShowNoMonitorsMessage));
// Wait for color temperature initialization to complete before saving
// This ensures we save the actual scanned values instead of defaults
if (colorTempTasks.Count > 0)
{
// Use fire-and-forget async method to avoid blocking UI thread
_ = WaitForColorTempAndSaveAsync(colorTempTasks);
}
else
{
// No color temperature tasks, save immediately
SaveMonitorsToSettings();
// Restore saved settings if enabled (async, don't block)
_ = ReloadMonitorSettingsAsync(null);
}
}
private async Task WaitForColorTempAndSaveAsync(IReadOnlyList<Task> colorTempTasks)
{
try
{
// Wait for all color temperature initialization tasks to complete
await Task.WhenAll(colorTempTasks);
// Save monitor information to settings.json and reload settings
// Must be done on UI thread since these methods access UI properties and observable collections
_dispatcherQueue.TryEnqueue(async () =>
{
try
{
SaveMonitorsToSettings();
// Restore saved settings if enabled (async)
await ReloadMonitorSettingsAsync(null); // Tasks already completed, pass null
}
catch (Exception innerEx)
{
Logger.LogError($"[WaitForColorTempAndSaveAsync] Error in UI thread operation: {innerEx.Message}");
}
});
}
catch (Exception ex)
{
Logger.LogWarning($"[WaitForColorTempAndSaveAsync] Color temperature initialization failed: {ex.Message}");
// Save anyway with whatever values we have
_dispatcherQueue.TryEnqueue(() =>
{
SaveMonitorsToSettings();
});
}
// Save monitor information to settings and reload
SaveMonitorsToSettings();
_ = ReloadMonitorSettingsAsync(null);
}
public async Task SetAllBrightnessAsync(int brightness)
@@ -192,35 +136,4 @@ public partial class MainViewModel
settings.Properties.Monitors
.Where(m => m.IsHidden)
.Select(m => m.InternalName));
/// <summary>
/// Safe wrapper for initializing color temperature asynchronously
/// </summary>
private async Task InitializeColorTemperatureSafeAsync(string monitorId, MonitorViewModel vm)
{
try
{
// Read current color temperature from hardware
await _monitorManager.InitializeColorTemperatureAsync(monitorId);
// Get the monitor and use the hardware value as-is
var monitor = _monitorManager.GetMonitor(monitorId);
if (monitor != null)
{
Logger.LogInfo($"[{monitorId}] Read color temperature from hardware: {monitor.CurrentColorTemperature}");
_dispatcherQueue.TryEnqueue(() =>
{
// Update color temperature without triggering hardware write
// Use the hardware value directly, even if not in the preset list
// This will also update monitor_state.json via MonitorStateManager
vm.UpdatePropertySilently(nameof(vm.ColorTemperature), monitor.CurrentColorTemperature);
});
}
}
catch (Exception ex)
{
Logger.LogWarning($"Failed to initialize color temperature for {monitorId}: {ex.Message}");
}
}
}