2
0

Add Reset and Detect buttons to Config dialog
Some checks failed
Build / build (push) Has been cancelled
Build and Release / build (push) Has been cancelled

- Reset button: clears custom labels, unhides all ports, removes discovered ports
- Detect button: tries common VCP 60 values to discover available input ports
- Version bumped to 1.1.2

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-10 02:41:42 -05:00
parent 0c860d19ea
commit fc3ebe14be
7 changed files with 198 additions and 17 deletions

View File

@@ -126,4 +126,57 @@ public static class MonitorConfigManager
{
_cachedConfig = null;
}
/// <summary>
/// Save a discovered port that the monitor didn't report in its possible values.
/// This ensures ports like DisplayPort-1 are remembered even if the monitor firmware doesn't list them.
/// </summary>
public static void AddDiscoveredPort(string serialNumber, string monitorName, int vcpValue, string defaultName)
{
var config = Load();
var monitorConfig = config.Monitors.FirstOrDefault(m => m.SerialNumber == serialNumber);
if (monitorConfig == null)
{
monitorConfig = new MonitorConfig { SerialNumber = serialNumber, MonitorName = monitorName };
config.Monitors.Add(monitorConfig);
}
// Check if port already exists
if (monitorConfig.Ports.Any(p => p.VcpValue == vcpValue))
return;
// Add the discovered port
monitorConfig.Ports.Add(new PortConfig
{
VcpValue = vcpValue,
DefaultName = defaultName,
CustomLabel = "",
IsHidden = false,
ShowInQuickSwitch = false
});
Save(config);
}
/// <summary>
/// Get any discovered ports from config that the monitor didn't report.
/// </summary>
public static List<InputSourceOption> GetDiscoveredPorts(string serialNumber, List<InputSourceOption> reportedOptions)
{
var discovered = new List<InputSourceOption>();
var monitorConfig = GetMonitorConfig(serialNumber);
foreach (var port in monitorConfig.Ports)
{
// If this port isn't in the reported options, it's a discovered port
if (!reportedOptions.Any(o => o.Value == port.VcpValue))
{
var name = !string.IsNullOrWhiteSpace(port.CustomLabel) ? port.CustomLabel : port.DefaultName;
discovered.Add(new InputSourceOption(port.VcpValue, name));
}
}
return discovered;
}
}

View File

@@ -39,17 +39,21 @@ public static class CMMCommand
CMMexe,
$"/GetValue {monitorSN} {vcpCode}");
// Empty result means timeout - don't retry, monitor is unresponsive
if (string.IsNullOrEmpty(output) && exitCode == -1)
// Timeout
if (exitCode == -1)
return string.Empty;
// Parse output - ControlMyMonitor outputs the value directly
var value = output?.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).LastOrDefault()?.Trim();
// ControlMyMonitor returns the value as the exit code
// Exit code > 0 means success with that value
if (exitCode > 0)
return exitCode.ToString();
if (!string.IsNullOrEmpty(value) && exitCode == 0)
// Also check stdout in case it outputs there
var value = output?.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).LastOrDefault()?.Trim();
if (!string.IsNullOrEmpty(value) && value != "0")
return value;
// Only retry on non-timeout failures
// Only retry on failure
if (attempt < maxRetries)
await Task.Delay(300);
}