diff --git a/CommonHelpers/RTSS.cs b/CommonHelpers/RTSS.cs index a5f27a4..d133723 100644 --- a/CommonHelpers/RTSS.cs +++ b/CommonHelpers/RTSS.cs @@ -7,11 +7,18 @@ namespace CommonHelpers { public static bool IsOSDForeground() { - return IsOSDForeground(out _); + return IsOSDForeground(out _, out _); } public static bool IsOSDForeground(out int processId) { + return IsOSDForeground(out processId, out _); + } + + public static bool IsOSDForeground(out int processId, out string? applicationName) + { + applicationName = null; + try { var id = GetTopLevelProcessId(); @@ -22,7 +29,10 @@ namespace CommonHelpers foreach (var app in OSD.GetAppEntries(AppFlags.MASK)) { if (app.ProcessId == processId) + { + applicationName = ExtractAppName(app.Name); return true; + } } return false; @@ -76,6 +86,13 @@ namespace CommonHelpers } } + public static List GetCurrentApps() + { + var apps = OSD.GetAppEntries(AppFlags.MASK).Select(e => ExtractAppName(e.Name)).ToList(); + + return apps; + } + public static uint EnableFlag(uint flag, bool status) { var current = SetFlags(~flag, status ? flag : 0); @@ -125,6 +142,18 @@ namespace CommonHelpers [DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow(); + private static string ExtractAppName(string fullName) + { + string res = fullName.Split('\\').Last(); + + if (res.ToLower().Contains(".exe")) + { + return res[..^4]; + } + + return res; + } + private static uint? GetTopLevelProcessId() { var hWnd = GetForegroundWindow(); diff --git a/PowerControl/Controller.cs b/PowerControl/Controller.cs index 5e17a24..acd9ccb 100644 --- a/PowerControl/Controller.cs +++ b/PowerControl/Controller.cs @@ -33,6 +33,8 @@ namespace PowerControl DateTime? neptuneDeviceNextKey; System.Windows.Forms.Timer neptuneTimer; + ProfilesController profilesController; + SharedData sharedData = SharedData.CreateNew(); static Controller() @@ -110,6 +112,9 @@ namespace PowerControl osdTimer.Interval = 250; osdTimer.Enabled = true; + profilesController = new ProfilesController(); + profilesController.Initialize(); + GlobalHotKey.RegisterHotKey(Settings.Default.MenuUpKey, () => { if (!RTSS.IsOSDForeground()) @@ -409,6 +414,9 @@ namespace PowerControl System.Windows.Threading.Dispatcher.CurrentDispatcher.BeginInvoke( new Action(() => { + Options.RefreshRate.Instance?.Reset(); + Options.FPSLimit.Instance?.Reset(); + rootMenu.Update(); }) ); diff --git a/PowerControl/Helpers/ProfileSettings.cs b/PowerControl/Helpers/ProfileSettings.cs new file mode 100644 index 0000000..a064058 --- /dev/null +++ b/PowerControl/Helpers/ProfileSettings.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; +using CommonHelpers; + +namespace PowerControl.Helper +{ + public class ProfileSettings : BaseSettings + { + private static string profilesPath = Path.Combine(Directory.GetCurrentDirectory(), "Profiles"); + + static ProfileSettings() + { + Directory.CreateDirectory(profilesPath); + } + + public ProfileSettings(string profileName) : base("Profile") + { + this.TouchSettings = true; + this.ConfigFile = Path.Combine(profilesPath, profileName + ".ini"); + + this.SettingChanging += delegate { }; + this.SettingChanged += delegate { }; + } + + public T Get(string key, T defaultValue) + { + return base.Get(key, defaultValue); + } + + public new bool Set(string key, T value) + { + return base.Set(key, value); + } + + public static bool CheckIfExists(string profileName) + { + foreach (FileInfo fi in Directory.CreateDirectory(profilesPath).GetFiles()) + { + if (fi.Name[^4..].Equals(".ini") && fi.Name[..^4].Equals(profileName)) + { + return true; + } + } + + return false; + } + } +} diff --git a/PowerControl/Helpers/ProfilesController.cs b/PowerControl/Helpers/ProfilesController.cs new file mode 100644 index 0000000..1231052 --- /dev/null +++ b/PowerControl/Helpers/ProfilesController.cs @@ -0,0 +1,137 @@ +using CommonHelpers; +using PowerControl.Helper; +using PowerControl.Menu; + +namespace PowerControl.Helpers +{ + public class ProfilesController + { + private const string IsTroubledKey = "IsTroubled"; + private const string DefaultName = "Default"; + + private string CurrentGame = string.Empty; + private ProfileSettings DefaultSettings = new ProfileSettings(DefaultName); + private ProfileSettings? CurrentSettings; + private static string[] troubledGames = { "dragonageinquisition" }; + + private System.Windows.Forms.Timer? timer; + + public ProfilesController() + { + timer = new System.Windows.Forms.Timer(); + } + + public void Initialize() + { + MenuStack.Root.ValueChanged += OnOptionValueChange; + + timer.Interval = 1000; + timer.Tick += (_, _) => + { + timer.Stop(); + + RefreshProfiles(); + + timer.Start(); + }; + timer.Start(); + } + + private void RefreshProfiles() + { + if (!DeviceManager.IsDeckOnlyDisplay()) + { + CurrentGame = string.Empty; + return; + } + + string? gameName; + + RTSS.IsOSDForeground(out _, out gameName); + + // If there's no foreground games keep current profile if possible + if (gameName == null && RTSS.GetCurrentApps().Contains(CurrentGame)) + { + gameName = CurrentGame; + } + + if (gameName == null && CurrentGame != DefaultName) + { + CurrentGame = DefaultName; + CurrentSettings = null; + + ApplyProfile(); + } + + if (gameName != null && CurrentGame != gameName) + { + CurrentGame = gameName; + CurrentSettings = ProfileSettings.CheckIfExists(CurrentGame) ? + new ProfileSettings(CurrentGame) : null; + + ApplyProfile(); + } + } + + private void ApplyProfile() + { + int delay = GetBoolValue(IsTroubledKey) ? 5200 : 0; + var options = MenuStack.Root.Items.Where(o => o is MenuItemWithOptions).Select(o => (MenuItemWithOptions)o).ToList(); + + foreach (var option in options) + { + string? key = option.PersistentKey; + + if (key != null) + { + option.Set(GetValue(option), delay, true); + } + } + } + + private void OnOptionValueChange(MenuItemWithOptions options, string? oldValue, string newValue) + { + string? key = options.PersistentKey; + + if (key != null) + { + SetValue(key, newValue); + } + } + + private void SetBoolValue(string key, bool value) + { + var settings = CurrentSettings ?? DefaultSettings; + + settings.Set(key, value); + } + + private bool GetBoolValue(string key) + { + var settings = CurrentSettings ?? DefaultSettings; + + return settings.Get(key, false); + } + + private void SetValue(string key, string value) + { + var settings = CurrentSettings ?? DefaultSettings; + settings.Set(key, value); + } + + private string GetValue(MenuItemWithOptions option) + { + if (CurrentSettings == null) + { + return GetDefaultValue(option); + } + + return CurrentSettings.Get(option.PersistentKey, GetDefaultValue(option)); + } + + private string GetDefaultValue(MenuItemWithOptions option) + { + return DefaultSettings.Get(option.PersistentKey, option.ResetValue?.Invoke() ?? string.Empty); + } + } +} diff --git a/PowerControl/Menu/MenuItemWithOptions.cs b/PowerControl/Menu/MenuItemWithOptions.cs index 52f886e..a25c34a 100644 --- a/PowerControl/Menu/MenuItemWithOptions.cs +++ b/PowerControl/Menu/MenuItemWithOptions.cs @@ -7,10 +7,12 @@ namespace PowerControl.Menu public string? ActiveOption { get; set; } public int ApplyDelay { get; set; } public bool CycleOptions { get; set; } = true; + public string? PersistentKey; public Func? CurrentValue { get; set; } public Func? OptionsValues { get; set; } public Func? ApplyValue { get; set; } + public Action? AfterApply { get; set; } public Func? ResetValue { get; set; } public event Action ValueChanged; @@ -29,7 +31,7 @@ namespace PowerControl.Menu if (delayTimer != null) delayTimer.Stop(); - FinalizeSet(); + FinalizeSet(delayTimer.Interval > ApplyDelay); }; } @@ -42,7 +44,7 @@ namespace PowerControl.Menu if (resetOption == null || resetOption == ActiveOption) return; - Set(resetOption, true); + Set(resetOption, 0); } public override void Update() @@ -74,35 +76,40 @@ namespace PowerControl.Menu ActiveOption = Options.First(); } - public void Set(String value, bool immediately = false) + public void Set(String value, int overrideDelay = -1, bool silent = false) { if (delayTimer != null) delayTimer.Stop(); SelectedOption = value; - if (ApplyDelay == 0 || immediately) + if (ApplyDelay == 0 || overrideDelay == 0) { - FinalizeSet(); + FinalizeSet(silent); return; } - delayTimer.Interval = ApplyDelay > 0 ? ApplyDelay : 1; + delayTimer.Interval = overrideDelay > 0 ? overrideDelay : ApplyDelay > 0 ? ApplyDelay : 1; delayTimer.Enabled = true; } - private void FinalizeSet() + private void FinalizeSet(bool silent = false) { var wasOption = ActiveOption; if (ApplyValue != null && SelectedOption != null) + { ActiveOption = ApplyValue(SelectedOption); + + if (AfterApply != null && !silent) + AfterApply(); + } else ActiveOption = SelectedOption; SelectedOption = null; - if (wasOption != ActiveOption && ActiveOption != null) + if (wasOption != ActiveOption && ActiveOption != null && !silent) ValueChanged(this, wasOption, ActiveOption); } @@ -120,7 +127,7 @@ namespace PowerControl.Menu { var item = new ToolStripMenuItem(option); item.Checked = option == (SelectedOption ?? ActiveOption); - item.Click += delegate { Set(option, true); }; + item.Click += delegate { Set(option, 0); }; toolStripItem.DropDownItems.Add(item); } @@ -133,7 +140,7 @@ namespace PowerControl.Menu if (Options.Count == 0) return; - Set(Options[Math.Clamp(index, 0, Options.Count - 1)], false); + Set(Options[Math.Clamp(index, 0, Options.Count - 1)]); } public override void SelectNext(int change) diff --git a/PowerControl/Options/FPSLimit.cs b/PowerControl/Options/FPSLimit.cs index 7b2c1d5..67de4ef 100644 --- a/PowerControl/Options/FPSLimit.cs +++ b/PowerControl/Options/FPSLimit.cs @@ -8,6 +8,7 @@ namespace PowerControl.Options public static Menu.MenuItemWithOptions Instance = new Menu.MenuItemWithOptions() { Name = "FPS Limit", + PersistentKey = "FPSLimit", ApplyDelay = 500, ResetValue = () => { return "Off"; }, OptionsValues = delegate () diff --git a/PowerControl/Options/RefreshRate.cs b/PowerControl/Options/RefreshRate.cs index 79f900f..fe52519 100644 --- a/PowerControl/Options/RefreshRate.cs +++ b/PowerControl/Options/RefreshRate.cs @@ -8,6 +8,7 @@ namespace PowerControl.Options public static Menu.MenuItemWithOptions Instance = new Menu.MenuItemWithOptions() { Name = "Refresh Rate", + PersistentKey = "RefreshRate", ApplyDelay = 1000, ResetValue = () => { return DisplayResolutionController.GetRefreshRates().Max().ToString(); }, OptionsValues = delegate () @@ -24,10 +25,14 @@ namespace PowerControl.Options ApplyValue = (selected) => { DisplayResolutionController.SetRefreshRate(int.Parse(selected)); + + return DisplayResolutionController.GetRefreshRate().ToString(); + }, + AfterApply = () => + { // force reset and refresh of FPS limit FPSLimit.Instance.Reset(); FPSLimit.Instance.Update(); - return DisplayResolutionController.GetRefreshRate().ToString(); } }; }