diff --git a/.idea/.idea.LittleBigMouse/.idea/avalonia.xml b/.idea/.idea.LittleBigMouse/.idea/avalonia.xml
new file mode 100644
index 00000000..1c057753
--- /dev/null
+++ b/.idea/.idea.LittleBigMouse/.idea/avalonia.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.LittleBigMouse/.idea/projectSettingsUpdater.xml b/.idea/.idea.LittleBigMouse/.idea/projectSettingsUpdater.xml
index 4bb9f4d2..ef20cb08 100644
--- a/.idea/.idea.LittleBigMouse/.idea/projectSettingsUpdater.xml
+++ b/.idea/.idea.LittleBigMouse/.idea/projectSettingsUpdater.xml
@@ -1,6 +1,8 @@
-
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.LittleBigMouse/.idea/workspace.xml b/.idea/.idea.LittleBigMouse/.idea/workspace.xml
index ff9885ce..c44583f4 100644
--- a/.idea/.idea.LittleBigMouse/.idea/workspace.xml
+++ b/.idea/.idea.LittleBigMouse/.idea/workspace.xml
@@ -4,6 +4,9 @@
HLab.Avalonia/HLab.Base.Avalonia.UITest/HLab.Base.Avalonia.UITest.csproj
HLab.Core/HLab.ColorTools.Benchmark/HLab.ColorTools.Benchmark.csproj
LittleBigMouse.Daemon/LittleBigMouse.Hook/LittleBigMouse.Hook.vcxproj
+ LittleBigMouse.Server/LittleBigMouse.Server.csproj
+ LittleBigMouse.Server/LittleBigMouse.Server.csproj
+ LittleBigMouse.Ui.Loader/LittleBigMouse.Ui.Loader.csproj
LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/LittleBigMouse.Ui.Avalonia.csproj
LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/LittleBigMouse.Ui.Avalonia.csproj
@@ -12,29 +15,29 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
+
-
+
+
+
+
+
+
+
@@ -53,8 +56,10 @@
".NET Launch Settings Profile.LittleBigMouse.Ui.Avalonia.executor": "Run",
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
- "XThreadsFramesViewSplitterKey": "0.68308353",
- "git-widget-placeholder": "Add-Options",
+ "RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
+ "XThreadsFramesViewSplitterKey": "0.50920635",
+ "git-widget-placeholder": "main",
+ "ignore.virus.scanning.warn.message": "true",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
@@ -62,21 +67,13 @@
"nodejs_package_manager_path": "npm",
"settings.editor.selected.configurable": "preferences.pluginManager",
"vue.rearranger.settings.migration": "true"
- },
- "keyToStringList": {
- "rider.external.source.directories": [
- "C:\\Users\\user\\AppData\\Roaming\\JetBrains\\Rider2024.1\\resharper-host\\DecompilerCache",
- "C:\\Users\\user\\AppData\\Roaming\\JetBrains\\Rider2024.1\\resharper-host\\SourcesCache",
- "C:\\Users\\user\\AppData\\Local\\Symbols\\src"
- ]
}
}]]>
-
+
-
@@ -84,11 +81,11 @@
+
-
+
-
@@ -96,11 +93,11 @@
+
-
+
-
@@ -108,11 +105,11 @@
+
-
+
-
@@ -120,11 +117,11 @@
+
-
+
-
@@ -132,11 +129,11 @@
+
-
+
-
@@ -144,11 +141,11 @@
+
-
+
-
@@ -156,11 +153,11 @@
+
-
+
-
@@ -168,11 +165,11 @@
+
-
+
-
@@ -180,8 +177,10 @@
+
+
@@ -197,8 +196,13 @@
+
+
+
+
+
@@ -215,8 +219,13 @@
+
+
+
+
+
@@ -227,6 +236,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -238,6 +325,7 @@
+
@@ -258,6 +346,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -280,4 +381,46 @@
+
+
+
+
+ file://$PROJECT_DIR$/LittleBigMouse.Hook/Geometry/Geometry.h
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ file://$PROJECT_DIR$/LittleBigMouse.Ui/LittleBigMouse.Ui.Avalonia/MonitorFrame/MonitorFrameView.axaml.cs
+ 34
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HLab.Avalonia b/HLab.Avalonia
index cc49b761..d4ea9fe6 160000
--- a/HLab.Avalonia
+++ b/HLab.Avalonia
@@ -1 +1 @@
-Subproject commit cc49b761c4a86b39b428ea5fd0f1c9a803182502
+Subproject commit d4ea9fe6c57b2a6e59ebe5b8fcc1e827eb473e6d
diff --git a/HLab.Core b/HLab.Core
index a76029e0..5ce89054 160000
--- a/HLab.Core
+++ b/HLab.Core
@@ -1 +1 @@
-Subproject commit a76029e08c0182544a822f74e4c313f2a81518a6
+Subproject commit 5ce890549c85280be39d55cde57c465540293b86
diff --git a/HLab.Sys/HLab.Sys.Argyll/ArgyllProbe.cs b/HLab.Sys/HLab.Sys.Argyll/ArgyllProbe.cs
index 5339078f..220a0d58 100644
--- a/HLab.Sys/HLab.Sys.Argyll/ArgyllProbe.cs
+++ b/HLab.Sys/HLab.Sys.Argyll/ArgyllProbe.cs
@@ -31,417 +31,419 @@ namespace HLab.Sys.Argyll;
public class ArgyllProbe : ReactiveObject
{
- public ArgyllProbe()
- {
- ConfigFromDipcalGUI();
- }
- public ArgyllProbe(bool autoconfig = true)
- {
- if(autoconfig) ConfigFromDipcalGUI();
- }
-
-
- private static IniFile _dispcalIni;
- private static IniFile DispcalIni
- {
- get
- {
- if (_dispcalIni == null)
- _dispcalIni = new IniFile(
- Path.Combine(
- Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
- @"DisplayCAL\DisplayCAL.ini"
- ));
-
- return _dispcalIni;
- }
-
- }
-
-
- private readonly double[] _xyz = { 0, 0, 0 };
- // private readonly double[] _lab = { 0, 0, 0 };
-
- private static void ArgyllSendKey(Process p, String key)
- {
- //System.Threading.Thread.Sleep(300);
- p.StandardInput.Flush();
- p.StandardInput.Write(key);
- p.StandardInput.Flush();
- }
-
- private bool _calibrating = false;
- private bool _spectrum = false;
-
- public string Name
- {
- get => _name;
- set => this.RaiseAndSetIfChanged(ref _name, value);
- }
- string _name;
-
- public double SpectrumFrom
- {
- get => _spectrumFrom;
- set => this.RaiseAndSetIfChanged(ref _spectrumFrom, value);
- }
- double _spectrumFrom;
-
- public double SpectrumTo
- {
- get => _spectrumTo;
- set => this.RaiseAndSetIfChanged(ref _spectrumTo, value);
- }
- double _spectrumTo;//c => c.Default(720.0));
-
- public int SpectrumSteps
- {
- get => _spectrumSteps;
- set => this.RaiseAndSetIfChanged(ref _spectrumSteps, value);
- }
- int _spectrumSteps;
-
- public double Cct
- {
- get => _cct;
- set => this.RaiseAndSetIfChanged(ref _cct, value);
- }
- double _cct;
-
- public double Cri
- {
- get => _cri;
- set => this.RaiseAndSetIfChanged(ref _cri, value);
- }
- double _cri;
-
- public double Tlci
- {
- get => _tlci;
- set => this.RaiseAndSetIfChanged(ref _tlci, value);
- }
- double _tlci;
-
- public double Lux
- {
- get => _lux;
- set => this.RaiseAndSetIfChanged(ref _lux, value);
- }
- double _lux;
-
- public ObservableCollection Spectrum { get; set; } = new ObservableCollection {0};
-
- public ObservableCollection WaveLength { get; set; } = new ObservableCollection {0};
- private void ArgyllOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
- {
- System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
-
- var line = outLine.Data;
-
- Console.WriteLine(line);
-
- if (line == null) return;
-
- if (sendingProcess is not Process p) return;
-
- if (_spectrum)
- {
- var s = line.Split(',');
-
- Spectrum.Clear();
- WaveLength.Clear();
-
- var nm = SpectrumFrom;
- var step = (SpectrumTo - SpectrumFrom)/(SpectrumSteps - 1);
-
- foreach (var t in s)
- {
- Spectrum.Add( double.Parse(t));
- WaveLength.Add(nm);
- nm += step;
- }
- _spectrum = false;
- }
-
-
- if (line.Contains("Spectrum from"))
- {
- var pos = line.IndexOf("Spectrum from", StringComparison.Ordinal);
- var sub = line[(pos + 14)..];
- var s = sub.Split(' ');
- SpectrumFrom = double.Parse(s[0]);
- SpectrumTo = double.Parse(s[2]);
- SpectrumSteps = int.Parse(s[5]);
- _spectrum = true;
- }
-
- if (line.Contains("Ambient"))
- {
- string[] s = line.Split(' ');
- Lux = double.Parse(s[3]);
- Cct = double.Parse(s[7].Replace("K",""));
- }
-
- if (line.Contains("(Ra)"))
- {
- string[] s = line.Split(' ');
- Cri = double.Parse(s[6]);
- }
-
- if (line.Contains("(Qa)"))
- {
- string[] s = line.Split(' ');
- Tlci = double.Parse(s[8]);
- }
-
- if (line.Contains("Error - Opening USB port"))
- ArgyllSendKey(p, "q");
-
- if (line.Contains("calibration position"))
- {
- if (!_calibrating)
- {
- // TODO
- //var result = MessageBox.Show("Place instrument in calibration position", "Instrument",
- // MessageBoxButton.OKCancel, MessageBoxImage.Information);
- //ArgyllSendKey(p, result == MessageBoxResult.OK ? "k" : "q");
-
- _calibrating = true;
- }
- else ArgyllSendKey(p, "k");
- }
-
- if (line.Contains("Place instrument"))
- {
- System.Threading.Thread.Sleep(300);
- p.StandardInput.Flush();
- //var result = MessageBox.Show("Place instrument in measure position", "Instrument",
+ public ArgyllProbe()
+ {
+ ConfigFromDipcalGUI();
+ }
+ public ArgyllProbe(bool autoconfig = true)
+ {
+ if (autoconfig) ConfigFromDipcalGUI();
+ }
+
+
+ private static IniFile _dispcalIni;
+ private static IniFile DispcalIni
+ {
+ get
+ {
+ if (_dispcalIni == null)
+ _dispcalIni = new IniFile(
+ Path.Combine(
+ Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
+ @"DisplayCAL\DisplayCAL.ini"
+ ));
+
+ return _dispcalIni;
+ }
+
+ }
+
+
+ private readonly double[] _xyz = { 0, 0, 0 };
+ // private readonly double[] _lab = { 0, 0, 0 };
+
+ private static void ArgyllSendKey(Process p, String key)
+ {
+ //System.Threading.Thread.Sleep(300);
+ p.StandardInput.Flush();
+ p.StandardInput.Write(key);
+ p.StandardInput.Flush();
+ }
+
+ private bool _calibrating = false;
+ private bool _spectrum = false;
+
+ public string Name
+ {
+ get => _name;
+ set => this.RaiseAndSetIfChanged(ref _name, value);
+ }
+ string _name;
+
+ public double SpectrumFrom
+ {
+ get => _spectrumFrom;
+ set => this.RaiseAndSetIfChanged(ref _spectrumFrom, value);
+ }
+ double _spectrumFrom;
+
+ public double SpectrumTo
+ {
+ get => _spectrumTo;
+ set => this.RaiseAndSetIfChanged(ref _spectrumTo, value);
+ }
+ double _spectrumTo;//c => c.Default(720.0));
+
+ public int SpectrumSteps
+ {
+ get => _spectrumSteps;
+ set => this.RaiseAndSetIfChanged(ref _spectrumSteps, value);
+ }
+ int _spectrumSteps;
+
+ public double Cct
+ {
+ get => _cct;
+ set => this.RaiseAndSetIfChanged(ref _cct, value);
+ }
+ double _cct;
+
+ public double Cri
+ {
+ get => _cri;
+ set => this.RaiseAndSetIfChanged(ref _cri, value);
+ }
+ double _cri;
+
+ public double Tlci
+ {
+ get => _tlci;
+ set => this.RaiseAndSetIfChanged(ref _tlci, value);
+ }
+ double _tlci;
+
+ public double Lux
+ {
+ get => _lux;
+ set => this.RaiseAndSetIfChanged(ref _lux, value);
+ }
+ double _lux;
+
+ public string Message
+ {
+ get => _message;
+ set => this.RaiseAndSetIfChanged(ref _message, value);
+ }
+ string _message;
+
+ public ObservableCollection Spectrum { get; set; } = new ObservableCollection { 0 };
+
+ public ObservableCollection WaveLength { get; set; } = new ObservableCollection { 0 };
+ private void ArgyllOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
+ {
+ System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
+
+ var line = outLine.Data;
+
+ Console.WriteLine(line);
+
+ if (line == null) return;
+
+ if (sendingProcess is not Process p) return;
+
+ if (_spectrum)
+ {
+ var s = line.Split(',');
+
+ Spectrum.Clear();
+ WaveLength.Clear();
+
+ var nm = SpectrumFrom;
+ var step = (SpectrumTo - SpectrumFrom) / (SpectrumSteps - 1);
+
+ foreach (var t in s)
+ {
+ Spectrum.Add(double.Parse(t));
+ WaveLength.Add(nm);
+ nm += step;
+ }
+ _spectrum = false;
+ }
+
+
+ if (line.Contains("Spectrum from"))
+ {
+ var pos = line.IndexOf("Spectrum from", StringComparison.Ordinal);
+ var sub = line[(pos + 14)..];
+ var s = sub.Split(' ');
+ SpectrumFrom = double.Parse(s[0]);
+ SpectrumTo = double.Parse(s[2]);
+ SpectrumSteps = int.Parse(s[5]);
+ _spectrum = true;
+ }
+
+ if (line.Contains("Ambient"))
+ {
+ string[] s = line.Split(' ');
+ Lux = double.Parse(s[3]);
+ Cct = double.Parse(s[7].Replace("K", ""));
+ }
+
+ if (line.Contains("(Ra)"))
+ {
+ string[] s = line.Split(' ');
+ Cri = double.Parse(s[6]);
+ }
+
+ if (line.Contains("(Qa)"))
+ {
+ string[] s = line.Split(' ');
+ Tlci = double.Parse(s[8]);
+ }
+
+ if (line.Contains("Error - Opening USB port"))
+ ArgyllSendKey(p, "q");
+
+ if (line.Contains("calibration position"))
+ {
+ if (!_calibrating)
+ {
+ // TODO
+ //var result = MessageBox.Show("Place instrument in calibration position", "Instrument",
// MessageBoxButton.OKCancel, MessageBoxImage.Information);
- //ArgyllSendKey(p, result == MessageBoxResult.OK ? "0" : "q");
- ArgyllSendKey(p, "0");
- }
-
- if (line.Contains("Result is XYZ:"))
- {
- int pos = line.IndexOf("XYZ: ", StringComparison.Ordinal);
- string sub = line.Substring(pos + 5);
- sub = sub.Remove(sub.IndexOf(','));
- string[] s = sub.Split(' ');
- for (int i = 0; i < 3; i++)
- {
- try
- {
- _xyz[i] = Double.Parse(s[i]);
- }
- catch { _xyz[i] = 0; }
- }
-
- _calibrating = false;
- //if (line.Contains("D50 Lab:"))
- //{
- // pos = line.IndexOf("D50 Lab:", StringComparison.Ordinal);
- // sub = line.Substring(pos + 9);
- // //sub.Remove(sub.IndexOf(','));
- // s = sub.Split(' ');
- // for (int i = 0; i < 3; i++)
- // {
- // try
- // {
- // _lab[i] = Double.Parse(s[i]);
- // }
- // catch { _lab[i] = 0; }
- // }
-
- //}
-
- //((Process)sendingProcess).Kill();
- }
- }
-
- public enum MeasurementMode
- {
- Emissive,
- Projector,
- Ambiant,
- Flash
- }
-
- public enum ObserverEnum
- {
- CIE_1931_2,
- CIE_1964_10,
- CIE_2012_10,
- CIE_2012_2,
- SB_1955_2,
- JV_1978_2,
- Shaw,
- }
-
- public static string ArgyllPath { get; set; }
-
- public int ColorTemp { get; set; } = 6500;
- public MeasurementMode Mode { get; set; } = MeasurementMode.Emissive;
- public bool HighResolution { get; set; } = true;
- public bool Adaptive { get; set; } = true;
- public bool ReadSpectrum { get; set; } = false;
- public bool ReadCri { get; set; } = false;
-
- private ObserverEnum Observer { get; set; } = ObserverEnum.CIE_1931_2;
-
- public static void PathFromDispcalGUI()
- {
- ArgyllPath = DispcalIni.ReadValue("Default", "argyll.dir", "");
- }
-
- public void ConfigFromDipcalGUI()
- {
- PathFromDispcalGUI();
-
- ColorTemp =
- int.Parse(DispcalIni.ReadValue("Default", "whitepoint.colortemp", "5000"));
-
- switch (DispcalIni.ReadValue("Default", "measurement_mode", "1"))
- {
- case "c": // CRT ???
- break;
- case "p": // CRT ???
- Mode = MeasurementMode.Projector;
- break;
- case "1":
- Mode = MeasurementMode.Emissive;
- break;
- }
-
- HighResolution = (DispcalIni.ReadValue("Default", "measurement_mode.highres", "0") == "1");
-
- Adaptive = (DispcalIni.ReadValue("Default", "measurement_mode.adaptive", "1") == "1");
-
- string obs = DispcalIni.ReadValue("Default", "observer", "1931_2");
- switch (obs)
- {
- case "1931_2":
- Observer = ObserverEnum.CIE_1931_2;
- break;
- case "1964_10":
- Observer = ObserverEnum.CIE_1964_10;
- break;
- case "1955_2":
- Observer = ObserverEnum.SB_1955_2;
- break;
- case "shaw":
- Observer = ObserverEnum.Shaw;
- break;
- case "1978_2":
- Observer = ObserverEnum.JV_1978_2;
- break;
- case "2012_2":
- Observer = ObserverEnum.CIE_2012_2;
- break;
- case "2012_10":
- Observer = ObserverEnum.CIE_2012_10;
- break;
- }
- }
-
- public string SpotReadArgs
- {
- get
- {
- string s = " -N";
- switch (Mode)
- {
- case MeasurementMode.Projector:
- s += " -pb";
- break;
- case MeasurementMode.Emissive:
- s += " -e";
- break;
- case MeasurementMode.Ambiant:
- s += " -a";
- break;
- case MeasurementMode.Flash:
- s += " -f";
- break;
- }
-
-
-
- if (HighResolution) s += " -H";
-
- if (!Adaptive) s += " -Y A";
-
- s += " -O";
-
- s += " -Q";
-
- switch (Observer)
- {
- case ObserverEnum.CIE_1931_2:
- s += " 1931_2";
- break;
- case ObserverEnum.CIE_1964_10:
- s += " 1964_10";
- break;
- case ObserverEnum.SB_1955_2:
- s += " 1955_2";
- break;
- case ObserverEnum.Shaw:
- s += " shaw";
- break;
- case ObserverEnum.JV_1978_2:
- s += " 1978_2";
- break;
- default:
- throw new ArgumentOutOfRangeException();
- }
-
- if (ReadSpectrum) s += " -s";
- if (ReadCri) s += " -T";
- return s;
- }
- }
-
-
- public bool Installed => ArgyllPath != "";
-
- public bool SpotRead()
- {
- if (!Installed) return false;
-
- do
- {
- ExecSpotRead();
- } while (_calibrating);
-
- return true;
- }
-
- public ProbedColor ProbedColor => new ProbedColorXYZ
- {
- Illuminant = ProbedColor.DIlluminant(ColorTemp),
- X = _xyz[0],
- Y = _xyz[1],
- Z = _xyz[2]
- };
-
- public void ExecSpotRead()
- {
- var aProc = Process.GetProcessesByName("Spotread");
- foreach (var t in aProc)
- {
+ //ArgyllSendKey(p, result == MessageBoxResult.OK ? "k" : "q");
+
+ Message = "Place instrument in calibration position";
+
+ _calibrating = true;
+ }
+ else ArgyllSendKey(p, "k");
+ }
+
+ if (line.Contains("Place instrument"))
+ {
+ System.Threading.Thread.Sleep(300);
+ p.StandardInput.Flush();
+
+ Message = "Place instrument in measure position";
+ //var result = MessageBox.Show("Place instrument in measure position", "Instrument",
+ // MessageBoxButton.OKCancel, MessageBoxImage.Information);
+ //ArgyllSendKey(p, result == MessageBoxResult.OK ? "0" : "q");
+ ArgyllSendKey(p, "0");
+ }
+
+ if (line.Contains("Result is XYZ:"))
+ {
+ int pos = line.IndexOf("XYZ: ", StringComparison.Ordinal);
+ string sub = line.Substring(pos + 5);
+ sub = sub.Remove(sub.IndexOf(','));
+ string[] s = sub.Split(' ');
+ for (int i = 0; i < 3; i++)
+ {
try
{
- t.Kill();
- if (!t.HasExited)
- t.WaitForExit();
-
+ _xyz[i] = Double.Parse(s[i]);
}
- catch (Exception) { }
- }
-
- var p = new Process
- {
- StartInfo =
+ catch { _xyz[i] = 0; }
+ }
+
+ _calibrating = false;
+ //if (line.Contains("D50 Lab:"))
+ //{
+ // pos = line.IndexOf("D50 Lab:", StringComparison.Ordinal);
+ // sub = line.Substring(pos + 9);
+ // //sub.Remove(sub.IndexOf(','));
+ // s = sub.Split(' ');
+ // for (int i = 0; i < 3; i++)
+ // {
+ // try
+ // {
+ // _lab[i] = Double.Parse(s[i]);
+ // }
+ // catch { _lab[i] = 0; }
+ // }
+
+ //}
+
+ //((Process)sendingProcess).Kill();
+ }
+ }
+
+ public enum MeasurementMode
+ {
+ Emissive,
+ Projector,
+ Ambiant,
+ Flash
+ }
+
+ public enum ObserverEnum
+ {
+ CIE_1931_2,
+ CIE_1964_10,
+ CIE_2012_10,
+ CIE_2012_2,
+ SB_1955_2,
+ JV_1978_2,
+ Shaw,
+ }
+
+ public static string ArgyllPath { get; set; }
+
+ public int ColorTemp { get; set; } = 6500;
+ public MeasurementMode Mode { get; set; } = MeasurementMode.Emissive;
+ public bool HighResolution { get; set; } = true;
+ public bool Adaptive { get; set; } = true;
+ public bool ReadSpectrum { get; set; } = false;
+ public bool ReadCri { get; set; } = false;
+
+ private ObserverEnum Observer { get; set; } = ObserverEnum.CIE_1931_2;
+
+ public static void PathFromDispcalGUI()
+ {
+ ArgyllPath = DispcalIni.ReadValue("Default", "argyll.dir", "");
+ }
+
+ public void ConfigFromDipcalGUI()
+ {
+ PathFromDispcalGUI();
+
+ ColorTemp =
+ int.Parse(DispcalIni.ReadValue("Default", "whitepoint.colortemp", "5000"));
+
+ switch (DispcalIni.ReadValue("Default", "measurement_mode", "1"))
+ {
+ case "c": // CRT ???
+ break;
+ case "p": // CRT ???
+ Mode = MeasurementMode.Projector;
+ break;
+ case "1":
+ Mode = MeasurementMode.Emissive;
+ break;
+ }
+
+ HighResolution = (DispcalIni.ReadValue("Default", "measurement_mode.highres", "0") == "1");
+
+ Adaptive = (DispcalIni.ReadValue("Default", "measurement_mode.adaptive", "1") == "1");
+
+ string obs = DispcalIni.ReadValue("Default", "observer", "1931_2");
+ switch (obs)
+ {
+ case "1931_2":
+ Observer = ObserverEnum.CIE_1931_2;
+ break;
+ case "1964_10":
+ Observer = ObserverEnum.CIE_1964_10;
+ break;
+ case "1955_2":
+ Observer = ObserverEnum.SB_1955_2;
+ break;
+ case "shaw":
+ Observer = ObserverEnum.Shaw;
+ break;
+ case "1978_2":
+ Observer = ObserverEnum.JV_1978_2;
+ break;
+ case "2012_2":
+ Observer = ObserverEnum.CIE_2012_2;
+ break;
+ case "2012_10":
+ Observer = ObserverEnum.CIE_2012_10;
+ break;
+ }
+ }
+
+ public string SpotReadArgs
+ {
+ get
+ {
+ string s = " -N";
+ switch (Mode)
+ {
+ case MeasurementMode.Projector:
+ s += " -pb";
+ break;
+ case MeasurementMode.Emissive:
+ s += " -e";
+ break;
+ case MeasurementMode.Ambiant:
+ s += " -a";
+ break;
+ case MeasurementMode.Flash:
+ s += " -f";
+ break;
+ }
+
+
+
+ if (HighResolution) s += " -H";
+
+ if (!Adaptive) s += " -Y A";
+
+ s += " -O";
+
+ s += " -Q";
+
+ s += Observer switch
+ {
+ ObserverEnum.CIE_1931_2 => " 1931_2",
+ ObserverEnum.CIE_1964_10 => " 1964_10",
+ ObserverEnum.SB_1955_2 => " 1955_2",
+ ObserverEnum.Shaw => " shaw",
+ ObserverEnum.JV_1978_2 => " 1978_2",
+ ObserverEnum.CIE_2012_2 => " 2012_2",
+ ObserverEnum.CIE_2012_10 => " 2012_10",
+ _ => throw new ArgumentOutOfRangeException()
+ };
+
+ if (ReadSpectrum) s += " -s";
+ if (ReadCri) s += " -T";
+ return s;
+ }
+ }
+
+
+ public bool Installed => ArgyllPath != "";
+
+ public bool SpotRead()
+ {
+ if (!Installed) return false;
+
+ do
+ {
+ ExecSpotRead();
+ } while (_calibrating);
+
+ return true;
+ }
+
+ public ProbedColor ProbedColor => new ProbedColorXYZ
+ {
+ Illuminant = ProbedColor.DIlluminant(ColorTemp),
+ X = _xyz[0],
+ Y = _xyz[1],
+ Z = _xyz[2]
+ };
+
+ public void ExecSpotRead()
+ {
+ var aProc = Process.GetProcessesByName("Spotread");
+ foreach (var t in aProc)
+ {
+ try
+ {
+ t.Kill();
+ if (!t.HasExited)
+ t.WaitForExit();
+
+ }
+ catch (Exception) { }
+ }
+
+ var p = new Process
+ {
+ StartInfo =
{
FileName = Path.Combine(ArgyllPath, @"Spotread.exe"),
Arguments = SpotReadArgs,
@@ -451,90 +453,90 @@ public void ExecSpotRead()
RedirectStandardInput = true,
CreateNoWindow = true
}
- };
-
- // p.StartInfo.Arguments = "-N -O -Y A";
-
- try
- {
- p.StartInfo.EnvironmentVariables.Add("ARGYLL_NOT_INTERACTIVE", "yes");
- }
- catch
- {
- }
-
- p.ErrorDataReceived += ArgyllOutputHandler;
- p.OutputDataReceived += ArgyllOutputHandler;
-
- p.Start();
- p.BeginErrorReadLine();
- p.BeginOutputReadLine();
-
- if (!p.HasExited) p.WaitForExit();
- }
-
- //TODO
-
- public void Save()
- {
- // Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
- // dlg.DefaultExt = ".probe";
- // dlg.Filter = "Probe documents (.probe)|*.probe";
- // bool? result = dlg.ShowDialog();
- // if (result == true)
- // {
- // // Open document
- // string filename = dlg.FileName;
- // Save(filename);
- // }
- }
-
- public void Save(string path)
- {
- XmlSerializer serializer = new XmlSerializer(typeof(ArgyllProbe));
- using (TextWriter writer = new StreamWriter(path))
- {
- serializer.Serialize(writer, this);
- }
- }
-
-
- public static ArgyllProbe Load()
- {
- //TODO
- //Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
- //dlg.DefaultExt = ".probe";
- //dlg.Filter = "Probe documents (.probe)|*.probe";
- //bool? result = dlg.ShowDialog();
- //if (result == true)
- //{
- // // Open document
- // string filename = dlg.FileName;
- // return Load(filename);
- //}
- return null;
- }
-
-
- public static ArgyllProbe Load(string path)
- {
- ArgyllProbe probe = null;
-
- XmlSerializer deserializer = new XmlSerializer(typeof(ArgyllProbe));
-
- try
- {
- TextReader reader = new StreamReader(path);
- probe = (ArgyllProbe)deserializer.Deserialize(reader);
- reader.Close();
- }
- catch (FileNotFoundException)
- {
-
- }
-
- return probe;
- }
+ };
+
+ // p.StartInfo.Arguments = "-N -O -Y A";
+
+ try
+ {
+ p.StartInfo.EnvironmentVariables.Add("ARGYLL_NOT_INTERACTIVE", "yes");
+ }
+ catch
+ {
+ }
+
+ p.ErrorDataReceived += ArgyllOutputHandler;
+ p.OutputDataReceived += ArgyllOutputHandler;
+
+ p.Start();
+ p.BeginErrorReadLine();
+ p.BeginOutputReadLine();
+
+ if (!p.HasExited) p.WaitForExit();
+ }
+
+ //TODO
+
+ public void Save()
+ {
+ // Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
+ // dlg.DefaultExt = ".probe";
+ // dlg.Filter = "Probe documents (.probe)|*.probe";
+ // bool? result = dlg.ShowDialog();
+ // if (result == true)
+ // {
+ // // Open document
+ // string filename = dlg.FileName;
+ // Save(filename);
+ // }
+ }
+
+ public void Save(string path)
+ {
+ XmlSerializer serializer = new XmlSerializer(typeof(ArgyllProbe));
+ using (TextWriter writer = new StreamWriter(path))
+ {
+ serializer.Serialize(writer, this);
+ }
+ }
+
+
+ public static ArgyllProbe Load()
+ {
+ //TODO
+ //Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
+ //dlg.DefaultExt = ".probe";
+ //dlg.Filter = "Probe documents (.probe)|*.probe";
+ //bool? result = dlg.ShowDialog();
+ //if (result == true)
+ //{
+ // // Open document
+ // string filename = dlg.FileName;
+ // return Load(filename);
+ //}
+ return null;
+ }
+
+
+ public static ArgyllProbe Load(string path)
+ {
+ ArgyllProbe probe = null;
+
+ XmlSerializer deserializer = new XmlSerializer(typeof(ArgyllProbe));
+
+ try
+ {
+ TextReader reader = new StreamReader(path);
+ probe = (ArgyllProbe)deserializer.Deserialize(reader);
+ reader.Close();
+ }
+ catch (FileNotFoundException)
+ {
+
+ }
+
+ return probe;
+ }
}
diff --git a/HLab.Sys/HLab.Sys.Argyll/HLab.Sys.Argyll.csproj b/HLab.Sys/HLab.Sys.Argyll/HLab.Sys.Argyll.csproj
index 209e50fa..2dce7de1 100644
--- a/HLab.Sys/HLab.Sys.Argyll/HLab.Sys.Argyll.csproj
+++ b/HLab.Sys/HLab.Sys.Argyll/HLab.Sys.Argyll.csproj
@@ -1,15 +1,15 @@

- net8.0
+ net10.0
AnyCPU;x64;x86
Debug;Release;ReleaseDebug
- 2.4.0.0
+ 2.5.0.0
-
-
+
+
diff --git a/HLab.Sys/HLab.Sys.Windows.MonitorVcp.Avalonia/DrawingContextExtention.cs b/HLab.Sys/HLab.Sys.Windows.MonitorVcp.Avalonia/DrawingContextExtention.cs
index ded79c71..34490836 100644
--- a/HLab.Sys/HLab.Sys.Windows.MonitorVcp.Avalonia/DrawingContextExtention.cs
+++ b/HLab.Sys/HLab.Sys.Windows.MonitorVcp.Avalonia/DrawingContextExtention.cs
@@ -14,9 +14,9 @@ public static void DrawContrast(this DrawingContext dc, Color colorA, Color col
{
var hz = orientation == Orientation.Horizontal;
var length = (hz?area.Width:area.Height)/count;
- var w = (hz?area.Height:area.Width)/2;
+ var w = (hz?area.Height:area.Width);
- var location = area.TopLeft; // was Location
+ var location = area.TopLeft;
var size = hz?new Size(length,w):new Size(w,length);
var move = hz ? new Vector(length, 0) : new Vector(0, length);
@@ -24,7 +24,6 @@ public static void DrawContrast(this DrawingContext dc, Color colorA, Color col
var dG = colorA.G < colorB.G ? +1 : colorA.G > colorB.G? -1 : 0;
var dB = colorA.B < colorB.B ? +1 : colorA.B > colorB.B? -1 : 0;
-
var color = colorA;
for (var i = 0; i < count; i++)
{
@@ -32,22 +31,6 @@ public static void DrawContrast(this DrawingContext dc, Color colorA, Color col
dc.RenderCircle(color,colorA,new Rect(location,size));
location += move;
}
-
- location = area.TopLeft + (hz ? new Vector(0,w) : new Vector(w,0));
-
- dR = -dR;
- dG = -dG;
- dB = -dB;
-
- color = colorB;
- for (var i = 0; i < count; i++)
- {
- color = new Color(0xFF,(byte)((int)color.R+dR), (byte)((int)color.G + dG) , (byte)((int)color.B + dB));
- dc.RenderCircle(color,colorB,new Rect(location,size));
- location += move;
- }
-
-
}
public static void DrawChessboard(this DrawingContext dc, Color colorA, Color colorB, Rect area, Size size)
@@ -100,9 +83,9 @@ double _g(double value, double gg)
}
var startColor =
- new ColorRGB(1.0, _g(colorA.Red / 2.0, startGamma), _g(colorA.Green / 2.0, startGamma), _g(colorA.Blue / 2.0, startGamma));
+ HLabColors.RGB(1.0, _g(colorA.Red / 2.0, startGamma), _g(colorA.Green / 2.0, startGamma), _g(colorA.Blue / 2.0, startGamma));
var endColor =
- new ColorRGB(1.0, _g(colorA.Red/2.0, endGamma), _g(colorA.Green/2.0, endGamma), _g(colorA.Blue/2.0, endGamma));
+ HLabColors.RGB(1.0, _g(colorA.Red/2.0, endGamma), _g(colorA.Green/2.0, endGamma), _g(colorA.Blue/2.0, endGamma));
// var startColor = Color.FromScRgb(f1.0, _g(colorA.ScG/2.0f, startGamma), _g(colorA.ScB/2.0f, startGamma));
// var endColor = Color.FromScRgb(1.0f, _g(colorA.ScR/2.0f, endGamma), _g(colorA.ScG/2.0f, endGamma), _g(colorA.ScB/2.0f, endGamma));
@@ -205,15 +188,10 @@ public static void DrawGradient(this DrawingContext dc, IColor colorA, I
{
var gc = new GradientCalculator(colorA,colorB,gamma);
- var brush = new SolidColorBrush();
-
var length = orientation == Orientation.Horizontal ? area.Width : area.Height;
if (length>500) { }
- var bench = new Stopwatch();
- bench.Start();
-
if (orientation == Orientation.Horizontal)
{
for (var p = 0.0; p < length; p++)
@@ -231,10 +209,6 @@ public static void DrawGradient(this DrawingContext dc, IColor colorA, I
}
}
-
- bench.Stop();
- Debug.WriteLine("Gradient : " + area + " : " + bench.ElapsedTicks);
-
}
class GradientCalculator
@@ -270,12 +244,12 @@ public GradientCalculator(IColor c1, IColor c2, double gamma)
_db = (colorB.Blue - _ba);
}
- float g(double value) => (float)Math.Pow(value, _invgamma);
+ double g(double value) => Math.Pow(value, _invgamma);
public ColorRGB Get(double p)
{
- return new ColorRGB(
+ return HLabColors.RGB(
g(_aa + _da * p),
g(_ra + _dr * p),
g(_ga + _dg * p),
diff --git a/HLab.Sys/HLab.Sys.Windows.MonitorVcp.Avalonia/HLab.Sys.Windows.MonitorVcp.Avalonia.csproj b/HLab.Sys/HLab.Sys.Windows.MonitorVcp.Avalonia/HLab.Sys.Windows.MonitorVcp.Avalonia.csproj
index 26ada263..6acf6c1c 100644
--- a/HLab.Sys/HLab.Sys.Windows.MonitorVcp.Avalonia/HLab.Sys.Windows.MonitorVcp.Avalonia.csproj
+++ b/HLab.Sys/HLab.Sys.Windows.MonitorVcp.Avalonia/HLab.Sys.Windows.MonitorVcp.Avalonia.csproj
@@ -1,19 +1,17 @@

- net8.0
+ net10.0
+ false
enable
enable
- AnyCPU;x64;x86
- 2.4.0.0
+ x64
+ 2.5.0.0
-
-
-
-
+
diff --git a/HLab.Sys/HLab.Sys.Windows.MonitorVcp.Avalonia/TestPattern.cs b/HLab.Sys/HLab.Sys.Windows.MonitorVcp.Avalonia/TestPattern.cs
index 3780cd0e..4ea27fc7 100644
--- a/HLab.Sys/HLab.Sys.Windows.MonitorVcp.Avalonia/TestPattern.cs
+++ b/HLab.Sys/HLab.Sys.Windows.MonitorVcp.Avalonia/TestPattern.cs
@@ -37,7 +37,8 @@ public enum TestPatternType
Solid,
Gradient,
Circle,
- Circles,
+ Contrast,
+ ContrastBoth,
Grid,
Gamma
}
@@ -54,7 +55,7 @@ public Window GetWindow(PixelPoint location, double width, double height)
{
return new Window
{
- SystemDecorations = SystemDecorations.None,
+ WindowDecorations = WindowDecorations.None,
CanResize = false,
Position = location,
Height = height,
@@ -123,23 +124,45 @@ public Color PatternColorB
{
c._onRender = e.NewValue.Value switch
{
- TestPatternType.Solid => (dc, rect, colorA, colorB, orient)
+ TestPatternType.Solid => (dc, rect, colorA, colorB, orientation)
=> dc.DrawRectangle(new SolidColorBrush(colorA), null, rect),
- TestPatternType.Gradient => (dc, rect, colorA, colorB, orient)
- => dc.DrawGradient(colorA.ToColor(), colorB.ToColor(), rect, orient, 1.0 / 2.2 /*2.124*/),
+ TestPatternType.Gradient => (dc, rect, colorA, colorB, orientation)
+ => dc.DrawGradient(colorA.ToColor(), colorB.ToColor(), rect, orientation, 1.0 / 2.2 /*2.124*/),
- TestPatternType.Circle => (dc, rect, colorA, colorB, orient)
+ TestPatternType.Circle => (dc, rect, colorA, colorB, orientation)
=> dc.RenderCircle(colorA, colorB, rect),
- TestPatternType.Circles => (dc, rect, colorA, colorB, orient)
- => dc.DrawContrast(colorA, colorB, rect, 5, orient),
+ TestPatternType.ContrastBoth => (dc, rect, colorA, colorB, orientation)
+ =>
+ {
+ Rect rectA, rectB;
+ if (orientation == Orientation.Vertical)
+ {
+ rectA = new Rect(rect.X, rect.Y, rect.Width / 2, rect.Height);
+ rectB = new Rect(rect.X + rect.Width / 2, rect.Y, rect.Width / 2, rect.Height);
+ }
+ else
+ {
+ rectA = new Rect(rect.X, rect.Y, rect.Width, rect.Height / 2);
+ rectB = new Rect(rect.X, rect.Y + rect.Height / 2, rect.Width, rect.Height / 2);
+ }
+
+ dc.DrawContrast(colorB, colorA, rectA, 5, orientation);
+ dc.DrawContrast(colorA, colorB, rectB, 5, orientation);
+ },
+
+ TestPatternType.Contrast => (dc, rect, colorA, colorB, orientation)
+ =>
+ {
+ dc.DrawContrast(colorA, colorB, rect, 5, orientation);
+ },
- TestPatternType.Grid => (dc, rect, colorA, colorB, orient)
+ TestPatternType.Grid => (dc, rect, colorA, colorB, orientation)
=> dc.DrawHomeCinemaPattern(rect),
- TestPatternType.Gamma => (dc, rect, colorA, colorB, orient)
- => dc.DrawGamma(colorA.ToColor(), colorB.ToColor(), rect, orient),
+ TestPatternType.Gamma => (dc, rect, colorA, colorB, orientation)
+ => dc.DrawGamma(colorA.ToColor(), colorB.ToColor(), rect, orientation),
_ => throw new ArgumentOutOfRangeException()
};
diff --git a/HLab.Sys/HLab.Sys.Windows.MonitorVcp.Avalonia/TestPatternWindow.axaml b/HLab.Sys/HLab.Sys.Windows.MonitorVcp.Avalonia/TestPatternWindow.axaml
index 7ebba162..a89e5657 100644
--- a/HLab.Sys/HLab.Sys.Windows.MonitorVcp.Avalonia/TestPatternWindow.axaml
+++ b/HLab.Sys/HLab.Sys.Windows.MonitorVcp.Avalonia/TestPatternWindow.axaml
@@ -7,7 +7,7 @@
xmlns:avalonia="clr-namespace:HLab.Sys.Windows.MonitorVcp.Avalonia"
mc:Ignorable="d"
Title="TestPatternWindow" Height="300" Width="300"
- SystemDecorations="None"
+ WindowDecorations="None"
ShowInTaskbar="False"
>
diff --git a/HLab.Sys/HLab.Sys.Windows.MonitorVcp/HLab.Sys.Windows.MonitorVcp.csproj b/HLab.Sys/HLab.Sys.Windows.MonitorVcp/HLab.Sys.Windows.MonitorVcp.csproj
index bf9f8a16..25f3b1f5 100644
--- a/HLab.Sys/HLab.Sys.Windows.MonitorVcp/HLab.Sys.Windows.MonitorVcp.csproj
+++ b/HLab.Sys/HLab.Sys.Windows.MonitorVcp/HLab.Sys.Windows.MonitorVcp.csproj
@@ -1,10 +1,10 @@

- net8.0
+ net10.0
x64;x86;AnyCpu
Debug;Release
- 2.4.0.0
+ 2.5.0.0
diff --git a/HLab.Sys/HLab.Sys.Windows.MonitorVcp/MonitorRgbLevel.cs b/HLab.Sys/HLab.Sys.Windows.MonitorVcp/MonitorRgbLevel.cs
index 44c8f4a3..e02611d9 100644
--- a/HLab.Sys/HLab.Sys.Windows.MonitorVcp/MonitorRgbLevel.cs
+++ b/HLab.Sys/HLab.Sys.Windows.MonitorVcp/MonitorRgbLevel.cs
@@ -1,4 +1,6 @@
using System;
+using System.Collections.Generic;
+using System.Linq;
using Avalonia.Styling;
using ReactiveUI;
@@ -6,26 +8,48 @@ namespace HLab.Sys.Windows.MonitorVcp;
public class MonitorRgbLevel : ReactiveObject
{
- readonly MonitorLevel[] _values = new MonitorLevel[3];
-
- public MonitorRgbLevel(CommandWorker parser, VcpGetter getter, VcpSetter setter)
- {
- for (var i = 0; i < 3; i++)
- _values[i] = new MonitorLevel(parser, getter, setter, (VcpComponent)i);
- }
-
- public MonitorRgbLevel Start()
- {
- foreach (var level in _values)
- level.Start();
-
- return this;
- }
-
- public MonitorLevel Channel(uint channel) { return _values[channel]; }
-
- public MonitorLevel Red => Channel(0);
- public MonitorLevel Green => Channel(1);
- public MonitorLevel Blue => Channel(2);
-
+ readonly MonitorLevel[] _values = new MonitorLevel[3];
+
+ public MonitorRgbLevel(CommandWorker parser, VcpGetter getter, VcpSetter setter)
+ {
+ for (var i = 0; i < 3; i++)
+ _values[i] = new MonitorLevel(parser, getter, setter, (VcpComponent)i);
+ }
+
+ public MonitorRgbLevel Start()
+ {
+ foreach (var level in _values)
+ level.Start();
+
+ return this;
+ }
+
+ public MonitorLevel Channel(uint channel) { return _values[channel]; }
+
+ public MonitorLevel Red => Channel(0);
+ public MonitorLevel Green => Channel(1);
+ public MonitorLevel Blue => Channel(2);
+
+ public void SetToMax()
+ {
+ foreach (var level in _values)
+ level.SetToMax();
+ }
+
+ public void SetToMin()
+ {
+ foreach (var level in _values)
+ level.SetToMin();
+ }
+
+ public void SetTo(uint[] value)
+ {
+ for (var i = 0; i < value.Length; i++)
+ {
+ if(_values.Length <= i) break;
+ _values[i].Value = value[i];
+ }
+ }
+
+ public uint[] GetValues() => _values.Select(t => t.Value).ToArray();
}
\ No newline at end of file
diff --git a/HLab.Sys/HLab.Sys.Windows.MonitorVcp/ProbeLut.cs b/HLab.Sys/HLab.Sys.Windows.MonitorVcp/ProbeLut.cs
index a2b5c62f..266dcf79 100644
--- a/HLab.Sys/HLab.Sys.Windows.MonitorVcp/ProbeLut.cs
+++ b/HLab.Sys/HLab.Sys.Windows.MonitorVcp/ProbeLut.cs
@@ -24,9 +24,13 @@ You should have received a copy of the GNU General Public License
#nullable enable
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
+using System.Reactive.Linq;
using System.Xml.Serialization;
+using DynamicData;
+using DynamicData.Binding;
using HLab.Sys.Argyll;
using HLab.Sys.Windows.Monitors;
using ReactiveUI;
@@ -35,213 +39,315 @@ namespace HLab.Sys.Windows.MonitorVcp;
public class ProbeLut : ReactiveObject
{
- public ProbedColor DIlluminant { get; }
+ //public ProbedColor DIlluminant { get; }
+
+ readonly MonitorDevice _monitor;
+
+ readonly SourceList _lut = new();
+
+
+ readonly ReadOnlyObservableCollection _sortedLut;
+ public ReadOnlyObservableCollection SortedLut => _sortedLut;
+
+ readonly SourceList _smoothLut = new();
+ readonly ReadOnlyObservableCollection _smoothLutCollection;
+ public ReadOnlyObservableCollection SmoothLut => _smoothLutCollection;
+
+ internal ProbeLut(MonitorDevice monitor)
+ {
+ _monitor = monitor;
+ Vcp = _monitor.Vcp();
+
+ _luminance = this.WhenAnyValue(
+ e => e.Vcp.Brightness.Value,
+ selector: e => GetLuminance()
+ ).ToProperty(this, _ => _.Luminance);
+
+ _lut
+ .Connect()
+ .Sort(SortExpressionComparer.Ascending(t => t.Y))
+ .ObserveOn(RxSchedulers.MainThreadScheduler)
+ .Bind(out _sortedLut)
+ .Subscribe();
+
+ _smoothLut
+ .Connect()
+ .Sort(SortExpressionComparer.Ascending(t => t.Y))
+ .ObserveOn(RxSchedulers.MainThreadScheduler)
+ .Bind(out _smoothLutCollection)
+ .Subscribe();
+ }
+
+ public (double Slope, double Intercept) LinearRegression(IEnumerablelist, Func getX, Func getY)
+ {
+ var sumX = 0.0;
+ var sumY = 0.0;
+ var sumXY = 0.0;
+ var sumX2 = 0.0;
+ var n = _sortedLut.Count;
+
+ foreach (var tune in list)
+ {
+ var x = getX(tune);
+ var y = getY(tune);
+
+ sumX += x;
+ sumY += y;
+ sumXY += x * y;
+ sumX2 += x * x;
+ }
+
+ var slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX);
+ var intercept = (sumY - slope * sumX) / n;
+
+ return (slope, intercept);
+ }
+
+ public void GenerateSmoothedCurve()
+ {
+ _smoothLut.Clear();
+
+ var(slopeY,interceptY) = LinearRegression(_sortedLut, t => t.Brightness, t => t.Y);
+ var(slopeR,interceptR) = LinearRegression(_sortedLut, t => t.Brightness, t => t.Red);
+ var(slopeG,interceptG) = LinearRegression(_sortedLut, t => t.Brightness, t => t.Green);
+ var(slopeB,interceptB) = LinearRegression(_sortedLut, t => t.Brightness, t => t.Blue);
+
+ var start = (int)_sortedLut.First().Brightness;
+ var end = (int)_sortedLut.Last().Brightness;
+
+ for (var i=start; i x.Brightness == brightness);
+ if (t == null) return false;
- List _lut = new();
+ _lut.Remove(t);
+ return true;
+ }
- internal ProbeLut(MonitorDevice monitor)
- {
- _monitor = monitor;
-
- _luminance = this.WhenAnyValue(
- e => e.Vcp.Brightness.Value,
- selector: e => GetLuminance()
- ).ToProperty(this, _ => _.Luminance);
- }
-
- public VcpControl Vcp => _monitor.Vcp();
-
- public bool RemoveBrightness(double brightness)
- {
- var t = _lut.FirstOrDefault(x => x.Brightness == brightness);
- if (t == null) return false;
-
- _lut.Remove(t);
- return true;
- }
-
- public bool RemoveLowBrightness(double maxGain)
- {
- var t = _lut.FirstOrDefault(x => (x.Brightness == 0 && x.MaxGain == maxGain));
- if (t == null) return false;
-
- _lut.Remove(t);
- return true;
- }
-
- public void Add(Tune tune)
- {
- _lut.Add(tune);
-
- _lut = _lut.OrderBy(x => x.Y).ToList();
- }
-
- public Tune FromLuminance(double luminance)
- {
- if (_lut.Count == 0) return Current;
-
- Tune tSup = null;
- Tune tInf = null;
-
- var i = 0;
- for (; i < _lut.Count && _lut[i].Y < luminance; i++)
- tInf = _lut[i];
-
- // luminance is more than monitor capabilities
- if (i >= _lut.Count) return tInf;
-
- tSup = _lut[i];
-
- if (tInf == null) return tSup;
-
- var dist = tSup.Y - tInf.Y;
- var ratio = (luminance - tInf.Y) / dist;
-
- var t = new Tune
- {
- Y = (uint)Math.Round(tInf.Y + (tSup.Y - tInf.Y) * ratio, 0),
- x = (uint)Math.Round(tInf.x + (tSup.x - tInf.x) * ratio, 0),
- y = (uint)Math.Round(tInf.y + (tSup.y - tInf.y) * ratio, 0),
-
- Brightness = (uint)Math.Round(tInf.Brightness + (tSup.Brightness - tInf.Brightness) * ratio, 0),
- Contrast = (uint)Math.Round(tInf.Contrast + (tSup.Contrast - tInf.Contrast) * ratio, 0),
-
- Red = (uint)Math.Round(tInf.Red + (tSup.Red - tInf.Red) * ratio, 0),
- Blue = (uint)Math.Round(tInf.Blue + (tSup.Blue - tInf.Blue) * ratio, 0),
- Green = (uint)Math.Round(tInf.Green + (tSup.Green - tInf.Green) * ratio, 0),
- };
-
- return t;
- }
-
- public Tune FromBrightness(double brightness)
- {
- if (_lut.Count == 0) return Current;
-
- Tune tSup = null;
- Tune tInf = null;
-
- var i = 0;
- for (; i < _lut.Count && _lut[i].Brightness < brightness; i++)
- tInf = _lut[i];
-
- // luminance is more than monitor capabilities
- if (i >= _lut.Count) return tInf;
-
- tSup = _lut[i];
-
- if (tInf == null) return tSup;
-
- var dist = tSup.Brightness - tInf.Brightness;
- var ratio = (brightness - tInf.Brightness) / dist;
-
- var t = new Tune
- {
- Y = (uint)Math.Round(tInf.Y + (tSup.Y - tInf.Y) * ratio, 0),
- x = (uint)Math.Round(tInf.x + (tSup.x - tInf.x) * ratio, 0),
- y = (uint)Math.Round(tInf.y + (tSup.y - tInf.y) * ratio, 0),
-
- Brightness = (uint)Math.Round(tInf.Brightness + (tSup.Brightness - tInf.Brightness) * ratio, 0),
- Contrast = (uint)Math.Round(tInf.Contrast + (tSup.Contrast - tInf.Contrast) * ratio, 0),
-
- Red = (uint)Math.Round(tInf.Red + (tSup.Red - tInf.Red) * ratio, 0),
- Blue = (uint)Math.Round(tInf.Blue + (tSup.Blue - tInf.Blue) * ratio, 0),
- Green = (uint)Math.Round(tInf.Green + (tSup.Green - tInf.Green) * ratio, 0),
- };
-
- return t;
- }
-
- double GetLuminance() => FromBrightness(Vcp.Brightness.Value).Y;
-
- void SetLuminance(double luminance)
- {
- var t = FromLuminance(luminance);
- Vcp.Brightness.Value = (uint)Math.Round(t.Brightness, 0);
- Vcp.Contrast.Value = (uint)Math.Round(t.Contrast, 0);
- Vcp.Gain.Red.Value = (uint)Math.Round(t.Red, 0);
- Vcp.Gain.Blue.Value = (uint)Math.Round(t.Blue, 0);
- Vcp.Gain.Green.Value = (uint)Math.Round(t.Green, 0);
- }
-
- public Tune Current => new Tune
- {
- Brightness = Vcp.Brightness.Value,
- Contrast = Vcp.Contrast.Value,
- Red = Vcp.Gain.Red.Value,
- Blue = Vcp.Gain.Blue.Value,
- Green = Vcp.Gain.Green.Value,
- };
-
- public double Luminance
- {
- get => _luminance.Value;
- set => SetLuminance(value);
- }
- readonly ObservableAsPropertyHelper _luminance;
-
- public double MaxLuminance =>
- (_lut.Count == 0) ? 1 : _lut.Last().Y;
-
- public double MinLuminance =>
- (_lut.Count == 0) ? 0 : _lut.First().Y;
-
- string GetConfigPath(bool create = false)
- {
- var path = Path.Combine(
- Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
- "Mgth", "LittleBigMouse"
- );
- path = Path.Combine(path, _monitor.Id);
- path = Path.Combine(path, "Luminance.xml");
-
- if(create) Directory.CreateDirectory(path);
-
- return path;
- }
-
- public void Save()
- {
- var serializer = new XmlSerializer(typeof(List));
- using TextWriter writer = new StreamWriter(GetConfigPath(true));
-
- serializer.Serialize(writer, _lut);
- }
-
- public void Load()
- {
- var deserializer = new XmlSerializer(typeof(List));
- try
- {
- using TextReader reader = new StreamReader(GetConfigPath());
- _lut = (List)deserializer.Deserialize(reader);
+ public bool RemoveLowBrightness(double maxGain)
+ {
+ var t = _sortedLut.FirstOrDefault(x => (x.Brightness == 0 && x.MaxGain == maxGain));
+ if (t == null) return false;
+
+ _lut.Remove(t);
+ return true;
+ }
+
+ public void Add(Tune tune)
+ {
+ _lut.Add(tune);
+ }
+
+ public Tune FromLuminance(double luminance)
+ {
+ if (_sortedLut.Count == 0) return Current;
+
+ Tune tSup = null;
+ Tune tInf = null;
+
+ var i = 0;
+ for (; i < _sortedLut.Count && _sortedLut[i].Y < luminance; i++)
+ tInf = _sortedLut[i];
+
+ // luminance is more than monitor capabilities
+ if (i >= _sortedLut.Count) return tInf;
+
+ tSup = _sortedLut[i];
+
+ if (tInf == null) return tSup;
+
+ var dist = tSup.Y - tInf.Y;
+ var ratio = (luminance - tInf.Y) / dist;
+
+ var t = new Tune
+ {
+ Date = tSup.Date > tInf.Date ? tSup.Date : tInf.Date,
+
+ Y = (uint)Math.Round(tInf.Y + (tSup.Y - tInf.Y) * ratio, 0),
+ x = (uint)Math.Round(tInf.x + (tSup.x - tInf.x) * ratio, 0),
+ y = (uint)Math.Round(tInf.y + (tSup.y - tInf.y) * ratio, 0),
+
+ Brightness = (uint)Math.Round(tInf.Brightness + (tSup.Brightness - tInf.Brightness) * ratio, 0),
+ Contrast = (uint)Math.Round(tInf.Contrast + (tSup.Contrast - tInf.Contrast) * ratio, 0),
+
+ Red = (uint)Math.Round(tInf.Red + (tSup.Red - tInf.Red) * ratio, 0),
+ Blue = (uint)Math.Round(tInf.Blue + (tSup.Blue - tInf.Blue) * ratio, 0),
+ Green = (uint)Math.Round(tInf.Green + (tSup.Green - tInf.Green) * ratio, 0),
+ };
+
+ return t;
+ }
+
+ public Tune FromBrightness(double brightness)
+ {
+ if (_sortedLut is null) return Current;
+ if (_sortedLut.Count == 0) return Current;
+
+ Tune tSup = null;
+ Tune tInf = null;
+
+ var i = 0;
+ for (; i < _sortedLut.Count && _sortedLut[i].Brightness < brightness; i++)
+ tInf = _sortedLut[i];
+
+ // luminance is more than monitor capabilities
+ if (i >= _lut.Count) return tInf;
+
+ tSup = _sortedLut[i];
+
+ if (tInf == null) return tSup;
+
+ var dist = tSup.Brightness - tInf.Brightness;
+ var ratio = (brightness - tInf.Brightness) / dist;
+
+ var t = new Tune
+ {
+ Date = tSup.Date > tInf.Date ? tSup.Date : tInf.Date,
+
+ Y = (uint)Math.Round(tInf.Y + (tSup.Y - tInf.Y) * ratio, 0),
+ x = (uint)Math.Round(tInf.x + (tSup.x - tInf.x) * ratio, 0),
+ y = (uint)Math.Round(tInf.y + (tSup.y - tInf.y) * ratio, 0),
+
+ Brightness = (uint)Math.Round(tInf.Brightness + (tSup.Brightness - tInf.Brightness) * ratio, 0),
+ Contrast = (uint)Math.Round(tInf.Contrast + (tSup.Contrast - tInf.Contrast) * ratio, 0),
+
+ Red = (uint)Math.Round(tInf.Red + (tSup.Red - tInf.Red) * ratio, 0),
+ Blue = (uint)Math.Round(tInf.Blue + (tSup.Blue - tInf.Blue) * ratio, 0),
+ Green = (uint)Math.Round(tInf.Green + (tSup.Green - tInf.Green) * ratio, 0),
+ };
+
+ return t;
+ }
+
+ double GetLuminance() => FromBrightness(Vcp.Brightness.Value).Y;
+
+ void SetLuminance(double luminance)
+ {
+ var t = FromLuminance(luminance);
+ Vcp.Brightness.Value = (uint)Math.Round(t.Brightness, 0);
+ Vcp.Contrast.Value = (uint)Math.Round(t.Contrast, 0);
+ Vcp.Gain.Red.Value = (uint)Math.Round(t.Red, 0);
+ Vcp.Gain.Blue.Value = (uint)Math.Round(t.Blue, 0);
+ Vcp.Gain.Green.Value = (uint)Math.Round(t.Green, 0);
+ }
+
+ public Tune Current
+ {
+ get
+ {
+ var vcp = Vcp;
+ var gain = vcp?.Gain;
+ if (vcp is null || gain is null) return new();
+ return new()
+ {
+ Date = DateTime.Now,
+ Brightness = vcp.Brightness?.Value??0,
+ Contrast = vcp.Contrast?.Value??0,
+ Red = gain.Red.Value,
+ Blue = gain.Blue.Value,
+ Green = gain.Green.Value,
+ };
+ }
+ }
+
+ public double Luminance
+ {
+ get => _luminance.Value;
+ set => SetLuminance(value);
+ }
+ readonly ObservableAsPropertyHelper _luminance;
+
+ public double MaxLuminance =>
+ (_sortedLut.Count == 0) ? 1 : _sortedLut.Last().Y;
+
+ public double MinLuminance =>
+ (_sortedLut.Count == 0) ? 0 : _sortedLut.First().Y;
+
+ string GetConfigPath(bool create = false)
+ {
+ var path = Path.Combine(
+ Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
+ "Mgth", "LittleBigMouse"
+ );
+ path = Path.Combine(path, _monitor.Id);
+ if (create) Directory.CreateDirectory(path);
+
+ path = Path.Combine(path, "Luminance.xml");
+
+ return path;
+ }
+
+ public void Save()
+ {
+ var serializer = new XmlSerializer(typeof(List));
+ using TextWriter writer = new StreamWriter(GetConfigPath(true));
+
+ serializer.Serialize(writer, SortedLut.ToList());
+ }
+
+ public void Load()
+ {
+ var deserializer = new XmlSerializer(typeof(List));
+ try
+ {
+ using TextReader reader = new StreamReader(GetConfigPath());
+ try
+ {
+ var lut = deserializer.Deserialize(reader) as IEnumerable;
+ if(lut is null) throw new Exception();
+
+ _lut.Clear();
+ foreach (var tune in lut) _lut.Add(tune);
+
+ GenerateSmoothedCurve();
+ }
+ finally
+ {
reader.Close();
- }
- catch (IOException ex) when(ex is FileNotFoundException or DirectoryNotFoundException)
- {
- _lut = new List
- {
- new()
- {
- Brightness = MinLuminance,
- Y = 0,
- Red = Vcp.Gain?.Red.Value ?? 0,
- Blue = Vcp.Gain?.Blue.Value ?? 0,
- Green = Vcp.Gain?.Green.Value ?? 0,
- Contrast = Vcp.Contrast?.Value ?? 0
- },
- new()
- {
- Brightness = MaxLuminance,
- Y = 160,
- Red = Vcp.Gain?.Red.Value ?? 0,
- Blue = Vcp.Gain?.Blue.Value ?? 0,
- Green = Vcp.Gain?.Green.Value ?? 0,
- Contrast = Vcp.Contrast?.Value ?? 0
- },
- };
- }
- }
+ }
+
+ }
+ catch (IOException ex) when (ex is FileNotFoundException or DirectoryNotFoundException)
+ {
+ _lut.Clear();
+
+ _lut.Add(new()
+ {
+ Brightness = MinLuminance,
+ Y = 0,
+ Red = Vcp.Gain?.Red.Value ?? 0,
+ Blue = Vcp.Gain?.Blue.Value ?? 0,
+ Green = Vcp.Gain?.Green.Value ?? 0,
+ Contrast = Vcp.Contrast?.Value ?? 0
+ }
+ );
+
+ _lut.Add(new()
+ {
+ Brightness = MaxLuminance,
+ Y = 160,
+ Red = Vcp.Gain?.Red.Value ?? 0,
+ Blue = Vcp.Gain?.Blue.Value ?? 0,
+ Green = Vcp.Gain?.Green.Value ?? 0,
+ Contrast = Vcp.Contrast?.Value ?? 0
+ }
+ );
+ }
+ }
}
\ No newline at end of file
diff --git a/HLab.Sys/HLab.Sys.Windows.MonitorVcp/Tune.cs b/HLab.Sys/HLab.Sys.Windows.MonitorVcp/Tune.cs
index fc079efd..8b20ca23 100644
--- a/HLab.Sys/HLab.Sys.Windows.MonitorVcp/Tune.cs
+++ b/HLab.Sys/HLab.Sys.Windows.MonitorVcp/Tune.cs
@@ -1,4 +1,5 @@
-using System.Linq;
+using System;
+using System.Linq;
using System.Xml.Serialization;
namespace HLab.Sys.Windows.MonitorVcp;
@@ -21,6 +22,8 @@ public class Tune
public double Green;
[XmlAttribute]
public double Blue;
+ [XmlAttribute]
+ public DateTime Date;
public double MaxGain => new[]{Red, Green, Blue}.Max();
public double MinGain => new[] { Red, Green, Blue }.Min();
diff --git a/HLab.Sys/HLab.Sys.Windows.Monitors/DeviceCaps.cs b/HLab.Sys/HLab.Sys.Windows.Monitors/DeviceCaps.cs
index f3dcecfc..d4b74f59 100644
--- a/HLab.Sys/HLab.Sys.Windows.Monitors/DeviceCaps.cs
+++ b/HLab.Sys/HLab.Sys.Windows.Monitors/DeviceCaps.cs
@@ -21,7 +21,7 @@ You should have received a copy of the GNU General Public License
http://www.mgth.fr
*/
-using Avalonia;
+using HLab.Geo;
namespace HLab.Sys.Windows.Monitors;
diff --git a/HLab.Sys/HLab.Sys.Windows.Monitors/DisplayDevice.cs b/HLab.Sys/HLab.Sys.Windows.Monitors/DisplayDevice.cs
index 786d6cdb..1a89bf67 100644
--- a/HLab.Sys/HLab.Sys.Windows.Monitors/DisplayDevice.cs
+++ b/HLab.Sys/HLab.Sys.Windows.Monitors/DisplayDevice.cs
@@ -24,19 +24,31 @@ You should have received a copy of the GNU General Public License
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
-using DynamicData;
+using System.Xml.Serialization;
namespace HLab.Sys.Windows.Monitors;
+[XmlInclude(typeof(PhysicalAdapter))]
+[XmlInclude(typeof(MonitorDeviceConnection))]
public class DisplayDevice
{
public override string ToString() => $"{GetType().Name} {DeviceName} {DeviceString}";
+ [XmlIgnore]
readonly List _children = [];
- internal void AddChild(DisplayDevice device)
+ bool IsChildOf(DisplayDevice device)
+ {
+ if (Parent == device) return true;
+ if (Parent == null) return false;
+ return Parent.IsChildOf(device);
+ }
+
+
+ internal void AddChild(DisplayDevice device)
{
- _children.Add(device);
+ if(device.Parent!=this) return;
+ _children.Add(device);
}
public IEnumerable AllChildren() where T : DisplayDevice
@@ -55,10 +67,15 @@ public IEnumerable AllMonitorDevices()
.Select(e => e.First())
.OrderBy(e => e.PhysicalId);
+ [XmlIgnore]
[JsonIgnore]
public DisplayDevice? Parent { get; set; }
- public IEnumerable Children => _children;
+ public List Children
+ {
+ get => _children;
+ set => throw new System.NotImplementedException();
+ }
///
/// Device name as returned by EnumDisplayDevices :
@@ -84,21 +101,25 @@ public IEnumerable AllMonitorDevices()
///
public string DeviceKey { get; init; } = "";
- public SourceList DisplayModes { get; } = new ();
+ [XmlIgnore]
+ public List DisplayModes { get; set; } = new ();
///
/// Device mode as returned by EnumDisplaySettingsEx :
///
///
+ [XmlIgnore]
public DisplayMode CurrentMode { get; init; }
+ [XmlIgnore]
public DeviceCaps Capabilities { get; init; }
+ [XmlIgnore]
public DeviceState State { get; init; }
public DisplayMode GetBestDisplayMode()
{
- var best = DisplayModes.Items.FirstOrDefault();
- foreach (var mode in DisplayModes.Items)
+ var best = DisplayModes.FirstOrDefault();
+ foreach (var mode in DisplayModes)
{
if (mode.BitsPerPixel < best.BitsPerPixel) continue;
if (mode.DisplayFrequency < best.DisplayFrequency) continue;
diff --git a/HLab.Sys/HLab.Sys.Windows.Monitors/DisplayMode.cs b/HLab.Sys/HLab.Sys.Windows.Monitors/DisplayMode.cs
index 32c61321..d422eb02 100644
--- a/HLab.Sys/HLab.Sys.Windows.Monitors/DisplayMode.cs
+++ b/HLab.Sys/HLab.Sys.Windows.Monitors/DisplayMode.cs
@@ -22,7 +22,7 @@ You should have received a copy of the GNU General Public License
*/
using System.Runtime.Serialization;
-using Avalonia;
+using HLab.Geo;
namespace HLab.Sys.Windows.Monitors;
diff --git a/HLab.Sys/HLab.Sys.Windows.Monitors/Edid.cs b/HLab.Sys/HLab.Sys.Windows.Monitors/Edid.cs
index 6ddf55d3..15ac273e 100644
--- a/HLab.Sys/HLab.Sys.Windows.Monitors/Edid.cs
+++ b/HLab.Sys/HLab.Sys.Windows.Monitors/Edid.cs
@@ -21,8 +21,8 @@ You should have received a copy of the GNU General Public License
http://www.mgth.fr
*/
-using Avalonia;
using System.Runtime.Serialization;
+using HLab.Geo;
namespace HLab.Sys.Windows.Monitors;
@@ -66,45 +66,47 @@ public interface IEdid
int Checksum { get; }
}
-
-public class Edid : IEdid
+public static class EdidParser
{
- public Edid(string key, byte[] edid)
+ public static Edid Parse(string key, byte[] edid)
{
- HKeyName = key;
+ var e = new Edid
+ {
+ HKeyName = key
+ };
- if (edid.Length <= 9) return;
+ if (edid.Length <= 9) return e;
- ManufacturerCode = "" + (char)(64 + ((edid[8] >> 2) & 0x1F))
+ e.ManufacturerCode = "" + (char)(64 + ((edid[8] >> 2) & 0x1F))
+ (char)(64 + (((edid[8] << 3) | (edid[9] >> 5)) & 0x1F))
+ (char)(64 + (edid[9] & 0x1F));
- if (edid.Length <= 11) return;
+ if (edid.Length <= 11) return e;
- ProductCode = (edid[10] + (edid[11] << 8)).ToString("X4");
+ e.ProductCode = (edid[10] + (edid[11] << 8)).ToString("X4");
- if (edid.Length <= 15) return;
+ if (edid.Length <= 15) return e;
var serial = "";
for (var i = 12; i <= 15; i++) serial = edid[i].ToString("X2") + serial;
- Serial = serial;
+ e.Serial = serial;
- if (edid.Length <= 16) return;
- Week = edid[16];
+ if (edid.Length <= 16) return e;
+ e.Week = edid[16];
- if (edid.Length < 18) return;
- Year = edid[17] + 1990;
+ if (edid.Length < 18) return e;
+ e.Year = edid[17] + 1990;
- if (edid.Length <= 19) return;
- Version = edid[18] + "." + edid[19];
+ if (edid.Length <= 19) return e;
+ e.Version = edid[18] + "." + edid[19];
- if (edid.Length <= 20) return;
+ if (edid.Length <= 20) return e;
- Digital = (edid[20] >> 7) == 1;
- if (Digital)
+ e.Digital = (edid[20] >> 7) == 1;
+ if (e.Digital)
{
- BitDepth = 4 + ((edid[20] & 0b01110000) >> 3);
- VideoInterface = (edid[20] & 0b1111) switch
+ e.BitDepth = 4 + ((edid[20] & 0b01110000) >> 3);
+ e.VideoInterface = (edid[20] & 0b1111) switch
{
0 => "undefined",
2 => "HDMIa",
@@ -119,42 +121,41 @@ public Edid(string key, byte[] edid)
{
}
- if (edid.Length <= 21) return;
+ if (edid.Length <= 21) return e;
- var h = edid[21] * 10;
+ e.PhysicalWidth = edid[21] * 10;
- if (edid.Length <= 22) return;
+ if (edid.Length <= 22) return e;
- var v = edid[22] * 10;
+ e.PhysicalHeight = edid[22] * 10;
- PhysicalSize = new Size(h, v);
- if (edid.Length <= 23) return;
+ if (edid.Length <= 23) return e;
if (edid[23] < 255)
{
- Gamma = 1.0 + edid[23] / 100.0;
+ e.Gamma = 1.0 + edid[23] / 100.0;
}
else
{
// todo : else check DI-EXT block
}
- if (edid.Length <= 24) return;
- DpmsStandbySupported = (edid[24] & (0b1 << 7)) > 0;
- DpmsSuspendSupported = (edid[24] & (0b1 << 6)) > 0;
- DpmsActiveOffSupported = (edid[24] & (0b1 << 5)) > 0;
+ if (edid.Length <= 24) return e;
+ e.DpmsStandbySupported = (edid[24] & (0b1 << 7)) > 0;
+ e.DpmsSuspendSupported = (edid[24] & (0b1 << 6)) > 0;
+ e.DpmsActiveOffSupported = (edid[24] & (0b1 << 5)) > 0;
- if (Digital)
+ if (e.Digital)
{
- YCrCb422Support = (edid[24] & (0b1 << 4)) > 0;
- YCrCb444Support = (edid[24] & (0b1 << 3)) > 0;
+ e.YCrCb422Support = (edid[24] & (0b1 << 4)) > 0;
+ e.YCrCb444Support = (edid[24] & (0b1 << 3)) > 0;
}
else
{
// todo : analog display
}
- if (edid.Length <= 34) return;
+ if (edid.Length <= 34) return e;
if ((edid[24] & (0b1 << 2)) > 0)
{
@@ -168,111 +169,115 @@ public Edid(string key, byte[] edid)
var whiteX = ((edid[26] >> 2) & 0b11) | (((int)edid[33]) << 2);
var whiteY = (edid[26] & 0b11) | (((int)edid[34]) << 2);
- RedX = ((double)redX) / 1024.0;
- RedY = ((double)redY) / 1024.0;
- GreenX = ((double)greenX) / 1024.0;
- GreenY = ((double)greenY) / 1024.0;
- BlueX = ((double)blueX) / 1024.0;
- BlueY = ((double)blueY) / 1024.0;
- WhiteX = ((double)whiteX) / 1024.0;
- WhiteY = ((double)whiteY) / 1024.0;
+ e.RedX = ((double)redX) / 1024.0;
+ e.RedY = ((double)redY) / 1024.0;
+ e.GreenX = ((double)greenX) / 1024.0;
+ e.GreenY = ((double)greenY) / 1024.0;
+ e.BlueX = ((double)blueX) / 1024.0;
+ e.BlueY = ((double)blueY) / 1024.0;
+ e.WhiteX = ((double)whiteX) / 1024.0;
+ e.WhiteY = ((double)whiteY) / 1024.0;
}
- if (edid.Length <= 68) return;
-
- PhysicalSize = new Size(
- ((edid[68] & 0xF0) << 4) + edid[66],
- ((edid[68] & 0x0F) << 8) + edid[67]
- );
+ if (edid.Length <= 68) return e;
- Model = Block((char)0xFC, edid);
+ e.PhysicalWidth = ((edid[68] & 0xF0) << 4) + edid[66];
+ e.PhysicalHeight = ((edid[68] & 0x0F) << 8) + edid[67];
- SerialNumber = Block((char)0xFF, edid);
+ e.Model = Block((char)0xFC, edid);
- if (edid.Length <= 127) return;
- Checksum = edid[127];
+ e.SerialNumber = Block((char)0xFF, edid);
+ if (edid.Length <= 127) return e;
+ e.Checksum = edid[127];
+ return e;
+ }
+ static string Block(char code, byte[] edid)
+ {
+ for (var i = 54; i <= 108; i += 18)
+ {
+ if (i >= edid.Length || edid[i] != 0 || edid[i + 1] != 0 || edid[i + 2] != 0 ||
+ edid[i + 3] != code) continue;
+ var s = "";
+ for (var j = i + 5; j < i + 18; j++)
+ {
+ var c = (char)edid[j];
+ if (c == (char)0x0A) break;
+ if (c == (char)0x00) break;
+ s += c;
+ }
+ return s;
+ }
+ return "";
}
+
+}
+
+
+public class Edid
+{
[DataMember]
- public string HKeyName { get; }
+ public string HKeyName { get; set; }
[DataMember]
- public string ProductCode { get; }
+ public string ProductCode { get; set; }
[DataMember]
- public string Serial { get; }
+ public string Serial { get; set; }
[DataMember]
- public Size PhysicalSize { get; }
+ public double PhysicalWidth { get; set; }
[DataMember]
- public string ManufacturerCode { get; }
+ public double PhysicalHeight { get; set; }
[DataMember]
- public string Model { get; }
+ public string ManufacturerCode { get; set; }
[DataMember]
- public string SerialNumber { get; }
+ public string Model { get; set; }
[DataMember]
- public int Week { get; }
+ public string SerialNumber { get; set; }
[DataMember]
- public int Year { get; }
+ public int Week { get; set; }
[DataMember]
- public string Version { get; }
+ public int Year { get; set; }
[DataMember]
- public bool Digital { get; }
+ public string Version { get; set; }
+ [DataMember]
+ public bool Digital { get; set; }
[DataMember]
- public int BitDepth { get; }
+ public int BitDepth { get; set; }
[DataMember]
- public string VideoInterface { get; }
+ public string VideoInterface { get; set; }
[DataMember]
- public double Gamma { get; }
+ public double Gamma { get; set; }
[DataMember]
- public bool DpmsStandbySupported { get; }
+ public bool DpmsStandbySupported { get; set; }
[DataMember]
- public bool DpmsSuspendSupported { get; }
+ public bool DpmsSuspendSupported { get; set; }
[DataMember]
- public bool DpmsActiveOffSupported { get; }
+ public bool DpmsActiveOffSupported { get; set; }
[DataMember]
- public bool YCrCb444Support { get; }
+ public bool YCrCb444Support { get; set; }
[DataMember]
- public bool YCrCb422Support { get; }
+ public bool YCrCb422Support { get; set; }
[DataMember]
- public double sRGB { get; }
+ public double sRGB { get; set; }
[DataMember]
- public double RedX { get; }
+ public double RedX { get; set; }
[DataMember]
- public double RedY { get; }
+ public double RedY { get; set; }
[DataMember]
- public double GreenX { get; }
+ public double GreenX { get; set; }
[DataMember]
- public double GreenY { get; }
+ public double GreenY { get; set; }
[DataMember]
- public double BlueX { get; }
+ public double BlueX { get; set; }
[DataMember]
- public double BlueY { get; }
+ public double BlueY { get ; set; }
[DataMember]
- public double WhiteX { get; }
+ public double WhiteX { get; set; }
[DataMember]
- public double WhiteY { get; }
+ public double WhiteY { get; set; }
[DataMember]
- public int Checksum { get; }
-
- static string Block(char code, byte[] edid)
- {
- for (var i = 54; i <= 108; i += 18)
- {
- if (i >= edid.Length || edid[i] != 0 || edid[i + 1] != 0 || edid[i + 2] != 0 ||
- edid[i + 3] != code) continue;
- var s = "";
- for (var j = i + 5; j < i + 18; j++)
- {
- var c = (char)edid[j];
- if (c == (char)0x0A) break;
- if (c == (char)0x00) break;
- s += c;
- }
- return s;
- }
- return "";
- }
-
+ public int Checksum { get; set; }
}
\ No newline at end of file
diff --git a/HLab.Sys/HLab.Sys.Windows.Monitors/Factory/MonitorDeviceHelper.cs b/HLab.Sys/HLab.Sys.Windows.Monitors/Factory/MonitorDeviceHelper.cs
index 67152838..3548397e 100644
--- a/HLab.Sys/HLab.Sys.Windows.Monitors/Factory/MonitorDeviceHelper.cs
+++ b/HLab.Sys/HLab.Sys.Windows.Monitors/Factory/MonitorDeviceHelper.cs
@@ -4,8 +4,7 @@
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
-using DynamicData;
-using Avalonia;
+using HLab.Geo;
using Microsoft.Win32;
using HLab.Sys.Windows.API;
@@ -282,7 +281,7 @@ public static string GetSourceId(string deviceId, Edid edid)
: $"{pnpCode}{edid.SerialNumber}_{edid.Week:X2}_{edid.Year:X4}_{edid.Checksum:X2}";
}
- public static Edid GetEdid(string deviceId)
+ public static Edid? GetEdid(string deviceId)
{
var devInfo = SetupDiGetClassDevsEx(
ref GUID_CLASS_MONITOR, //class GUID
@@ -330,7 +329,7 @@ public static Edid GetEdid(string deviceId)
using var keyEdid = RegistryKey(hEdidRegKey);
var edid = (byte[])keyEdid.GetValue("EDID");
- return edid != null ? new Edid(hKeyName, edid) : null;
+ return edid != null ? EdidParser.Parse(hKeyName, edid) : null;
}
}
}
diff --git a/HLab.Sys/HLab.Sys.Windows.Monitors/HLab.Sys.Windows.Monitors.csproj b/HLab.Sys/HLab.Sys.Windows.Monitors/HLab.Sys.Windows.Monitors.csproj
index f475baed..8b97f634 100644
--- a/HLab.Sys/HLab.Sys.Windows.Monitors/HLab.Sys.Windows.Monitors.csproj
+++ b/HLab.Sys/HLab.Sys.Windows.Monitors/HLab.Sys.Windows.Monitors.csproj
@@ -1,22 +1,24 @@

- net8.0
+ net10.0
x64;x86;AnyCpu
enable
HLab.Sys.Windows.Monitors
Debug;Release
true
12
- 2.4.0.0
+ 2.5.0.0
-
-
+
+
+
+
diff --git a/HLab.Sys/HLab.Sys.Windows.Monitors/MonitorDevice.cs b/HLab.Sys/HLab.Sys.Windows.Monitors/MonitorDevice.cs
index b8a4df45..7f25f480 100644
--- a/HLab.Sys/HLab.Sys.Windows.Monitors/MonitorDevice.cs
+++ b/HLab.Sys/HLab.Sys.Windows.Monitors/MonitorDevice.cs
@@ -1,200 +1,28 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics;
-using System.Globalization;
-using System.Runtime.Serialization;
-using Avalonia;
-using Avalonia.Controls;
-using Microsoft.Win32;
+using System.Xml.Serialization;
namespace HLab.Sys.Windows.Monitors;
public class MonitorDevice : IEquatable
{
- [DataMember] public string Id { get; init; } = "";
- [DataMember] public string PnpCode { get; init; } = "";
- [DataMember] public string PhysicalId { get; set; } = "";
- [DataMember] public string SourceId { get; set; } = "";
- [DataMember] public IEdid Edid { get; init; }
- [DataMember] public string MonitorNumber { get; set; } = "";
+ public string Id { get; init; } = "";
+ public string PnpCode { get; init; } = "";
+ public string PhysicalId { get; set; } = "";
+ public string SourceId { get; set; } = "";
+ public Edid Edid { get; set; }
+ public string MonitorNumber { get; set; } = "";
- public List Connections = new ();
+ [XmlIgnore]
+ public List Connections = new();
- public override bool Equals(object obj)
- {
- if(obj is MonitorDevice other) return Id == other.Id;
- return base.Equals(obj);
- }
+ public override bool Equals(object obj)
+ {
+ if (obj is MonitorDevice other) return Id == other.Id;
+ return base.Equals(obj);
+ }
- public override int GetHashCode() => HashCode.Combine(Id);
-
- public bool Equals(MonitorDevice other) => Id == other.Id;
-}
-
-public class MonitorDeviceConnection : DisplayDevice
-{
- public new PhysicalAdapter Parent
- {
- get {
- if (base.Parent is PhysicalAdapter adapter) return adapter;
- throw new InvalidOperationException("Parent is not a PhysicalAdapter");
- }
- set => base.Parent = value;
- }
-
- public MonitorDevice Monitor { get; set; }
-
- class EdidDesign : IEdid
- {
- public EdidDesign()
- {
- if(!Design.IsDesignMode) throw new InvalidOperationException("Only for design mode");
- }
-
- public string HKeyName => "HKLM://";
- public string ManufacturerCode => "SAM";
- public string ProductCode { get; }
- public string Serial { get; }
- public int Week => 42;
- public int Year { get; }
- public string Version { get; }
- public bool Digital { get; }
- public int BitDepth { get; }
- public string VideoInterface { get; }
- public Size PhysicalSize => new Size(600, 340);
- public string Model => "S24D300";
- public string SerialNumber => "S/N: 123456789";
- public double Gamma => 2.2;
- public bool DpmsStandbySupported => true;
- public bool DpmsSuspendSupported => true;
- public bool DpmsActiveOffSupported => true;
- public bool YCrCb444Support => true;
- public bool YCrCb422Support => true;
- public double sRGB => 0.98;
- public double RedX => 0.64;
- public double RedY => 0.33;
- public double GreenX => 0.3;
- public double GreenY => 0.6;
- public double BlueX => 0.15;
- public double BlueY => 0.06;
- public double WhiteX => 0.3127;
- public double WhiteY => 0.3127;
- public int Checksum => int.MinValue;
- }
-
- public static MonitorDeviceConnection MonitorDesign
- {
- get
- {
- if(!Design.IsDesignMode) throw new InvalidOperationException("Only for design mode");
-
- return new MonitorDeviceConnection
- {
- //Edid = new EdidDesign()
- };
- }
- }
-
- //------------------------------------------------------------------------
- public override bool Equals(object obj) => obj is MonitorDeviceConnection other ? Id == other.Id : base.Equals(obj);
-
-
- public override int GetHashCode() {
- return ("DisplayMonitor" + Id).GetHashCode();
- }
-
- void OpenRegKey(string keyString) {
-
- keyString = keyString.Replace(@"\MACHINE\",@"\HKEY_LOCAL_MACHINE\");
- keyString = keyString.Replace(@"\USER\",@"\HKEY_CURRENT_USER\");
-
- using (var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Applets\Regedit", true)) {
-
- if(key == null) return;
- var value = key.GetValue("LastKey").ToString();
-
- var list = value.Split('\\');
- if(list.Length > 0)
- {
- keyString = keyString.Replace(@"\REGISTRY\",@$"{list[0]}\");
- key.SetValue("LastKey", keyString);
- }
- }
-
- Process.Start("regedit.exe");
- }
-
-
- public void DisplayValues(Action addValue) {
- //addValue("Registry", Edid.HKeyName, () => { OpenRegKey(Edid.HKeyName); }, false);
- //addValue("Microsoft Id", PhysicalId, null, false);
-
- if(Parent != null)
- {
- // EnumDisplaySettings
- addValue("", "EnumDisplaySettings", null, true);
- addValue("DisplayOrientation", Parent.CurrentMode?.DisplayOrientation.ToString() ?? "", null, false);
- addValue("Position", Parent.CurrentMode?.Position.ToString() ?? "", null, false);
- addValue("Pels", Parent.CurrentMode?.Pels.ToString() ?? "", null, false);
- addValue("BitsPerPixel", Parent.CurrentMode?.BitsPerPixel.ToString() ?? "", null, false);
- addValue("DisplayFrequency", Parent.CurrentMode?.DisplayFrequency.ToString() ?? "", null, false);
- addValue("DisplayFlags", Parent.CurrentMode?.DisplayFlags.ToString() ?? "", null, false);
- addValue("DisplayFixedOutput", Parent.CurrentMode?.DisplayFixedOutput.ToString() ?? "", null, false);
-
- // GetDeviceCaps
- addValue("", "GetDeviceCaps", null, true);
- addValue("Size", Parent.Capabilities.Size.ToString(), null, false);
- addValue("Res", Parent.Capabilities.Resolution.ToString(), null, false);
- addValue("LogPixels", Parent.Capabilities.LogPixels.ToString(), null, false);
- addValue("BitsPixel", Parent.Capabilities.BitsPixel.ToString(), null, false);
- //AddValue("Color Planes", Monitor.Adapter.DeviceCaps.Planes.ToString());
- addValue("Aspect", Parent.Capabilities.Aspect.ToString(), null, false);
- //AddValue("BltAlignment", Monitor.Adapter.DeviceCaps.BltAlignment.ToString());
-
- //GetDpiForMonitor
- addValue("", "GetDpiForMonitor", null, true);
- addValue("EffectiveDpi", Parent.EffectiveDpi.ToString(), null, false);
- addValue("AngularDpi", Parent.AngularDpi.ToString(), null, false);
- addValue("RawDpi", Parent.RawDpi.ToString(), null, false);
-
- // GetMonitorInfo
- addValue("", "GetMonitorInfo", null, true);
- addValue("Primary", Parent.Primary.ToString(), null, false);
- addValue("MonitorArea", Parent.MonitorArea.ToString(), null, false);
- addValue("WorkArea", Parent.WorkArea.ToString(), null, false);
-
-
- //// EDID
- //addValue("", "EDID", null, true);
- //addValue("ManufacturerCode", Edid?.ManufacturerCode, null, false);
- //addValue("ProductCode", Edid?.ProductCode, null, false);
- //addValue("Serial", Edid?.Serial, null, false);
- //addValue("Model", Edid?.Model, null, false);
- //addValue("SerialNo", Edid?.SerialNumber, null, false);
- //addValue("SizeInMm", Edid?.PhysicalSize.ToString(), null, false);
- //addValue("VideoInterface", Edid?.VideoInterface.ToString(), null, false);
-
- // GetScaleFactorForMonitor
- addValue("", "GetScaleFactorForMonitor", null, true);
- addValue("ScaleFactor", Parent.ScaleFactor.ToString(CultureInfo.CurrentCulture) ?? "", null, false);
-
- // EnumDisplayDevices
- addValue("", "EnumDisplayDevices", null, true);
- addValue("DeviceId", Parent.Id, null, false);
- addValue("DeviceKey", Parent.DeviceKey, null, false);
- addValue("DeviceString", Parent.DeviceString, null, false);
- addValue("DeviceName", Parent.DeviceName, null, false);
- addValue("StateFlags", Parent.State.ToString(), null, false);
- }
-
- addValue("", "EnumDisplayDevices", null, true);
- addValue("DeviceId", Id, null, false);
- addValue("DeviceKey", DeviceKey, null, false);
- addValue("DeviceString", DeviceString, null, false);
- addValue("DeviceName", DeviceName, null, false);
- addValue("StateFlags", State.ToString(), null, false);
-
- }
- public override string ToString() => DeviceString;
+ public override int GetHashCode() => HashCode.Combine(Id);
+ public bool Equals(MonitorDevice other) => Id == other.Id;
}
\ No newline at end of file
diff --git a/HLab.Sys/HLab.Sys.Windows.Monitors/MonitorDeviceConnection.cs b/HLab.Sys/HLab.Sys.Windows.Monitors/MonitorDeviceConnection.cs
new file mode 100644
index 00000000..8007d908
--- /dev/null
+++ b/HLab.Sys/HLab.Sys.Windows.Monitors/MonitorDeviceConnection.cs
@@ -0,0 +1,186 @@
+using System;
+using System.Diagnostics;
+using System.Globalization;
+using System.Xml.Serialization;
+using Microsoft.Win32;
+
+namespace HLab.Sys.Windows.Monitors;
+
+public class MonitorDeviceConnection : DisplayDevice
+{
+ [XmlIgnore]
+ public new PhysicalAdapter Parent
+ {
+ get
+ {
+ if (base.Parent is PhysicalAdapter adapter) return adapter;
+ throw new InvalidOperationException("Parent is not a PhysicalAdapter");
+ }
+ set => base.Parent = value;
+ }
+
+ public MonitorDevice Monitor { get; set; }
+
+ class EdidDesign : Edid
+ {
+ public EdidDesign()
+ {
+ //if (!Design.IsDesignMode) throw new InvalidOperationException("Only for design mode");
+ HKeyName = "HKLM://";
+ ManufacturerCode = "SAM";
+ ProductCode = "S24D300";
+ Serial= "123456789";
+ Week = 42;
+ Year = 2024;
+ Version = "1.0";
+ Digital = true;
+ BitDepth = 8;
+ VideoInterface = "Dvi";
+ PhysicalWidth = 600;
+ PhysicalHeight = 340;
+ Model = "S24D300";
+ SerialNumber = "S/N: 123456789";
+ Gamma = 2.2;
+ DpmsStandbySupported = true;
+ DpmsSuspendSupported = true;
+ DpmsActiveOffSupported = true;
+ YCrCb444Support = true;
+ YCrCb422Support = true;
+ sRGB = 0.98;
+ RedX = 0.64;
+ RedY = 0.33;
+ GreenX = 0.3;
+ GreenY = 0.6;
+ BlueX = 0.15;
+ BlueY = 0.06;
+ WhiteX = 0.3127;
+ WhiteY = 0.3127;
+ Checksum = int.MinValue;
+ }
+
+ }
+
+ public static MonitorDeviceConnection MonitorDesign
+ {
+ get
+ {
+ //if (!Design.IsDesignMode) throw new InvalidOperationException("Only for design mode");
+
+ return new MonitorDeviceConnection
+ {
+ Monitor = new MonitorDevice
+ {
+ Edid = new EdidDesign()
+ },
+ };
+ }
+ }
+
+ //------------------------------------------------------------------------
+ public override bool Equals(object obj) => obj is MonitorDeviceConnection other ? Id == other.Id : base.Equals(obj);
+
+
+ public override int GetHashCode()
+ {
+ return ("DisplayMonitor" + Id).GetHashCode();
+ }
+
+ void OpenRegKey(string keyString)
+ {
+
+ keyString = keyString.Replace(@"\MACHINE\", @"\HKEY_LOCAL_MACHINE\");
+ keyString = keyString.Replace(@"\USER\", @"\HKEY_CURRENT_USER\");
+
+ using (var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Applets\Regedit", true))
+ {
+
+ if (key == null) return;
+ var value = key.GetValue("LastKey").ToString();
+
+ var list = value.Split('\\');
+ if (list.Length > 0)
+ {
+ keyString = keyString.Replace(@"\REGISTRY\", @$"{list[0]}\");
+ key.SetValue("LastKey", keyString);
+ }
+ }
+
+ Process.Start("regedit.exe");
+ }
+
+
+ public void DisplayValues(Action addValue)
+ {
+ //addValue("Registry", Edid.HKeyName, () => { OpenRegKey(Edid.HKeyName); }, false);
+ //addValue("Microsoft Id", PhysicalId, null, false);
+
+ if (Parent != null)
+ {
+ // EnumDisplaySettings
+ addValue("", "EnumDisplaySettings", null, true);
+ addValue("DisplayOrientation", Parent.CurrentMode?.DisplayOrientation.ToString() ?? "", null, false);
+ addValue("Position", Parent.CurrentMode?.Position.ToString() ?? "", null, false);
+ addValue("Pels", Parent.CurrentMode?.Pels.ToString() ?? "", null, false);
+ addValue("BitsPerPixel", Parent.CurrentMode?.BitsPerPixel.ToString() ?? "", null, false);
+ addValue("DisplayFrequency", Parent.CurrentMode?.DisplayFrequency.ToString() ?? "", null, false);
+ addValue("DisplayFlags", Parent.CurrentMode?.DisplayFlags.ToString() ?? "", null, false);
+ addValue("DisplayFixedOutput", Parent.CurrentMode?.DisplayFixedOutput.ToString() ?? "", null, false);
+
+ // GetDeviceCaps
+ addValue("", "GetDeviceCaps", null, true);
+ addValue("Size", Parent.Capabilities.Size.ToString(), null, false);
+ addValue("Res", Parent.Capabilities.Resolution.ToString(), null, false);
+ addValue("LogPixels", Parent.Capabilities.LogPixels.ToString(), null, false);
+ addValue("BitsPixel", Parent.Capabilities.BitsPixel.ToString(), null, false);
+ //AddValue("Color Planes", Monitor.Adapter.DeviceCaps.Planes.ToString());
+ addValue("Aspect", Parent.Capabilities.Aspect.ToString(), null, false);
+ //AddValue("BltAlignment", Monitor.Adapter.DeviceCaps.BltAlignment.ToString());
+
+ //GetDpiForMonitor
+ addValue("", "GetDpiForMonitor", null, true);
+ addValue("EffectiveDpi", Parent.EffectiveDpi.ToString(), null, false);
+ addValue("AngularDpi", Parent.AngularDpi.ToString(), null, false);
+ addValue("RawDpi", Parent.RawDpi.ToString(), null, false);
+
+ // GetMonitorInfo
+ addValue("", "GetMonitorInfo", null, true);
+ addValue("Primary", Parent.Primary.ToString(), null, false);
+ addValue("MonitorArea", Parent.MonitorArea.ToString(), null, false);
+ addValue("WorkArea", Parent.WorkArea.ToString(), null, false);
+
+
+ //// EDID
+ addValue("", "EDID", null, true);
+ addValue("ManufacturerCode", Monitor?.Edid?.ManufacturerCode, null, false);
+ addValue("ProductCode", Monitor?.Edid?.ProductCode, null, false);
+ addValue("Serial", Monitor?.Edid?.Serial, null, false);
+ addValue("Model", Monitor?.Edid?.Model, null, false);
+ addValue("SerialNo", Monitor?.Edid?.SerialNumber, null, false);
+ addValue("SizeInMm H", Monitor?.Edid?.PhysicalWidth.ToString(), null, false);
+ addValue("SizeInMm V", Monitor?.Edid?.PhysicalHeight.ToString(), null, false);
+ addValue("VideoInterface", Monitor?.Edid?.VideoInterface.ToString(), null, false);
+
+ // GetScaleFactorForMonitor
+ addValue("", "GetScaleFactorForMonitor", null, true);
+ addValue("ScaleFactor", Parent.ScaleFactor.ToString(CultureInfo.CurrentCulture) ?? "", null, false);
+
+ // EnumDisplayDevices
+ addValue("", "EnumDisplayDevices", null, true);
+ addValue("DeviceId", Parent.Id, null, false);
+ addValue("DeviceKey", Parent.DeviceKey, null, false);
+ addValue("DeviceString", Parent.DeviceString, null, false);
+ addValue("DeviceName", Parent.DeviceName, null, false);
+ addValue("StateFlags", Parent.State.ToString(), null, false);
+ }
+
+ addValue("", "EnumDisplayDevices", null, true);
+ addValue("DeviceId", Id, null, false);
+ addValue("DeviceKey", DeviceKey, null, false);
+ addValue("DeviceString", DeviceString, null, false);
+ addValue("DeviceName", DeviceName, null, false);
+ addValue("StateFlags", State.ToString(), null, false);
+
+ }
+ public override string ToString() => DeviceString;
+
+}
\ No newline at end of file
diff --git a/HLab.Sys/HLab.Sys.Windows.Monitors/MonitorDeviceDesign.cs b/HLab.Sys/HLab.Sys.Windows.Monitors/MonitorDeviceDesign.cs
index 922e1083..918e940a 100644
--- a/HLab.Sys/HLab.Sys.Windows.Monitors/MonitorDeviceDesign.cs
+++ b/HLab.Sys/HLab.Sys.Windows.Monitors/MonitorDeviceDesign.cs
@@ -1,5 +1,4 @@
using System;
-using Avalonia.Controls;
namespace HLab.Sys.Windows.Monitors;
@@ -7,7 +6,7 @@ public class MonitorDeviceDesign : MonitorDeviceConnection
{
MonitorDeviceDesign()
{
- if(!Design.IsDesignMode) throw new InvalidOperationException("Only for design mode");
+ //if(!Design.IsDesignMode) throw new InvalidOperationException("Only for design mode");
Monitor = new MonitorDevice{
diff --git a/HLab.Sys/HLab.Sys.Windows.Monitors/MonitorsService.cs b/HLab.Sys/HLab.Sys.Windows.Monitors/MonitorsService.cs
index 23d61cfc..161c8ac9 100644
--- a/HLab.Sys/HLab.Sys.Windows.Monitors/MonitorsService.cs
+++ b/HLab.Sys/HLab.Sys.Windows.Monitors/MonitorsService.cs
@@ -27,7 +27,7 @@ You should have received a copy of the GNU General Public License
using System;
using System.IO;
using System.Runtime.Serialization;
-using Avalonia.Media;
+using HLab.ColorTools;
using HLab.Sys.Windows.API;
using HLab.Sys.Windows.Monitors.Factory;
@@ -55,7 +55,7 @@ public void UpdateDevices()
_root = null;
}
- [DataMember] public Color Background { get; set; }
+ [DataMember] public ColorRGB Background { get; set; }
[DataMember] public DesktopWallpaperPosition WallpaperPosition { get; set; }
diff --git a/HLab.Sys/HLab.Sys.Windows.Monitors/PhysicalAdapter.cs b/HLab.Sys/HLab.Sys.Windows.Monitors/PhysicalAdapter.cs
index 3e419a04..76330f97 100644
--- a/HLab.Sys/HLab.Sys.Windows.Monitors/PhysicalAdapter.cs
+++ b/HLab.Sys/HLab.Sys.Windows.Monitors/PhysicalAdapter.cs
@@ -1,11 +1,13 @@
-using Avalonia;
-using System.Runtime.Serialization;
+using System.Runtime.Serialization;
using HLab.Sys.Windows.API;
+using System.Xml.Serialization;
+using HLab.Geo;
namespace HLab.Sys.Windows.Monitors;
public class PhysicalAdapter : DisplayDevice
{
+ [XmlIgnore]
public nint HMonitor { get; set; }
// MONITORINFOEX
diff --git a/HLab.Sys/HLab.Sys.Windows.Monitors/WinApiExtentions.cs b/HLab.Sys/HLab.Sys.Windows.Monitors/WinApiExtentions.cs
index 3db1de6c..fcad9e86 100644
--- a/HLab.Sys/HLab.Sys.Windows.Monitors/WinApiExtentions.cs
+++ b/HLab.Sys/HLab.Sys.Windows.Monitors/WinApiExtentions.cs
@@ -1,7 +1,7 @@
-using Avalonia;
-using DynamicData;
+using DynamicData;
using HLab.Sys.Windows.API;
using System;
+using HLab.Geo;
namespace HLab.Sys.Windows.Monitors;
diff --git a/LittleBigMouse-Hook-Rust/.idea/.gitignore b/LittleBigMouse-Hook-Rust/.idea/.gitignore
new file mode 100644
index 00000000..13566b81
--- /dev/null
+++ b/LittleBigMouse-Hook-Rust/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/LittleBigMouse-Hook-Rust/.idea/LittleBigMouse-Hook-Rust.iml b/LittleBigMouse-Hook-Rust/.idea/LittleBigMouse-Hook-Rust.iml
new file mode 100644
index 00000000..cf84ae4a
--- /dev/null
+++ b/LittleBigMouse-Hook-Rust/.idea/LittleBigMouse-Hook-Rust.iml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/LittleBigMouse-Hook-Rust/.idea/modules.xml b/LittleBigMouse-Hook-Rust/.idea/modules.xml
new file mode 100644
index 00000000..b29cd61a
--- /dev/null
+++ b/LittleBigMouse-Hook-Rust/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/LittleBigMouse-Hook-Rust/.idea/vcs.xml b/LittleBigMouse-Hook-Rust/.idea/vcs.xml
new file mode 100644
index 00000000..626bd4b1
--- /dev/null
+++ b/LittleBigMouse-Hook-Rust/.idea/vcs.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/LittleBigMouse-Hook-Rust/Cargo.lock b/LittleBigMouse-Hook-Rust/Cargo.lock
new file mode 100644
index 00000000..e9259fdf
--- /dev/null
+++ b/LittleBigMouse-Hook-Rust/Cargo.lock
@@ -0,0 +1,25 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "LittleBigMouse-Hook-Rust"
+version = "0.1.0"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
+
+[[package]]
+name = "num-traits"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+dependencies = [
+ "autocfg",
+]
diff --git a/LittleBigMouse-Hook-Rust/Cargo.toml b/LittleBigMouse-Hook-Rust/Cargo.toml
new file mode 100644
index 00000000..1dcb2e11
--- /dev/null
+++ b/LittleBigMouse-Hook-Rust/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "LittleBigMouse-Hook-Rust"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies]
+num-traits = "0.2"
diff --git a/LittleBigMouse-Hook-Rust/src/engine.rs b/LittleBigMouse-Hook-Rust/src/engine.rs
new file mode 100644
index 00000000..202308a0
--- /dev/null
+++ b/LittleBigMouse-Hook-Rust/src/engine.rs
@@ -0,0 +1,135 @@
+use std::collections::HashMap;
+
+// Supposant que ces modules existent ailleurs dans le projet
+use crate::geometry::{Point, Rect};
+use crate::xml::tinyxml2;
+use crate::zones::zone_link::ZoneLink;
+use crate::zones::zones_layout::ZonesLayout;
+
+pub struct Zone {
+ travels: HashMap<*const Zone, Vec>>,
+ pixels_bounds: Rect,
+ physical_bounds: Rect,
+ physical_inside: Rect,
+ pub id: i32,
+ pub device_id: String,
+ pub name: String,
+ pub main: Option<*mut Zone>,
+ pub left_zones: Option<*mut ZoneLink>,
+ pub top_zones: Option<*mut ZoneLink>,
+ pub right_zones: Option<*mut ZoneLink>,
+ pub bottom_zones: Option<*mut ZoneLink>,
+ pub dpi: f64,
+}
+
+impl PartialEq for Zone {
+ fn eq(&self, other: &Self) -> bool {
+ self.name == other.name
+ }
+}
+
+impl Zone {
+ fn get_travel_pixels(&self, zones: &[*const Zone], target: *const Zone) -> Vec> {
+ // Implémentation à ajouter
+ Vec::new()
+ }
+
+ pub fn new(
+ id: i32,
+ device_id: String,
+ name: String,
+ pixels_bounds: Rect,
+ physical_bounds: Rect,
+ main: Option<*mut Zone>,
+ ) -> Self {
+ Zone {
+ travels: HashMap::new(),
+ pixels_bounds,
+ physical_bounds,
+ physical_inside: physical_bounds, // À ajuster selon les besoins
+ id,
+ device_id,
+ name,
+ main,
+ left_zones: None,
+ top_zones: None,
+ right_zones: None,
+ bottom_zones: None,
+ dpi: 0.0,
+ }
+ }
+
+ pub fn pixels_bounds(&self) -> Rect {
+ self.pixels_bounds
+ }
+
+ pub fn physical_bounds(&self) -> Rect {
+ self.physical_bounds
+ }
+
+ pub fn physical_inside(&self) -> Rect {
+ self.physical_inside
+ }
+
+ pub fn is_main(&self) -> bool {
+ self.main.is_none()
+ }
+
+ pub fn compute_dpi(&mut self) {
+ // Implémentation à ajouter
+ }
+
+ pub fn init_zone_links(&self, layout: &ZonesLayout) {
+ // Implémentation à ajouter
+ }
+
+ pub fn to_physical(&self, px: Point) -> Point {
+ // Implémentation à ajouter
+ Point::new(0.0, 0.0)
+ }
+
+ pub fn to_pixels(&self, mm: Point) -> Point {
+ // Implémentation à ajouter
+ Point::new(0, 0)
+ }
+
+ pub fn center_pixel(&self) -> Point {
+ // Implémentation à ajouter
+ Point::new(0, 0)
+ }
+
+ pub fn contains(&self, point: &Point) -> bool {
+ // Implémentation à ajouter
+ false
+ }
+
+ pub fn contains_mm(&self, mm: &Point) -> bool {
+ // Implémentation à ajouter
+ false
+ }
+
+ pub fn inside_pixels_bounds(&self, px: Point) -> Point {
+ // Implémentation à ajouter
+ Point::new(0, 0)
+ }
+
+ pub fn inside_physical_bounds(&self, mm: Point) -> Point {
+ // Implémentation à ajouter
+ Point::new(0.0, 0.0)
+ }
+
+ pub fn travel_pixels(&mut self, zones: &[*const Zone], target: *const Zone) -> &mut Vec> {
+ // Implémentation à ajouter
+ self.travels.entry(target).or_insert_with(Vec::new)
+ }
+
+ pub fn horizontal_reachable(&self, mm: &Point) -> bool {
+ // Implémentation à ajouter
+ false
+ }
+
+ pub fn vertical_reachable(&self, mm: &Point) -> bool {
+ // Implémentation à ajouter
+ false
+ }
+}
diff --git a/LittleBigMouse-Hook-Rust/src/line.rs b/LittleBigMouse-Hook-Rust/src/line.rs
new file mode 100644
index 00000000..b9874fd5
--- /dev/null
+++ b/LittleBigMouse-Hook-Rust/src/line.rs
@@ -0,0 +1,112 @@
+use crate::point::Point;
+
+#[derive(Debug)]
+pub struct Line {
+ // Y = slope * X + origin
+ slope: f64,
+ // y pour x==0
+ origin: T,
+}
+
+impl Line
+where
+ T: Copy + std::ops::Div