mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
204 lines
7.0 KiB
C#
204 lines
7.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Timers;
|
|
using Artemis.Core.Modules;
|
|
using Newtonsoft.Json;
|
|
using Serilog;
|
|
|
|
namespace Artemis.Core.Services;
|
|
|
|
internal class ModuleService : IModuleService
|
|
{
|
|
private readonly Timer _activationUpdateTimer;
|
|
private readonly ILogger _logger;
|
|
private readonly List<Module> _modules;
|
|
private readonly IProfileService _profileService;
|
|
private readonly object _updateLock = new();
|
|
|
|
private Module? _activationOverride;
|
|
|
|
public ModuleService(ILogger logger, IPluginManagementService pluginManagementService, IProfileService profileService)
|
|
{
|
|
_logger = logger;
|
|
_profileService = profileService;
|
|
|
|
_activationUpdateTimer = new Timer(2000);
|
|
_activationUpdateTimer.Start();
|
|
_activationUpdateTimer.Elapsed += ActivationUpdateTimerOnElapsed;
|
|
|
|
pluginManagementService.PluginFeatureEnabled += PluginManagementServiceOnPluginFeatureEnabled;
|
|
pluginManagementService.PluginFeatureDisabled += PluginManagementServiceOnPluginFeatureDisabled;
|
|
_modules = pluginManagementService.GetFeaturesOfType<Module>().ToList();
|
|
foreach (Module module in _modules)
|
|
ImportDefaultProfiles(module);
|
|
}
|
|
|
|
protected virtual void OnModuleActivated(ModuleEventArgs e)
|
|
{
|
|
ModuleActivated?.Invoke(this, e);
|
|
}
|
|
|
|
protected virtual void OnModuleDeactivated(ModuleEventArgs e)
|
|
{
|
|
ModuleDeactivated?.Invoke(this, e);
|
|
}
|
|
|
|
private void OverrideActivate(Module module)
|
|
{
|
|
try
|
|
{
|
|
if (module.IsActivated)
|
|
return;
|
|
|
|
// If activating while it should be deactivated, its an override
|
|
bool shouldBeActivated = module.EvaluateActivationRequirements();
|
|
module.Activate(!shouldBeActivated);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_logger.Error(new ArtemisPluginFeatureException(module, "Failed to activate module.", e), "Failed to activate module");
|
|
throw;
|
|
}
|
|
}
|
|
|
|
private void OverrideDeactivate(Module module)
|
|
{
|
|
try
|
|
{
|
|
if (!module.IsActivated)
|
|
return;
|
|
|
|
// If deactivating while it should be activated, its an override
|
|
bool shouldBeActivated = module.EvaluateActivationRequirements();
|
|
// No need to deactivate if it is not in an overridden state
|
|
if (shouldBeActivated && !module.IsActivatedOverride)
|
|
return;
|
|
|
|
module.Deactivate(true);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_logger.Error(new ArtemisPluginFeatureException(module, "Failed to deactivate module.", e), "Failed to deactivate module");
|
|
throw;
|
|
}
|
|
}
|
|
|
|
private void ActivationUpdateTimerOnElapsed(object? sender, ElapsedEventArgs e)
|
|
{
|
|
UpdateModuleActivation();
|
|
}
|
|
|
|
private void PluginManagementServiceOnPluginFeatureEnabled(object? sender, PluginFeatureEventArgs e)
|
|
{
|
|
lock (_updateLock)
|
|
{
|
|
if (e.PluginFeature is Module module && !_modules.Contains(module))
|
|
{
|
|
ImportDefaultProfiles(module);
|
|
_modules.Add(module);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void PluginManagementServiceOnPluginFeatureDisabled(object? sender, PluginFeatureEventArgs e)
|
|
{
|
|
lock (_updateLock)
|
|
{
|
|
if (e.PluginFeature is Module module)
|
|
_modules.Remove(module);
|
|
}
|
|
}
|
|
|
|
private void ImportDefaultProfiles(Module module)
|
|
{
|
|
try
|
|
{
|
|
List<ProfileConfiguration> profileConfigurations = _profileService.ProfileCategories.SelectMany(c => c.ProfileConfigurations).ToList();
|
|
foreach ((DefaultCategoryName categoryName, string profilePath) in module.DefaultProfilePaths)
|
|
{
|
|
ProfileConfigurationExportModel? profileConfigurationExportModel =
|
|
JsonConvert.DeserializeObject<ProfileConfigurationExportModel>(File.ReadAllText(profilePath), IProfileService.ExportSettings);
|
|
if (profileConfigurationExportModel?.ProfileEntity == null)
|
|
throw new ArtemisCoreException($"Default profile at path {profilePath} contains no valid profile data");
|
|
if (profileConfigurations.Any(p => p.Entity.ProfileId == profileConfigurationExportModel.ProfileEntity.Id))
|
|
continue;
|
|
|
|
ProfileCategory category = _profileService.ProfileCategories.FirstOrDefault(c => c.Name == categoryName.ToString()) ??
|
|
_profileService.CreateProfileCategory(categoryName.ToString());
|
|
|
|
_profileService.ImportProfile(category, profileConfigurationExportModel, false, true, null);
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_logger.Warning(e, "Failed to import default profiles for module {module}", module);
|
|
}
|
|
}
|
|
|
|
public void UpdateModuleActivation()
|
|
{
|
|
lock (_updateLock)
|
|
{
|
|
try
|
|
{
|
|
_activationUpdateTimer.Elapsed -= ActivationUpdateTimerOnElapsed;
|
|
foreach (Module module in _modules)
|
|
{
|
|
if (module.IsActivatedOverride)
|
|
continue;
|
|
|
|
if (module.IsAlwaysAvailable)
|
|
{
|
|
module.Activate(false);
|
|
continue;
|
|
}
|
|
|
|
module.Profiler.StartMeasurement("EvaluateActivationRequirements");
|
|
bool shouldBeActivated = module.IsEnabled && module.EvaluateActivationRequirements();
|
|
module.Profiler.StopMeasurement("EvaluateActivationRequirements");
|
|
|
|
if (shouldBeActivated && !module.IsActivated)
|
|
{
|
|
module.Activate(false);
|
|
OnModuleActivated(new ModuleEventArgs(module));
|
|
}
|
|
else if (!shouldBeActivated && module.IsActivated)
|
|
{
|
|
module.Deactivate(false);
|
|
OnModuleDeactivated(new ModuleEventArgs(module));
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
_activationUpdateTimer.Elapsed += ActivationUpdateTimerOnElapsed;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SetActivationOverride(Module? module)
|
|
{
|
|
lock (_updateLock)
|
|
{
|
|
if (_activationOverride != null)
|
|
OverrideDeactivate(_activationOverride);
|
|
_activationOverride = module;
|
|
if (_activationOverride != null)
|
|
OverrideActivate(_activationOverride);
|
|
}
|
|
}
|
|
|
|
public void UpdateActiveModules(double deltaTime)
|
|
{
|
|
lock (_updateLock)
|
|
{
|
|
foreach (Module module in _modules)
|
|
module.InternalUpdate(deltaTime);
|
|
}
|
|
}
|
|
|
|
public event EventHandler<ModuleEventArgs>? ModuleActivated;
|
|
public event EventHandler<ModuleEventArgs>? ModuleDeactivated;
|
|
} |