├── .github
└── workflows
│ └── dotnet.yml
├── .gitignore
├── .gitmodules
├── LICENSE.md
├── README.md
├── Slate.API
└── Slate.API.csproj
├── Slate.Asus
├── Acpi
│ ├── AcpiDumper.cs
│ ├── AsusAcpiEndpoint.cs
│ ├── AsusAcpiProxy.cs
│ ├── AsusIoCtl.cs
│ ├── DevsMethod.cs
│ ├── DstsMethod.cs
│ ├── Endpoints
│ │ ├── AsusDevsEndpoint.cs
│ │ └── AsusDstsEndpoint.cs
│ ├── FunctionSets
│ │ └── WmnbFunction.cs
│ ├── KeyPressRequest.cs
│ ├── RequiresAcpiSessionAttribute.cs
│ └── here_be_dragons
├── AssemblyInfo.cs
├── AtkWmiEventID.cs
├── Extensions.cs
├── FanCurve.cs
├── FanCurvePoint.cs
├── MuxSwitchMode.cs
├── Native
│ └── Kernel32.cs
├── PerformancePreset.cs
└── Slate.Asus.csproj
├── Slate.sln
└── Slate
├── App.axaml
├── App.axaml.cs
├── Controller
├── ApplicationController.AniMeMatrix.cs
├── ApplicationController.Application.cs
├── ApplicationController.Fans.cs
├── ApplicationController.GraphicsAndDisplay.cs
├── ApplicationController.Keyboard.cs
├── ApplicationController.PowerManagement.cs
└── ApplicationController.cs
├── FodyWeavers.xml
├── FodyWeavers.xsd
├── Infrastructure
├── Extensions.cs
├── Native
│ ├── PowrProf.cs
│ └── User32.cs
├── PowerManagement
│ ├── PowerMode.cs
│ └── ProcessorBoostLevel.cs
├── Services
│ ├── IApplicationExecutionService.cs
│ ├── IAsusAnimeMatrixService.cs
│ ├── IAsusAuraService.cs
│ ├── IAsusHalService.cs
│ ├── IDisplayManagementService.cs
│ ├── IHardwareMonitorService.cs
│ ├── IInputInjectionService.cs
│ ├── IPowerManagementService.cs
│ ├── ISettingsService.cs
│ ├── IShutdownService.cs
│ ├── IStorageService.cs
│ ├── IWmiEventService.cs
│ └── Implementations
│ │ ├── ApplicationExecutionService.cs
│ │ ├── AsusAnimeMatrixService.cs
│ │ ├── AsusAuraService.cs
│ │ ├── AsusHalService.cs
│ │ ├── DisplayManagementService.cs
│ │ ├── HardwareMonitorService.cs
│ │ ├── InputInjectionService.cs
│ │ ├── PowerManagementService.cs
│ │ ├── SettingsService.cs
│ │ ├── ShutdownService.cs
│ │ ├── StorageService.cs
│ │ └── WmiEventService.cs
├── Settings
│ ├── SettingsBase.cs
│ └── SettingsComponent.cs
├── SystemParameters.cs
└── WMI
│ └── ManagementEvent.cs
├── Model
├── ColorWrapper.cs
├── KeyBind.cs
├── KeyBindMode.cs
├── MediaKey.cs
├── Messaging
│ └── Messages.cs
└── Settings
│ ├── Components
│ ├── AniMeMatrixSettings.cs
│ ├── ApplicationSettings.cs
│ ├── FansSettings.cs
│ ├── GraphicsAndDisplaySettings.cs
│ ├── KeyboardSettings.cs
│ └── PowerManagementSettings.cs
│ └── ControlCenterSettings.cs
├── Program.cs
├── Resources
├── Animations
│ ├── power_saving_1.gif
│ ├── power_saving_2.gif
│ ├── shutdown_1.gif
│ ├── shutdown_2.gif
│ ├── sleep_1.gif
│ ├── sleep_2.gif
│ ├── start_1.gif
│ └── start_2.gif
├── Fonts
│ ├── fa5_brands.otf
│ └── segoe_fluent.ttf
├── Icons
│ └── icon.ico
├── Paths
│ ├── AuraIcon.axaml
│ ├── FanIcon.axaml
│ ├── MicrophoneIcon.axaml
│ └── RogLogo.axaml
└── Styles
│ ├── BrightnessSelector.axaml
│ ├── Card.axaml
│ ├── LinkIcon.axaml
│ ├── MediaPanelRadioButton.axaml
│ ├── SwitchRadioButton.axaml
│ ├── ToggleSwitch.axaml
│ └── Transitions.axaml
├── Slate.csproj
├── View
├── Control
│ ├── Icons
│ │ ├── FAIcon.axaml
│ │ ├── FAIcon.axaml.cs
│ │ ├── SFIcon.axaml
│ │ └── SFIcon.axaml.cs
│ ├── PageElements
│ │ ├── AniMeMatrixBuiltInSelector.axaml
│ │ ├── AniMeMatrixBuiltInSelector.axaml.cs
│ │ ├── AuraColorControl.axaml
│ │ ├── AuraColorControl.axaml.cs
│ │ ├── SettingsPalette.axaml
│ │ └── SettingsPalette.axaml.cs
│ └── Primitives
│ │ ├── BrightnessSelector.axaml
│ │ ├── BrightnessSelector.axaml.cs
│ │ ├── Card.axaml
│ │ ├── Card.axaml.cs
│ │ ├── CoreStatisticsDisplay.axaml
│ │ ├── CoreStatisticsDisplay.axaml.cs
│ │ ├── DualSwitch.axaml
│ │ ├── DualSwitch.axaml.cs
│ │ ├── EditableChart.axaml
│ │ ├── EditableChart.axaml.cs
│ │ ├── GifRadioButton.axaml
│ │ ├── GifRadioButton.axaml.cs
│ │ ├── KeyBindingControl.axaml
│ │ ├── KeyBindingControl.axaml.cs
│ │ ├── MainMenuButton.axaml
│ │ └── MainMenuButton.axaml.cs
├── Page
│ ├── AniMeMatrixPage.axaml
│ ├── AniMeMatrixPage.axaml.cs
│ ├── ApplicationPage.axaml
│ ├── ApplicationPage.axaml.cs
│ ├── DebugPage.axaml
│ ├── DebugPage.axaml.cs
│ ├── FansPage.axaml
│ ├── FansPage.axaml.cs
│ ├── GraphicsAndDisplayPage.axaml
│ ├── GraphicsAndDisplayPage.axaml.cs
│ ├── KeyboardBindingsPage.axaml
│ ├── KeyboardBindingsPage.axaml.cs
│ ├── KeyboardPage.axaml
│ ├── KeyboardPage.axaml.cs
│ ├── MainMenuPage.axaml
│ ├── MainMenuPage.axaml.cs
│ ├── PowerManagementPage.axaml
│ └── PowerManagementPage.axaml.cs
├── Pages.cs
└── Window
│ ├── AnimatedWindow.cs
│ ├── MainWindow.axaml
│ ├── MainWindow.axaml.cs
│ └── WindowSlideOrigin.cs
├── ViewModel
├── Control
│ ├── AuraColorControlViewModel.cs
│ ├── CoreStatisticsDisplayViewModel.cs
│ └── SettingsPaletteViewModel.cs
├── Page
│ ├── AniMeMatrixPageViewModel.cs
│ ├── ApplicationPageViewModel.cs
│ ├── DebugPageViewModel.cs
│ ├── FansPageViewModel.cs
│ ├── GraphicsAndDisplayPageViewModel.cs
│ ├── KeyboardBindingsPageViewModel.cs
│ ├── KeyboardPageViewModel.cs
│ └── PowerManagementPageViewModel.cs
└── Window
│ └── MainWindowViewModel.cs
└── app.manifest
/.github/workflows/dotnet.yml:
--------------------------------------------------------------------------------
1 | name: .NET
2 |
3 | on:
4 | push:
5 | branches: [ "master" ]
6 | pull_request:
7 | branches: [ "master" ]
8 | workflow_dispatch:
9 |
10 | jobs:
11 | build:
12 | runs-on: windows-latest
13 |
14 | steps:
15 | - uses: actions/checkout@v3
16 | with:
17 | submodules: recursive
18 | - name: Setup .NET
19 | uses: actions/setup-dotnet@v3
20 | with:
21 | dotnet-version: 7.0.x
22 | - name: Restore dependencies
23 | run: dotnet restore
24 | - name: Build
25 | run: dotnet build --no-restore
26 | - name: Upload a Build Artifact
27 | uses: actions/upload-artifact@v3.1.2
28 | with:
29 | name: Zephyrus-Control-Center_DEBUG
30 | path: Slate/bin/Debug/net7.0
31 | if-no-files-found: error
32 | retention-days: 30
33 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | bin/
2 | obj/
3 | /packages/
4 | riderModule.iml
5 | /_ReSharper.Caches/
6 | .idea/
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "Dependencies/Glitonea"]
2 | path = Dependencies/Glitonea
3 | url = https://github.com/vddCore/Glitonea.git
4 | [submodule "Dependencies/Avalonia.GIF"]
5 | path = Dependencies/Avalonia.GIF
6 | url = https://github.com/vddCore/Avalonia.GIF.git
7 | [submodule "Dependencies/Starlight"]
8 | path = Dependencies/Starlight
9 | url = https://github.com/vddCore/Starlight.git
10 |
--------------------------------------------------------------------------------
/Slate.API/Slate.API.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net7.0
4 | enable
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Slate.Asus/Acpi/AcpiDumper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using Microsoft.Win32;
6 | using Slate.Asus.Native;
7 |
8 | namespace Slate.Asus.Acpi
9 | {
10 | public static class AcpiDumper
11 | {
12 | private const int AcpiId = 0x41435049; // 'A' 'C' 'P' 'I'
13 |
14 | public static int[] FetchFirmwareAcpiTableList(bool skipLicenseKeyTable = true)
15 | {
16 | var dataSize = Kernel32.EnumSystemFirmwareTables(AcpiId, null, 0);
17 | var data = new byte[dataSize];
18 |
19 | if (dataSize > 0)
20 | {
21 | if (Kernel32.EnumSystemFirmwareTables(AcpiId, data, dataSize) > 0)
22 | {
23 | var ret = new int[dataSize / 4];
24 | Buffer.BlockCopy(data, 0, ret, 0, (int)dataSize);
25 |
26 | return ret.Where(
27 | x => x.ToFourCharacterCode() != "SSDT"
28 | && (skipLicenseKeyTable && x.ToFourCharacterCode() != "MSDM")
29 | ).Distinct().ToArray();
30 | }
31 | }
32 |
33 | return new int[0];
34 | }
35 |
36 | public static void DumpFirmwareAcpiTable(int tableId, Stream outStream)
37 | {
38 | var dataSize = Kernel32.GetSystemFirmwareTable(
39 | AcpiId,
40 | tableId,
41 | null,
42 | 0
43 | );
44 |
45 | var data = new byte[dataSize];
46 | Kernel32.GetSystemFirmwareTable(
47 | AcpiId,
48 | tableId,
49 | data,
50 | dataSize
51 | );
52 |
53 | outStream.Write(data);
54 | }
55 |
56 | public static int[] FetchRegistryAcpiTableList(bool skipLicenseKeyTable)
57 | {
58 | using (var hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default))
59 | {
60 | using (var subKey = hklm.OpenSubKey($"HARDWARE\\ACPI"))
61 | {
62 | return subKey!
63 | .GetSubKeyNames()
64 | .Select(x => x.ToFourCharacterCodeInteger())
65 | .Where(x => skipLicenseKeyTable && x.ToFourCharacterCode() != "MSDM")
66 | .ToArray();
67 | }
68 | }
69 | }
70 |
71 | public static void DumpRegistryAcpiTable(int tableId, Stream outStream)
72 | {
73 | var data = ReadAcpiTableFromRegistry(tableId.ToFourCharacterCode());
74 | outStream.Write(data);
75 | }
76 |
77 | private static byte[] ReadAcpiTableFromRegistry(string fourcc)
78 | {
79 | // We drill into the registry for SSDTs & co.
80 | // precisely because GetSystemFirmwareTable
81 | // is absolute Dogshit. For fuck's sake, why
82 | // couldn't it be an enumerator?
83 | //
84 | var disposeList = new List();
85 |
86 | using (var hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default))
87 | {
88 | using (var subKey = hklm.OpenSubKey($"HARDWARE\\ACPI\\{fourcc}"))
89 | {
90 | var currentKey = subKey;
91 | object? value;
92 |
93 | do
94 | {
95 | var subKeyNames = currentKey!.GetSubKeyNames();
96 |
97 | value = currentKey.GetValue("00000000");
98 | if (value != null)
99 | break;
100 |
101 | if (subKeyNames.Length == 0)
102 | {
103 | // We've drilled as deep as we can and still no data.
104 | // Unfortunate.
105 | break;
106 | }
107 |
108 | currentKey = currentKey.OpenSubKey(subKeyNames[0]);
109 | disposeList.Add(currentKey!);
110 | } while (value == null);
111 |
112 | foreach (var key in disposeList)
113 | key.Dispose();
114 |
115 | if (value == null)
116 | {
117 | throw new InvalidOperationException($"No registry data for {fourcc}.");
118 | }
119 |
120 | return (byte[])value;
121 | }
122 | }
123 | }
124 | }
125 | }
--------------------------------------------------------------------------------
/Slate.Asus/Acpi/AsusAcpiEndpoint.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Slate.Asus.Acpi.FunctionSets;
3 |
4 | namespace Slate.Asus.Acpi
5 | {
6 | public abstract class AsusAcpiEndpoint where T : struct
7 | {
8 | private readonly AsusAcpiProxy _proxy;
9 |
10 | public WmnbFunction Method { get; }
11 |
12 | protected AsusAcpiEndpoint(AsusAcpiProxy proxy, WmnbFunction method)
13 | {
14 | _proxy = proxy;
15 | Method = method;
16 | }
17 |
18 | public byte[] ReadBytes(T method, int count, params byte[] args)
19 | {
20 | var methodData = BitConverter.GetBytes((int)Convert.ChangeType(method, TypeCode.Int32));
21 | var methodArguments = new byte[sizeof(int) + args.Length];
22 |
23 | Array.Copy(methodData, 0, methodArguments, 0, sizeof(int));
24 | Array.Copy(args, 0, methodArguments, sizeof(int), args.Length);
25 |
26 | return _proxy.InvokeWMI(Method, count, args: methodArguments);
27 | }
28 |
29 | public int ReadInt32(T method, params byte[] args)
30 | {
31 | return BitConverter.ToInt32(
32 | ReadBytes(method, sizeof(int), args)
33 | );
34 | }
35 |
36 | public bool ReadBoolean(T method, params byte[] args)
37 | {
38 | return ReadInt32(method, args) != 0;
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/Slate.Asus/Acpi/AsusAcpiProxy.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using Slate.Asus.Acpi.Endpoints;
4 | using Slate.Asus.Acpi.FunctionSets;
5 | using Slate.Asus.Native;
6 |
7 | namespace Slate.Asus.Acpi
8 | {
9 | public class AsusAcpiProxy : IDisposable
10 | {
11 | private readonly nint _objectHandle;
12 |
13 | public AsusDstsEndpoint DSTS { get; }
14 | public AsusDevsEndpoint DEVS { get; }
15 |
16 | public AsusAcpiProxy(string acpiDevicePath = @"\\.\\ATKACPI")
17 | {
18 | _objectHandle = Kernel32.CreateFile(
19 | acpiDevicePath,
20 | Kernel32.GENERIC_READ | Kernel32.GENERIC_WRITE,
21 | Kernel32.FILE_SHARE_READ | Kernel32.FILE_SHARE_WRITE,
22 | 0,
23 | Kernel32.OPEN_EXISTING,
24 | Kernel32.FILE_ATTRIBUTE_NORMAL,
25 | 0
26 | );
27 |
28 | if (_objectHandle < 0)
29 | {
30 | throw new IOException($"Failed to acquire ACPI interface at '{acpiDevicePath}'.");
31 | }
32 |
33 | DSTS = new AsusDstsEndpoint(this);
34 | DEVS = new AsusDevsEndpoint(this);
35 | }
36 |
37 | public byte[] InvokeWMI(WmnbFunction wmnbFunction, int outBufferSize = 20, params byte[] args)
38 | {
39 | var inBuffer = new byte[sizeof(int) * 2 + args.Length];
40 | var outBuffer = new byte[outBufferSize];
41 |
42 | Array.Copy(
43 | BitConverter.GetBytes((int)wmnbFunction), 0,
44 | inBuffer, 0, sizeof(int)
45 | );
46 |
47 | Array.Copy(
48 | BitConverter.GetBytes(args.Length), 0,
49 | inBuffer, 4, sizeof(int)
50 | );
51 |
52 | Array.Copy(args, 0, inBuffer, 8, args.Length);
53 |
54 | unsafe
55 | {
56 | fixed (byte* inPtr = inBuffer)
57 | fixed (byte* outPtr = outBuffer)
58 | {
59 | Write(AsusIoCtl.InvokeWmnbFunction, inPtr, inBuffer.Length, outPtr, outBuffer.Length);
60 | }
61 | }
62 |
63 | return outBuffer;
64 | }
65 |
66 | private unsafe uint Write(AsusIoCtl ioctl, byte* input, int inputLength, byte* output, int outputLength)
67 | {
68 | var requestSuccessful = Kernel32.DeviceIoControl(
69 | _objectHandle,
70 | (nuint)ioctl,
71 | input,
72 | inputLength,
73 | output,
74 | outputLength,
75 | out var ret,
76 | 0
77 | );
78 |
79 | if (!requestSuccessful)
80 | {
81 | throw new IOException($"Unable to write to ACPI interface: {Kernel32.GetLastError():X8}");
82 | }
83 |
84 | return ret;
85 | }
86 |
87 | public void Dispose()
88 | {
89 | Kernel32.CloseHandle(_objectHandle);
90 | }
91 | }
92 | }
--------------------------------------------------------------------------------
/Slate.Asus/Acpi/AsusIoCtl.cs:
--------------------------------------------------------------------------------
1 | namespace Slate.Asus.Acpi
2 | {
3 | public enum AsusIoCtl
4 | {
5 | AssignEvent = 0x00222400,
6 | InvokeAcpiFunction = 0x00222404,
7 | GetNotifyCode = 0x00222408,
8 | InvokeWmnbFunction = 0x0022240C
9 | }
10 | }
--------------------------------------------------------------------------------
/Slate.Asus/Acpi/DevsMethod.cs:
--------------------------------------------------------------------------------
1 | namespace Slate.Asus.Acpi
2 | {
3 | public enum DevsMethod
4 | {
5 | SetDisplayOverdrive = 0x00050019,
6 | SetMuxSwitch = 0x00090016,
7 | SetEcoMode = 0x00090020,
8 | Unk_0x00010003 = 0x00010003, // ACPI: CWAP
9 | Unk_0x00010012 = 0x00010012, // ACPI: WLED
10 | Unk_0x00010013 = 0x00010013, // ACPI: BLED
11 | SimulateKeyPress = 0x00100021,
12 | Unk_0x00100022 = 0x00100022,
13 | SetCpuFanCurve = 0x00110024,
14 | SetGpuFanCurve = 0x00110025,
15 | SetCpuFanSpeedDirect = 0x00110022,
16 | SetGpuFanSpeedDirect = 0x00110023,
17 | SetBatteryChargeTarget = 0x00120057,
18 | SetPerformancePreset = 0x00120075,
19 | SetTotalPPT = 0x001200A0,
20 | SetCpuEDC = 0x001200A1,
21 | SetCpuTDC = 0x001200A2,
22 | Unk_0x001200A3 = 0x001200A3, // ACPI: PLON
23 | SetCpuPPT = 0x001200B0, // ACPI: PLAO
24 | Unk_0x001200B1 = 0x001200B1, // ACPI: PLPS
25 | Unk_0x001200C0 = 0x001200C0, // no-op
26 | Unk_0x001200C1 = 0x001200C1, // ACPI: PLFW
27 | Unk_0x001200C2 = 0x001200C2, // no-op
28 | Unk_0x00130022 = 0x00130022, // ACPI: APSC
29 | }
30 | }
--------------------------------------------------------------------------------
/Slate.Asus/Acpi/DstsMethod.cs:
--------------------------------------------------------------------------------
1 | namespace Slate.Asus.Acpi
2 | {
3 | public enum DstsMethod
4 | {
5 | Unk_0x00010001 = 0x00010001,
6 | Unk_0x00010002 = 0x00010002,
7 | Unk_0x00010011 = 0x00010011,
8 | Unk_0x00010013 = 0x00010013,
9 | GetDisplayOverdriveStatus = 0x00050019,
10 | Unk_0x00080041 = 0x00080041,
11 | Unk_0x00080042 = 0x00080042,
12 | Unk_0x00080043 = 0x00080043,
13 | Unk_0x00080044 = 0x00080044,
14 | GetMuxSwitchStatus = 0x00090016,
15 | GetEcoModeStatus = 0x00090020,
16 | Unk_0x00100051 = 0x00100051,
17 | GetCpuFanSpeed = 0x00110013,
18 | GetGpuFanSpeed = 0x00110014,
19 | Unk_0x00110015 = 0x00110015,
20 | Unk_0x00110016 = 0x00110016,
21 | Unk_0x00110022 = 0x00110022,
22 | Unk_0x00110023 = 0x00110023,
23 | GetCpuFanCurve = 0x00110024,
24 | GetGpuFanCurve = 0x00110025,
25 | Unk_0x00110026 = 0x00110026,
26 | Unk_0x00110027 = 0x00110027,
27 | /**
28 | * & with 0x00010000 == IsSupported
29 | * & with 0x00000010 == IsOverheating
30 | * & with 0x00000001 == IsRunning
31 | * Not present in G14 ACPI but...
32 | **/
33 | GetFanDustySupportedStatus = 0x0011001E,
34 | Unk_0x00120057 = 0x00120057,
35 | Unk_0x00120061 = 0x00120061,
36 | GetFanCurveCount = 0x00120075,
37 | Unk_0x00120079 = 0x00120079,
38 | Unk_0x00120093 = 0x00120093,
39 | GetCpuTemperature = 0x00120094,
40 | GetGpuTemperature = 0x00120097,
41 | Unk_0x0012006C = 0x0012006C,
42 | Unk_0x001200A0 = 0x001200A0,
43 | Unk_0x001200A1 = 0x001200A1,
44 | Unk_0x001200A2 = 0x001200A2,
45 | Unk_0x001200A3 = 0x001200A3,
46 | Unk_0x001200B0 = 0x001200B0,
47 | Unk_0x001200B1 = 0x001200B1,
48 | Unk_0x001200C1 = 0x001200C1,
49 | Unk_0x00130021 = 0x00130021,
50 | Unk_0x00130022 = 0x00130022,
51 | Unk_0x00130031 = 0x00130031,
52 | Unk_0x00050019 = 0x00050019,
53 | Unk_0x00050020 = 0x00050020,
54 | Unk_0x00060023 = 0x00060023,
55 | Unk_0x00060024 = 0x00060024,
56 | Unk_0x00060026 = 0x00060026,
57 | Unk_0x00060061 = 0x00060061,
58 | }
59 | }
--------------------------------------------------------------------------------
/Slate.Asus/Acpi/Endpoints/AsusDevsEndpoint.cs:
--------------------------------------------------------------------------------
1 | using Slate.Asus.Acpi.FunctionSets;
2 |
3 | namespace Slate.Asus.Acpi.Endpoints
4 | {
5 | public class AsusDevsEndpoint : AsusAcpiEndpoint
6 | {
7 | public AsusDevsEndpoint(AsusAcpiProxy proxy)
8 | : base(proxy, WmnbFunction.DEVS)
9 | {
10 | }
11 |
12 | public void SimulateKeyPress(KeyPressRequest request)
13 | {
14 | _ = ReadInt32(
15 | DevsMethod.SimulateKeyPress,
16 | (byte)request
17 | );
18 | }
19 |
20 | public void SetPerformancePreset(PerformancePreset preset)
21 | {
22 | _ = ReadInt32(
23 | DevsMethod.SetPerformancePreset,
24 | (byte)preset
25 | );
26 | }
27 |
28 | public void SetCpuFanDutyCycle(byte dutyCycle)
29 | {
30 | _ = ReadInt32(
31 | DevsMethod.SetCpuFanSpeedDirect,
32 | dutyCycle
33 | );
34 | }
35 |
36 | public void SetGpuFanDutyCycle(byte dutyCycle)
37 | {
38 | _ = ReadInt32(
39 | DevsMethod.SetGpuFanSpeedDirect,
40 | dutyCycle
41 | );
42 | }
43 |
44 | public void SetCpuFanCurve(FanCurve curve)
45 | {
46 | _ = ReadInt32(
47 | DevsMethod.SetCpuFanCurve,
48 | curve.RawData
49 | );
50 | }
51 |
52 | public void SetGpuFanCurve(FanCurve curve)
53 | {
54 | _ = ReadInt32(
55 | DevsMethod.SetGpuFanCurve,
56 | curve.RawData
57 | );
58 | }
59 |
60 | public void SetMuxSwitch(MuxSwitchMode mode)
61 | {
62 | _ = ReadInt32(
63 | DevsMethod.SetMuxSwitch,
64 | (byte)mode
65 | );
66 | }
67 |
68 | /**
69 | * Calling this will crash your system if MUX switch is set
70 | * to Discrete. I mean - you *will* have to power-cycle it.
71 | *
72 | * Manually. Oh, also, you'll have to re-enable the discrete
73 | * GPU in Device Manager. Likewise - manually.
74 | *
75 | * But hey, this is a low-level API. Who am I to judge.
76 | **/
77 | public void SetEcoMode(bool enable)
78 | {
79 | _ = ReadInt32(
80 | DevsMethod.SetEcoMode,
81 | enable ? (byte)1 : (byte)0
82 | );
83 | }
84 |
85 | public void SetDisplayOverdrive(bool enable)
86 | {
87 | _ = ReadInt32(
88 | DevsMethod.SetDisplayOverdrive,
89 | enable ? (byte)1 : (byte)0
90 | );
91 | }
92 |
93 | public void SetBatteryChargeTarget(byte value)
94 | {
95 | _ = ReadInt32(
96 | DevsMethod.SetBatteryChargeTarget,
97 | value
98 | );
99 | }
100 |
101 | /**
102 | * These are probably the most dangerous ACPI calls.
103 | *
104 | * I'm not sure how much you can fuck your system up
105 | * by providing invalid data, and I don't trust ASUS
106 | * to obey any hard limits after seeing some of the
107 | * driver disassembly.
108 | *
109 | * Once again - this is a low-level API. Provide bogus
110 | * data at your own risk, then suffer the consequences.
111 | **/
112 | public void SetTotalPPT(byte totalPpt)
113 | {
114 | _ = ReadInt32(
115 | DevsMethod.SetTotalPPT,
116 | totalPpt
117 | );
118 | }
119 |
120 | public void SetCpuPPT(byte cpuPpt)
121 | {
122 | _ = ReadInt32(
123 | DevsMethod.SetCpuPPT,
124 | cpuPpt
125 | );
126 | }
127 | }
128 | }
--------------------------------------------------------------------------------
/Slate.Asus/Acpi/Endpoints/AsusDstsEndpoint.cs:
--------------------------------------------------------------------------------
1 | using Slate.Asus.Acpi.FunctionSets;
2 |
3 | namespace Slate.Asus.Acpi.Endpoints
4 | {
5 | public class AsusDstsEndpoint : AsusAcpiEndpoint
6 | {
7 | public int CpuFanSpeed => (ReadInt32(DstsMethod.GetCpuFanSpeed) & 0xFFFF) * 100;
8 | public int GpuFanSpeed => (ReadInt32(DstsMethod.GetGpuFanSpeed) & 0xFFFF) * 100;
9 |
10 | public int CpuTemperatureCelsius => ReadInt32(DstsMethod.GetCpuTemperature) & 0xFFFF;
11 | public int GpuTemperatureCelsius => ReadInt32(DstsMethod.GetGpuTemperature) & 0xFFFF;
12 |
13 | public MuxSwitchMode MuxSwitchMode => (MuxSwitchMode)(ReadInt32(DstsMethod.GetMuxSwitchStatus) & 0xFFFF);
14 |
15 | public bool IsGraphicsPowerSavingEnabled => (ReadInt32(DstsMethod.GetEcoModeStatus) & 0xFFFF) != 0;
16 | public bool IsDisplayOverdriveEnabled => (ReadInt32(DstsMethod.GetDisplayOverdriveStatus) & 0xFFFF) != 0;
17 |
18 | internal AsusDstsEndpoint(AsusAcpiProxy proxy)
19 | : base(proxy, WmnbFunction.DSTS)
20 | {
21 | }
22 |
23 | public FanCurve ReadRawCpuFanCurve(PerformancePreset preset)
24 | => new(ReadBytes(
25 | DstsMethod.GetCpuFanCurve,
26 | 16,
27 | MapPresetToDstsParameter(preset)
28 | ));
29 |
30 | public FanCurve ReadRawGpuFanCurve(PerformancePreset preset)
31 | => new(ReadBytes(
32 | DstsMethod.GetGpuFanCurve,
33 | 16,
34 | MapPresetToDstsParameter(preset)
35 | ));
36 |
37 | /**
38 | * ASUS fucked up and now I have to pay the price.
39 | *
40 | * For some reason Silent and Performance are inverted for
41 | * GetCpuFanCurve and GetGpuFanCurve -- it's inconsistent
42 | * with SetPerformancePreset in DEVS.
43 | *
44 | * Of course not. That'd make way too much sense.
45 | * Am I glad I don't work in there.
46 | **/
47 | private byte MapPresetToDstsParameter(PerformancePreset preset)
48 | {
49 | return preset switch
50 | {
51 | PerformancePreset.Performance => (byte)PerformancePreset.Silent,
52 | PerformancePreset.Silent => (byte)PerformancePreset.Performance,
53 | _ => (byte)PerformancePreset.Balanced
54 | };
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/Slate.Asus/Acpi/FunctionSets/WmnbFunction.cs:
--------------------------------------------------------------------------------
1 | namespace Slate.Asus.Acpi.FunctionSets
2 | {
3 | public enum WmnbFunction
4 | {
5 | INIT = 0x54494E49, // 'T' 'I' 'N' 'I' | IIA0
6 | BSTS = 0x53545342, // 'S' 'T' 'S' 'B'
7 | SFUN = 0x4E554653, // 'N' 'U' 'F' 'S'
8 | WDOG = 0x474F4457, // 'G' 'O' 'D' 'W' | IIA0
9 | KBNI = 0x494E424B, // 'I' 'N' 'B' 'K'
10 | SCDG = 0x47444353, // 'G' 'D' 'C' 'S' | IIA0, IIA1
11 | SPEC = 0x43455053, // 'C' 'E' 'P' 'S' | IIA0
12 | OSVR = 0x5256534F, // 'R' 'V' 'O' 'S' | IIA0
13 | VERS = 0x53524556, // 'S' 'R' 'E' 'V' | IIA0, IIA1
14 | GLCD = 0x44434C47, // 'D' 'C' 'L' 'G'
15 | ANVI = 0x49564E41, // 'I' 'V' 'N' 'A'
16 | MWGF = 0x4647574D, // 'F' 'G' 'W' 'M'
17 | DSTS = 0x53545344, // 'S' 'T' 'S' 'D'
18 | DEVS = 0x53564544 // 'S' 'V' 'E' 'D'
19 | }
20 | }
--------------------------------------------------------------------------------
/Slate.Asus/Acpi/KeyPressRequest.cs:
--------------------------------------------------------------------------------
1 | namespace Slate.Asus.Acpi
2 | {
3 | public enum KeyPressRequest : byte
4 | {
5 | DecreaseScreenBrightness = 0x10,
6 | IncreaseScreenBrightness = 0x20,
7 | EnterHardSleepMode = 0x35, // S3
8 | TriggerM4 = 0x38,
9 | TriggerTouchpadToggleKey = 0x6B,
10 | EnterLightSleepMode = 0x6C, // S1
11 | TriggerM3 = 0x7C,
12 | Unk_0x9E = 0x9E,
13 | Unk_0x88__Q0B = 0x88, // No-op on GA402
14 | Unk_0x8A__Q72 = 0x8A,
15 | Unk_0xA8 = 0xA8,
16 | Unk_0xA9 = 0xA9,
17 | Unk_0xAA = 0xAA,
18 | Unk_0xAB = 0xAB,
19 | TriggerFanModeCycleKey = 0xAE,
20 | TriggerAuraKey = 0xB3,
21 | IncreaseKeyboardBrightness = 0xC4,
22 | DecreaseKeyboardBrigthness = 0xC5,
23 | }
24 | }
--------------------------------------------------------------------------------
/Slate.Asus/Acpi/RequiresAcpiSessionAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Slate.Asus.Acpi
4 | {
5 | [AttributeUsage(AttributeTargets.Method)]
6 | public class RequiresAcpiSessionAttribute : Attribute
7 | {
8 | }
9 | }
--------------------------------------------------------------------------------
/Slate.Asus/Acpi/here_be_dragons:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vddCore/Zephyrus-Control-Center/176f305e44f0f893e95e2d7f8e98f3be0f924c67/Slate.Asus/Acpi/here_be_dragons
--------------------------------------------------------------------------------
/Slate.Asus/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Versioning;
2 |
3 | [assembly: SupportedOSPlatform("windows")]
--------------------------------------------------------------------------------
/Slate.Asus/AtkWmiEventID.cs:
--------------------------------------------------------------------------------
1 | namespace Slate.Asus
2 | {
3 | public enum AtkWmiEventID
4 | {
5 | KeyPressM4 = 56,
6 | PowerAdapterUnplugged = 87,
7 | PowerAdapterPlugged = 88,
8 |
9 | /**
10 | * Happens when USB-C or barrel plug
11 | * is connected to or disconnected
12 | * from the laptop.
13 | **/
14 | ExternalPowerStateChanged = 123,
15 | KeyPressM3 = 124,
16 | KeyPressFnF10 = 107,
17 | KeyPressFnF5 = 174,
18 | KeyPressFnF4 = 179,
19 |
20 | /**
21 | * Happens when a HDMI cable is slotted
22 | * into the built-in socket or plugged-out
23 | * of it.
24 | */
25 | HdmiConnectionStateChanged = 192,
26 | KeyPressFnF3 = 196,
27 | KeyPressFnF2 = 197,
28 |
29 | /**
30 | * Happens with 88 only in this particular order.
31 | *
32 | * 1. Barrel connector state change detected. (207)
33 | * 2. External power plugged-in. (88)
34 | * 3. Notify power state has changed. (123)
35 | */
36 | BarrelConnectorPluggedIn = 207
37 | }
38 | }
--------------------------------------------------------------------------------
/Slate.Asus/Extensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 |
4 | namespace Slate.Asus
5 | {
6 | internal static class Extensions
7 | {
8 | public static (int IndexOf, int Value) Nearest(this int[] array, int value)
9 | {
10 | var bestIndex = -1;
11 | var bestValue = int.MaxValue;
12 | var minDiff = int.MaxValue;
13 |
14 | for (var i = 0; i < array.Length; i++)
15 | {
16 | var diff = Math.Abs((long)array[i] - value);
17 |
18 | if (minDiff > diff)
19 | {
20 | minDiff = (int)diff;
21 | bestValue = array[i];
22 | bestIndex = i;
23 | }
24 | }
25 |
26 | return (bestIndex, bestValue);
27 | }
28 |
29 | public static string ToFourCharacterCode(this int value)
30 | {
31 | var bytes = BitConverter.GetBytes(value);
32 | return $"{(char)bytes[0]}{(char)bytes[1]}{(char)bytes[2]}{(char)bytes[3]}";
33 | }
34 |
35 | public static int ToFourCharacterCodeInteger(this string fourcc)
36 | {
37 | if (fourcc.Length != 4)
38 | {
39 | throw new ArgumentException(
40 | "FOUR character code has FOUR characters. What do you not understand?",
41 | nameof(fourcc)
42 | );
43 | }
44 |
45 | var bytes = new[]
46 | {
47 | (byte)fourcc[0],
48 | (byte)fourcc[1],
49 | (byte)fourcc[2],
50 | (byte)fourcc[3]
51 | };
52 |
53 | return BitConverter.ToInt32(bytes);
54 | }
55 |
56 | public static int ReverseBytes(this int value)
57 | {
58 | var bytes = BitConverter.GetBytes(value);
59 | return BitConverter.ToInt32(bytes.Reverse().ToArray());
60 | }
61 | }
62 | }
--------------------------------------------------------------------------------
/Slate.Asus/FanCurve.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using System.Text.Json.Serialization;
4 |
5 | namespace Slate.Asus
6 | {
7 | public record FanCurve
8 | {
9 | public const int MaximumFanRPM = 6500;
10 | public const int MinimumFanRPM = 1800;
11 | public const int MinimumTemperature = 20;
12 | public const int MaximumTemperature = 110;
13 |
14 | public byte[] RawData { get; set; } = new byte[16];
15 | public FanCurvePoint[] Points { get; set; } = new FanCurvePoint[8];
16 |
17 | [JsonConstructor]
18 | public FanCurve()
19 | {
20 | }
21 |
22 | public FanCurve(byte[] rawData)
23 | {
24 | if (rawData.Length != 16)
25 | {
26 | throw new ArgumentException(
27 | $"Expected a 16-byte array. The provided array is {rawData.Length} long.",
28 | nameof(rawData)
29 | );
30 | }
31 |
32 | RawData = rawData;
33 |
34 | for (var i = 0; i < 8; i++)
35 | {
36 | Points[i] = new FanCurvePoint(
37 | RawData[i],
38 | RawData[i + 8]
39 | );
40 | }
41 | }
42 |
43 | public FanCurve(FanCurvePoint[] points)
44 | {
45 | if (points.Length != 8)
46 | {
47 | throw new ArgumentException(
48 | $"Expected an 8-point fan curve. The provided array has {points.Length} of them.",
49 | nameof(points)
50 | );
51 | }
52 |
53 | Points = points;
54 |
55 | for (var i = 0; i < 8; i++)
56 | {
57 | RawData[i] = Points[i].Temperature;
58 | RawData[i + 8] = Points[i].LookupTableIndex;
59 | }
60 | }
61 |
62 | public override string ToString()
63 | {
64 | var sb = new StringBuilder();
65 |
66 | foreach (var b in RawData)
67 | {
68 | sb.Append($"{b:X2} ");
69 | }
70 |
71 | sb.AppendLine();
72 |
73 | foreach (var b in RawData)
74 | {
75 | sb.Append($"{b:D3} ");
76 | }
77 |
78 | return sb.ToString();
79 | }
80 | }
81 | }
--------------------------------------------------------------------------------
/Slate.Asus/FanCurvePoint.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace Slate.Asus
5 | {
6 | public struct FanCurvePoint
7 | {
8 | /**
9 | * ASUS' firmware does not calculate anything.
10 | * Instead, we have this neat lookup table.
11 | *
12 | * I guess.
13 | *
14 | * Nothing makes sense about this fucking software.
15 | *
16 | * *sobs*
17 | **/
18 | [JsonIgnore]
19 | private static readonly int[] _rpmLookupForward = new[]
20 | {
21 | 1799, 1800, 1800, 1900, 1900, 2000,
22 | 2000, 2100, 2100, 2100, 2200, 2200,
23 | 2300, 2300, 2300, 2400, 2400, 2400,
24 | 2500, 2500, 2600, 2600, 2700, 2700,
25 | 2800, 2800, 2900, 2900, 2900, 3000,
26 | 3000, 3100, 3100, 3200, 3200, 3300,
27 | 3300, 3400, 3400, 3500, 3500, 3500,
28 | 3600, 3600, 3700, 3700, 3800, 3800,
29 | 3800, 3900, 3900, 4000, 4000, 4100,
30 | 4100, 4100, 4200, 4200, 4200, 4300,
31 | 4300, 4400, 4400, 4500, 4500, 4500,
32 | 4600, 4600, 4700, 4700, 4800, 4800,
33 | 4800, 4900, 4900, 5000, 5000, 5000,
34 | 5100, 5100, 5200, 5200, 5300, 5300,
35 | 5400, 5400, 5400, 5500, 5500, 5600,
36 | 5600, 5600, 5700, 5700, 5800, 5800,
37 | 5900, 5900, 5900, 6000, 6000, 6100,
38 | 6100, 6200, 6200, 6300, 6300, 6300,
39 | 6400, 6400, 6500
40 | };
41 |
42 | ///
43 | /// Represents X axis on the fan curve.
44 | ///
45 | public byte Temperature { get; set; }
46 |
47 | ///
48 | /// Represents Y axis on the fan curve (RPM LUT index).
49 | ///
50 | public byte LookupTableIndex { get; set; }
51 |
52 | ///
53 | /// Actual RPM based on the lookup table index.
54 | ///
55 | [JsonIgnore]
56 | public int RPM => _rpmLookupForward[LookupTableIndex];
57 |
58 | [JsonConstructor]
59 | public FanCurvePoint()
60 | {
61 | }
62 |
63 | public FanCurvePoint(byte temperature, byte lookupTableIndex)
64 | {
65 | Temperature = temperature;
66 | LookupTableIndex = (byte)Math.Min(_rpmLookupForward.Length, lookupTableIndex);
67 | }
68 |
69 | public static (byte, int) Approximate(int rpm)
70 | {
71 | if (rpm < 1800)
72 | return (0, 849);
73 |
74 | var result = _rpmLookupForward.Nearest(rpm);
75 | return ((byte)result.IndexOf, result.Value);
76 | }
77 | }
78 | }
--------------------------------------------------------------------------------
/Slate.Asus/MuxSwitchMode.cs:
--------------------------------------------------------------------------------
1 | namespace Slate.Asus
2 | {
3 | public enum MuxSwitchMode : byte
4 | {
5 | Discrete = 0,
6 | Switched = 1
7 | }
8 | }
--------------------------------------------------------------------------------
/Slate.Asus/Native/Kernel32.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 |
3 | namespace Slate.Asus.Native
4 | {
5 | internal static class Kernel32
6 | {
7 | private const string LibraryName = "kernel32.dll";
8 |
9 | public const nuint GENERIC_READ = 0x80000000;
10 | public const nuint GENERIC_WRITE = 0x40000000;
11 | public const nuint OPEN_EXISTING = 3;
12 | public const nuint FILE_ATTRIBUTE_NORMAL = 0x80;
13 | public const nuint FILE_SHARE_READ = 0x01;
14 | public const nuint FILE_SHARE_WRITE = 0x02;
15 |
16 | [DllImport(LibraryName, CharSet = CharSet.Unicode)]
17 | public static extern nint CreateFile(
18 | [MarshalAs(UnmanagedType.LPWStr)] string lpFileName,
19 | nuint dwDesiredAccess,
20 | nuint dwShareMode,
21 | nint lpSecurityAttributes,
22 | nuint dwCreationDisposition,
23 | nuint dwFlagsAndAttributes,
24 | nint hTemplateFile
25 | );
26 |
27 | [DllImport(LibraryName, SetLastError = true)]
28 | public static extern unsafe bool DeviceIoControl(
29 | nint hDevice,
30 | nuint dwIoControlCode,
31 | byte* lpInBuffer,
32 | [MarshalAs(UnmanagedType.U4)] int nInBufferSize,
33 | byte* lpOutBuffer,
34 | [MarshalAs(UnmanagedType.U4)] int nOutBufferSize,
35 | out uint lpBytesReturned,
36 | nint lpOverlapped
37 | );
38 |
39 | [DllImport(LibraryName)]
40 | public static extern uint GetSystemFirmwareTable(
41 | int FirmwareTableProviderSignature,
42 | int FirmwareTableID,
43 | [In, Out, MarshalAs(UnmanagedType.LPArray)]
44 | byte[]? pFirmwareBuffer,
45 | uint BufferSize
46 | );
47 |
48 | [DllImport(LibraryName)]
49 | public static extern uint EnumSystemFirmwareTables(
50 | [In] int FirmwareTableProviderSignature,
51 | [In, Out, MarshalAs(UnmanagedType.LPArray)]
52 | byte[]? pFirmwareBuffer,
53 | uint BufferSize
54 | );
55 |
56 | [DllImport(LibraryName)]
57 | public static extern nint GetLastError();
58 |
59 | [DllImport(LibraryName)]
60 | public static extern bool CloseHandle(nint hObject);
61 | }
62 | }
--------------------------------------------------------------------------------
/Slate.Asus/PerformancePreset.cs:
--------------------------------------------------------------------------------
1 | namespace Slate.Asus
2 | {
3 | public enum PerformancePreset : byte
4 | {
5 | Silent = 2,
6 | Balanced = 0,
7 | Performance = 1
8 | }
9 | }
--------------------------------------------------------------------------------
/Slate.Asus/Slate.Asus.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net7.0
4 | win-x64
5 | enable
6 | true
7 | false
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Slate.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Slate", "Slate\Slate.csproj", "{65A10EE6-CB91-4582-A962-B72E9746C06B}"
4 | EndProject
5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Slate.API", "Slate.API\Slate.API.csproj", "{67226973-C1D0-4DE3-905A-B75676584383}"
6 | EndProject
7 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Slate.Asus", "Slate.Asus\Slate.Asus.csproj", "{612B40B6-06B6-4EE5-BB20-4A4AA0983062}"
8 | EndProject
9 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dependencies", "Dependencies", "{1AC64CCC-023F-4454-AB73-AD12CD19B7E3}"
10 | EndProject
11 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Glitonea", "Dependencies\Glitonea\Glitonea.csproj", "{11F333ED-ECDD-4191-A48C-55C68C1D8634}"
12 | EndProject
13 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Starlight", "Dependencies\Starlight\Starlight\Starlight.csproj", "{765DDC4A-E8B5-49F9-BC95-1B934F4A263F}"
14 | EndProject
15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AvaloniaGif", "Dependencies\Avalonia.GIF\AvaloniaGif\AvaloniaGif.csproj", "{830404FA-3ADD-42D9-8EC3-B76904AF0F5B}"
16 | EndProject
17 | Global
18 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
19 | Debug|Any CPU = Debug|Any CPU
20 | Release|Any CPU = Release|Any CPU
21 | AcpiTesting|Any CPU = AcpiTesting|Any CPU
22 | EndGlobalSection
23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
24 | {65A10EE6-CB91-4582-A962-B72E9746C06B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 | {65A10EE6-CB91-4582-A962-B72E9746C06B}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 | {65A10EE6-CB91-4582-A962-B72E9746C06B}.Release|Any CPU.ActiveCfg = Release|Any CPU
27 | {65A10EE6-CB91-4582-A962-B72E9746C06B}.Release|Any CPU.Build.0 = Release|Any CPU
28 | {65A10EE6-CB91-4582-A962-B72E9746C06B}.AcpiTesting|Any CPU.ActiveCfg = AcpiTesting|Any CPU
29 | {65A10EE6-CB91-4582-A962-B72E9746C06B}.AcpiTesting|Any CPU.Build.0 = AcpiTesting|Any CPU
30 | {11F333ED-ECDD-4191-A48C-55C68C1D8634}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31 | {11F333ED-ECDD-4191-A48C-55C68C1D8634}.Debug|Any CPU.Build.0 = Debug|Any CPU
32 | {11F333ED-ECDD-4191-A48C-55C68C1D8634}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 | {11F333ED-ECDD-4191-A48C-55C68C1D8634}.Release|Any CPU.Build.0 = Release|Any CPU
34 | {11F333ED-ECDD-4191-A48C-55C68C1D8634}.AcpiTesting|Any CPU.ActiveCfg = AcpiTesting|Any CPU
35 | {11F333ED-ECDD-4191-A48C-55C68C1D8634}.AcpiTesting|Any CPU.Build.0 = AcpiTesting|Any CPU
36 | {765DDC4A-E8B5-49F9-BC95-1B934F4A263F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37 | {765DDC4A-E8B5-49F9-BC95-1B934F4A263F}.Debug|Any CPU.Build.0 = Debug|Any CPU
38 | {765DDC4A-E8B5-49F9-BC95-1B934F4A263F}.Release|Any CPU.ActiveCfg = Release|Any CPU
39 | {765DDC4A-E8B5-49F9-BC95-1B934F4A263F}.Release|Any CPU.Build.0 = Release|Any CPU
40 | {765DDC4A-E8B5-49F9-BC95-1B934F4A263F}.AcpiTesting|Any CPU.ActiveCfg = Debug|Any CPU
41 | {765DDC4A-E8B5-49F9-BC95-1B934F4A263F}.AcpiTesting|Any CPU.Build.0 = Debug|Any CPU
42 | {830404FA-3ADD-42D9-8EC3-B76904AF0F5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
43 | {830404FA-3ADD-42D9-8EC3-B76904AF0F5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
44 | {830404FA-3ADD-42D9-8EC3-B76904AF0F5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
45 | {830404FA-3ADD-42D9-8EC3-B76904AF0F5B}.Release|Any CPU.Build.0 = Release|Any CPU
46 | {830404FA-3ADD-42D9-8EC3-B76904AF0F5B}.AcpiTesting|Any CPU.ActiveCfg = Debug|Any CPU
47 | {830404FA-3ADD-42D9-8EC3-B76904AF0F5B}.AcpiTesting|Any CPU.Build.0 = Debug|Any CPU
48 | {67226973-C1D0-4DE3-905A-B75676584383}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
49 | {67226973-C1D0-4DE3-905A-B75676584383}.Debug|Any CPU.Build.0 = Debug|Any CPU
50 | {67226973-C1D0-4DE3-905A-B75676584383}.Release|Any CPU.ActiveCfg = Release|Any CPU
51 | {67226973-C1D0-4DE3-905A-B75676584383}.Release|Any CPU.Build.0 = Release|Any CPU
52 | {67226973-C1D0-4DE3-905A-B75676584383}.AcpiTesting|Any CPU.ActiveCfg = Debug|Any CPU
53 | {67226973-C1D0-4DE3-905A-B75676584383}.AcpiTesting|Any CPU.Build.0 = Debug|Any CPU
54 | {612B40B6-06B6-4EE5-BB20-4A4AA0983062}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
55 | {612B40B6-06B6-4EE5-BB20-4A4AA0983062}.Debug|Any CPU.Build.0 = Debug|Any CPU
56 | {612B40B6-06B6-4EE5-BB20-4A4AA0983062}.Release|Any CPU.ActiveCfg = Release|Any CPU
57 | {612B40B6-06B6-4EE5-BB20-4A4AA0983062}.Release|Any CPU.Build.0 = Release|Any CPU
58 | {612B40B6-06B6-4EE5-BB20-4A4AA0983062}.AcpiTesting|Any CPU.ActiveCfg = Debug|Any CPU
59 | {612B40B6-06B6-4EE5-BB20-4A4AA0983062}.AcpiTesting|Any CPU.Build.0 = Debug|Any CPU
60 | EndGlobalSection
61 | GlobalSection(NestedProjects) = preSolution
62 | {830404FA-3ADD-42D9-8EC3-B76904AF0F5B} = {1AC64CCC-023F-4454-AB73-AD12CD19B7E3}
63 | {11F333ED-ECDD-4191-A48C-55C68C1D8634} = {1AC64CCC-023F-4454-AB73-AD12CD19B7E3}
64 | {765DDC4A-E8B5-49F9-BC95-1B934F4A263F} = {1AC64CCC-023F-4454-AB73-AD12CD19B7E3}
65 | EndGlobalSection
66 | EndGlobal
67 |
--------------------------------------------------------------------------------
/Slate/App.axaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Timers;
3 | using Avalonia;
4 | using Avalonia.Controls;
5 | using Avalonia.Controls.ApplicationLifetimes;
6 | using Avalonia.Markup.Xaml;
7 | using Avalonia.Platform;
8 | using Glitonea;
9 | using Glitonea.Extensions;
10 | using Glitonea.Mvvm.Messaging;
11 | using LiveChartsCore;
12 | using LiveChartsCore.SkiaSharpView;
13 | using PropertyChanged;
14 | using Slate.Model.Messaging;
15 | using Slate.View.Window;
16 |
17 | namespace Slate
18 | {
19 | [DoNotNotify]
20 | public class App : Application
21 | {
22 | private readonly Timer _globalTimer = new(250);
23 | private IPlatformSettings? _platformSettings;
24 |
25 | private ulong _globalTickCount;
26 |
27 | public override void Initialize()
28 | {
29 | GlitoneaCore.Initialize();
30 |
31 | Message.Subscribe(this, OnMainWindowTransitionFinished);
32 |
33 | AvaloniaXamlLoader.Load(this);
34 | LiveCharts.Configure(c => c
35 | .AddSkiaSharp()
36 | .AddDarkTheme()
37 | );
38 |
39 | _globalTimer.Elapsed += GlobalTime_Elapsed;
40 | }
41 |
42 | public override void OnFrameworkInitializationCompleted()
43 | {
44 | if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
45 | {
46 | desktop.MainWindow = new MainWindow();
47 | }
48 |
49 | base.OnFrameworkInitializationCompleted();
50 |
51 | TrayIcon.GetIcons(this)![0].IsVisible = true;
52 | PlatformSettings!.ColorValuesChanged += PlatformSettings_ColorValuesChanged;
53 | }
54 |
55 | private void OnMainWindowTransitionFinished(MainWindowTransitionFinishedMessage msg)
56 | {
57 | if (msg.WasSlidingIn)
58 | {
59 | _globalTimer.Start();
60 | }
61 | else
62 | {
63 | _globalTimer.Stop();
64 | }
65 | }
66 |
67 | private void TrayIcon_Clicked(object? sender, EventArgs e)
68 | {
69 | Message.Broadcast();
70 | }
71 |
72 | private void GlobalTime_Elapsed(object? sender, ElapsedEventArgs elapsedEventArgs)
73 | {
74 | new GlobalTickMessage(++_globalTickCount)
75 | .Broadcast();
76 | }
77 |
78 | private void Quit_Clicked(object? sender, EventArgs e)
79 | {
80 | this.GetDesktopLifetime()
81 | .Shutdown();
82 | }
83 |
84 | private void PlatformSettings_ColorValuesChanged(object? sender, PlatformColorValues e)
85 | {
86 | new SystemAccentColorChangedMessage(
87 | e.AccentColor1,
88 | e.AccentColor2,
89 | e.AccentColor3
90 | ).Broadcast();
91 | }
92 | }
93 | }
--------------------------------------------------------------------------------
/Slate/Controller/ApplicationController.AniMeMatrix.cs:
--------------------------------------------------------------------------------
1 | using Glitonea.Mvvm.Messaging;
2 | using Slate.Model.Messaging;
3 | using Slate.Model.Settings.Components;
4 |
5 | namespace Slate.Controller
6 | {
7 | public partial class ApplicationController
8 | {
9 | private AniMeMatrixSettings AniMeMatrixSettings => ControlCenterSettings.AniMeMatrix;
10 |
11 | private void SubscribeToAniMeMatrixSettings()
12 | {
13 | Message.Subscribe(this, OnAniMeMatrixBrightnessChanged);
14 | Message.Subscribe(this, OnAniMeMatrixBuiltInsChanged);
15 | }
16 |
17 | private void OnAniMeMatrixBuiltInsChanged(AniMeMatrixBuiltInsChangedMessage msg)
18 | {
19 | _asusAnimeMatrixService.SetBuiltInAnimation(
20 | msg.PreferPowerSavingAnimation,
21 | msg.BuiltInConfiguration
22 | );
23 | }
24 |
25 | private void OnAniMeMatrixBrightnessChanged(AniMeMatrixBrightnessChangedMessage msg)
26 | {
27 | _asusAnimeMatrixService.SetBrightness(msg.BrightnessLevel);
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/Slate/Controller/ApplicationController.Application.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using Glitonea.Mvvm.Messaging;
4 | using Microsoft.Win32;
5 | using Slate.Model.Messaging;
6 | using Slate.Model.Settings.Components;
7 |
8 | namespace Slate.Controller
9 | {
10 | public partial class ApplicationController
11 | {
12 | private ApplicationSettings ApplicationSettings => ControlCenterSettings.Application;
13 |
14 | private void SubscribeToApplicationSettings()
15 | {
16 | Message.Subscribe(this, OnStartupLaunchChanged);
17 | }
18 |
19 | private void OnStartupLaunchChanged(StartupLaunchChangedMessage msg)
20 | {
21 | using var regKey = Registry.CurrentUser.OpenSubKey(
22 | "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
23 | true
24 | );
25 |
26 | try
27 | {
28 | if (msg.Enabled)
29 | {
30 | regKey?.SetValue(
31 | ApplicationName,
32 | Process.GetCurrentProcess().MainModule!.FileName
33 | );
34 | }
35 | else
36 | {
37 | regKey?.DeleteValue(ApplicationName, false);
38 | }
39 | }
40 | catch (Exception)
41 | {
42 | ApplicationSettings.RunOnStartup = false;
43 | }
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/Slate/Controller/ApplicationController.Fans.cs:
--------------------------------------------------------------------------------
1 | using Glitonea.Mvvm.Messaging;
2 | using Slate.Model.Messaging;
3 | using Slate.Model.Settings.Components;
4 |
5 | namespace Slate.Controller
6 | {
7 | public partial class ApplicationController
8 | {
9 | private FansSettings FansSettings => ControlCenterSettings.Fans;
10 |
11 | private void SubscribeToFansSettings()
12 | {
13 | Message.Subscribe(this, OnCpuFanCurveUpdated);
14 | Message.Subscribe(this, OnGpuFanCurveUpdated);
15 | Message.Subscribe(this, OnManualFanOverrideUpdated);
16 | }
17 |
18 | private void OnManualFanOverrideUpdated(ManualFanOverrideUpdatedMessage msg)
19 | {
20 | _asusHalService.SetPerformancePreset(FansSettings.PerformancePreset);
21 |
22 | if (msg.IsOverrideEnabled)
23 | {
24 | _asusHalService.SetCpuFanDutyCycle(msg.CpuDutyCycle);
25 | _asusHalService.SetGpuFanDutyCycle(msg.GpuDutyCycle);
26 | }
27 | else
28 | {
29 | _asusHalService.WriteCpuFanCurve(FansSettings.CpuFanCurve!);
30 | _asusHalService.WriteGpuFanCurve(FansSettings.GpuFanCurve!);
31 | }
32 | }
33 |
34 | private void OnCpuFanCurveUpdated(CpuFanCurveUpdatedMessage msg)
35 | {
36 | _asusHalService.WriteCpuFanCurve(msg.Curve);
37 | }
38 |
39 | private void OnGpuFanCurveUpdated(GpuFanCurveUpdatedMessage msg)
40 | {
41 | _asusHalService.WriteGpuFanCurve(msg.Curve);
42 | }
43 | }
44 | }
--------------------------------------------------------------------------------
/Slate/Controller/ApplicationController.GraphicsAndDisplay.cs:
--------------------------------------------------------------------------------
1 | using Glitonea.Mvvm.Messaging;
2 | using Slate.Model.Messaging;
3 | using Slate.Model.Settings.Components;
4 |
5 | namespace Slate.Controller
6 | {
7 | public partial class ApplicationController
8 | {
9 | private GraphicsAndDisplaySettings GraphicsAndDisplaySettings => ControlCenterSettings.GraphicsAndDisplay;
10 |
11 | private void SubscribeToGraphicsAndDisplaySettings()
12 | {
13 | Message.Subscribe(this, OnGraphicsModeChanged);
14 | Message.Subscribe(this, OnGraphicsPowerSavingModeChanged);
15 | Message.Subscribe(this, OnDisplayOverdriveChanged);
16 | Message.Subscribe(this, OnDisplayRefreshRateChanged);
17 | }
18 |
19 | private void OnGraphicsModeChanged(MuxSwitchModeChangedMessage msg)
20 | {
21 | _asusHalService.SetGraphicsMode(msg.MuxSwitchMode);
22 | }
23 |
24 | private void OnGraphicsPowerSavingModeChanged(EcoModeChangedMessage msg)
25 | {
26 | _asusHalService.SetEcoMode(msg.Enabled);
27 | }
28 |
29 | private void OnDisplayOverdriveChanged(DisplayOverdriveChangedMessage msg)
30 | {
31 | _asusHalService.SetDisplayOverdrive(msg.Enabled);
32 | }
33 |
34 | private void OnDisplayRefreshRateChanged(DisplayRefreshRateChangedMessage msg)
35 | {
36 | _displayManagementService.SetInternalDisplayRefreshRate(msg.RefreshRate);
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/Slate/Controller/ApplicationController.Keyboard.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using System.IO;
3 | using Avalonia.Threading;
4 | using Glitonea.Mvvm.Messaging;
5 | using Slate.Asus;
6 | using Slate.Model;
7 | using Slate.Model.Messaging;
8 | using Slate.Model.Settings.Components;
9 |
10 | namespace Slate.Controller
11 | {
12 | public partial class ApplicationController
13 | {
14 | private KeyboardSettings KeyboardSettings => ControlCenterSettings.Keyboard;
15 |
16 | private void SubscribeToKeyboardSettings()
17 | {
18 | Message.Subscribe(this, OnAuraSettingsChanged);
19 | }
20 |
21 | private void HandleSpecialKeyPress(AtkWmiEventID ev)
22 | {
23 | switch (ev)
24 | {
25 | case AtkWmiEventID.KeyPressM3:
26 | HandleKeyPress(KeyboardSettings.BindM3);
27 | break;
28 |
29 | case AtkWmiEventID.KeyPressM4:
30 | HandleKeyPress(KeyboardSettings.BindM4);
31 | break;
32 |
33 | case AtkWmiEventID.KeyPressFnF4:
34 | HandleKeyPress(KeyboardSettings.BindF4);
35 | break;
36 |
37 | case AtkWmiEventID.KeyPressFnF5:
38 | HandleKeyPress(KeyboardSettings.BindF5);
39 | break;
40 | }
41 | }
42 |
43 | private void HandleKeyPress(KeyBind keyBind)
44 | {
45 | switch (keyBind.Mode)
46 | {
47 | case KeyBindMode.Default:
48 | {
49 | Dispatcher.UIThread.Post(() =>
50 | {
51 | Message.Broadcast();
52 | });
53 |
54 | break;
55 | }
56 |
57 | case KeyBindMode.Media:
58 | _inputInjectionService.SimulateMediaKeyPress(keyBind.MediaKey);
59 | break;
60 |
61 | case KeyBindMode.Command:
62 | {
63 | new Process
64 | {
65 | StartInfo = new ProcessStartInfo(keyBind.Command ?? string.Empty)
66 | {
67 | WorkingDirectory = Path.GetDirectoryName(keyBind.Command)
68 | }
69 | }.Start();
70 |
71 | break;
72 | }
73 | }
74 | }
75 |
76 | private void OnAuraSettingsChanged(AuraSettingsChangedMessage msg)
77 | {
78 | _asusAuraService.WriteAuraSettings(
79 | msg.Animation,
80 | msg.PrimaryColor,
81 | msg.SecondaryColor,
82 | msg.AnimationSpeed
83 | );
84 | }
85 | }
86 | }
--------------------------------------------------------------------------------
/Slate/Controller/ApplicationController.PowerManagement.cs:
--------------------------------------------------------------------------------
1 | using Glitonea.Mvvm.Messaging;
2 | using Slate.Infrastructure.PowerManagement;
3 | using Slate.Model.Messaging;
4 | using Slate.Model.Settings.Components;
5 |
6 | namespace Slate.Controller
7 | {
8 | public partial class ApplicationController
9 | {
10 | private PowerManagementSettings PowerManagementSettings => ControlCenterSettings.PowerManagement;
11 |
12 | private void SubscribeToPowerManagementSettings()
13 | {
14 | Message.Subscribe(this, OnCpuBoostModeChanged);
15 | Message.Subscribe(this, OnBatteryChargeLimitChanged);
16 | Message.Subscribe(this, OnPowerTargetsChanged);
17 | }
18 |
19 | private void OnCpuBoostModeChanged(CpuBoostModeChangedMessage msg)
20 | {
21 | _powerManagementService.WriteProcessorBoostState(
22 | PowerMode.AC,
23 | msg.EnableOnAC
24 | ? ProcessorBoostLevel.Aggressive
25 | : ProcessorBoostLevel.Disabled
26 | );
27 |
28 | _powerManagementService.WriteProcessorBoostState(
29 | PowerMode.DC,
30 | msg.EnableOnDC
31 | ? ProcessorBoostLevel.Aggressive
32 | : ProcessorBoostLevel.Disabled
33 | );
34 |
35 | _powerManagementService.CommitCurrentPowerSchemeChanges();
36 | }
37 |
38 | private void OnBatteryChargeLimitChanged(BatteryChargeLimitChangedMessage msg)
39 | {
40 | _asusHalService.SetBatteryChargeTarget(msg.Value);
41 | }
42 |
43 | private void OnPowerTargetsChanged(PowerTargetsChangedMessage msg)
44 | {
45 | _asusHalService.SetPlatformPowerTargets(
46 | msg.TotalSystemPPT,
47 | msg.CpuPPT
48 | );
49 | }
50 | }
51 | }
--------------------------------------------------------------------------------
/Slate/FodyWeavers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/Slate/FodyWeavers.xsd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Used to control if the On_PropertyName_Changed feature is enabled.
12 |
13 |
14 |
15 |
16 | Used to control if the Dependent properties feature is enabled.
17 |
18 |
19 |
20 |
21 | Used to control if the IsChanged property feature is enabled.
22 |
23 |
24 |
25 |
26 | Used to change the name of the method that fires the notify event. This is a string that accepts multiple values in a comma separated form.
27 |
28 |
29 |
30 |
31 | Used to control if equality checks should be inserted. If false, equality checking will be disabled for the project.
32 |
33 |
34 |
35 |
36 | Used to control if equality checks should use the Equals method resolved from the base class.
37 |
38 |
39 |
40 |
41 | Used to control if equality checks should use the static Equals method resolved from the base class.
42 |
43 |
44 |
45 |
46 | Used to turn off build warnings from this weaver.
47 |
48 |
49 |
50 |
51 | Used to turn off build warnings about mismatched On_PropertyName_Changed methods.
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
60 |
61 |
62 |
63 |
64 | A comma-separated list of error codes that can be safely ignored in assembly verification.
65 |
66 |
67 |
68 |
69 | 'false' to turn off automatic generation of the XML Schema file.
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/Slate/Infrastructure/Extensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.ObjectModel;
3 | using System.Linq;
4 | using LiveChartsCore.Defaults;
5 | using Slate.Asus;
6 |
7 | namespace Slate.Infrastructure
8 | {
9 | internal static class Extensions
10 | {
11 | public static ObservableCollection ToChartValues(this FanCurve curve, bool spaceOut = true)
12 | {
13 | if (spaceOut)
14 | {
15 | var copy = curve;
16 |
17 | for (var i = 0; i < copy.Points.Length - 1; i++)
18 | {
19 | var a = copy.Points[i + 1].Temperature;
20 | var b = copy.Points[i].Temperature;
21 | var diff = a - b;
22 |
23 | if (diff < 5)
24 | {
25 | for (var j = i; j >= 0; j--)
26 | {
27 | var newTemp = copy.Points[j].Temperature - (5 - diff);
28 |
29 | if (newTemp < FanCurve.MinimumTemperature)
30 | newTemp = FanCurve.MinimumTemperature + (j * 5);
31 |
32 | copy.Points[j].Temperature = (byte)newTemp;
33 | }
34 | }
35 | }
36 |
37 | curve = copy;
38 | }
39 |
40 | return new ObservableCollection(
41 | curve.Points.Select(
42 | x => new ObservablePoint(
43 | x.Temperature,
44 | x.RPM
45 | )
46 | )
47 | );
48 | }
49 |
50 | public static FanCurve ToFanCurve(this ObservableCollection values)
51 | {
52 | var points = new FanCurvePoint[8];
53 |
54 | for (var i = 0; i < 8; i++)
55 | {
56 | var x = (byte)(values[i].X!);
57 | var (y, _) = FanCurvePoint.Approximate((int)values[i].Y!);
58 |
59 | points[i] = new FanCurvePoint(x, y);
60 | }
61 |
62 | return new FanCurve(points);
63 | }
64 |
65 | public static string ToFourCharacterCode(this int value)
66 | {
67 | var bytes = BitConverter.GetBytes(value);
68 | return $"{(char)bytes[0]}{(char)bytes[1]}{(char)bytes[2]}{(char)bytes[3]}";
69 | }
70 | }
71 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Native/PowrProf.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace Slate.Infrastructure.Native
5 | {
6 | internal static class PowrProf
7 | {
8 | public const string LibraryName = "powrprof.dll";
9 |
10 | public static readonly Guid GUID_PROCESSOR_SETTINGS_SUBGROUP = new("54533251-82BE-4824-96C1-47B60B740D00");
11 | public static readonly Guid GUID_PROCESSOR_PERFORMANCE_BOOST_SETTING = new("BE337238-0D82-4146-A960-4F3749D470C7");
12 |
13 | [DllImport(LibraryName, CharSet = CharSet.Unicode)]
14 | public static extern nuint PowerGetActiveScheme(
15 | nint UserPowerKey,
16 | [Out, MarshalAs(UnmanagedType.LPStruct)] out Guid ActivePolicyGuid
17 | );
18 |
19 | [DllImport(LibraryName, CharSet = CharSet.Unicode)]
20 | public static extern nuint PowerSetActiveScheme(
21 | nint RootPowerKey,
22 | [MarshalAs(UnmanagedType.LPStruct)] Guid SchemeGuid
23 | );
24 |
25 | [DllImport(LibraryName, CharSet = CharSet.Unicode)]
26 | public static extern nuint PowerWriteDCValueIndex(
27 | nint RootPowerKey,
28 | [MarshalAs(UnmanagedType.LPStruct)] Guid SchemeGuid,
29 | [MarshalAs(UnmanagedType.LPStruct)] Guid SubGroupOfPowerSettingsGuid,
30 | [MarshalAs(UnmanagedType.LPStruct)] Guid PowerSettingGuid,
31 | int AcValueIndex
32 | );
33 |
34 | [DllImport(LibraryName, CharSet = CharSet.Unicode)]
35 | public static extern nuint PowerWriteACValueIndex(
36 | nint RootPowerKey,
37 | [MarshalAs(UnmanagedType.LPStruct)] Guid SchemeGuid,
38 | [MarshalAs(UnmanagedType.LPStruct)] Guid SubGroupOfPowerSettingsGuid,
39 | [MarshalAs(UnmanagedType.LPStruct)] Guid PowerSettingGuid,
40 | int AcValueIndex
41 | );
42 |
43 | [DllImport(LibraryName, CharSet = CharSet.Unicode)]
44 | public static extern nuint PowerReadACValueIndex(
45 | nint RootPowerKey,
46 | [MarshalAs(UnmanagedType.LPStruct)] Guid SchemeGuid,
47 | [MarshalAs(UnmanagedType.LPStruct)] Guid SubGroupOfPowerSettingsGuid,
48 | [MarshalAs(UnmanagedType.LPStruct)] Guid PowerSettingGuid,
49 | out int AcValueIndex
50 | );
51 |
52 | [DllImport(LibraryName, CharSet = CharSet.Unicode)]
53 | public static extern nuint PowerReadDCValueIndex(
54 | nint RootPowerKey,
55 | [MarshalAs(UnmanagedType.LPStruct)] Guid SchemeGuid,
56 | [MarshalAs(UnmanagedType.LPStruct)] Guid SubGroupOfPowerSettingsGuid,
57 | [MarshalAs(UnmanagedType.LPStruct)] Guid PowerSettingGuid,
58 | out int AcValueIndex
59 | );
60 | }
61 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/PowerManagement/PowerMode.cs:
--------------------------------------------------------------------------------
1 | namespace Slate.Infrastructure.PowerManagement
2 | {
3 | /**
4 | * Weisdjafjdsfj why not use a boolean?
5 | * IDK, looks nicer. More expressive I guess.
6 | *
7 | * Memory-efficiency? That's so 1980s.
8 | */
9 | public enum PowerMode : byte /* Here, takes just 1 instead of 4 now. (: */
10 | {
11 | AC,
12 | DC
13 | }
14 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/PowerManagement/ProcessorBoostLevel.cs:
--------------------------------------------------------------------------------
1 | namespace Slate.Infrastructure.PowerManagement
2 | {
3 | public enum ProcessorBoostLevel
4 | {
5 | Disabled,
6 | Enabled,
7 | Aggressive,
8 | EfficientEnabled,
9 | EfficientAggressive,
10 | AggressiveAtGuaranteed,
11 | EfficientAgressiveAtGuaranteed
12 | }
13 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Services/IApplicationExecutionService.cs:
--------------------------------------------------------------------------------
1 | using Glitonea.Mvvm;
2 |
3 | namespace Slate.Infrastructure.Services
4 | {
5 | public interface IApplicationExecutionService : IService
6 | {
7 | void RunElevatedProcess(string path);
8 | }
9 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Services/IAsusAnimeMatrixService.cs:
--------------------------------------------------------------------------------
1 | using Glitonea.Mvvm;
2 | using Starlight.Asus;
3 | using Starlight.Asus.AnimeMatrix;
4 |
5 | namespace Slate.Infrastructure.Services
6 | {
7 | public interface IAsusAnimeMatrixService : IService
8 | {
9 | void SetBrightness(BrightnessLevel level);
10 | void SetBuiltInAnimation(bool enable, AnimeMatrixBuiltIn builtIn);
11 | }
12 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Services/IAsusAuraService.cs:
--------------------------------------------------------------------------------
1 | using System.Drawing;
2 | using Glitonea.Mvvm;
3 | using Starlight.Asus.Aura;
4 |
5 | namespace Slate.Infrastructure.Services
6 | {
7 | public interface IAsusAuraService : IService
8 | {
9 | bool IsAvailable { get; }
10 |
11 | void WriteAuraSettings(
12 | AuraAnimation animation,
13 | Color primaryColor,
14 | Color secondaryColor,
15 | AuraAnimationSpeed speed
16 | );
17 | }
18 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Services/IAsusHalService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Management;
4 | using Glitonea.Mvvm;
5 | using Slate.Asus;
6 |
7 | namespace Slate.Infrastructure.Services
8 | {
9 | public interface IAsusHalService : IService
10 | {
11 | bool IsAcpiSessionOpen { get; }
12 |
13 | void SubscribeToWmiEvent(Action handler);
14 | void UnsubscribeFromWmiEvent(Action handler);
15 | void OpenAcpiSession();
16 | int ReadCpuFanSpeed();
17 | int ReadGpuFanSpeed();
18 | float ReadCpuTemperatureCelsius();
19 | float ReadGpuTemperatureCelsius();
20 | void SetPerformancePreset(PerformancePreset preset);
21 | void SetCpuFanDutyCycle(byte dutyCycle);
22 | void SetGpuFanDutyCycle(byte dutyCycle);
23 | FanCurve ReadBuiltInCpuFanCurve(PerformancePreset performancePreset);
24 | FanCurve ReadBuiltInGpuFanCurve(PerformancePreset performancePreset);
25 | void WriteCpuFanCurve(FanCurve curve);
26 | void WriteGpuFanCurve(FanCurve curve);
27 | void SetGraphicsMode(MuxSwitchMode mode);
28 | MuxSwitchMode GetGraphicsMode();
29 | void SetEcoMode(bool enable);
30 | bool GetEcoMode();
31 | void SetDisplayOverdrive(bool enable);
32 | bool GetDisplayOverdrive();
33 | void SetBatteryChargeTarget(int value);
34 | void SetPlatformPowerTargets(byte totalSystemPpt, byte cpuPpt);
35 | void DumpWmiRegisters(Stream outStream);
36 | int[] FetchFirmwareAcpiTableList(bool skipLicenseKeyTable = true);
37 | void DumpFirmwareAcpiTable(int tableId, Stream outStream);
38 | int[] FetchRegistryAcpiTableList(bool skipLicenseKeyTable = true);
39 | void DumpRegistryAcpiTable(int tableId, Stream outStream);
40 | void CloseAcpiSession();
41 |
42 | }
43 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Services/IDisplayManagementService.cs:
--------------------------------------------------------------------------------
1 | using Glitonea.Mvvm;
2 |
3 | namespace Slate.Infrastructure.Services
4 | {
5 | public interface IDisplayManagementService : IService
6 | {
7 | bool SetInternalDisplayRefreshRate(uint refreshRate);
8 | uint GetInternalDisplayRefreshRate();
9 | }
10 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Services/IHardwareMonitorService.cs:
--------------------------------------------------------------------------------
1 | using Glitonea.Mvvm;
2 |
3 | namespace Slate.Infrastructure.Services
4 | {
5 | public interface IHardwareMonitorService : IService
6 | {
7 | int CpuFanRPM { get; }
8 | int CpuTemperature { get; }
9 |
10 | int GpuFanRPM { get; }
11 | int GpuTemperature { get; }
12 | }
13 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Services/IInputInjectionService.cs:
--------------------------------------------------------------------------------
1 | using Glitonea.Mvvm;
2 | using Slate.Model;
3 |
4 | namespace Slate.Infrastructure.Services
5 | {
6 | public interface IInputInjectionService : IService
7 | {
8 | void SimulateMediaKeyPress(MediaKey mediaKey);
9 | }
10 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Services/IPowerManagementService.cs:
--------------------------------------------------------------------------------
1 | using Glitonea.Mvvm;
2 | using Slate.Infrastructure.PowerManagement;
3 |
4 | namespace Slate.Infrastructure.Services
5 | {
6 | public interface IPowerManagementService : IService
7 | {
8 | ProcessorBoostLevel ReadProcessorBoostState(PowerMode powerMode);
9 | void WriteProcessorBoostState(PowerMode powerMode, ProcessorBoostLevel boostLevel);
10 |
11 | void CommitCurrentPowerSchemeChanges();
12 | }
13 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Services/ISettingsService.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 | using Glitonea.Mvvm;
3 | using Slate.Model.Settings;
4 |
5 | namespace Slate.Infrastructure.Services
6 | {
7 | public interface ISettingsService : IService
8 | {
9 | ControlCenterSettings? ControlCenter { get; }
10 | Task Save();
11 | }
12 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Services/IShutdownService.cs:
--------------------------------------------------------------------------------
1 | using Glitonea.Mvvm;
2 |
3 | namespace Slate.Infrastructure.Services
4 | {
5 | public interface IShutdownService : IService
6 | {
7 | void RequestSystemReboot(string reason);
8 | }
9 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Services/IStorageService.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using Glitonea.Mvvm;
3 |
4 | namespace Slate.Infrastructure.Services
5 | {
6 | public interface IStorageService : IService
7 | {
8 | string BaseDirectory { get; }
9 |
10 | FileStream CreateFile(string storageRelativePath);
11 | FileStream OpenOrCreateFile(string storageRelativePath);
12 | }
13 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Services/IWmiEventService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Management;
3 | using Glitonea.Mvvm;
4 |
5 | namespace Slate.Infrastructure.Services
6 | {
7 | public interface IWmiEventService : IService
8 | {
9 | void SubscribeTo(string eventProvider, Action handler);
10 | void UnsubscribeFrom(string eventProvider, Action handler);
11 | }
12 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Services/Implementations/ApplicationExecutionService.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using System.IO;
3 |
4 | namespace Slate.Infrastructure.Services.Implementations
5 | {
6 | public class ApplicationExecutionService : IApplicationExecutionService
7 | {
8 | public void RunElevatedProcess(string path)
9 | {
10 | Process.Start(new ProcessStartInfo
11 | {
12 | UseShellExecute = true,
13 | WorkingDirectory = Path.GetDirectoryName(path),
14 | FileName = path,
15 | Verb = "runas"
16 | });
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Services/Implementations/AsusAnimeMatrixService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Starlight.Asus;
3 | using Starlight.Asus.AnimeMatrix;
4 |
5 | namespace Slate.Infrastructure.Services.Implementations
6 | {
7 | public class AsusAnimeMatrixService : IAsusAnimeMatrixService, IDisposable
8 | {
9 | private readonly AnimeMatrixDevice _device;
10 |
11 | public AsusAnimeMatrixService()
12 | {
13 | _device = new AnimeMatrixDevice();
14 | }
15 |
16 | public void SetBrightness(BrightnessLevel level)
17 | => _device.SetBrightness(level);
18 |
19 | public void SetBuiltInAnimation(bool enable, AnimeMatrixBuiltIn builtIn)
20 | => _device.SetBuiltInAnimation(enable, builtIn);
21 |
22 | public void Dispose()
23 | {
24 | _device.Dispose();
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Services/Implementations/AsusAuraService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Drawing;
3 | using Starlight.Asus.Aura;
4 |
5 | namespace Slate.Infrastructure.Services.Implementations
6 | {
7 | public class AsusAuraService : IAsusAuraService, IDisposable
8 | {
9 | private readonly AuraDevice? _auraDevice;
10 |
11 | public bool IsAvailable => _auraDevice != null;
12 |
13 | public AsusAuraService()
14 | {
15 | try
16 | {
17 | _auraDevice = new AuraDevice();
18 | }
19 | catch
20 | {
21 | /* Ignore any exceptions. */
22 | }
23 | }
24 |
25 | public void WriteAuraSettings(
26 | AuraAnimation animation,
27 | Color primaryColor,
28 | Color secondaryColor,
29 | AuraAnimationSpeed speed
30 | )
31 | {
32 | ThrowIfUnavailable();
33 |
34 | _auraDevice!.Mode.Animate(
35 | 0,
36 | animation,
37 | primaryColor,
38 | secondaryColor,
39 | speed
40 | );
41 | }
42 |
43 | public void Dispose()
44 | => _auraDevice?.Dispose();
45 |
46 | private void ThrowIfUnavailable()
47 | {
48 | if (!IsAvailable)
49 | throw new InvalidOperationException("ASUS Aura device was not found on your system.");
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Services/Implementations/DisplayManagementService.cs:
--------------------------------------------------------------------------------
1 | using Slate.Infrastructure.Native;
2 |
3 | namespace Slate.Infrastructure.Services.Implementations
4 | {
5 | public class DisplayManagementService : IDisplayManagementService
6 | {
7 | public bool SetInternalDisplayRefreshRate(uint refreshRate)
8 | {
9 | if (User32.QueryDisplayConfig(
10 | User32.QDC.ONLY_ACTIVE_PATHS,
11 | out var pathInfos,
12 | out var modeInfos,
13 | out _
14 | ) != 0)
15 | {
16 | return false;
17 | }
18 |
19 | for (var i = 0; i < pathInfos.Length; i++)
20 | {
21 | var path = pathInfos[i];
22 |
23 | if ((path.flags & 1) != 0
24 | && (path.targetInfo.outputTechnology & User32.DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY.INTERNAL) != 0)
25 | {
26 | for (var j = 0; j < modeInfos.Length; j++)
27 | {
28 | var mode = modeInfos[j];
29 |
30 | if (mode.infoType == User32.DISPLAYCONFIG_MODE_INFO_TYPE.TARGET &&
31 | mode.id == path.targetInfo.id)
32 | {
33 | modeInfos[j].targetMode.targetVideoSignalInfo.vSyncFreq.Numerator = refreshRate;
34 | }
35 | }
36 | }
37 | }
38 |
39 | return User32.SetDisplayConfig(
40 | (uint)pathInfos.Length,
41 | pathInfos,
42 | (uint)modeInfos.Length,
43 | modeInfos,
44 | User32.SDC.APPLY
45 | | User32.SDC.USE_SUPPLIED_DISPLAY_CONFIG
46 | | User32.SDC.SAVE_TO_DATABASE
47 | ) == 0;
48 | }
49 |
50 | public uint GetInternalDisplayRefreshRate()
51 | {
52 | if (User32.QueryDisplayConfig(
53 | User32.QDC.ONLY_ACTIVE_PATHS,
54 | out var pathInfos,
55 | out var modeInfos,
56 | out _
57 | ) == 0)
58 | {
59 | for (var i = 0; i < pathInfos.Length; i++)
60 | {
61 | var path = pathInfos[i];
62 |
63 | if ((path.flags & 1) != 0
64 | && (path.targetInfo.outputTechnology
65 | & User32.DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY.INTERNAL) != 0)
66 | {
67 | for (var j = 0; j < modeInfos.Length; j++)
68 | {
69 | var mode = modeInfos[j];
70 |
71 | if (mode.infoType == User32.DISPLAYCONFIG_MODE_INFO_TYPE.TARGET &&
72 | mode.id == path.targetInfo.id)
73 | {
74 | return modeInfos[j].targetMode.targetVideoSignalInfo.vSyncFreq.Numerator;
75 | }
76 | }
77 | }
78 | }
79 | }
80 |
81 | return 0;
82 | }
83 | }
84 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Services/Implementations/HardwareMonitorService.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using Glitonea.Mvvm.Messaging;
3 | using Slate.Model.Messaging;
4 |
5 | namespace Slate.Infrastructure.Services.Implementations
6 | {
7 | public class HardwareMonitorService : IHardwareMonitorService, INotifyPropertyChanged
8 | {
9 | private readonly IAsusHalService _asusHalService;
10 |
11 | public event PropertyChangedEventHandler? PropertyChanged;
12 |
13 | public int CpuFanRPM { get; private set; }
14 | public int CpuTemperature { get; private set; }
15 |
16 | public int GpuFanRPM { get; private set; }
17 | public int GpuTemperature { get; private set; }
18 |
19 | public HardwareMonitorService(IAsusHalService asusHalService)
20 | {
21 | _asusHalService = asusHalService;
22 |
23 | Message.Subscribe(this, OnGlobalTick);
24 | }
25 |
26 | private void OnGlobalTick(GlobalTickMessage _)
27 | {
28 | if (!_asusHalService.IsAcpiSessionOpen)
29 | return;
30 |
31 | CpuFanRPM = _asusHalService.ReadCpuFanSpeed();
32 | CpuTemperature = (int)_asusHalService.ReadCpuTemperatureCelsius();
33 |
34 | GpuFanRPM = _asusHalService.ReadGpuFanSpeed();
35 | GpuTemperature = (int)_asusHalService.ReadGpuTemperatureCelsius();
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Services/Implementations/InputInjectionService.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 | using Slate.Infrastructure.Native;
3 | using Slate.Model;
4 |
5 | namespace Slate.Infrastructure.Services.Implementations
6 | {
7 | public class InputInjectionService : IInputInjectionService
8 | {
9 | public void SimulateMediaKeyPress(MediaKey mediaKey)
10 | {
11 | switch (mediaKey)
12 | {
13 | case MediaKey.Previous:
14 | SendInput(User32.VK_MEDIA_PREV_TRACK);
15 | break;
16 |
17 | case MediaKey.PlayPause:
18 | SendInput(User32.VK_MEDIA_PLAY_PAUSE);
19 | break;
20 |
21 | case MediaKey.Stop:
22 | SendInput(User32.VK_MEDIA_STOP);
23 | break;
24 |
25 | case MediaKey.Next:
26 | SendInput(User32.VK_MEDIA_NEXT_TRACK);
27 | break;
28 | }
29 | }
30 |
31 | private void SendInput(ushort vkCode)
32 | {
33 | var inputDown = new User32.INPUT
34 | {
35 | type = User32.INPUT_TYPE.KEYBOARD,
36 | union = new User32.INPUTUNION
37 | {
38 | ki = new User32.KEYBDINPUT
39 | {
40 | wVk = vkCode,
41 | dwFlags = 0
42 | }
43 | }
44 | };
45 |
46 | var inputUp = new User32.INPUT
47 | {
48 | type = User32.INPUT_TYPE.KEYBOARD,
49 | union = new User32.INPUTUNION
50 | {
51 | ki = new User32.KEYBDINPUT
52 | {
53 | wVk = vkCode,
54 | dwFlags = User32.KEYEVENTF.KEYUP
55 | }
56 | }
57 | };
58 |
59 | User32.SendInput(2, new[] { inputDown, inputUp }, Marshal.SizeOf());
60 | }
61 | }
62 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Services/Implementations/PowerManagementService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Slate.Infrastructure.Native;
3 | using Slate.Infrastructure.PowerManagement;
4 |
5 | namespace Slate.Infrastructure.Services.Implementations
6 | {
7 | public class PowerManagementService : IPowerManagementService
8 | {
9 | public ProcessorBoostLevel ReadProcessorBoostState(PowerMode powerMode)
10 | {
11 | PowrProf.PowerGetActiveScheme(0, out var activeSchemeGuid);
12 |
13 | if (powerMode == PowerMode.AC)
14 | {
15 | PowrProf.PowerReadACValueIndex(
16 | nint.Zero,
17 | activeSchemeGuid,
18 | PowrProf.GUID_PROCESSOR_SETTINGS_SUBGROUP,
19 | PowrProf.GUID_PROCESSOR_PERFORMANCE_BOOST_SETTING,
20 | out int value
21 | );
22 |
23 | return (ProcessorBoostLevel)value;
24 | }
25 | else if (powerMode == PowerMode.DC)
26 | {
27 | PowrProf.PowerReadDCValueIndex(
28 | nint.Zero,
29 | activeSchemeGuid,
30 | PowrProf.GUID_PROCESSOR_SETTINGS_SUBGROUP,
31 | PowrProf.GUID_PROCESSOR_PERFORMANCE_BOOST_SETTING,
32 | out int value
33 | );
34 |
35 | return (ProcessorBoostLevel)value;
36 | }
37 |
38 | /**
39 | * Boo-hoo it would have been avoided by design if only you used a boolean.
40 | * Shut it. It's open-source and I'm having fun here.
41 | */
42 | throw new ArgumentException($"Invalid power mode provided UwU: {powerMode}.");
43 | }
44 |
45 | public void WriteProcessorBoostState(PowerMode powerMode, ProcessorBoostLevel boostLevel)
46 | {
47 | PowrProf.PowerGetActiveScheme(0, out var activeSchemeGuid);
48 |
49 | if (powerMode == PowerMode.AC)
50 | {
51 | PowrProf.PowerWriteACValueIndex(
52 | nint.Zero,
53 | activeSchemeGuid,
54 | PowrProf.GUID_PROCESSOR_SETTINGS_SUBGROUP,
55 | PowrProf.GUID_PROCESSOR_PERFORMANCE_BOOST_SETTING,
56 | (int)boostLevel
57 | );
58 | }
59 | else if (powerMode == PowerMode.DC)
60 | {
61 | PowrProf.PowerWriteDCValueIndex(
62 | nint.Zero,
63 | activeSchemeGuid,
64 | PowrProf.GUID_PROCESSOR_SETTINGS_SUBGROUP,
65 | PowrProf.GUID_PROCESSOR_PERFORMANCE_BOOST_SETTING,
66 | (int)boostLevel
67 | );
68 |
69 | }
70 | else
71 | {
72 | throw new ArgumentException($"Invalid power mode provided UwU: {powerMode}.");
73 | }
74 | }
75 |
76 | public void CommitCurrentPowerSchemeChanges()
77 | {
78 | PowrProf.PowerGetActiveScheme(0, out var activeSchemeGuid);
79 | PowrProf.PowerSetActiveScheme(0, activeSchemeGuid);
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Services/Implementations/SettingsService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Text.Json;
4 | using System.Threading.Tasks;
5 | using Slate.Model.Settings;
6 |
7 | namespace Slate.Infrastructure.Services.Implementations
8 | {
9 | public class SettingsService : ISettingsService
10 | {
11 | private const string SettingsFileName = "zcc_settings.json";
12 |
13 | private readonly IStorageService _storageService;
14 |
15 | public ControlCenterSettings? ControlCenter { get; private set; }
16 |
17 | public SettingsService(IStorageService storageService)
18 | {
19 | _storageService = storageService;
20 | ReadOrCreateSettings();
21 | }
22 |
23 | public async Task Save()
24 | {
25 | using (var fs = _storageService.CreateFile(SettingsFileName))
26 | {
27 | await JsonSerializer.SerializeAsync(fs, ControlCenter, new JsonSerializerOptions
28 | {
29 | WriteIndented = true,
30 | });
31 | }
32 | }
33 |
34 | private void ReadOrCreateSettings()
35 | {
36 | try
37 | {
38 | using (var fs = _storageService.OpenOrCreateFile(SettingsFileName))
39 | using (var sr = new StreamReader(fs))
40 | {
41 | ControlCenter = JsonSerializer.Deserialize(
42 | sr.ReadToEnd()
43 | );
44 | }
45 | }
46 | catch (Exception)
47 | {
48 | // todo show a message box, log a failure. anything.
49 | ControlCenter = new ControlCenterSettings();
50 | Save().Wait();
51 | }
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Services/Implementations/ShutdownService.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 |
3 | namespace Slate.Infrastructure.Services.Implementations
4 | {
5 | public class ShutdownService : IShutdownService
6 | {
7 | public void RequestSystemReboot(string reason)
8 | {
9 | Process.Start(
10 | new ProcessStartInfo("shutdown.exe", $"/r /f /t 0 /c \"{reason}\"")
11 | {
12 | UseShellExecute = true
13 | }
14 | );
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Services/Implementations/StorageService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 |
4 | namespace Slate.Infrastructure.Services.Implementations
5 | {
6 | public class StorageService : IStorageService
7 | {
8 | private const string AppStorageDirectoryName = "ZephyrusControlCenter";
9 |
10 | public string BaseDirectory { get; }
11 |
12 | public StorageService()
13 | {
14 | BaseDirectory = GetOrCreateUserDataDirectory();
15 | }
16 |
17 | public FileStream CreateFile(string storageRelativePath)
18 | {
19 | var absolutePath = Path.Combine(BaseDirectory, storageRelativePath);
20 | var targetDirectory = Path.GetDirectoryName(absolutePath);
21 |
22 | Directory.CreateDirectory(targetDirectory!);
23 |
24 | return new FileStream(
25 | absolutePath,
26 | FileMode.Create,
27 | FileAccess.ReadWrite,
28 | FileShare.Read
29 | );
30 | }
31 |
32 | public FileStream OpenOrCreateFile(string storageRelativePath)
33 | {
34 | var absolutePath = Path.Combine(BaseDirectory, storageRelativePath);
35 | var targetDirectory = Path.GetDirectoryName(absolutePath);
36 |
37 | Directory.CreateDirectory(targetDirectory!);
38 |
39 | return new FileStream(
40 | absolutePath,
41 | FileMode.OpenOrCreate,
42 | FileAccess.ReadWrite,
43 | FileShare.Read
44 | );
45 | }
46 |
47 | private string GetOrCreateUserDataDirectory()
48 | {
49 | var appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
50 | var appSettingsPath = Path.Combine(appDataPath, AppStorageDirectoryName);
51 |
52 | Directory.CreateDirectory(appSettingsPath);
53 |
54 | return appSettingsPath;
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Services/Implementations/WmiEventService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Management;
5 | using Slate.Infrastructure.WMI;
6 |
7 | namespace Slate.Infrastructure.Services.Implementations
8 | {
9 | public class WmiEventService : IWmiEventService, IDisposable
10 | {
11 | private Dictionary? _eventRegistry = new();
12 |
13 | public void SubscribeTo(string eventProvider, Action handler)
14 | {
15 | ThrowIfDisposed();
16 |
17 | if (!_eventRegistry!.ContainsKey(eventProvider))
18 | {
19 | _eventRegistry.Add(eventProvider, new ManagementEvent(eventProvider));
20 | }
21 |
22 | _eventRegistry[eventProvider].Subscribe(handler);
23 | }
24 |
25 | public void UnsubscribeFrom(string eventProvider, Action handler)
26 | {
27 | ThrowIfDisposed();
28 |
29 | if (!_eventRegistry!.ContainsKey(eventProvider))
30 | {
31 | return;
32 | }
33 |
34 | _eventRegistry[eventProvider].Unsubscribe(handler);
35 |
36 | if (!_eventRegistry.Any())
37 | {
38 | _eventRegistry.Remove(eventProvider);
39 | }
40 | }
41 |
42 | public void Dispose()
43 | {
44 | if (_eventRegistry == null)
45 | {
46 | throw new InvalidOperationException("This service has already been disposed.");
47 | }
48 |
49 | foreach (var kvp in _eventRegistry)
50 | {
51 | kvp.Value.Dispose();
52 | }
53 |
54 | _eventRegistry.Clear();
55 | _eventRegistry = null;
56 | }
57 |
58 | private void ThrowIfDisposed()
59 | {
60 | if (_eventRegistry == null)
61 | {
62 | throw new InvalidOperationException("This service has been disposed.");
63 | }
64 | }
65 | }
66 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Settings/SettingsBase.cs:
--------------------------------------------------------------------------------
1 | namespace Slate.Infrastructure.Settings
2 | {
3 | public abstract class SettingsBase : SettingsComponent
4 | {
5 | // Marker
6 | }
7 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/Settings/SettingsComponent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using Slate.Model.Messaging;
4 |
5 | namespace Slate.Infrastructure.Settings
6 | {
7 | public abstract class SettingsComponent : INotifyPropertyChanged
8 | {
9 | private bool _isEventSuppresed;
10 |
11 | public event PropertyChangedEventHandler? PropertyChanged;
12 |
13 | protected SettingsComponent()
14 | {
15 | PropertyChanged += RaiseSettingsModified;
16 | }
17 |
18 | protected void RaiseSettingsModified(object? sender, PropertyChangedEventArgs e)
19 | {
20 | if (_isEventSuppresed)
21 | return;
22 |
23 | OnSettingsModified(e.PropertyName);
24 |
25 | new SettingsModifiedMessage(this, e.PropertyName)
26 | .Broadcast();
27 | }
28 |
29 | protected virtual void OnSettingsModified(string? propertyName)
30 | {
31 | }
32 |
33 | protected void WithEventSuppressed(Action action)
34 | {
35 | _isEventSuppresed = true;
36 |
37 | try
38 | {
39 | action();
40 | }
41 | finally
42 | {
43 | _isEventSuppresed = false;
44 | }
45 | }
46 | }
47 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/SystemParameters.cs:
--------------------------------------------------------------------------------
1 | using System.Drawing;
2 | using Avalonia.Controls;
3 | using Slate.Infrastructure.Native;
4 |
5 | namespace Slate.Infrastructure
6 | {
7 | public static class SystemParameters
8 | {
9 | public static Size PrimaryScreenSize => new(
10 | User32.GetSystemMetrics(User32.SM_CXSCREEN),
11 | User32.GetSystemMetrics(User32.SM_CYSCREEN)
12 | );
13 |
14 | public static Size WorkingAreaSize
15 | {
16 | get
17 | {
18 | var rect = new User32.RECT();
19 |
20 | User32.SystemParametersInfoW(User32.SPI_GETWORKAREA, 0, ref rect, 0);
21 |
22 | return new(rect.right - rect.left, rect.bottom - rect.top);
23 | }
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/Slate/Infrastructure/WMI/ManagementEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Management;
4 |
5 | namespace Slate.Infrastructure.WMI
6 | {
7 | public class ManagementEvent : IDisposable
8 | {
9 | private ManagementEventWatcher Watcher { get; }
10 | private HashSet> Subscribers { get; } = new();
11 |
12 | public ManagementEvent(string eventProvider)
13 | {
14 | Watcher = new ManagementEventWatcher(
15 | "root\\WMI",
16 | $"SELECT * FROM {eventProvider}"
17 | );
18 |
19 | Watcher.EventArrived += Watcher_EventArrived;
20 | Watcher.Start();
21 | }
22 |
23 | public void Subscribe(Action subscriber)
24 | {
25 | Subscribers.Add(subscriber);
26 | }
27 |
28 | public void Unsubscribe(Action subscriber)
29 | {
30 | Subscribers.Remove(subscriber);
31 | }
32 |
33 | private void Watcher_EventArrived(object sender, EventArrivedEventArgs e)
34 | {
35 | var invocationList = new List>(Subscribers);
36 |
37 | foreach (var subscriber in invocationList)
38 | subscriber.Invoke(e.NewEvent);
39 | }
40 |
41 | public void Dispose()
42 | {
43 | Watcher.Stop();
44 | Watcher.Dispose();
45 | }
46 | }
47 | }
--------------------------------------------------------------------------------
/Slate/Model/ColorWrapper.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace Slate.Model
5 | {
6 | public record ColorWrapper : INotifyPropertyChanged
7 | {
8 | public byte R { get; set; }
9 | public byte G { get; set; }
10 | public byte B { get; set; }
11 |
12 | [JsonIgnore]
13 | public System.Drawing.Color HardwareColor
14 | {
15 | get => System.Drawing.Color.FromArgb(R, G, B);
16 | set
17 | {
18 | R = value.R;
19 | G = value.G;
20 | B = value.B;
21 | }
22 | }
23 |
24 | [JsonIgnore]
25 | public Avalonia.Media.Color MediaRGB
26 | {
27 | get => Avalonia.Media.Color.FromRgb(R, G, B);
28 | set
29 | {
30 | R = value.R;
31 | G = value.G;
32 | B = value.B;
33 | }
34 | }
35 |
36 | [JsonIgnore]
37 | public Avalonia.Media.HsvColor MediaHSV
38 | {
39 | get => new(MediaRGB);
40 | set => MediaRGB = value.ToRgb();
41 | }
42 |
43 | public event PropertyChangedEventHandler? PropertyChanged;
44 |
45 | public ColorWrapper()
46 | {
47 | }
48 |
49 | public ColorWrapper(System.Drawing.Color color)
50 | {
51 | HardwareColor = color;
52 | }
53 |
54 | public ColorWrapper(Avalonia.Media.Color color)
55 | {
56 | MediaRGB = color;
57 | }
58 |
59 | public ColorWrapper(byte r, byte g, byte b)
60 | : this()
61 | {
62 | R = r;
63 | G = g;
64 | B = b;
65 | }
66 |
67 | }
68 | }
--------------------------------------------------------------------------------
/Slate/Model/KeyBind.cs:
--------------------------------------------------------------------------------
1 | namespace Slate.Model
2 | {
3 | public struct KeyBind
4 | {
5 | public KeyBindMode Mode { get; set; } = KeyBindMode.Default;
6 | public MediaKey MediaKey { get; set; } = MediaKey.PlayPause;
7 |
8 | public string? Command { get; set; }
9 |
10 | public KeyBind()
11 | {
12 | }
13 |
14 | public KeyBind(KeyBindMode mode)
15 | {
16 | Mode = mode;
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/Slate/Model/KeyBindMode.cs:
--------------------------------------------------------------------------------
1 | namespace Slate.Model
2 | {
3 | public enum KeyBindMode
4 | {
5 | Default,
6 | Media,
7 | Command
8 | }
9 | }
--------------------------------------------------------------------------------
/Slate/Model/MediaKey.cs:
--------------------------------------------------------------------------------
1 | namespace Slate.Model
2 | {
3 | public enum MediaKey
4 | {
5 | Previous,
6 | Next,
7 | Stop,
8 | PlayPause
9 | }
10 | }
--------------------------------------------------------------------------------
/Slate/Model/Messaging/Messages.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Media;
2 | using Glitonea.Mvvm.Messaging;
3 | using Slate.Asus;
4 | using Slate.Infrastructure.Settings;
5 | using Slate.View;
6 | using Starlight.Asus;
7 | using Starlight.Asus.AnimeMatrix;
8 | using Starlight.Asus.Aura;
9 |
10 | namespace Slate.Model.Messaging
11 | {
12 | public sealed record GlobalTickMessage(ulong TotalTicksElapsed)
13 | : Message;
14 |
15 | public sealed record TrayIconClickedMessage
16 | : Message;
17 |
18 | public sealed record MainWindowLoadedMessage
19 | : Message;
20 |
21 | public sealed record MainWindowTransitionFinishedMessage(bool WasSlidingIn)
22 | : Message;
23 |
24 | public sealed record NavigationRequestedMessage(PageMarker PageMarker)
25 | : Message;
26 |
27 | public sealed record NavigatedToPageMessage(PageMarker PageMarker)
28 | : Message;
29 |
30 | public sealed record NavigatedBackMessage(PageMarker CurrentPage)
31 | : Message;
32 |
33 | public sealed record SettingsModifiedMessage(
34 | SettingsComponent Origin,
35 | string? PropertyName
36 | ) : Message;
37 |
38 | public sealed record StartupLaunchChangedMessage(bool Enabled)
39 | : Message;
40 |
41 | public sealed record UpdateCheckChangedMessage(bool Enabled)
42 | : Message;
43 |
44 | public sealed record CpuFanCurveUpdatedMessage(FanCurve Curve)
45 | : Message;
46 |
47 | public sealed record GpuFanCurveUpdatedMessage(FanCurve Curve)
48 | : Message;
49 |
50 | public sealed record PerformancePresetUpdatedMessage(PerformancePreset Preset)
51 | : Message;
52 |
53 | public sealed record ManualFanOverrideUpdatedMessage(
54 | bool IsOverrideEnabled,
55 | byte CpuDutyCycle,
56 | byte GpuDutyCycle
57 | ) : Message;
58 |
59 | public sealed record MuxSwitchModeChangedMessage(MuxSwitchMode MuxSwitchMode)
60 | : Message;
61 |
62 | public sealed record EcoModeChangedMessage(bool Enabled)
63 | : Message;
64 |
65 | public sealed record EcoModeTransitionStartedMessage
66 | : Message;
67 |
68 | public sealed record EcoModeTransitionFinishedMessage
69 | : Message;
70 |
71 | public sealed record DisplayOverdriveChangedMessage(bool Enabled)
72 | : Message;
73 |
74 | public sealed record DisplayRefreshRateChangedMessage(uint RefreshRate)
75 | : Message;
76 |
77 | public sealed record CpuBoostModeChangedMessage(
78 | bool EnableOnAC,
79 | bool EnableOnDC
80 | ) : Message;
81 |
82 | public sealed record BatteryChargeLimitChangedMessage(int Value)
83 | : Message;
84 |
85 | public sealed record PowerTargetsChangedMessage(
86 | byte TotalSystemPPT,
87 | byte CpuPPT
88 | ) : Message;
89 |
90 | public sealed record AuraSettingsChangedMessage(
91 | AuraAnimation Animation,
92 | System.Drawing.Color PrimaryColor,
93 | System.Drawing.Color SecondaryColor,
94 | AuraAnimationSpeed AnimationSpeed
95 | ) : Message;
96 |
97 | public sealed record AuraFollowSystemAccentColorStateChangedMessage(
98 | bool Enabled
99 | ) : Message;
100 |
101 | public sealed record AniMeMatrixBrightnessChangedMessage(
102 | BrightnessLevel BrightnessLevel
103 | ) : Message;
104 |
105 | public sealed record AniMeMatrixBuiltInsChangedMessage(
106 | bool PreferPowerSavingAnimation,
107 | AnimeMatrixBuiltIn BuiltInConfiguration
108 | ) : Message;
109 |
110 | public sealed record SystemAccentColorChangedMessage(
111 | Color PrimaryAccentColor,
112 | Color SecondaryAccentColor,
113 | Color TertiaryAccentColor
114 | ) : Message;
115 | }
--------------------------------------------------------------------------------
/Slate/Model/Settings/Components/AniMeMatrixSettings.cs:
--------------------------------------------------------------------------------
1 | using Slate.Infrastructure.Settings;
2 | using Slate.Model.Messaging;
3 | using Starlight.Asus;
4 | using Starlight.Asus.AnimeMatrix;
5 |
6 | namespace Slate.Model.Settings.Components
7 | {
8 | public class AniMeMatrixSettings : SettingsComponent
9 | {
10 | public BrightnessLevel Brightness { get; set; } = BrightnessLevel.Bright;
11 |
12 | public bool PreferPowerSavingAnimation { get; set; } = true;
13 | public AnimeMatrixBuiltIn.Running RunningBuiltIn { get; set; } = AnimeMatrixBuiltIn.Running.RogLogoGlitch;
14 | public AnimeMatrixBuiltIn.Sleeping SleepingBuiltIn { get; set; } = AnimeMatrixBuiltIn.Sleeping.Starfield;
15 | public AnimeMatrixBuiltIn.Shutdown ShutdownBuiltIn { get; set; } = AnimeMatrixBuiltIn.Shutdown.GlitchOut;
16 | public AnimeMatrixBuiltIn.Startup StartupBuiltIn { get; set; } = AnimeMatrixBuiltIn.Startup.GlitchConstruction;
17 |
18 | protected override void OnSettingsModified(string? propertyName)
19 | {
20 | switch (propertyName)
21 | {
22 | case nameof(Brightness):
23 | {
24 | new AniMeMatrixBrightnessChangedMessage(Brightness)
25 | .Broadcast();
26 |
27 | break;
28 | }
29 |
30 | case nameof(PreferPowerSavingAnimation):
31 | case nameof(RunningBuiltIn) when PreferPowerSavingAnimation:
32 | case nameof(SleepingBuiltIn):
33 | case nameof(ShutdownBuiltIn):
34 | case nameof(StartupBuiltIn):
35 | {
36 | new AniMeMatrixBuiltInsChangedMessage(
37 | PreferPowerSavingAnimation,
38 | new AnimeMatrixBuiltIn(
39 | RunningBuiltIn,
40 | SleepingBuiltIn,
41 | ShutdownBuiltIn,
42 | StartupBuiltIn
43 | )
44 | ).Broadcast();
45 |
46 | break;
47 | }
48 | }
49 | }
50 | }
51 | }
--------------------------------------------------------------------------------
/Slate/Model/Settings/Components/ApplicationSettings.cs:
--------------------------------------------------------------------------------
1 | using Slate.Infrastructure.Settings;
2 | using Slate.Model.Messaging;
3 |
4 | namespace Slate.Model.Settings.Components
5 | {
6 | public class ApplicationSettings : SettingsComponent
7 | {
8 | public bool RunOnStartup { get; set; }
9 | public bool CheckForUpdates { get; set; }
10 |
11 | protected override void OnSettingsModified(string? propertyName)
12 | {
13 | switch (propertyName)
14 | {
15 | case nameof(RunOnStartup):
16 | {
17 | WithEventSuppressed(() =>
18 | {
19 | new StartupLaunchChangedMessage(RunOnStartup)
20 | .Broadcast();
21 | });
22 |
23 | break;
24 | }
25 | }
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/Slate/Model/Settings/Components/FansSettings.cs:
--------------------------------------------------------------------------------
1 | using Slate.Asus;
2 | using Slate.Infrastructure.Settings;
3 | using Slate.Model.Messaging;
4 |
5 | namespace Slate.Model.Settings.Components
6 | {
7 | public class FansSettings : SettingsComponent
8 | {
9 | public FanCurve? CpuFanCurve { get; set; }
10 | public FanCurve? GpuFanCurve { get; set; }
11 |
12 | public PerformancePreset PerformancePreset { get; set; } = PerformancePreset.Balanced;
13 | public bool IsManualOverrideEnabled { get; set; } = false;
14 | public byte ManualCpuFanDutyCycle { get; set; } = 64;
15 | public byte ManualGpuFanDutyCycle { get; set; } = 64;
16 |
17 | protected override void OnSettingsModified(string? propertyName)
18 | {
19 | switch (propertyName)
20 | {
21 | case nameof(PerformancePreset):
22 | {
23 | new PerformancePresetUpdatedMessage(PerformancePreset)
24 | .Broadcast();
25 |
26 | break;
27 | }
28 |
29 | case nameof(CpuFanCurve):
30 | {
31 | new CpuFanCurveUpdatedMessage(CpuFanCurve!)
32 | .Broadcast();
33 |
34 | break;
35 | }
36 |
37 | case nameof(GpuFanCurve):
38 | {
39 | new GpuFanCurveUpdatedMessage(GpuFanCurve!)
40 | .Broadcast();
41 |
42 | break;
43 | }
44 |
45 | case nameof(IsManualOverrideEnabled):
46 | case nameof(ManualCpuFanDutyCycle) when IsManualOverrideEnabled:
47 | case nameof(ManualGpuFanDutyCycle) when IsManualOverrideEnabled:
48 | {
49 | new ManualFanOverrideUpdatedMessage(
50 | IsManualOverrideEnabled,
51 | ManualCpuFanDutyCycle,
52 | ManualGpuFanDutyCycle
53 | ).Broadcast();
54 |
55 | break;
56 | }
57 | }
58 | }
59 | }
60 | }
--------------------------------------------------------------------------------
/Slate/Model/Settings/Components/GraphicsAndDisplaySettings.cs:
--------------------------------------------------------------------------------
1 | using Slate.Asus;
2 | using Slate.Infrastructure;
3 | using Slate.Infrastructure.Settings;
4 | using Slate.Model.Messaging;
5 |
6 | namespace Slate.Model.Settings.Components
7 | {
8 | public class GraphicsAndDisplaySettings : SettingsComponent
9 | {
10 | public bool? IsEcoModeEnabled { get; set; }
11 | public bool? IsDisplayOverdriveEnabled { get; set; }
12 | public uint DisplayRefreshRate { get; set; } = 144;
13 |
14 | public MuxSwitchMode? MuxSwitchMode { get; set; }
15 |
16 | protected override void OnSettingsModified(string? propertyName)
17 | {
18 | switch (propertyName)
19 | {
20 | case nameof(IsEcoModeEnabled):
21 | {
22 | new EcoModeChangedMessage(
23 | IsEcoModeEnabled!.Value
24 | ).Broadcast();
25 |
26 | break;
27 | }
28 |
29 | case nameof(IsDisplayOverdriveEnabled):
30 | {
31 | new DisplayOverdriveChangedMessage(
32 | IsDisplayOverdriveEnabled!.Value
33 | ).Broadcast();
34 |
35 | break;
36 | }
37 |
38 | case nameof(DisplayRefreshRate):
39 | {
40 | new DisplayRefreshRateChangedMessage(
41 | DisplayRefreshRate
42 | ).Broadcast();
43 |
44 | break;
45 | }
46 |
47 | case nameof(MuxSwitchMode):
48 | {
49 | new MuxSwitchModeChangedMessage(
50 | MuxSwitchMode!.Value
51 | ).Broadcast();
52 |
53 | break;
54 | }
55 | }
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/Slate/Model/Settings/Components/KeyboardSettings.cs:
--------------------------------------------------------------------------------
1 | using System.Drawing;
2 | using Slate.Infrastructure.Settings;
3 | using Slate.Model.Messaging;
4 | using Starlight.Asus.Aura;
5 |
6 | namespace Slate.Model.Settings.Components
7 | {
8 | public class KeyboardSettings : SettingsComponent
9 | {
10 | public bool FollowSystemAccentColor { get; set; } = false;
11 |
12 | public AuraAnimation Animation { get; set; } = AuraAnimation.Static;
13 | public ColorWrapper PrimaryColor { get; set; } = new(Color.White);
14 | public ColorWrapper SecondaryColor { get; set; } = new(Color.White);
15 | public AuraAnimationSpeed AnimationSpeed { get; set; } = AuraAnimationSpeed.Medium;
16 |
17 | public KeyBind BindM3 { get; set; } = new(KeyBindMode.Default);
18 | public KeyBind BindM4 { get; set; } = new(KeyBindMode.Default);
19 | public KeyBind BindF4 { get; set; } = new(KeyBindMode.Default);
20 | public KeyBind BindF5 { get; set; } = new(KeyBindMode.Default);
21 |
22 | protected override void OnSettingsModified(string? propertyName)
23 | {
24 | switch (propertyName)
25 | {
26 | case nameof(Animation):
27 | case nameof(PrimaryColor):
28 | case nameof(SecondaryColor):
29 | case nameof(AnimationSpeed):
30 | {
31 | new AuraSettingsChangedMessage(
32 | Animation,
33 | PrimaryColor.HardwareColor,
34 | SecondaryColor.HardwareColor,
35 | AnimationSpeed
36 | ).Broadcast();
37 |
38 | break;
39 | }
40 |
41 | case nameof(FollowSystemAccentColor):
42 | {
43 | new AuraFollowSystemAccentColorStateChangedMessage(
44 | FollowSystemAccentColor
45 | ).Broadcast();
46 |
47 | break;
48 | }
49 | }
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/Slate/Model/Settings/Components/PowerManagementSettings.cs:
--------------------------------------------------------------------------------
1 | using Slate.Infrastructure.Settings;
2 | using Slate.Model.Messaging;
3 |
4 | namespace Slate.Model.Settings.Components
5 | {
6 | public class PowerManagementSettings : SettingsComponent
7 | {
8 | public bool IsProcessorBoostActiveOnAC { get; set; } = true;
9 | public bool IsProcessorBoostActiveOnDC { get; set; } = false;
10 |
11 | public int BatteryChargeLimit { get; set; } = 85; /* percent of course */
12 | public byte TotalSystemPPT { get; set; } = 90;
13 | public byte ProcessorPPT { get; set; } = 60;
14 |
15 | protected override void OnSettingsModified(string? propertyName)
16 | {
17 | switch (propertyName)
18 | {
19 | case nameof(IsProcessorBoostActiveOnAC):
20 | case nameof(IsProcessorBoostActiveOnDC):
21 | {
22 | new CpuBoostModeChangedMessage(
23 | IsProcessorBoostActiveOnAC,
24 | IsProcessorBoostActiveOnDC
25 | ).Broadcast();
26 |
27 | break;
28 | }
29 |
30 | case nameof(BatteryChargeLimit):
31 | {
32 | new BatteryChargeLimitChangedMessage(
33 | BatteryChargeLimit
34 | ).Broadcast();
35 |
36 | break;
37 | }
38 |
39 | case nameof(TotalSystemPPT):
40 | case nameof(ProcessorPPT):
41 | {
42 | WithEventSuppressed(() =>
43 | {
44 | if (ProcessorPPT > TotalSystemPPT)
45 | ProcessorPPT = TotalSystemPPT;
46 | });
47 |
48 | new PowerTargetsChangedMessage(
49 | TotalSystemPPT,
50 | ProcessorPPT
51 | ).Broadcast();
52 |
53 | break;
54 | }
55 | }
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/Slate/Model/Settings/ControlCenterSettings.cs:
--------------------------------------------------------------------------------
1 | using Slate.Infrastructure.Settings;
2 | using Slate.Model.Settings.Components;
3 |
4 | namespace Slate.Model.Settings
5 | {
6 | public class ControlCenterSettings : SettingsBase
7 | {
8 | public ApplicationSettings Application { get; set; } = new();
9 | public FansSettings Fans { get; set; } = new();
10 | public GraphicsAndDisplaySettings GraphicsAndDisplay { get; set; } = new();
11 | public PowerManagementSettings PowerManagement { get; set; } = new();
12 | public KeyboardSettings Keyboard { get; set; } = new();
13 | public AniMeMatrixSettings AniMeMatrix { get; set; } = new();
14 | }
15 | }
--------------------------------------------------------------------------------
/Slate/Program.cs:
--------------------------------------------------------------------------------
1 | using Avalonia;
2 | using System;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Runtime.InteropServices;
6 | using Glitonea.Mvvm.Messaging;
7 | using Slate.Infrastructure.Native;
8 | using Slate.Model.Messaging;
9 |
10 | #if ACPITESTING
11 | using System.Diagnostics;
12 | using Slate.Infrastructure.Asus.Acpi;
13 | #endif
14 |
15 | namespace Slate
16 | {
17 | internal class Program
18 | {
19 | [STAThread]
20 | public static void Main(string[] args)
21 | {
22 | #if ACPITESTING
23 | var proxy = new AsusAcpiProxy();
24 |
25 | var names = Enum.GetNames(typeof(DstsMethod));
26 |
27 | using (var sw = new StreamWriter("acpivars.txt"))
28 | {
29 | foreach (var name in names)
30 | {
31 | try
32 | {
33 | sw.WriteLine(
34 | $"{name}: {proxy.DSTS.ReadInt32((DstsMethod)Enum.Parse(typeof(DstsMethod), name)):X8}"
35 | );
36 | }
37 | catch
38 | {
39 | // ignore
40 | }
41 | }
42 | }
43 |
44 | Debugger.Break();
45 | #else
46 | // var hook = User32.SetWindowsHookEx(User32.WH_KEYBOARD_LL, KeyboardProc, 0, 0);
47 |
48 | var app = BuildAvaloniaApp()
49 | .StartWithClassicDesktopLifetime(args);
50 | #endif
51 | }
52 | //
53 | // private static nint KeyboardProc(int nCode, nint wParam, nint lParam)
54 | // {
55 | // var str = Marshal.PtrToStructure(lParam);
56 | //
57 | // if (wParam == User32.WM_KEYDOWN || wParam == User32.WM_SYSKEYDOWN || wParam == User32.WM_KEYUP || wParam == User32.WM_SYSKEYUP)
58 | // {
59 | // Debug.WriteLine($"{nCode:X8} : {str.vkCode}");
60 | // }
61 | //
62 | // return User32.CallNextHookEx(0, nCode, wParam, lParam);
63 | // }
64 |
65 | public static AppBuilder BuildAvaloniaApp()
66 | => AppBuilder
67 | .Configure()
68 | .UsePlatformDetect()
69 | .With(new Win32PlatformOptions
70 | {
71 | UseWindowsUIComposition = true
72 | })
73 | .LogToTrace()
74 | .AfterSetup((_) => Message.Broadcast());
75 | }
76 | }
--------------------------------------------------------------------------------
/Slate/Resources/Animations/power_saving_1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vddCore/Zephyrus-Control-Center/176f305e44f0f893e95e2d7f8e98f3be0f924c67/Slate/Resources/Animations/power_saving_1.gif
--------------------------------------------------------------------------------
/Slate/Resources/Animations/power_saving_2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vddCore/Zephyrus-Control-Center/176f305e44f0f893e95e2d7f8e98f3be0f924c67/Slate/Resources/Animations/power_saving_2.gif
--------------------------------------------------------------------------------
/Slate/Resources/Animations/shutdown_1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vddCore/Zephyrus-Control-Center/176f305e44f0f893e95e2d7f8e98f3be0f924c67/Slate/Resources/Animations/shutdown_1.gif
--------------------------------------------------------------------------------
/Slate/Resources/Animations/shutdown_2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vddCore/Zephyrus-Control-Center/176f305e44f0f893e95e2d7f8e98f3be0f924c67/Slate/Resources/Animations/shutdown_2.gif
--------------------------------------------------------------------------------
/Slate/Resources/Animations/sleep_1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vddCore/Zephyrus-Control-Center/176f305e44f0f893e95e2d7f8e98f3be0f924c67/Slate/Resources/Animations/sleep_1.gif
--------------------------------------------------------------------------------
/Slate/Resources/Animations/sleep_2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vddCore/Zephyrus-Control-Center/176f305e44f0f893e95e2d7f8e98f3be0f924c67/Slate/Resources/Animations/sleep_2.gif
--------------------------------------------------------------------------------
/Slate/Resources/Animations/start_1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vddCore/Zephyrus-Control-Center/176f305e44f0f893e95e2d7f8e98f3be0f924c67/Slate/Resources/Animations/start_1.gif
--------------------------------------------------------------------------------
/Slate/Resources/Animations/start_2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vddCore/Zephyrus-Control-Center/176f305e44f0f893e95e2d7f8e98f3be0f924c67/Slate/Resources/Animations/start_2.gif
--------------------------------------------------------------------------------
/Slate/Resources/Fonts/fa5_brands.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vddCore/Zephyrus-Control-Center/176f305e44f0f893e95e2d7f8e98f3be0f924c67/Slate/Resources/Fonts/fa5_brands.otf
--------------------------------------------------------------------------------
/Slate/Resources/Fonts/segoe_fluent.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vddCore/Zephyrus-Control-Center/176f305e44f0f893e95e2d7f8e98f3be0f924c67/Slate/Resources/Fonts/segoe_fluent.ttf
--------------------------------------------------------------------------------
/Slate/Resources/Icons/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vddCore/Zephyrus-Control-Center/176f305e44f0f893e95e2d7f8e98f3be0f924c67/Slate/Resources/Icons/icon.ico
--------------------------------------------------------------------------------
/Slate/Resources/Paths/AuraIcon.axaml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
13 |
14 |
15 |
16 |
17 |
18 |
20 |
21 |
22 |
23 |
24 |
25 |
27 |
28 |
29 |
30 |
31 |
32 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Slate/Resources/Paths/FanIcon.axaml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
12 |
13 |
14 |
15 |
16 |
17 |
19 |
20 |
21 |
22 |
23 |
24 |
26 |
27 |
28 |
29 |
30 |
31 |
33 |
34 |
35 |
36 |
37 |
38 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/Slate/Resources/Paths/MicrophoneIcon.axaml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
13 |
14 |
17 |
18 |
21 |
22 |
25 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Slate/Resources/Paths/RogLogo.axaml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Slate/Resources/Styles/BrightnessSelector.axaml:
--------------------------------------------------------------------------------
1 |
5 |
8 |
9 |
12 |
13 |
16 |
17 |
20 |
21 |
24 |
25 |
28 |
--------------------------------------------------------------------------------
/Slate/Resources/Styles/Card.axaml:
--------------------------------------------------------------------------------
1 |
5 |
31 |
--------------------------------------------------------------------------------
/Slate/Resources/Styles/LinkIcon.axaml:
--------------------------------------------------------------------------------
1 |
3 |
18 |
19 |
22 |
23 |
26 |
--------------------------------------------------------------------------------
/Slate/Resources/Styles/Transitions.axaml:
--------------------------------------------------------------------------------
1 |
4 |
13 |
14 |
23 |
--------------------------------------------------------------------------------
/Slate/View/Control/Icons/FAIcon.axaml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/Slate/View/Control/Icons/FAIcon.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia;
2 | using Avalonia.Controls;
3 | using PropertyChanged;
4 |
5 | namespace Slate.View.Control.Icons
6 | {
7 | [DoNotNotify]
8 | public partial class FAIcon : UserControl
9 | {
10 | public static readonly StyledProperty GlyphProperty
11 | = AvaloniaProperty.Register(nameof(Glyph));
12 |
13 | public char Glyph
14 | {
15 | get => GetValue(GlyphProperty);
16 | set => SetValue(GlyphProperty, value);
17 | }
18 |
19 | public FAIcon()
20 | {
21 | InitializeComponent();
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/Slate/View/Control/Icons/SFIcon.axaml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/Slate/View/Control/Icons/SFIcon.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia;
2 | using Avalonia.Controls;
3 | using PropertyChanged;
4 |
5 | namespace Slate.View.Control.Icons
6 | {
7 | [DoNotNotify]
8 | public partial class SFIcon : UserControl
9 | {
10 | public static readonly StyledProperty GlyphProperty
11 | = AvaloniaProperty.Register(nameof(Glyph));
12 |
13 | public char Glyph
14 | {
15 | get => GetValue(GlyphProperty);
16 | set => SetValue(GlyphProperty, value);
17 | }
18 |
19 | public SFIcon()
20 | {
21 | InitializeComponent();
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/Slate/View/Control/PageElements/AuraColorControl.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using PropertyChanged;
3 |
4 | namespace Slate.View.Control.PageElements
5 | {
6 | [DoNotNotify]
7 | public partial class AuraColorControl : UserControl
8 | {
9 | public AuraColorControl()
10 | {
11 | InitializeComponent();
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/Slate/View/Control/PageElements/SettingsPalette.axaml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
16 |
17 |
18 |
19 |
20 |
21 |
23 |
24 |
25 |
26 |
29 |
30 |
31 |
32 |
33 |
34 |
37 |
38 |
39 |
40 |
41 |
42 |
45 |
46 |
47 |
48 |
49 |
50 |
53 |
54 |
55 |
56 |
57 |
58 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/Slate/View/Control/PageElements/SettingsPalette.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Controls;
2 | using PropertyChanged;
3 |
4 | namespace Slate.View.Control.PageElements
5 | {
6 | [DoNotNotify]
7 | public partial class SettingsPalette : UserControl
8 | {
9 | public SettingsPalette()
10 | {
11 | InitializeComponent();
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/Slate/View/Control/Primitives/BrightnessSelector.axaml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
14 |
15 |
22 |
23 |
30 |
31 |
37 |
38 |
--------------------------------------------------------------------------------
/Slate/View/Control/Primitives/BrightnessSelector.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia;
2 | using Avalonia.Controls;
3 | using Avalonia.Interactivity;
4 | using PropertyChanged;
5 | using Starlight.Asus;
6 |
7 | namespace Slate.View.Control.Primitives
8 | {
9 | [DoNotNotify]
10 | public partial class BrightnessSelector : UserControl
11 | {
12 | public static readonly StyledProperty BrightnessLevelProperty
13 | = AvaloniaProperty.Register(nameof(BrightnessLevel));
14 |
15 | public BrightnessLevel BrightnessLevel
16 | {
17 | get => GetValue(BrightnessLevelProperty);
18 | set => SetValue(BrightnessLevelProperty, value);
19 | }
20 |
21 | public BrightnessSelector()
22 | {
23 | InitializeComponent();
24 | }
25 |
26 | protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
27 | {
28 | UpdateButtonStates(BrightnessLevel);
29 |
30 | base.OnAttachedToVisualTree(e);
31 | }
32 |
33 | protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
34 | {
35 | if (change.Property == BrightnessLevelProperty)
36 | {
37 | UpdateButtonStates(BrightnessLevel);
38 | }
39 |
40 | base.OnPropertyChanged(change);
41 | }
42 |
43 | private void UpdateButtonStates(BrightnessLevel level)
44 | {
45 | OffButton.IsChecked = level == BrightnessLevel.Off;
46 | DimButton.IsChecked = level == BrightnessLevel.Dim;
47 | MediumButton.IsChecked = level == BrightnessLevel.Medium;
48 | BrightButton.IsChecked = level == BrightnessLevel.Bright;
49 | }
50 |
51 | private void OffButton_Click(object? sender, RoutedEventArgs e)
52 | => BrightnessLevel = BrightnessLevel.Off;
53 |
54 | private void DimButton_Click(object? sender, RoutedEventArgs e)
55 | => BrightnessLevel = BrightnessLevel.Dim;
56 |
57 | private void MediumButton_Click(object? sender, RoutedEventArgs e)
58 | => BrightnessLevel = BrightnessLevel.Medium;
59 |
60 | private void BrightButton_Click(object? sender, RoutedEventArgs e)
61 | => BrightnessLevel = BrightnessLevel.Bright;
62 | }
63 | }
--------------------------------------------------------------------------------
/Slate/View/Control/Primitives/Card.axaml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Slate/View/Control/Primitives/Card.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia;
2 | using Avalonia.Controls;
3 | using PropertyChanged;
4 |
5 | namespace Slate.View.Control.Primitives
6 | {
7 | [DoNotNotify]
8 | public partial class Card : UserControl
9 | {
10 | public static readonly StyledProperty