LenovoLegionToolkit
976 строк · 30.5 Кб
1using System;
2using System.Collections.Generic;
3using System.Collections.ObjectModel;
4using System.Diagnostics;
5using System.Drawing;
6using System.IO;
7using System.Linq;
8using System.Text;
9using LenovoLegionToolkit.Lib.Extensions;
10using Newtonsoft.Json;
11using Octokit;
12
13namespace LenovoLegionToolkit.Lib;
14
15public readonly struct BatteryInformation
16{
17public bool IsCharging { get; init; }
18public int BatteryPercentage { get; init; }
19public int BatteryLifeRemaining { get; init; }
20public int FullBatteryLifeRemaining { get; init; }
21public int DischargeRate { get; init; }
22public int EstimateChargeRemaining { get; init; }
23public int DesignCapacity { get; init; }
24public int FullChargeCapacity { get; init; }
25public int CycleCount { get; init; }
26public bool IsLowBattery { get; init; }
27public double? BatteryTemperatureC { get; init; }
28public DateTime? ManufactureDate { get; init; }
29public DateTime? FirstUseDate { get; init; }
30}
31
32public readonly struct BiosVersion
33{
34public string Prefix { get; }
35public int? Version { get; }
36
37public BiosVersion(string prefix, int? version)
38{
39Prefix = prefix;
40Version = version;
41}
42
43public bool IsHigherOrEqualThan(BiosVersion other)
44{
45if (!Prefix.Equals(other.Prefix, StringComparison.InvariantCultureIgnoreCase))
46return false;
47
48if (Version is null || other.Version is null)
49return true;
50
51return Version >= other.Version;
52}
53
54public bool IsLowerThan(BiosVersion other)
55{
56if (!Prefix.Equals(other.Prefix, StringComparison.InvariantCultureIgnoreCase))
57return false;
58
59if (Version is null || other.Version is null)
60return true;
61
62return Version < other.Version;
63}
64
65public override string ToString() => $"{nameof(Prefix)}: {Prefix}, {nameof(Version)}: {Version}";
66}
67
68public readonly struct Brightness
69{
70public byte Value { get; private init; }
71
72public static implicit operator Brightness(byte value) => new() { Value = value };
73}
74
75public readonly struct DiscreteCapability
76{
77public CapabilityID Id { get; }
78public int Value { get; }
79
80public DiscreteCapability(CapabilityID id, int value)
81{
82Id = id;
83Value = value;
84}
85}
86
87public readonly struct DisplayAdvancedColorInfo
88{
89public bool AdvancedColorSupported { get; }
90public bool AdvancedColorEnabled { get; }
91public bool WideColorEnforced { get; }
92public bool AdvancedColorForceDisabled { get; }
93
94public DisplayAdvancedColorInfo(bool advancedColorSupported, bool advancedColorEnabled, bool wideColorEnforced, bool advancedColorForceDisabled)
95{
96AdvancedColorSupported = advancedColorSupported;
97AdvancedColorEnabled = advancedColorEnabled;
98WideColorEnforced = wideColorEnforced;
99AdvancedColorForceDisabled = advancedColorForceDisabled;
100}
101}
102
103public readonly struct DriverInfo
104{
105public string DeviceId { get; init; }
106public string HardwareId { get; init; }
107public Version? Version { get; init; }
108public DateTime? Date { get; init; }
109}
110
111public readonly struct FanTableData
112{
113public FanTableType Type { get; init; }
114public byte FanId { get; init; }
115public byte SensorId { get; init; }
116public ushort[] FanSpeeds { get; init; }
117public ushort[] Temps { get; init; }
118
119public override string ToString() =>
120$"{nameof(Type)}: {Type}," +
121$" {nameof(FanId)}: {FanId}," +
122$" {nameof(SensorId)}: {SensorId}," +
123$" {nameof(FanSpeeds)}: [{string.Join(", ", FanSpeeds)}]," +
124$" {nameof(Temps)}: [{string.Join(", ", Temps)}]," +
125$" {nameof(Type)}: {Type}";
126}
127
128public readonly struct FanTable
129{
130// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
131// ReSharper disable MemberCanBePrivate.Global
132// ReSharper disable IdentifierTypo
133// ReSharper disable InconsistentNaming
134
135public byte FSTM { get; init; }
136public byte FSID { get; init; }
137public uint FSTL { get; init; }
138public ushort FSS0 { get; init; }
139public ushort FSS1 { get; init; }
140public ushort FSS2 { get; init; }
141public ushort FSS3 { get; init; }
142public ushort FSS4 { get; init; }
143public ushort FSS5 { get; init; }
144public ushort FSS6 { get; init; }
145public ushort FSS7 { get; init; }
146public ushort FSS8 { get; init; }
147public ushort FSS9 { get; init; }
148
149// ReSharper restore AutoPropertyCanBeMadeGetOnly.Global
150// ReSharper restore MemberCanBePrivate.Global
151// ReSharper restore IdentifierTypo
152// ReSharper restore InconsistentNaming
153
154public FanTable(ushort[] fanTable)
155{
156if (fanTable.Length != 10)
157// ReSharper disable once LocalizableElement
158throw new ArgumentException("Fan table length must be 10.", nameof(fanTable));
159
160FSTM = 1;
161FSID = 0;
162FSTL = 0;
163FSS0 = fanTable[0];
164FSS1 = fanTable[1];
165FSS2 = fanTable[2];
166FSS3 = fanTable[3];
167FSS4 = fanTable[4];
168FSS5 = fanTable[5];
169FSS6 = fanTable[6];
170FSS7 = fanTable[7];
171FSS8 = fanTable[8];
172FSS9 = fanTable[9];
173}
174
175public ushort[] GetTable() => new[] { FSS0, FSS1, FSS2, FSS3, FSS4, FSS5, FSS6, FSS7, FSS8, FSS9 };
176
177public byte[] GetBytes()
178{
179using var ms = new MemoryStream(new byte[64]);
180ms.WriteByte(FSTM);
181ms.WriteByte(FSID);
182ms.Write(BitConverter.GetBytes(FSTL));
183ms.Write(BitConverter.GetBytes(FSS0));
184ms.Write(BitConverter.GetBytes(FSS1));
185ms.Write(BitConverter.GetBytes(FSS2));
186ms.Write(BitConverter.GetBytes(FSS3));
187ms.Write(BitConverter.GetBytes(FSS4));
188ms.Write(BitConverter.GetBytes(FSS5));
189ms.Write(BitConverter.GetBytes(FSS6));
190ms.Write(BitConverter.GetBytes(FSS7));
191ms.Write(BitConverter.GetBytes(FSS8));
192ms.Write(BitConverter.GetBytes(FSS9));
193return ms.ToArray();
194}
195
196public override string ToString() =>
197$"{nameof(FSTM)}: {FSTM}," +
198$" {nameof(FSID)}: {FSID}," +
199$" {nameof(FSTL)}: {FSTL}," +
200$" {nameof(FSS0)}: {FSS0}," +
201$" {nameof(FSS1)}: {FSS1}," +
202$" {nameof(FSS2)}: {FSS2}," +
203$" {nameof(FSS3)}: {FSS3}," +
204$" {nameof(FSS4)}: {FSS4}," +
205$" {nameof(FSS5)}: {FSS5}," +
206$" {nameof(FSS6)}: {FSS6}," +
207$" {nameof(FSS7)}: {FSS7}," +
208$" {nameof(FSS8)}: {FSS8}," +
209$" {nameof(FSS9)}: {FSS9}";
210}
211
212public readonly struct FanTableInfo
213{
214public FanTableData[] Data { get; }
215public FanTable Table { get; }
216
217public FanTableInfo(FanTableData[] data, FanTable table)
218{
219Data = data;
220Table = table;
221}
222
223public override string ToString() =>
224$"{nameof(Data)}: [{string.Join(", ", Data)}]," +
225$" {nameof(Table)}: {Table}";
226}
227
228public readonly struct GPUOverclockInfo
229{
230public static readonly GPUOverclockInfo Zero = new();
231
232public int CoreDeltaMhz { get; init; }
233public int MemoryDeltaMhz { get; init; }
234
235
236#region Equality
237
238public override bool Equals(object? obj)
239{
240return obj is GPUOverclockInfo other && Equals(other);
241}
242
243public override int GetHashCode()
244{
245return HashCode.Combine(CoreDeltaMhz, MemoryDeltaMhz);
246}
247
248public static bool operator ==(GPUOverclockInfo left, GPUOverclockInfo right) => left.Equals(right);
249
250public static bool operator !=(GPUOverclockInfo left, GPUOverclockInfo right) => !left.Equals(right);
251
252#endregion
253
254public override string ToString() => $"{nameof(CoreDeltaMhz)}: {CoreDeltaMhz}, {nameof(MemoryDeltaMhz)}: {MemoryDeltaMhz}";
255
256}
257
258public readonly struct GodModeDefaults
259{
260public int? CPULongTermPowerLimit { get; init; }
261public int? CPUShortTermPowerLimit { get; init; }
262public int? CPUPeakPowerLimit { get; init; }
263public int? CPUCrossLoadingPowerLimit { get; init; }
264public int? CPUPL1Tau { get; init; }
265public int? APUsPPTPowerLimit { get; init; }
266public int? CPUTemperatureLimit { get; init; }
267public int? GPUPowerBoost { get; init; }
268public int? GPUConfigurableTGP { get; init; }
269public int? GPUTemperatureLimit { get; init; }
270public int? GPUTotalProcessingPowerTargetOnAcOffsetFromBaseline { get; init; }
271public int? GPUToCPUDynamicBoost { get; init; }
272public FanTable? FanTable { get; init; }
273public bool? FanFullSpeed { get; init; }
274
275public override string ToString() =>
276$"{nameof(CPULongTermPowerLimit)}: {CPULongTermPowerLimit}," +
277$" {nameof(CPUShortTermPowerLimit)}: {CPUShortTermPowerLimit}," +
278$" {nameof(CPUPeakPowerLimit)}: {CPUPeakPowerLimit}," +
279$" {nameof(CPUCrossLoadingPowerLimit)}: {CPUCrossLoadingPowerLimit}," +
280$" {nameof(CPUPL1Tau)}: {CPUPL1Tau}," +
281$" {nameof(APUsPPTPowerLimit)}: {APUsPPTPowerLimit}," +
282$" {nameof(CPUTemperatureLimit)}: {CPUTemperatureLimit}," +
283$" {nameof(GPUPowerBoost)}: {GPUPowerBoost}," +
284$" {nameof(GPUConfigurableTGP)}: {GPUConfigurableTGP}," +
285$" {nameof(GPUTemperatureLimit)}: {GPUTemperatureLimit}," +
286$" {nameof(GPUTotalProcessingPowerTargetOnAcOffsetFromBaseline)}: {GPUTotalProcessingPowerTargetOnAcOffsetFromBaseline}," +
287$" {nameof(GPUToCPUDynamicBoost)}: {GPUToCPUDynamicBoost}," +
288$" {nameof(FanTable)}: {FanTable}," +
289$" {nameof(FanFullSpeed)}: {FanFullSpeed}";
290}
291
292public readonly struct GodModeState
293{
294public Guid ActivePresetId { get; init; }
295public ReadOnlyDictionary<Guid, GodModePreset> Presets { get; init; }
296}
297
298public readonly struct GodModePreset
299{
300public string Name { get; init; }
301public StepperValue? CPULongTermPowerLimit { get; init; }
302public StepperValue? CPUShortTermPowerLimit { get; init; }
303public StepperValue? CPUPeakPowerLimit { get; init; }
304public StepperValue? CPUCrossLoadingPowerLimit { get; init; }
305public StepperValue? CPUPL1Tau { get; init; }
306public StepperValue? APUsPPTPowerLimit { get; init; }
307public StepperValue? CPUTemperatureLimit { get; init; }
308public StepperValue? GPUPowerBoost { get; init; }
309public StepperValue? GPUConfigurableTGP { get; init; }
310public StepperValue? GPUTemperatureLimit { get; init; }
311public StepperValue? GPUTotalProcessingPowerTargetOnAcOffsetFromBaseline { get; init; }
312public StepperValue? GPUToCPUDynamicBoost { get; init; }
313public FanTableInfo? FanTableInfo { get; init; }
314public bool? FanFullSpeed { get; init; }
315public int? MinValueOffset { get; init; }
316public int? MaxValueOffset { get; init; }
317
318public override string ToString() =>
319$"{nameof(Name)}: {Name}," +
320$" {nameof(CPULongTermPowerLimit)}: {CPULongTermPowerLimit}," +
321$" {nameof(CPUShortTermPowerLimit)}: {CPUShortTermPowerLimit}," +
322$" {nameof(CPUPeakPowerLimit)}: {CPUPeakPowerLimit}," +
323$" {nameof(CPUCrossLoadingPowerLimit)}: {CPUCrossLoadingPowerLimit}," +
324$" {nameof(CPUPL1Tau)}: {CPUPL1Tau}," +
325$" {nameof(APUsPPTPowerLimit)}: {APUsPPTPowerLimit}," +
326$" {nameof(CPUTemperatureLimit)}: {CPUTemperatureLimit}," +
327$" {nameof(GPUPowerBoost)}: {GPUPowerBoost}," +
328$" {nameof(GPUConfigurableTGP)}: {GPUConfigurableTGP}," +
329$" {nameof(GPUTemperatureLimit)}: {GPUTemperatureLimit}," +
330$" {nameof(GPUTotalProcessingPowerTargetOnAcOffsetFromBaseline)}: {GPUTotalProcessingPowerTargetOnAcOffsetFromBaseline}," +
331$" {nameof(GPUToCPUDynamicBoost)}: {GPUToCPUDynamicBoost}," +
332$" {nameof(FanTableInfo)}: {FanTableInfo}," +
333$" {nameof(FanFullSpeed)}: {FanFullSpeed}," +
334$" {nameof(MinValueOffset)}: {MinValueOffset}," +
335$" {nameof(MaxValueOffset)}: {MaxValueOffset}";
336}
337
338public readonly struct GPUStatus
339{
340public GPUState State { get; }
341public string? PerformanceState { get; }
342public List<Process> Processes { get; }
343public int ProcessCount => Processes.Count;
344
345public GPUStatus(GPUState state, string? performanceState, List<Process> processes)
346{
347State = state;
348PerformanceState = performanceState;
349Processes = processes;
350}
351}
352
353public readonly struct HardwareId
354{
355public static readonly HardwareId Empty = new();
356
357public string Vendor { get; init; }
358public string Device { get; init; }
359
360#region Equality
361
362public override bool Equals(object? obj)
363{
364if (obj is not HardwareId other)
365return false;
366
367if (!Vendor.Equals(other.Vendor, StringComparison.InvariantCultureIgnoreCase))
368return false;
369
370if (!Device.Equals(other.Device, StringComparison.InvariantCultureIgnoreCase))
371return false;
372
373return true;
374}
375
376public override int GetHashCode() => HashCode.Combine(Vendor, Device);
377
378public static bool operator ==(HardwareId left, HardwareId right) => left.Equals(right);
379
380public static bool operator !=(HardwareId left, HardwareId right) => !left.Equals(right);
381
382#endregion
383}
384
385public readonly struct MachineInformation
386{
387public readonly struct FeatureData
388{
389public static readonly FeatureData Unknown = new() { Source = SourceType.Unknown };
390
391public enum SourceType
392{
393Unknown,
394Flags,
395CapabilityData
396}
397
398public SourceType Source { get; init; }
399public bool IGPUMode { get; init; }
400public bool AIChip { get; init; }
401public bool FlipToStart { get; init; }
402public bool NvidiaGPUDynamicDisplaySwitching { get; init; }
403public bool InstantBootAc { get; init; }
404public bool InstantBootUsbPowerDelivery { get; init; }
405public bool AMDSmartShiftMode { get; init; }
406public bool AMDSkinTemperatureTracking { get; init; }
407}
408
409public readonly struct PropertyData
410{
411public bool SupportsGodMode => SupportsGodModeV1 || SupportsGodModeV2;
412
413public (bool status, bool connectivity) SupportsAlwaysOnAc { get; init; }
414public bool SupportsGodModeV1 { get; init; }
415public bool SupportsGodModeV2 { get; init; }
416public bool SupportsGSync { get; init; }
417public bool SupportsIGPUMode { get; init; }
418public bool SupportsAIMode { get; init; }
419public bool SupportBootLogoChange { get; init; }
420public bool HasQuietToPerformanceModeSwitchingBug { get; init; }
421public bool HasGodModeToOtherModeSwitchingBug { get; init; }
422public bool IsExcludedFromLenovoLighting { get; init; }
423public bool IsExcludedFromPanelLogoLenovoLighting { get; init; }
424}
425
426public string Vendor { get; init; }
427public string MachineType { get; init; }
428public string Model { get; init; }
429public string SerialNumber { get; init; }
430public BiosVersion? BiosVersion { get; init; }
431public string? BiosVersionRaw { get; init; }
432public PowerModeState[] SupportedPowerModes { get; init; }
433public int SmartFanVersion { get; init; }
434public int LegionZoneVersion { get; init; }
435public FeatureData Features { get; init; }
436public PropertyData Properties { get; init; }
437}
438
439public struct Package
440{
441public string Id { get; init; }
442public string Title { get; init; }
443public string Description { get; init; }
444public string Version { get; init; }
445public string Category { get; init; }
446public string FileName { get; init; }
447public string FileSize { get; init; }
448public string? FileCrc { get; init; }
449public DateTime ReleaseDate { get; init; }
450public string? Readme { get; init; }
451public string FileLocation { get; init; }
452public bool IsUpdate { get; init; }
453public RebootType Reboot { get; init; }
454
455private string? _index;
456
457public string Index
458{
459get
460{
461_index ??= new StringBuilder()
462.Append(Title)
463.Append(Description)
464.Append(Version)
465.Append(Category)
466.Append(FileName)
467.ToString();
468return _index;
469}
470}
471}
472
473public readonly struct Notification
474{
475public NotificationType Type { get; }
476
477public object[] Args { get; }
478
479public Notification(NotificationType type, params object[] args)
480{
481Type = type;
482Args = args;
483}
484
485public override string ToString()
486{
487return $"{nameof(Type)}: {Type}," +
488$" {nameof(Args)}: [{string.Join(", ", Args)}]";
489}
490}
491
492public readonly struct PowerPlan
493{
494public Guid Guid { get; }
495public string Name { get; }
496public bool IsActive { get; }
497
498public PowerPlan(Guid guid, string name, bool isActive)
499{
500Guid = guid;
501Name = name;
502IsActive = isActive;
503}
504
505public override string ToString() => Name;
506}
507
508public readonly struct ProcessEventInfo
509{
510public ProcessEventInfoType Type { get; }
511
512public ProcessInfo Process { get; }
513
514public ProcessEventInfo(ProcessEventInfoType type, ProcessInfo process)
515{
516Type = type;
517Process = process;
518}
519}
520
521public readonly struct ProcessInfo : IComparable
522{
523public static ProcessInfo FromPath(string path) => new(Path.GetFileNameWithoutExtension(path), path);
524
525public string Name { get; }
526
527public string? ExecutablePath { get; }
528
529[JsonConstructor]
530public ProcessInfo(string name, string? executablePath)
531{
532Name = name;
533ExecutablePath = executablePath;
534}
535
536public override string ToString() => $"{nameof(Name)}: {Name}, {nameof(ExecutablePath)}: {ExecutablePath}";
537
538#region Equality
539
540public int CompareTo(object? obj)
541{
542var other = obj is null ? default : (ProcessInfo)obj;
543var result = string.Compare(Name, other.Name, StringComparison.InvariantCultureIgnoreCase);
544return result != 0 ? result : string.Compare(ExecutablePath, other.ExecutablePath, StringComparison.InvariantCultureIgnoreCase);
545}
546
547public override bool Equals(object? obj) => obj is ProcessInfo info && Name == info.Name && ExecutablePath == info.ExecutablePath;
548
549public override int GetHashCode() => HashCode.Combine(Name, ExecutablePath);
550
551public static bool operator ==(ProcessInfo left, ProcessInfo right) => left.Equals(right);
552
553public static bool operator !=(ProcessInfo left, ProcessInfo right) => !(left == right);
554
555public static bool operator <(ProcessInfo left, ProcessInfo right) => left.CompareTo(right) < 0;
556
557public static bool operator <=(ProcessInfo left, ProcessInfo right) => left.CompareTo(right) <= 0;
558
559public static bool operator >(ProcessInfo left, ProcessInfo right) => left.CompareTo(right) > 0;
560
561public static bool operator >=(ProcessInfo left, ProcessInfo right) => left.CompareTo(right) >= 0;
562
563#endregion
564}
565
566public readonly struct RangeCapability
567{
568public CapabilityID Id { get; }
569public int DefaultValue { get; }
570public int Min { get; }
571public int Max { get; }
572public int Step { get; }
573
574public RangeCapability(CapabilityID id, int defaultValue, int min, int max, int step)
575{
576Id = id;
577DefaultValue = defaultValue;
578Min = min;
579Max = max;
580Step = step;
581}
582}
583
584public readonly struct RGBColor
585{
586public static readonly RGBColor Black = new(0, 0, 0);
587public static readonly RGBColor White = new(255, 255, 255);
588
589public byte R { get; }
590public byte G { get; }
591public byte B { get; }
592
593[JsonConstructor]
594public RGBColor(byte r, byte g, byte b)
595{
596R = r;
597G = g;
598B = b;
599}
600
601#region Equality
602
603public override bool Equals(object? obj)
604{
605return obj is RGBColor color && R == color.R && G == color.G && B == color.B;
606}
607
608public override int GetHashCode() => (R, G, B).GetHashCode();
609
610public static bool operator ==(RGBColor left, RGBColor right) => left.Equals(right);
611
612public static bool operator !=(RGBColor left, RGBColor right) => !left.Equals(right);
613
614#endregion
615
616public override string ToString() => $"{nameof(R)}: {R}, {nameof(G)}: {G}, {nameof(B)}: {B}";
617}
618
619public readonly struct RGBKeyboardBacklightBacklightPresetDescription
620{
621public RGBKeyboardBacklightEffect Effect { get; } = RGBKeyboardBacklightEffect.Static;
622public RGBKeyboardBacklightSpeed Speed { get; } = RGBKeyboardBacklightSpeed.Slowest;
623public RGBKeyboardBacklightBrightness Brightness { get; } = RGBKeyboardBacklightBrightness.Low;
624public RGBColor Zone1 { get; } = RGBColor.White;
625public RGBColor Zone2 { get; } = RGBColor.White;
626public RGBColor Zone3 { get; } = RGBColor.White;
627public RGBColor Zone4 { get; } = RGBColor.White;
628
629[JsonConstructor]
630public RGBKeyboardBacklightBacklightPresetDescription(
631RGBKeyboardBacklightEffect effect,
632RGBKeyboardBacklightSpeed speed,
633RGBKeyboardBacklightBrightness brightness,
634RGBColor zone1,
635RGBColor zone2,
636RGBColor zone3,
637RGBColor zone4)
638{
639Effect = effect;
640Speed = speed;
641Brightness = brightness;
642Zone1 = zone1;
643Zone2 = zone2;
644Zone3 = zone3;
645Zone4 = zone4;
646}
647
648#region Equality
649
650public override bool Equals(object? obj)
651{
652return obj is RGBKeyboardBacklightBacklightPresetDescription settings &&
653Effect == settings.Effect &&
654Speed == settings.Speed &&
655Brightness == settings.Brightness &&
656Zone1.Equals(settings.Zone1) &&
657Zone2.Equals(settings.Zone2) &&
658Zone3.Equals(settings.Zone3) &&
659Zone4.Equals(settings.Zone4);
660}
661
662public override int GetHashCode() => HashCode.Combine(Effect, Speed, Brightness, Zone1, Zone2, Zone3, Zone4);
663
664public static bool operator ==(RGBKeyboardBacklightBacklightPresetDescription left, RGBKeyboardBacklightBacklightPresetDescription right)
665{
666return left.Equals(right);
667}
668
669public static bool operator !=(RGBKeyboardBacklightBacklightPresetDescription left, RGBKeyboardBacklightBacklightPresetDescription right)
670{
671return !(left == right);
672}
673
674#endregion
675
676public override string ToString() =>
677$"{nameof(Effect)}: {Effect}," +
678$" {nameof(Speed)}: {Speed}," +
679$" {nameof(Brightness)}: {Brightness}," +
680$" {nameof(Zone1)}: {Zone1}," +
681$" {nameof(Zone2)}: {Zone2}," +
682$" {nameof(Zone3)}: {Zone3}," +
683$" {nameof(Zone4)}: {Zone4}";
684}
685
686public readonly struct RGBKeyboardBacklightState
687{
688public RGBKeyboardBacklightPreset SelectedPreset { get; }
689public Dictionary<RGBKeyboardBacklightPreset, RGBKeyboardBacklightBacklightPresetDescription> Presets { get; }
690
691[JsonConstructor]
692public RGBKeyboardBacklightState(RGBKeyboardBacklightPreset selectedPreset, Dictionary<RGBKeyboardBacklightPreset, RGBKeyboardBacklightBacklightPresetDescription> presets)
693{
694SelectedPreset = selectedPreset;
695Presets = presets;
696}
697}
698
699public readonly struct SensorData
700{
701public static readonly SensorData Empty = new()
702{
703Utilization = -1,
704CoreClock = -1,
705MaxCoreClock = -1,
706MemoryClock = -1,
707MaxMemoryClock = -1,
708Temperature = -1,
709MaxTemperature = -1,
710FanSpeed = -1,
711MaxFanSpeed = -1
712};
713
714public int Utilization { get; init; }
715public int MaxUtilization { get; init; }
716public int CoreClock { get; init; }
717public int MaxCoreClock { get; init; }
718public int MemoryClock { get; init; }
719public int MaxMemoryClock { get; init; }
720public int Temperature { get; init; }
721public int MaxTemperature { get; init; }
722public int FanSpeed { get; init; }
723public int MaxFanSpeed { get; init; }
724
725public override string ToString() =>
726$"{nameof(Utilization)}: {Utilization}," +
727$" {nameof(MaxUtilization)}: {MaxUtilization}," +
728$" {nameof(CoreClock)}: {CoreClock}," +
729$" {nameof(MaxCoreClock)}: {MaxCoreClock}," +
730$" {nameof(MemoryClock)}: {MemoryClock}," +
731$" {nameof(MaxMemoryClock)}: {MaxMemoryClock}," +
732$" {nameof(Temperature)}: {Temperature}," +
733$" {nameof(MaxTemperature)}: {MaxTemperature}," +
734$" {nameof(FanSpeed)}: {FanSpeed}," +
735$" {nameof(MaxFanSpeed)}: {MaxFanSpeed}";
736}
737
738public readonly struct SensorsData
739{
740public static readonly SensorsData Empty = new() { CPU = SensorData.Empty, GPU = SensorData.Empty };
741
742public SensorData CPU { get; init; }
743public SensorData GPU { get; init; }
744
745public override string ToString() => $"{nameof(CPU)}: {CPU}, {nameof(GPU)}: {GPU}";
746}
747
748public readonly struct SensorSettings
749{
750public int CPUSensorID { get; init; }
751public int GPUSensorID { get; init; }
752public int CPUFanID { get; init; }
753public int GPUFanID { get; init; }
754}
755
756public readonly struct DpiScale : IDisplayName, IEquatable<DpiScale>
757{
758public int Scale { get; }
759
760[JsonIgnore]
761public string DisplayName => $"{Scale}%";
762
763[JsonConstructor]
764public DpiScale(int scale)
765{
766Scale = scale;
767}
768
769#region Equality
770
771public override bool Equals(object? obj) => obj is DpiScale rate && Equals(rate);
772
773public bool Equals(DpiScale other) => Scale == other.Scale;
774
775public override int GetHashCode() => HashCode.Combine(Scale);
776
777public static bool operator ==(DpiScale left, DpiScale right) => left.Equals(right);
778
779public static bool operator !=(DpiScale left, DpiScale right) => !(left == right);
780
781#endregion
782}
783
784public readonly struct RefreshRate : IDisplayName, IEquatable<RefreshRate>
785{
786public int Frequency { get; }
787
788[JsonIgnore]
789public string DisplayName => $"{Frequency} Hz";
790
791[JsonConstructor]
792public RefreshRate(int frequency)
793{
794Frequency = frequency;
795}
796
797public override string ToString() => $"{Frequency}Hz";
798
799#region Equality
800
801public override bool Equals(object? obj) => obj is RefreshRate rate && Equals(rate);
802
803public bool Equals(RefreshRate other) => Frequency == other.Frequency;
804
805public override int GetHashCode() => HashCode.Combine(Frequency);
806
807public static bool operator ==(RefreshRate left, RefreshRate right) => left.Equals(right);
808
809public static bool operator !=(RefreshRate left, RefreshRate right) => !(left == right);
810
811#endregion
812}
813
814public readonly struct Resolution : IDisplayName, IEquatable<Resolution>, IComparable<Resolution>
815{
816[JsonProperty]
817private int Width { get; }
818
819[JsonProperty]
820private int Height { get; }
821
822[JsonIgnore]
823public string DisplayName => $"{Width} × {Height}";
824
825[JsonConstructor]
826public Resolution(int width, int height)
827{
828Width = width;
829Height = height;
830}
831
832public Resolution(Size size) : this(size.Width, size.Height) { }
833
834public override string ToString() => $"{Width}x{Height}";
835
836public int CompareTo(Resolution other)
837{
838var widthComparison = Width.CompareTo(other.Width);
839return widthComparison != 0
840? widthComparison
841: Height.CompareTo(other.Height);
842}
843
844#region Conversion
845
846public static explicit operator Resolution(Size value) => new(value);
847
848public static implicit operator Size(Resolution data) => new(data.Width, data.Height);
849
850#endregion
851
852#region Equality
853
854public override bool Equals(object? obj) => obj is Resolution other && Equals(other);
855
856public bool Equals(Resolution other) => Width == other.Width && Height == other.Height;
857
858public override int GetHashCode() => HashCode.Combine(Width, Height);
859
860public static bool operator ==(Resolution left, Resolution right) => left.Equals(right);
861
862public static bool operator !=(Resolution left, Resolution right) => !(left == right);
863
864#endregion
865
866}
867
868public readonly struct SpectrumKeyboardBacklightEffect
869{
870public SpectrumKeyboardBacklightEffectType Type { get; }
871public SpectrumKeyboardBacklightSpeed Speed { get; }
872public SpectrumKeyboardBacklightDirection Direction { get; }
873public SpectrumKeyboardBacklightClockwiseDirection ClockwiseDirection { get; }
874public RGBColor[] Colors { get; }
875public ushort[] Keys { get; }
876
877public SpectrumKeyboardBacklightEffect(SpectrumKeyboardBacklightEffectType type,
878SpectrumKeyboardBacklightSpeed speed,
879SpectrumKeyboardBacklightDirection direction,
880SpectrumKeyboardBacklightClockwiseDirection clockwiseDirection,
881RGBColor[] colors,
882ushort[] keys)
883{
884Type = type;
885Speed = speed;
886Direction = direction;
887ClockwiseDirection = clockwiseDirection;
888Colors = colors;
889Keys = type.IsAllLightsEffect() ? Array.Empty<ushort>() : keys;
890}
891}
892
893public readonly struct StepperValue
894{
895public int Value { get; }
896public int Min { get; }
897public int Max { get; }
898public int Step { get; }
899public int[] Steps { get; }
900public int? DefaultValue { get; }
901
902public StepperValue(int value, int min, int max, int step, int[] steps, int? defaultValue)
903{
904Value = value;
905Min = min;
906Max = max;
907Step = step;
908Steps = steps;
909DefaultValue = defaultValue;
910}
911
912public StepperValue WithValue(int value) => new(value, Min, Max, Step, Steps, DefaultValue);
913
914public override string ToString() =>
915$"{nameof(Value)}: {Value}," +
916$" {nameof(Min)}: {Min}," +
917$" {nameof(Max)}: {Max}," +
918$" {nameof(Step)}: {Step}," +
919$" {nameof(Steps)}: [{string.Join(", ", Steps)}]," +
920$" {nameof(DefaultValue)} : {DefaultValue}";
921}
922
923public readonly struct Time
924{
925public int Hour { get; init; }
926public int Minute { get; init; }
927
928#region Equality
929
930public override bool Equals(object? obj) => obj is Time time && Hour == time.Hour && Minute == time.Minute;
931
932public override int GetHashCode() => HashCode.Combine(Hour, Minute);
933
934public static bool operator ==(Time left, Time right) => left.Equals(right);
935
936public static bool operator !=(Time left, Time right) => !(left == right);
937
938#endregion
939}
940
941public readonly struct Update
942{
943public Version Version { get; }
944public string Title { get; }
945public string Description { get; }
946public DateTimeOffset Date { get; }
947public string? Url { get; }
948
949public Update(Release release)
950{
951Version = Version.Parse(release.TagName);
952Title = release.Name;
953Description = release.Body;
954Date = release.PublishedAt ?? release.CreatedAt;
955Url = release.Assets.Where(ra => ra.Name.EndsWith("setup.exe", StringComparison.InvariantCultureIgnoreCase)).Select(ra => ra.BrowserDownloadUrl).FirstOrDefault();
956}
957}
958
959public readonly struct WarrantyInfo
960{
961public DateTime? Start { get; init; }
962public DateTime? End { get; init; }
963public Uri? Link { get; init; }
964}
965
966public readonly struct WindowSize
967{
968public double Width { get; }
969public double Height { get; }
970
971public WindowSize(double width, double height)
972{
973Width = width;
974Height = height;
975}
976}
977