using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using Artemis.Core.DryIoc.Factories; using Artemis.Core.ScriptingProviders; using Artemis.Storage; using DryIoc; using HidSharp; using RGB.NET.Core; using Serilog; using Serilog.Events; using SkiaSharp; namespace Artemis.Core.Services; /// /// Provides Artemis's core update loop /// internal class CoreService : ICoreService { private readonly ILogger _logger; private readonly PluginSetting _loggingLevel; private readonly IPluginManagementService _pluginManagementService; private readonly IRenderService _renderService; // ReSharper disable UnusedParameter.Local public CoreService(IContainer container, ILogger logger, ISettingsService settingsService, IPluginManagementService pluginManagementService, IProfileService profileService, IModuleService moduleService, IScriptingService scriptingService, IRenderService renderService) { Constants.CorePlugin.Container = container; _logger = logger; _pluginManagementService = pluginManagementService; _renderService = renderService; _loggingLevel = settingsService.GetSetting("Core.LoggingLevel", LogEventLevel.Debug); _loggingLevel.SettingChanged += (sender, args) => ApplyLoggingLevel(); } public bool IsElevated { get; set; } public bool IsInitialized { get; set; } public void Initialize() { if (IsInitialized) throw new ArtemisCoreException("Cannot initialize the core as it is already initialized."); _logger.Information("Initializing Artemis Core version {CurrentVersion}", Constants.CurrentVersion); _logger.Information("Startup arguments: {StartupArguments}", Constants.StartupArguments); _logger.Information("Elevated permissions: {IsElevated}", IsElevated); _logger.Information("Stopwatch high resolution: {IsHighResolution}", Stopwatch.IsHighResolution); ApplyLoggingLevel(); ProcessMonitor.Start(); // Don't remove even if it looks useless // Just this line should prevent a certain someone from removing HidSharp as an unused dependency as well Version? hidSharpVersion = Assembly.GetAssembly(typeof(HidDevice))!.GetName().Version; _logger.Debug("Forcing plugins to use HidSharp {HidSharpVersion}", hidSharpVersion); // Initialize the services _pluginManagementService.CopyBuiltInPlugins(); _pluginManagementService.LoadPlugins(IsElevated); _pluginManagementService.StartHotReload(); _renderService.Initialize(); OnInitialized(); } private void ApplyLoggingLevel() { string? argument = Constants.StartupArguments.FirstOrDefault(a => a.StartsWith("--logging")); if (argument != null) { // Parse the provided log level string[] parts = argument.Split('='); if (parts.Length == 2 && Enum.TryParse(typeof(LogEventLevel), parts[1], true, out object? logLevelArgument)) { _logger.Information("Setting logging level to {loggingLevel} from startup argument", (LogEventLevel)logLevelArgument!); LoggerFactory.LoggingLevelSwitch.MinimumLevel = (LogEventLevel)logLevelArgument; } else { _logger.Warning("Failed to set log level from startup argument {argument}", argument); _logger.Information("Setting logging level to {loggingLevel}", _loggingLevel.Value); LoggerFactory.LoggingLevelSwitch.MinimumLevel = _loggingLevel.Value; } } else { _logger.Information("Setting logging level to {loggingLevel}", _loggingLevel.Value); LoggerFactory.LoggingLevelSwitch.MinimumLevel = _loggingLevel.Value; } } public event EventHandler? Initialized; private void OnInitialized() { IsInitialized = true; Initialized?.Invoke(this, EventArgs.Empty); } }