diff --git a/CommonHelpers/GlobalConfig.cs b/CommonHelpers/GlobalConfig.cs index cef3348..960ab61 100644 --- a/CommonHelpers/GlobalConfig.cs +++ b/CommonHelpers/GlobalConfig.cs @@ -21,4 +21,23 @@ namespace CommonHelpers Detail, Full } + + public enum OverlayEnabled : uint + { + Yes = 378313, + No + } + + [StructLayout(LayoutKind.Sequential)] + public struct FanModeSetting + { + public FanMode Current, Desired; + } + + [StructLayout(LayoutKind.Sequential)] + public struct OverlayModeSetting + { + public OverlayMode Current, Desired; + public OverlayEnabled CurrentEnabled, DesiredEnabled; + } } diff --git a/CommonHelpers/SharedData.cs b/CommonHelpers/SharedData.cs new file mode 100644 index 0000000..3de8b88 --- /dev/null +++ b/CommonHelpers/SharedData.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using System.IO.MemoryMappedFiles; +using System.Linq; +using System.Runtime.InteropServices; +using System.Runtime.Serialization.Formatters.Binary; +using System.Text; +using System.Threading.Tasks; + +namespace CommonHelpers +{ + public class SharedData : IDisposable where T : unmanaged + { + const int MMF_MAX_SIZE = 256; + + private MemoryMappedFile mmf; + + private SharedData() + { } + + public T NewValue() + { + return default(T); + } + + public bool GetValue(out T value) + { + using (MemoryMappedViewStream mmvStream = mmf.CreateViewStream()) + { + value = default(T); + + if (!mmvStream.CanRead) + return false; + + byte[] buffer = new byte[MMF_MAX_SIZE]; + mmvStream.Read(buffer, 0, buffer.Length); + + var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); + try + { + var output = Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); + if (output is null) + return false; + + value = (T)output; + return true; + } + catch + { + return false; + } + finally + { + handle.Free(); + } + } + } + + public bool SetValue(T value) + { + using (MemoryMappedViewStream mmvStream = mmf.CreateViewStream()) + { + if (!mmvStream.CanWrite) + return false; + + byte[] buffer = new byte[MMF_MAX_SIZE]; + var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); + try + { + Marshal.StructureToPtr(value, handle.AddrOfPinnedObject(), false); + } + catch + { + return false; + } + finally + { + handle.Free(); + } + + mmvStream.Write(buffer, 0, buffer.Length); + return true; + } + } + + public static bool GetExistingValue(out T value) + { + try + { + using (var shared = OpenExisting()) + { + if (shared.GetValue(out value)) + return true; + } + } + catch + { + value = default(T); + } + return false; + } + + public static bool SetExistingValue(T value) + { + try + { + using (var shared = OpenExisting()) + { + if (shared.SetValue(value)) + return true; + } + } + catch + { + } + return false; + } + + public void Dispose() + { + mmf.Dispose(); + } + + public static String GetUniqueName() + { + return String.Format("Global_{0}_Setting", typeof(T).Name); + } + + public static SharedData CreateNew(String? name = null) + { + return new SharedData() + { + mmf = MemoryMappedFile.CreateOrOpen(name ?? GetUniqueName(), MMF_MAX_SIZE) + }; + } + + public static SharedData OpenExisting(String? name = null) + { + return new SharedData() + { + mmf = MemoryMappedFile.OpenExisting(name ?? GetUniqueName()) + }; + } + } +} diff --git a/FanControl/FanControlForm.cs b/FanControl/FanControlForm.cs index afb87b5..cfd789c 100644 --- a/FanControl/FanControlForm.cs +++ b/FanControl/FanControlForm.cs @@ -1,4 +1,4 @@ -using CommonHelpers; +using CommonHelpers; using CommonHelpers.FromLibreHardwareMonitor; using FanControl.Properties; using System; @@ -24,6 +24,8 @@ namespace FanControl "Starts Steam Deck Fan Control on Windows startup." ); + private SharedData sharedData = SharedData.CreateNew(); + public FanControlForm() { InitializeComponent(); @@ -122,8 +124,19 @@ namespace FanControl fanControl.SetMode(FanMode.Default); } + private void SharedData_Update() + { + if (sharedData.GetValue(out var value) && Enum.IsDefined(value.Desired)) + { + setFanMode((FanMode)value.Desired); + } + + sharedData.SetValue(new FanModeSetting() { Current = fanControl.Mode }); + } + private void fanLoopTimer_Tick(object sender, EventArgs e) { + SharedData_Update(); fanControl.Update(); } diff --git a/PerformanceOverlay/Controller.cs b/PerformanceOverlay/Controller.cs index df7d939..f7562d3 100644 --- a/PerformanceOverlay/Controller.cs +++ b/PerformanceOverlay/Controller.cs @@ -1,4 +1,4 @@ -using CommonHelpers; +using CommonHelpers; using CommonHelpers.FromLibreHardwareMonitor; using Microsoft.VisualBasic.Logging; using PerformanceOverlay.External; @@ -32,6 +32,8 @@ namespace PerformanceOverlay "Starts Performance Overlay on Windows startup." ); + SharedData sharedData = SharedData.CreateNew(); + public Controller() { contextMenu = new System.Windows.Forms.ContextMenuStrip(components); @@ -142,8 +144,37 @@ namespace PerformanceOverlay updateContextItems(contextMenu); } + private void SharedData_Update() + { + if (sharedData.GetValue(out var value)) + { + if (Enum.IsDefined(value.Desired)) + { + Settings.Default.OSDModeParsed = (OverlayMode)value.Desired; + Settings.Default.ShowOSD = true; + Settings.Default.Save(); + updateContextItems(contextMenu); + } + + if (Enum.IsDefined(value.DesiredEnabled)) + { + Settings.Default.ShowOSD = (OverlayEnabled)value.DesiredEnabled == OverlayEnabled.Yes; + Settings.Default.Save(); + updateContextItems(contextMenu); + } + } + + sharedData.SetValue(new OverlayModeSetting() + { + Current = Settings.Default.OSDModeParsed, + CurrentEnabled = Settings.Default.ShowOSD ? OverlayEnabled.Yes : OverlayEnabled.No + }); + } + private void OsdTimer_Tick(object? sender, EventArgs e) { + SharedData_Update(); + try { notifyIcon.Text = TitleWithVersion + ". RTSS Version: " + OSD.Version; diff --git a/PowerControl/MenuStack.cs b/PowerControl/MenuStack.cs index 7273b4b..83b6fdb 100644 --- a/PowerControl/MenuStack.cs +++ b/PowerControl/MenuStack.cs @@ -1,4 +1,5 @@ -using System; +using CommonHelpers; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -101,6 +102,79 @@ namespace PowerControl Options = { "Auto", 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600 }, ApplyDelay = 1000, Visible = false + }, + new Menu.MenuItemSeparator(), + new Menu.MenuItemWithOptions() + { + Name = "OSD", + ApplyDelay = 500, + OptionsValues = delegate() + { + return Enum.GetValues().Select(item => (object)item).ToArray(); + }, + CurrentValue = delegate() + { + if (SharedData.GetExistingValue(out var value)) + return value.CurrentEnabled; + return null; + }, + ApplyValue = delegate(object selected) + { + if (!SharedData.GetExistingValue(out var value)) + return null; + value.DesiredEnabled = (OverlayEnabled)selected; + if (!SharedData.SetExistingValue(value)) + return null; + return selected; + } + }, + new Menu.MenuItemWithOptions() + { + Name = "OSD Mode", + ApplyDelay = 500, + OptionsValues = delegate() + { + return Enum.GetValues().Select(item => (object)item).ToArray(); + }, + CurrentValue = delegate() + { + if (SharedData.GetExistingValue(out var value)) + return value.Current; + return null; + }, + ApplyValue = delegate(object selected) + { + if (!SharedData.GetExistingValue(out var value)) + return null; + value.Desired = (OverlayMode)selected; + if (!SharedData.SetExistingValue(value)) + return null; + return selected; + } + }, + new Menu.MenuItemWithOptions() + { + Name = "FAN", + ApplyDelay = 500, + OptionsValues = delegate() + { + return Enum.GetValues().Select(item => (object)item).ToArray(); + }, + CurrentValue = delegate() + { + if (SharedData.GetExistingValue(out var value)) + return value.Current; + return null; + }, + ApplyValue = delegate(object selected) + { + if (!SharedData.GetExistingValue(out var value)) + return null; + value.Desired = (FanMode)selected; + if (!SharedData.SetExistingValue(value)) + return null; + return selected; + } } } };