Skip to content

Commit 7b30fae

Browse files
committed
Initial commit
1 parent 7b2faaa commit 7b30fae

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+5060
-0
lines changed

SimpleKVM.sln

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.30413.136
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SimpleKVM", "SimpleKVM\SimpleKVM.csproj", "{090189E7-24E1-4D14-AAE0-5C6904D3FCE6}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{090189E7-24E1-4D14-AAE0-5C6904D3FCE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{090189E7-24E1-4D14-AAE0-5C6904D3FCE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{090189E7-24E1-4D14-AAE0-5C6904D3FCE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{090189E7-24E1-4D14-AAE0-5C6904D3FCE6}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {BBFE32E1-703D-45CD-A589-F33C599736CC}
24+
EndGlobalSection
25+
EndGlobal

SimpleKVM/Converter.cs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
namespace SimpleKVM
2+
{
3+
public static class Converter
4+
{
5+
public static (int Feet, double Inches) CentimetresToFeetInches(double centimetres)
6+
{
7+
var feet = centimetres / 2.54 / 12;
8+
var iFeet = (int)feet;
9+
var inches = (feet - iFeet) * 12;
10+
11+
return (iFeet, inches);
12+
}
13+
14+
public static string CentimetresToFeetInchesString(double centimetres, string footSymbol = " foot", string inchesSymbol = " inches")
15+
{
16+
(var feet, var inches) = CentimetresToFeetInches(centimetres);
17+
return $"{feet:N0}{footSymbol}, {inches:N0}{inchesSymbol}";
18+
}
19+
}
20+
}

SimpleKVM/Displays/DisplaySystem.cs

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Runtime.InteropServices;
5+
using System.Text;
6+
7+
namespace SimpleKVM.Displays
8+
{
9+
public static class DisplaySystem
10+
{
11+
public static IList<Monitor> GetMonitors()
12+
{
13+
List<Monitor> result;
14+
15+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
16+
{
17+
result = Displays.win.DisplaySystem.GetMonitors()
18+
.Cast<Monitor>()
19+
.ToList();
20+
21+
return result;
22+
}
23+
24+
result = new List<Monitor>();
25+
return result;
26+
}
27+
}
28+
}

SimpleKVM/Displays/IInputSelector.cs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
5+
namespace SimpleKVM.Displays
6+
{
7+
public interface IInputSelector
8+
{
9+
10+
}
11+
}

SimpleKVM/Displays/Monitor.cs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using Newtonsoft.Json;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Text;
5+
6+
namespace SimpleKVM.Displays
7+
{
8+
public abstract class Monitor
9+
{
10+
public string MonitorUniqueId = "";
11+
12+
[JsonIgnoreAttribute]
13+
public string Model = "";
14+
15+
[JsonIgnoreAttribute]
16+
public int CurrentSource;
17+
18+
[JsonIgnoreAttribute]
19+
public List<int> ValidSources = new List<int>();
20+
21+
public abstract bool SetSource(int newSourceId);
22+
}
23+
}
+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using DDCKVMService;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Diagnostics;
5+
using System.IO;
6+
using System.Linq;
7+
using System.Management;
8+
using System.Runtime.InteropServices;
9+
using System.Text;
10+
using System.Text.RegularExpressions;
11+
12+
namespace SimpleKVM.Displays.win
13+
{
14+
public static class DisplaySystem
15+
{
16+
static readonly Regex modelRegex = new Regex(@"model\((.*?)\)");
17+
static readonly Regex sourcesRegex = new Regex(@"(?<=\s)60\((.*?)\)");
18+
19+
static List<Monitor>? cachedMonitorList;
20+
public static IList<Monitor> GetMonitors()
21+
{
22+
if (cachedMonitorList == null)
23+
{
24+
25+
cachedMonitorList = new List<Monitor>();
26+
27+
int monitorId = 0;
28+
MonitorController.GetDevices(physicalMonitors =>
29+
{
30+
physicalMonitors
31+
.ForEach(physicalMonitor =>
32+
{
33+
physicalMonitor.GetVCPRegister(0x60, out uint currentSourceId);
34+
35+
var caps = physicalMonitor.GetVCPCapabilities();
36+
if (caps != null)
37+
{
38+
var model = modelRegex.Match(caps).Groups[1].Value;
39+
var sources = sourcesRegex.Match(caps).Groups[1].Value.Split(' ').Select(x => Convert.ToUInt32(x, 16)).ToArray();
40+
physicalMonitor.GetVCPRegister(0x60, out uint currentSource);
41+
42+
var newMonitor = new Monitor()
43+
{
44+
MonitorUniqueId = $"{++monitorId}",
45+
Model = model,
46+
CurrentSource = (int)currentSourceId,
47+
ValidSources = sources.Cast<int>().ToList()
48+
};
49+
50+
cachedMonitorList.Add(newMonitor);
51+
}
52+
});
53+
});
54+
}
55+
56+
return cachedMonitorList;
57+
}
58+
}
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
using DDCKVMService;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Diagnostics;
5+
using System.IO;
6+
using System.Linq;
7+
using System.Text;
8+
using System.Text.RegularExpressions;
9+
10+
namespace SimpleKVM.Displays.win
11+
{
12+
public static class DisplaySystem_1
13+
{
14+
public static string ControlMyMonitorExe => Path.Combine(AppDomain.CurrentDomain.BaseDirectory ?? "", @"ext\win\controlmymonitor\ControlMyMonitor.exe");
15+
16+
public static IList<Monitor> GetMonitors()
17+
{
18+
var selfPath = AppDomain.CurrentDomain.BaseDirectory;
19+
20+
if (selfPath == null)
21+
{
22+
return new List<Monitor>();
23+
}
24+
25+
var controlMyMonitorExe = Path.Combine(selfPath, @"ext\win\controlmymonitor\ControlMyMonitor.exe");
26+
27+
var monitorListCommand = new ProcessStartInfo
28+
{
29+
FileName = ControlMyMonitorExe,
30+
Arguments = "/smonitors"
31+
};
32+
33+
var monitorListStdout = monitorListCommand.StartAndReadStdout();
34+
35+
/*
36+
Monitor Device Name: "\\.\DISPLAY1\Monitor0"
37+
Monitor Name: "VX4380 SERIES"
38+
Serial Number: ""
39+
Adapter Name: "NVIDIA GeForce GTX 760"
40+
Monitor ID: "MONITOR\VSC5B34\{4d36e96e-e325-11ce-bfc1-08002be10318}\0004"
41+
42+
Monitor Device Name: "\\.\DISPLAY2\Monitor0"
43+
Monitor Name: "VX4380 SERIES"
44+
Serial Number: ""
45+
Adapter Name: "NVIDIA GeForce GTX 760"
46+
Monitor ID: "MONITOR\VSC5B34\{4d36e96e-e325-11ce-bfc1-08002be10318}\0000"
47+
*/
48+
49+
var result = monitorListStdout
50+
.SplitAndKeep("Monitor Device Name")
51+
.Where(line => !string.IsNullOrEmpty(line))
52+
.AsParallel()
53+
.AsOrdered()
54+
.Select(block =>
55+
{
56+
var dict = Regex
57+
.Split(block, "\r\n|\r|\n")
58+
.Where(line => !string.IsNullOrEmpty(line))
59+
.Select(line => line.Split(new[] { ": " }, StringSplitOptions.None))
60+
.ToDictionary(tokens => tokens[0], tokens => tokens[1].Replace("\"", "").RemoveNonPrintable());
61+
62+
var monitorInfoCommand = new ProcessStartInfo
63+
{
64+
FileName = controlMyMonitorExe,
65+
Arguments = $"/scomma \"\" \"{dict["Monitor Name"]}"
66+
};
67+
68+
var monitorInfo = monitorInfoCommand.StartAndReadStdout();
69+
70+
//VPC Code
71+
//60,Input Select,Read+Write,18,19,"15, 16, 17, 18"
72+
var inputSelectLine = Regex
73+
.Split(monitorInfo, "\r\n|\r|\n")
74+
.Where(line => line.StartsWith("60"))
75+
.FirstOrDefault();
76+
77+
var inputSelectLineTokens = Regex.Split(inputSelectLine, "(?:^|,)(\"(?:[^\"]+|\"\")*\"|[^,]*)") //split based on commas, taking into account double-quotes
78+
.Where(line => !string.IsNullOrEmpty(line))
79+
.Select(line => line.Replace("\"", ""))
80+
.ToList();
81+
82+
83+
var currentSource = int.Parse(inputSelectLineTokens[3]);
84+
85+
var validSources = inputSelectLineTokens[5]
86+
.Split(new[] { ", " }, StringSplitOptions.None)
87+
.Select(source => int.Parse(source))
88+
.OrderBy(source => source)
89+
.ToList();
90+
91+
return new Monitor()
92+
{
93+
//AdapterName = dict["Adapter Name"],
94+
//MonitorDeviceName = dict["Monitor Device Name"],
95+
//MonitorId = dict["Monitor ID"],
96+
//MonitorName = dict["Monitor Name"],
97+
//SerialNumber = dict["Serial Number"],
98+
99+
CurrentSource = currentSource,
100+
ValidSources = validSources
101+
};
102+
})
103+
.ToList();
104+
105+
return result;
106+
}
107+
}
108+
}

0 commit comments

Comments
 (0)