Skip to content

Commit

Permalink
Fix #998
Browse files Browse the repository at this point in the history
  • Loading branch information
BartoszCichecki committed Oct 21, 2023
1 parent dd425c9 commit 8b5ca48
Show file tree
Hide file tree
Showing 20 changed files with 219 additions and 9 deletions.
15 changes: 13 additions & 2 deletions LenovoLegionToolkit.Lib.Automation/AutomationProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using LenovoLegionToolkit.Lib.Automation.Pipeline;
using LenovoLegionToolkit.Lib.Automation.Pipeline.Triggers;
using LenovoLegionToolkit.Lib.Automation.Utils;
using LenovoLegionToolkit.Lib.Controllers.GodMode;
using LenovoLegionToolkit.Lib.Listeners;
using LenovoLegionToolkit.Lib.Utils;
using NeoSmart.AsyncLock;
Expand All @@ -19,6 +20,7 @@ public class AutomationProcessor
private readonly NativeWindowsMessageListener _nativeWindowsMessageListener;
private readonly PowerStateListener _powerStateListener;
private readonly PowerModeListener _powerModeListener;
private readonly GodModeController _godModeController;
private readonly GameAutoListener _gameAutoListener;
private readonly ProcessAutoListener _processAutoListener;
private readonly TimeAutoListener _timeAutoListener;
Expand All @@ -38,6 +40,7 @@ public AutomationProcessor(AutomationSettings settings,
NativeWindowsMessageListener nativeWindowsMessageListener,
PowerStateListener powerStateListener,
PowerModeListener powerModeListener,
GodModeController godModeController,
GameAutoListener gameAutoListener,
ProcessAutoListener processAutoListener,
TimeAutoListener timeAutoListener,
Expand All @@ -47,6 +50,7 @@ public AutomationProcessor(AutomationSettings settings,
_nativeWindowsMessageListener = nativeWindowsMessageListener ?? throw new ArgumentNullException(nameof(nativeWindowsMessageListener));
_powerStateListener = powerStateListener ?? throw new ArgumentNullException(nameof(powerStateListener));
_powerModeListener = powerModeListener ?? throw new ArgumentNullException(nameof(powerModeListener));
_godModeController = godModeController ?? throw new ArgumentNullException(nameof(godModeController));
_gameAutoListener = gameAutoListener ?? throw new ArgumentNullException(nameof(gameAutoListener));
_processAutoListener = processAutoListener ?? throw new ArgumentNullException(nameof(processAutoListener));
_timeAutoListener = timeAutoListener ?? throw new ArgumentNullException(nameof(timeAutoListener));
Expand All @@ -61,7 +65,8 @@ public async Task InitializeAsync()
{
_nativeWindowsMessageListener.Changed += NativeWindowsMessageListener_Changed;
_powerStateListener.Changed += PowerStateListener_Changed;
_powerModeListener.Changed += PowerModeListenerOnChanged;
_powerModeListener.Changed += PowerModeListener_Changed;
_godModeController.PresetChanged += GodModeController_PresetChanged;

_pipelines = _settings.Store.Pipelines.ToList();

Expand Down Expand Up @@ -254,12 +259,18 @@ private async void PowerStateListener_Changed(object? sender, EventArgs _)
await ProcessEvent(e).ConfigureAwait(false);
}

private async void PowerModeListenerOnChanged(object? sender, PowerModeState powerModeState)
private async void PowerModeListener_Changed(object? sender, PowerModeState powerModeState)
{
var e = new PowerModeAutomationEvent { PowerModeState = powerModeState };
await ProcessEvent(e).ConfigureAwait(false);
}

private async void GodModeController_PresetChanged(object? sender, Guid presetId)
{
var e = new CustomModePresetAutomationEvent { Id = presetId };
await ProcessEvent(e).ConfigureAwait(false);
}

private async void GameAutoListener_Changed(object? sender, bool started)
{
var e = new GameAutomationEvent { Started = started };
Expand Down
5 changes: 5 additions & 0 deletions LenovoLegionToolkit.Lib.Automation/IAutomationEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ public struct PowerStateAutomationEvent : IAutomationEvent { }
public PowerModeState PowerModeState { get; init; }
}

public readonly struct CustomModePresetAutomationEvent : IAutomationEvent
{
public Guid Id { get; init; }
}

public readonly struct GameAutomationEvent : IAutomationEvent
{
public bool Started { get; init; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace LenovoLegionToolkit.Lib.Automation.Pipeline;

public class AutomationPipeline
{
// ReSharper disable once PropertyCanBeMadeInitOnly.Global
public Guid Id { get; set; } = Guid.NewGuid();

public string? IconName { get; set; }
Expand All @@ -21,8 +22,10 @@ public class AutomationPipeline

public IAutomationPipelineTrigger? Trigger { get; set; }

// ReSharper disable once PropertyCanBeMadeInitOnly.Global
public List<IAutomationStep> Steps { get; set; } = new();

// ReSharper disable once PropertyCanBeMadeInitOnly.Global
public bool IsExclusive { get; set; } = true;

[JsonIgnore]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System;
using System.Threading.Tasks;
using LenovoLegionToolkit.Lib.Automation.Resources;
using LenovoLegionToolkit.Lib.Controllers.GodMode;
using Newtonsoft.Json;

namespace LenovoLegionToolkit.Lib.Automation.Pipeline.Triggers;

public class GodModePresetChangedAutomationPipelineTrigger : IGodModePresetChangedAutomationPipelineTrigger
{
[JsonIgnore]
public string DisplayName => Resource.GodModePresetChangedAutomationPipelineTrigger_DisplayName;

public Guid PresetId { get; }

[JsonConstructor]
public GodModePresetChangedAutomationPipelineTrigger(Guid presetId)
{
PresetId = presetId;
}

public Task<bool> IsMatchingEvent(IAutomationEvent automationEvent)
{
if (automationEvent is not CustomModePresetAutomationEvent e)
return Task.FromResult(false);

return Task.FromResult(e.Id == PresetId);
}

public async Task<bool> IsMatchingState()
{
var controller = IoCContainer.Resolve<GodModeController>();
return PresetId == await controller.GetActivePresetIdAsync().ConfigureAwait(false);
}

public void UpdateEnvironment(ref AutomationEnvironment environment) { /* Ignored */ }

public IAutomationPipelineTrigger DeepCopy() => new GodModePresetChangedAutomationPipelineTrigger(PresetId);

public IGodModePresetChangedAutomationPipelineTrigger DeepCopy(Guid presetId) => new GodModePresetChangedAutomationPipelineTrigger(presetId);

public override bool Equals(object? obj)
{
return obj is GodModePresetChangedAutomationPipelineTrigger t && PresetId == t.PresetId;
}

public override int GetHashCode() => HashCode.Combine(PresetId);

public override string ToString() => $"{nameof(PresetId)}: {PresetId}";
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ public interface IPowerModeAutomationPipelineTrigger : IAutomationPipelineTrigge
IPowerModeAutomationPipelineTrigger DeepCopy(PowerModeState powerModeState);
}

public interface IGodModePresetChangedAutomationPipelineTrigger : IAutomationPipelineTrigger
{
Guid PresetId { get; }

IGodModePresetChangedAutomationPipelineTrigger DeepCopy(Guid powerModeState);
}

public interface IGameAutomationPipelineTrigger : IDisallowDuplicatesAutomationPipelineTrigger { }

public interface IProcessesAutomationPipelineTrigger : IAutomationPipelineTrigger
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions LenovoLegionToolkit.Lib.Automation/Resources/Resource.resx
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,7 @@
<data name="OverclockDiscreteGPUAutomationStepState_On" xml:space="preserve">
<value>On</value>
</data>
<data name="GodModePresetChangedAutomationPipelineTrigger_DisplayName" xml:space="preserve">
<value>When Custom Mode preset changes</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public abstract class AbstractGodModeController : IGodModeController
protected readonly VantageDisabler VantageDisabler;
protected readonly LegionZoneDisabler LegionZoneDisabler;

public event EventHandler<Guid>? PresetChanged;

protected AbstractGodModeController(GodModeSettings settings, VantageDisabler vantageDisabler, LegionZoneDisabler legionZoneDisabler)
{
_settings = settings ?? throw new ArgumentNullException(nameof(settings));
Expand All @@ -27,6 +29,8 @@ protected AbstractGodModeController(GodModeSettings settings, VantageDisabler va

public abstract Task<bool> NeedsLegionZoneDisabledAsync();

public Task<Guid> GetActivePresetIdAsync() => Task.FromResult(_settings.Store.ActivePresetId);

public Task<string?> GetActivePresetNameAsync()
{
var store = _settings.Store;
Expand Down Expand Up @@ -121,7 +125,9 @@ public Task<FanTable> GetDefaultFanTableAsync()

protected abstract Task<GodModePreset> GetDefaultStateAsync();

protected async Task<GodModeSettings.GodModeSettingsStore.Preset> GetActivePresetAsync()
protected void RaisePresetChanged(Guid presetId) => PresetChanged?.Invoke(this, presetId);

protected async Task<(Guid, GodModeSettings.GodModeSettingsStore.Preset)> GetActivePresetAsync()
{
if (!IsValidStore(_settings.Store))
{
Expand All @@ -136,7 +142,7 @@ public Task<FanTable> GetDefaultFanTableAsync()
var presets = _settings.Store.Presets;

if (presets.TryGetValue(activePresetId, out var activePreset))
return activePreset;
return (activePresetId, activePreset);

throw new InvalidOperationException($"Preset with ID {activePresetId} not found.");
}
Expand Down
20 changes: 20 additions & 0 deletions LenovoLegionToolkit.Lib/Controllers/GodMode/GodModeController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@ public class GodModeController : IGodModeController
private readonly IGodModeController _controllerV1;
private readonly IGodModeController _controllerV2;

public event EventHandler<Guid>? PresetChanged
{
add
{
_controllerV1.PresetChanged += value;
_controllerV2.PresetChanged += value;
}
remove
{
_controllerV1.PresetChanged -= value;
_controllerV2.PresetChanged -= value;
}
}

public GodModeController(GodModeControllerV1 controllerV1, GodModeControllerV2 controllerV2)
{
_controllerV1 = controllerV1 ?? throw new ArgumentNullException(nameof(controllerV1));
Expand All @@ -28,6 +42,12 @@ public async Task<bool> NeedsLegionZoneDisabledAsync()
return await controller.NeedsLegionZoneDisabledAsync().ConfigureAwait(false);
}

public async Task<Guid> GetActivePresetIdAsync()
{
var controller = await GetControllerAsync().ConfigureAwait(false);
return await controller.GetActivePresetIdAsync().ConfigureAwait(false);
}

public async Task<string?> GetActivePresetNameAsync()
{
var controller = await GetControllerAsync().ConfigureAwait(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public override async Task ApplyStateAsync()
if (Log.Instance.IsTraceEnabled)
Log.Instance.Trace($"Applying state...");

var preset = await GetActivePresetAsync().ConfigureAwait(false);
var (presetId, preset) = await GetActivePresetAsync().ConfigureAwait(false);

var cpuLongTermPowerLimit = preset.CPULongTermPowerLimit;
var cpuShortTermPowerLimit = preset.CPUShortTermPowerLimit;
Expand Down Expand Up @@ -252,8 +252,10 @@ public override async Task ApplyStateAsync()
}
}

RaisePresetChanged(presetId);

if (Log.Instance.IsTraceEnabled)
Log.Instance.Trace($"State applied.");
Log.Instance.Trace($"State applied. [name={preset.Name}, id={presetId}]");
}

public override Task<FanTable> GetMinimumFanTableAsync()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public override async Task ApplyStateAsync()
if (Log.Instance.IsTraceEnabled)
Log.Instance.Trace($"Applying state...");

var preset = await GetActivePresetAsync().ConfigureAwait(false);
var (presetId, preset) = await GetActivePresetAsync().ConfigureAwait(false);

var settings = new Dictionary<CapabilityID, StepperValue?>
{
Expand Down Expand Up @@ -132,8 +132,10 @@ public override async Task ApplyStateAsync()
}
}

RaisePresetChanged(presetId);

if (Log.Instance.IsTraceEnabled)
Log.Instance.Trace($"State applied.");
Log.Instance.Trace($"State applied. [name={preset.Name}, id={presetId}]");
}

public override Task<FanTable> GetMinimumFanTableAsync()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace LenovoLegionToolkit.Lib.Controllers.GodMode;

public interface IGodModeController
{
event EventHandler<Guid> PresetChanged;
Task<bool> NeedsVantageDisabledAsync();
Task<bool> NeedsLegionZoneDisabledAsync();
Task<Guid> GetActivePresetIdAsync();
Task<string?> GetActivePresetNameAsync();
Task<GodModeState> GetStateAsync();
Task SetStateAsync(GodModeState state);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using LenovoLegionToolkit.Lib.Automation.Pipeline.Triggers;
using LenovoLegionToolkit.Lib.Automation.Steps;
using LenovoLegionToolkit.Lib.Extensions;
using LenovoLegionToolkit.Lib.Settings;
using LenovoLegionToolkit.Lib.Utils;
using LenovoLegionToolkit.WPF.Controls.Automation.Steps;
using LenovoLegionToolkit.WPF.Extensions;
Expand All @@ -29,6 +30,7 @@ public class AutomationPipelineControl : UserControl
private readonly TaskCompletionSource _initializedTaskCompletionSource = new();

private readonly AutomationProcessor _automationProcessor = IoCContainer.Resolve<AutomationProcessor>();
private readonly GodModeSettings _godModeSettings = IoCContainer.Resolve<GodModeSettings>();

private readonly CardExpander _cardExpander = new()
{
Expand Down Expand Up @@ -249,6 +251,15 @@ private string GenerateSubtitle()
if (AutomationPipeline.Trigger is IPowerModeAutomationPipelineTrigger pm)
result += $" | {Resource.AutomationPipelineControl_SubtitlePart_PowerMode}: {pm.PowerModeState.GetDisplayName()}";

if (AutomationPipeline.Trigger is IGodModePresetChangedAutomationPipelineTrigger gmpt)
{
var name = _godModeSettings.Store.Presets.Where(kv => kv.Key == gmpt.PresetId)
.Select(kv => kv.Value.Name)
.DefaultIfEmpty("-")
.First();
result += $" | {Resource.AutomationPipelineControl_SubtitlePart_Preset}: {name}";
}

if (AutomationPipeline.Trigger is IProcessesAutomationPipelineTrigger pt && pt.Processes.Any())
result += $" | {Resource.AutomationPipelineControl_SubtitlePart_Apps}: {string.Join(", ", pt.Processes.Select(p => p.Name))}";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public static class AutomationPipelineTriggerExtensions
{
IPowerStateAutomationPipelineTrigger => SymbolRegular.BatteryCharge24,
IPowerModeAutomationPipelineTrigger => SymbolRegular.Gauge24,
IGodModePresetChangedAutomationPipelineTrigger => SymbolRegular.Gauge24,
IGameAutomationPipelineTrigger => SymbolRegular.XboxController24,
IProcessesAutomationPipelineTrigger => SymbolRegular.WindowConsole20,
IUserInactivityPipelineTrigger => SymbolRegular.ClockAlarm24,
Expand Down
9 changes: 9 additions & 0 deletions LenovoLegionToolkit.WPF/Resources/Resource.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions LenovoLegionToolkit.WPF/Resources/Resource.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1928,4 +1928,7 @@ Requires restart.</value>
<data name="NotificationAutomationStepControl_Title" xml:space="preserve">
<value>Show notification</value>
</data>
<data name="AutomationPipelineControl_SubtitlePart_Preset" xml:space="preserve">
<value>Preset</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ private void CancelButton_Click(object sender, RoutedEventArgs e)
private static bool IsValid(IAutomationPipelineTrigger trigger) => trigger switch
{
IPowerModeAutomationPipelineTrigger => true,
IGodModePresetChangedAutomationPipelineTrigger => true,
IProcessesAutomationPipelineTrigger => true,
IUserInactivityPipelineTrigger ut when ut.InactivityTimeSpan > TimeSpan.Zero => true,
ITimeAutomationPipelineTrigger => true,
Expand All @@ -102,6 +103,7 @@ private void CancelButton_Click(object sender, RoutedEventArgs e)
private static IAutomationPipelineTriggerTabItemContent<IAutomationPipelineTrigger>? Create(IAutomationPipelineTrigger trigger) => trigger switch
{
IPowerModeAutomationPipelineTrigger pmt => new PowerModeAutomationPipelineTriggerTabItemContent(pmt),
IGodModePresetChangedAutomationPipelineTrigger gmpt => new GodModePresetPipelineTriggerTabItemContent(gmpt),
IProcessesAutomationPipelineTrigger pt => new ProcessAutomationPipelineTriggerTabItemControl(pt),
IUserInactivityPipelineTrigger ut when ut.InactivityTimeSpan > TimeSpan.Zero => new UserInactivityPipelineTriggerTabItemContent(ut),
ITimeAutomationPipelineTrigger tt => new TimeAutomationPipelineTriggerTabItemContent(tt),
Expand Down
Loading

0 comments on commit 8b5ca48

Please sign in to comment.