mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Plugins - Reworked most of the activation logic
This commit is contained in:
parent
1e0dc1894d
commit
b56966c585
@ -8,11 +8,11 @@ namespace Artemis.Core
|
||||
{
|
||||
}
|
||||
|
||||
public PluginEventArgs(PluginInfo pluginInfo)
|
||||
public PluginEventArgs(Plugin plugin)
|
||||
{
|
||||
PluginInfo = pluginInfo;
|
||||
Plugin = plugin;
|
||||
}
|
||||
|
||||
public PluginInfo PluginInfo { get; }
|
||||
public Plugin Plugin { get; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
public class PluginImplementationEventArgs : EventArgs
|
||||
{
|
||||
public PluginImplementationEventArgs()
|
||||
{
|
||||
}
|
||||
|
||||
public PluginImplementationEventArgs(PluginImplementation pluginImplementation)
|
||||
{
|
||||
PluginImplementation = pluginImplementation;
|
||||
}
|
||||
|
||||
public PluginImplementation PluginImplementation { get; }
|
||||
}
|
||||
}
|
||||
@ -4,19 +4,19 @@ namespace Artemis.Core
|
||||
{
|
||||
public class ArtemisPluginException : Exception
|
||||
{
|
||||
public ArtemisPluginException(PluginInfo pluginInfo)
|
||||
public ArtemisPluginException(Plugin plugin)
|
||||
{
|
||||
PluginInfo = pluginInfo;
|
||||
Plugin = plugin;
|
||||
}
|
||||
|
||||
public ArtemisPluginException(PluginInfo pluginInfo, string message) : base(message)
|
||||
public ArtemisPluginException(Plugin plugin, string message) : base(message)
|
||||
{
|
||||
PluginInfo = pluginInfo;
|
||||
Plugin = plugin;
|
||||
}
|
||||
|
||||
public ArtemisPluginException(PluginInfo pluginInfo, string message, Exception inner) : base(message, inner)
|
||||
public ArtemisPluginException(Plugin plugin, string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
PluginInfo = pluginInfo;
|
||||
Plugin = plugin;
|
||||
}
|
||||
|
||||
public ArtemisPluginException(string message) : base(message)
|
||||
@ -27,6 +27,6 @@ namespace Artemis.Core
|
||||
{
|
||||
}
|
||||
|
||||
public PluginInfo PluginInfo { get; }
|
||||
public Plugin Plugin { get; }
|
||||
}
|
||||
}
|
||||
@ -10,12 +10,12 @@ namespace Artemis.Core.Ninject
|
||||
{
|
||||
private static readonly List<PluginSettings> PluginSettings = new List<PluginSettings>();
|
||||
private readonly IPluginRepository _pluginRepository;
|
||||
private readonly IPluginService _pluginService;
|
||||
private readonly IPluginManagementService _pluginManagementService;
|
||||
|
||||
internal PluginSettingsProvider(IPluginRepository pluginRepository, IPluginService pluginService)
|
||||
internal PluginSettingsProvider(IPluginRepository pluginRepository, IPluginManagementService pluginManagementService)
|
||||
{
|
||||
_pluginRepository = pluginRepository;
|
||||
_pluginService = pluginService;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
}
|
||||
|
||||
protected override PluginSettings CreateInstance(IContext context)
|
||||
@ -27,7 +27,7 @@ namespace Artemis.Core.Ninject
|
||||
// First try by PluginInfo parameter
|
||||
PluginInfo pluginInfo = parentRequest.Parameters.FirstOrDefault(p => p.Name == "PluginInfo")?.GetValue(context, null) as PluginInfo;
|
||||
if (pluginInfo == null)
|
||||
pluginInfo = _pluginService.GetPluginByAssembly(parentRequest.Service.Assembly)?.PluginInfo;
|
||||
pluginInfo = _pluginManagementService.GetPluginByAssembly(parentRequest.Service.Assembly)?.PluginInfo;
|
||||
// Fall back to assembly based detection
|
||||
if (pluginInfo == null)
|
||||
throw new ArtemisCoreException("PluginSettings can only be injected with the PluginInfo parameter provided " +
|
||||
|
||||
@ -1,18 +1,131 @@
|
||||
namespace Artemis.Core
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Artemis.Storage.Entities.Plugins;
|
||||
using McMaster.NETCore.Plugins;
|
||||
using Ninject;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a plugin
|
||||
/// </summary>
|
||||
public abstract class Plugin
|
||||
public class Plugin : PropertyChangedBase, IDisposable
|
||||
{
|
||||
private readonly List<PluginImplementation> _implementations;
|
||||
|
||||
private bool _isEnabled;
|
||||
|
||||
internal Plugin(PluginInfo info, DirectoryInfo directory)
|
||||
{
|
||||
Info = info;
|
||||
Directory = directory;
|
||||
|
||||
_implementations = new List<PluginImplementation>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin GUID
|
||||
/// </summary>
|
||||
public Guid Guid => Info.Guid;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin info related to this plugin
|
||||
/// </summary>
|
||||
public PluginInfo Info { get; internal set; }
|
||||
public PluginInfo Info { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The plugins root directory
|
||||
/// </summary>
|
||||
public DirectoryInfo Directory { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a configuration dialog for this plugin that is accessible in the UI under Settings > Plugins
|
||||
/// </summary>
|
||||
public PluginConfigurationDialog ConfigurationDialog { get; protected set; }
|
||||
public PluginConfigurationDialog? ConfigurationDialog { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the user enabled the plugin or not
|
||||
/// </summary>
|
||||
public bool IsEnabled
|
||||
{
|
||||
get => _isEnabled;
|
||||
private set => SetAndNotify(ref _isEnabled, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a read-only collection of all implementations this plugin provides
|
||||
/// </summary>
|
||||
public ReadOnlyCollection<PluginImplementation> Implementations => _implementations.AsReadOnly();
|
||||
|
||||
/// <summary>
|
||||
/// The assembly the plugin code lives in
|
||||
/// </summary>
|
||||
internal Assembly? Assembly { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Ninject kernel of the plugin
|
||||
/// </summary>
|
||||
internal IKernel? Kernel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The PluginLoader backing this plugin
|
||||
/// </summary>
|
||||
internal PluginLoader? PluginLoader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The entity representing the plugin
|
||||
/// </summary>
|
||||
internal PluginEntity? Entity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Resolves the relative path provided in the <paramref name="path" /> parameter to an absolute path
|
||||
/// </summary>
|
||||
/// <param name="path">The path to resolve</param>
|
||||
/// <returns>An absolute path pointing to the provided relative path</returns>
|
||||
public string? ResolveRelativePath(string path)
|
||||
{
|
||||
return path == null ? null : Path.Combine(Directory.FullName, path);
|
||||
}
|
||||
|
||||
internal void ApplyToEntity()
|
||||
{
|
||||
Entity.Id = Guid;
|
||||
Entity.IsEnabled = IsEnabled;
|
||||
}
|
||||
|
||||
internal void AddImplementation(PluginImplementation implementation)
|
||||
{
|
||||
implementation.Plugin = this;
|
||||
_implementations.Add(implementation);
|
||||
}
|
||||
|
||||
public void SetEnabled(bool enable)
|
||||
{
|
||||
if (IsEnabled == enable)
|
||||
return;
|
||||
|
||||
if (!enable && Implementations.Any(e => e.IsEnabled))
|
||||
throw new ArtemisCoreException("Cannot disable this plugin because it still has enabled implementations");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return Info.ToString();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (PluginImplementation pluginImplementation in Implementations)
|
||||
pluginImplementation.Dispose();
|
||||
|
||||
Kernel?.Dispose();
|
||||
PluginLoader?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,27 +1,44 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.Storage.Entities.Plugins;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an implementation of a certain type provided by a plugin
|
||||
/// </summary>
|
||||
public abstract class PluginImplementation : IDisposable
|
||||
public abstract class PluginImplementation : PropertyChangedBase, IDisposable
|
||||
{
|
||||
private Exception? _loadException;
|
||||
private bool _isEnabled;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin that provides this implementation
|
||||
/// </summary>
|
||||
public Plugin Plugin { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin info related to this plugin
|
||||
/// </summary>
|
||||
public PluginInfo PluginInfo { get; internal set; }
|
||||
public Plugin? Plugin { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the plugin is enabled
|
||||
/// </summary>
|
||||
public bool IsEnabled { get; internal set; }
|
||||
public bool IsEnabled
|
||||
{
|
||||
get => _isEnabled;
|
||||
internal set => SetAndNotify(ref _isEnabled, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the exception thrown while loading
|
||||
/// </summary>
|
||||
public Exception? LoadException
|
||||
{
|
||||
get => _loadException;
|
||||
internal set => SetAndNotify(ref _loadException, value);
|
||||
}
|
||||
|
||||
internal PluginImplementationEntity? Entity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Called when the implementation is activated
|
||||
@ -35,62 +52,75 @@ namespace Artemis.Core
|
||||
|
||||
internal void SetEnabled(bool enable, bool isAutoEnable = false)
|
||||
{
|
||||
if (enable && !IsEnabled)
|
||||
if (enable == IsEnabled)
|
||||
return;
|
||||
|
||||
if (Plugin == null)
|
||||
throw new ArtemisCoreException("Cannot enable a plugin implementation that is not associated with a plugin");
|
||||
|
||||
lock (Plugin)
|
||||
{
|
||||
if (!Plugin.IsEnabled)
|
||||
throw new ArtemisCoreException("Cannot enable a plugin implementation of a disabled plugin");
|
||||
|
||||
if (!enable)
|
||||
{
|
||||
IsEnabled = false;
|
||||
|
||||
// Even if disable failed, still leave it in a disabled state to avoid more issues
|
||||
InternalDisable();
|
||||
OnDisabled();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (isAutoEnable && PluginInfo.GetLockFileCreated())
|
||||
if (isAutoEnable && GetLockFileCreated())
|
||||
{
|
||||
// Don't wrap existing lock exceptions, simply rethrow them
|
||||
if (PluginInfo.LoadException is ArtemisPluginLockException)
|
||||
throw PluginInfo.LoadException;
|
||||
if (LoadException is ArtemisPluginLockException)
|
||||
throw LoadException;
|
||||
|
||||
throw new ArtemisPluginLockException(PluginInfo.LoadException);
|
||||
throw new ArtemisPluginLockException(LoadException);
|
||||
}
|
||||
|
||||
IsEnabled = true;
|
||||
PluginInfo.IsEnabled = true;
|
||||
PluginInfo.CreateLockFile();
|
||||
CreateLockFile();
|
||||
|
||||
// Allow up to 15 seconds for plugins to activate.
|
||||
// This means plugins that need more time should do their long running tasks in a background thread, which is intentional
|
||||
// Little meh: Running this from a different thread could cause deadlocks
|
||||
Task enableTask = Task.Run(InternalEnable);
|
||||
if (!enableTask.Wait(TimeSpan.FromSeconds(15)))
|
||||
throw new ArtemisPluginException(PluginInfo, "Plugin load timeout");
|
||||
ManualResetEvent wait = new ManualResetEvent(false);
|
||||
Thread work = new Thread(() =>
|
||||
{
|
||||
InternalEnable();
|
||||
wait.Set();
|
||||
});
|
||||
work.Start();
|
||||
wait.WaitOne(TimeSpan.FromSeconds(15));
|
||||
if (work.IsAlive)
|
||||
{
|
||||
work.Abort();
|
||||
throw new ArtemisPluginException(Plugin, "Plugin load timeout");
|
||||
}
|
||||
|
||||
PluginInfo.LoadException = null;
|
||||
LoadException = null;
|
||||
OnEnabled();
|
||||
}
|
||||
// If enable failed, put it back in a disabled state
|
||||
catch (Exception e)
|
||||
{
|
||||
IsEnabled = false;
|
||||
PluginInfo.IsEnabled = false;
|
||||
PluginInfo.LoadException = e;
|
||||
LoadException = e;
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!(PluginInfo.LoadException is ArtemisPluginLockException))
|
||||
PluginInfo.DeleteLockFile();
|
||||
// Clean up the lock file unless the failure was due to the lock file
|
||||
// After all, we failed but not miserably :)
|
||||
if (!(LoadException is ArtemisPluginLockException))
|
||||
DeleteLockFile();
|
||||
}
|
||||
}
|
||||
else if (!enable && IsEnabled)
|
||||
{
|
||||
IsEnabled = false;
|
||||
PluginInfo.IsEnabled = false;
|
||||
|
||||
// Even if disable failed, still leave it in a disabled state to avoid more issues
|
||||
InternalDisable();
|
||||
OnDisabled();
|
||||
}
|
||||
// A failed load is still enabled in plugin info (to avoid disabling it permanently after a fail)
|
||||
// update even that when manually disabling
|
||||
else if (!enable && !IsEnabled)
|
||||
{
|
||||
PluginInfo.IsEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void InternalEnable()
|
||||
@ -109,6 +139,35 @@ namespace Artemis.Core
|
||||
Disable();
|
||||
}
|
||||
|
||||
#region Loading
|
||||
|
||||
internal void CreateLockFile()
|
||||
{
|
||||
if (Plugin == null)
|
||||
throw new ArtemisCoreException("Cannot lock a plugin implementation that is not associated with a plugin");
|
||||
|
||||
File.Create(Plugin.ResolveRelativePath($"{GetType().FullName}.lock")).Close();
|
||||
}
|
||||
|
||||
internal void DeleteLockFile()
|
||||
{
|
||||
if (Plugin == null)
|
||||
throw new ArtemisCoreException("Cannot lock a plugin implementation that is not associated with a plugin");
|
||||
|
||||
if (GetLockFileCreated())
|
||||
File.Delete(Plugin.ResolveRelativePath($"{GetType().FullName}.lock"));
|
||||
}
|
||||
|
||||
internal bool GetLockFileCreated()
|
||||
{
|
||||
if (Plugin == null)
|
||||
throw new ArtemisCoreException("Cannot lock a plugin implementation that is not associated with a plugin");
|
||||
|
||||
return File.Exists(Plugin.ResolveRelativePath($"{GetType().FullName}.lock"));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -1,10 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using Artemis.Storage.Entities.Plugins;
|
||||
using McMaster.NETCore.Plugins;
|
||||
using Newtonsoft.Json;
|
||||
using Ninject;
|
||||
using Stylet;
|
||||
|
||||
namespace Artemis.Core
|
||||
@ -16,14 +11,11 @@ namespace Artemis.Core
|
||||
public class PluginInfo : PropertyChangedBase
|
||||
{
|
||||
private string _description;
|
||||
private DirectoryInfo _directory;
|
||||
private Guid _guid;
|
||||
private string _icon;
|
||||
private Plugin _instance;
|
||||
private bool _isEnabled;
|
||||
private Exception _loadException;
|
||||
private string _main;
|
||||
private string _name;
|
||||
private Plugin _plugin;
|
||||
private Version _version;
|
||||
|
||||
internal PluginInfo()
|
||||
@ -92,93 +84,19 @@ namespace Artemis.Core
|
||||
internal set => SetAndNotify(ref _main, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The plugins root directory
|
||||
/// </summary>
|
||||
public DirectoryInfo Directory
|
||||
{
|
||||
get => _directory;
|
||||
internal set => SetAndNotify(ref _directory, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin this info is associated with
|
||||
/// </summary>
|
||||
public Plugin Instance
|
||||
public Plugin Plugin
|
||||
{
|
||||
get => _instance;
|
||||
internal set => SetAndNotify(ref _instance, value);
|
||||
get => _plugin;
|
||||
internal set => SetAndNotify(ref _plugin, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the user enabled the plugin or not
|
||||
/// </summary>
|
||||
public bool IsEnabled
|
||||
{
|
||||
get => _isEnabled;
|
||||
internal set => SetAndNotify(ref _isEnabled, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the exception thrown while loading
|
||||
/// </summary>
|
||||
public Exception LoadException
|
||||
{
|
||||
get => _loadException;
|
||||
internal set => SetAndNotify(ref _loadException, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The assembly the plugin code lives in
|
||||
/// </summary>
|
||||
public Assembly Assembly { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Ninject kernel of the plugin
|
||||
/// </summary>
|
||||
public IKernel Kernel { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// The PluginLoader backing this plugin
|
||||
/// </summary>
|
||||
internal PluginLoader PluginLoader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The entity representing the plugin
|
||||
/// </summary>
|
||||
internal PluginEntity PluginEntity { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Name} v{Version} - {Guid}";
|
||||
}
|
||||
|
||||
public string? ResolveRelativePath(string path)
|
||||
{
|
||||
return path == null ? null : Path.Combine(Directory.FullName, path);
|
||||
}
|
||||
|
||||
internal void ApplyToEntity()
|
||||
{
|
||||
PluginEntity.Id = Guid;
|
||||
PluginEntity.IsEnabled = IsEnabled;
|
||||
}
|
||||
|
||||
internal void CreateLockFile()
|
||||
{
|
||||
File.Create(Path.Combine(Directory.FullName, "artemis.lock")).Close();
|
||||
}
|
||||
|
||||
internal void DeleteLockFile()
|
||||
{
|
||||
if (GetLockFileCreated())
|
||||
File.Delete(Path.Combine(Directory.FullName, "artemis.lock"));
|
||||
}
|
||||
|
||||
internal bool GetLockFileCreated()
|
||||
{
|
||||
return File.Exists(Path.Combine(Directory.FullName, "artemis.lock"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -19,9 +19,9 @@ namespace Artemis.Core
|
||||
Interval = interval;
|
||||
Action = action;
|
||||
|
||||
PluginInfo.Instance.Enabled += InstanceOnEnabled;
|
||||
PluginInfo.Instance.Disabled += InstanceOnDisabled;
|
||||
if (PluginInfo.Instance.IsEnabled)
|
||||
PluginInfo.Plugin.Enabled += InstanceOnEnabled;
|
||||
PluginInfo.Plugin.Disabled += InstanceOnDisabled;
|
||||
if (PluginInfo.Plugin.IsEnabled)
|
||||
Start();
|
||||
}
|
||||
|
||||
@ -31,9 +31,9 @@ namespace Artemis.Core
|
||||
Interval = interval;
|
||||
AsyncAction = asyncAction;
|
||||
|
||||
PluginInfo.Instance.Enabled += InstanceOnEnabled;
|
||||
PluginInfo.Instance.Disabled += InstanceOnDisabled;
|
||||
if (PluginInfo.Instance.IsEnabled)
|
||||
PluginInfo.Plugin.Enabled += InstanceOnEnabled;
|
||||
PluginInfo.Plugin.Disabled += InstanceOnDisabled;
|
||||
if (PluginInfo.Plugin.IsEnabled)
|
||||
Start();
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ namespace Artemis.Core
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (!PluginInfo.Instance.IsEnabled)
|
||||
if (!PluginInfo.Plugin.IsEnabled)
|
||||
throw new ArtemisPluginException("Cannot start a timed update for a disabled plugin");
|
||||
|
||||
if (_timer != null)
|
||||
@ -99,7 +99,7 @@ namespace Artemis.Core
|
||||
|
||||
private void TimerOnElapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
if (!PluginInfo.Instance.IsEnabled)
|
||||
if (!PluginInfo.Plugin.IsEnabled)
|
||||
return;
|
||||
|
||||
lock (this)
|
||||
@ -108,7 +108,7 @@ namespace Artemis.Core
|
||||
_lastEvent = DateTime.Now;
|
||||
|
||||
// Modules don't always want to update, honor that
|
||||
if (PluginInfo.Instance is Module module && !module.IsUpdateAllowed)
|
||||
if (PluginInfo.Plugin is Module module && !module.IsUpdateAllowed)
|
||||
return;
|
||||
|
||||
if (Action != null)
|
||||
|
||||
@ -28,7 +28,7 @@ namespace Artemis.Core.Services
|
||||
private readonly Stopwatch _frameStopWatch;
|
||||
private readonly ILogger _logger;
|
||||
private readonly PluginSetting<LogEventLevel> _loggingLevel;
|
||||
private readonly IPluginService _pluginService;
|
||||
private readonly IPluginManagementService _pluginManagementService;
|
||||
private readonly IProfileService _profileService;
|
||||
private readonly IRgbService _rgbService;
|
||||
private readonly ISurfaceService _surfaceService;
|
||||
@ -36,14 +36,14 @@ namespace Artemis.Core.Services
|
||||
private List<Module> _modules;
|
||||
|
||||
// ReSharper disable once UnusedParameter.Local - Storage migration service is injected early to ensure it runs before anything else
|
||||
public CoreService(IKernel kernel, ILogger logger, StorageMigrationService _, ISettingsService settingsService, IPluginService pluginService,
|
||||
public CoreService(IKernel kernel, ILogger logger, StorageMigrationService _, ISettingsService settingsService, IPluginManagementService pluginManagementService,
|
||||
IRgbService rgbService, ISurfaceService surfaceService, IProfileService profileService, IModuleService moduleService)
|
||||
{
|
||||
Kernel = kernel;
|
||||
Constants.CorePluginInfo.Kernel = kernel;
|
||||
|
||||
_logger = logger;
|
||||
_pluginService = pluginService;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
_rgbService = rgbService;
|
||||
_surfaceService = surfaceService;
|
||||
_profileService = profileService;
|
||||
@ -57,8 +57,8 @@ namespace Artemis.Core.Services
|
||||
_rgbService.Surface.Updated += SurfaceOnUpdated;
|
||||
_loggingLevel.SettingChanged += (sender, args) => ApplyLoggingLevel();
|
||||
|
||||
_pluginService.PluginEnabled += (sender, args) => UpdatePluginCache();
|
||||
_pluginService.PluginDisabled += (sender, args) => UpdatePluginCache();
|
||||
_pluginManagementService.PluginEnabled += (sender, args) => UpdatePluginCache();
|
||||
_pluginManagementService.PluginDisabled += (sender, args) => UpdatePluginCache();
|
||||
}
|
||||
|
||||
public TimeSpan FrameTime { get; private set; }
|
||||
@ -68,7 +68,7 @@ namespace Artemis.Core.Services
|
||||
public void Dispose()
|
||||
{
|
||||
// Dispose services
|
||||
_pluginService.Dispose();
|
||||
_pluginManagementService.Dispose();
|
||||
}
|
||||
|
||||
public bool IsInitialized { get; set; }
|
||||
@ -85,8 +85,8 @@ namespace Artemis.Core.Services
|
||||
DeserializationLogger.Initialize(Kernel);
|
||||
|
||||
// Initialize the services
|
||||
_pluginService.CopyBuiltInPlugins();
|
||||
_pluginService.LoadPlugins(StartupArguments.Contains("--ignore-plugin-lock"));
|
||||
_pluginManagementService.CopyBuiltInPlugins();
|
||||
_pluginManagementService.LoadPlugins(StartupArguments.Contains("--ignore-plugin-lock"));
|
||||
|
||||
ArtemisSurface surfaceConfig = _surfaceService.ActiveSurface;
|
||||
if (surfaceConfig != null)
|
||||
@ -133,8 +133,8 @@ namespace Artemis.Core.Services
|
||||
|
||||
private void UpdatePluginCache()
|
||||
{
|
||||
_modules = _pluginService.GetPluginsOfType<Module>().Where(p => p.IsEnabled).ToList();
|
||||
_dataModelExpansions = _pluginService.GetPluginsOfType<BaseDataModelExpansion>().Where(p => p.IsEnabled).ToList();
|
||||
_modules = _pluginManagementService.GetPluginsOfType<Module>().Where(p => p.IsEnabled).ToList();
|
||||
_dataModelExpansions = _pluginManagementService.GetPluginsOfType<BaseDataModelExpansion>().Where(p => p.IsEnabled).ToList();
|
||||
}
|
||||
|
||||
private void ConfigureJsonConvert()
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using RGB.NET.Core;
|
||||
|
||||
@ -8,7 +9,7 @@ namespace Artemis.Core.Services
|
||||
/// <summary>
|
||||
/// A service providing plugin management
|
||||
/// </summary>
|
||||
public interface IPluginService : IArtemisService, IDisposable
|
||||
public interface IPluginManagementService : IArtemisService, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates whether or not plugins are currently being loaded
|
||||
@ -35,7 +36,7 @@ namespace Artemis.Core.Services
|
||||
/// Loads the plugin defined in the provided <see cref="PluginInfo" />
|
||||
/// </summary>
|
||||
/// <param name="pluginInfo">The plugin info defining the plugin to load</param>
|
||||
void LoadPlugin(PluginInfo pluginInfo);
|
||||
void LoadPlugin(DirectoryInfo pluginInfo);
|
||||
|
||||
/// <summary>
|
||||
/// Unloads the plugin defined in the provided <see cref="PluginInfo" />
|
||||
@ -48,13 +49,13 @@ namespace Artemis.Core.Services
|
||||
/// </summary>
|
||||
/// <param name="pluginImplementation"></param>
|
||||
/// <param name="isAutoEnable">If true, fails if there is a lock file present</param>
|
||||
void EnablePlugin(PluginImplementation pluginImplementation, bool isAutoEnable = false);
|
||||
void EnablePluginImplementation(PluginImplementation pluginImplementation, bool isAutoEnable = false);
|
||||
|
||||
/// <summary>
|
||||
/// Disables the provided plugin
|
||||
/// </summary>
|
||||
/// <param name="pluginImplementation"></param>
|
||||
void DisablePlugin(PluginImplementation pluginImplementation);
|
||||
void DisablePluginImplementation(PluginImplementation pluginImplementation);
|
||||
|
||||
/// <summary>
|
||||
/// Finds the plugin info related to the plugin
|
||||
|
||||
@ -17,22 +17,22 @@ namespace Artemis.Core.Services
|
||||
private static readonly SemaphoreSlim ActiveModuleSemaphore = new SemaphoreSlim(1, 1);
|
||||
private readonly ILogger _logger;
|
||||
private readonly IModuleRepository _moduleRepository;
|
||||
private readonly IPluginService _pluginService;
|
||||
private readonly IPluginManagementService _pluginManagementService;
|
||||
private readonly IProfileService _profileService;
|
||||
|
||||
public ModuleService(ILogger logger, IModuleRepository moduleRepository, IPluginService pluginService, IProfileService profileService)
|
||||
public ModuleService(ILogger logger, IModuleRepository moduleRepository, IPluginManagementService pluginManagementService, IProfileService profileService)
|
||||
{
|
||||
_logger = logger;
|
||||
_moduleRepository = moduleRepository;
|
||||
_pluginService = pluginService;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
_profileService = profileService;
|
||||
_pluginService.PluginEnabled += PluginServiceOnPluginEnabled;
|
||||
_pluginManagementService.PluginEnabled += PluginManagementServiceOnPluginManagementEnabled;
|
||||
|
||||
Timer activationUpdateTimer = new Timer(2000);
|
||||
activationUpdateTimer.Start();
|
||||
activationUpdateTimer.Elapsed += ActivationUpdateTimerOnElapsed;
|
||||
|
||||
foreach (Module module in _pluginService.GetPluginsOfType<Module>())
|
||||
foreach (Module module in _pluginManagementService.GetPluginsOfType<Module>())
|
||||
InitialiseOrApplyPriority(module);
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ namespace Artemis.Core.Services
|
||||
_logger.Information("Clearing active module override");
|
||||
|
||||
// Always deactivate all other modules whenever override is called
|
||||
List<Module> modules = _pluginService.GetPluginsOfType<Module>().ToList();
|
||||
List<Module> modules = _pluginManagementService.GetPluginsOfType<Module>().ToList();
|
||||
foreach (Module module in modules.Where(m => m != overrideModule))
|
||||
OverrideDeactivate(module, overrideModule != null);
|
||||
|
||||
@ -97,7 +97,7 @@ namespace Artemis.Core.Services
|
||||
Stopwatch stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
|
||||
List<Module> modules = _pluginService.GetPluginsOfType<Module>().ToList();
|
||||
List<Module> modules = _pluginManagementService.GetPluginsOfType<Module>().ToList();
|
||||
List<Task> tasks = new List<Task>();
|
||||
foreach (Module module in modules)
|
||||
{
|
||||
@ -128,7 +128,7 @@ namespace Artemis.Core.Services
|
||||
if (module.PriorityCategory == category && module.Priority == priority)
|
||||
return;
|
||||
|
||||
List<Module> modules = _pluginService.GetPluginsOfType<Module>().Where(m => m.PriorityCategory == category).OrderBy(m => m.Priority).ToList();
|
||||
List<Module> modules = _pluginManagementService.GetPluginsOfType<Module>().Where(m => m.PriorityCategory == category).OrderBy(m => m.Priority).ToList();
|
||||
if (modules.Contains(module))
|
||||
modules.Remove(module);
|
||||
|
||||
@ -234,9 +234,9 @@ namespace Artemis.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
private void PluginServiceOnPluginEnabled(object sender, PluginEventArgs e)
|
||||
private void PluginManagementServiceOnPluginManagementEnabled(object sender, PluginEventArgs e)
|
||||
{
|
||||
if (e.PluginInfo.Instance is Module module)
|
||||
if (e.PluginInfo.Plugin is Module module)
|
||||
InitialiseOrApplyPriority(module);
|
||||
}
|
||||
|
||||
|
||||
@ -22,19 +22,19 @@ namespace Artemis.Core.Services
|
||||
/// <summary>
|
||||
/// Provides access to plugin loading and unloading
|
||||
/// </summary>
|
||||
internal class PluginService : IPluginService
|
||||
internal class PluginManagementService : IPluginManagementService
|
||||
{
|
||||
private readonly IKernel _kernel;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IPluginRepository _pluginRepository;
|
||||
private readonly List<PluginInfo> _plugins;
|
||||
private readonly List<Plugin> _plugins;
|
||||
|
||||
public PluginService(IKernel kernel, ILogger logger, IPluginRepository pluginRepository)
|
||||
public PluginManagementService(IKernel kernel, ILogger logger, IPluginRepository pluginRepository)
|
||||
{
|
||||
_kernel = kernel;
|
||||
_logger = logger;
|
||||
_pluginRepository = pluginRepository;
|
||||
_plugins = new List<PluginInfo>();
|
||||
_plugins = new List<Plugin>();
|
||||
|
||||
// Ensure the plugins directory exists
|
||||
if (!Directory.Exists(Constants.DataFolder + "plugins"))
|
||||
@ -43,6 +43,8 @@ namespace Artemis.Core.Services
|
||||
|
||||
public bool LoadingPlugins { get; private set; }
|
||||
|
||||
#region Built in plugins
|
||||
|
||||
public void CopyBuiltInPlugins()
|
||||
{
|
||||
OnCopyingBuildInPlugins();
|
||||
@ -101,6 +103,10 @@ namespace Artemis.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Plugins
|
||||
|
||||
public void LoadPlugins(bool ignorePluginLock)
|
||||
{
|
||||
if (LoadingPlugins)
|
||||
@ -119,15 +125,7 @@ namespace Artemis.Core.Services
|
||||
{
|
||||
try
|
||||
{
|
||||
// Load the metadata
|
||||
string metadataFile = Path.Combine(subDirectory.FullName, "plugin.json");
|
||||
if (!File.Exists(metadataFile)) _logger.Warning(new ArtemisPluginException("Couldn't find the plugins metadata file at " + metadataFile), "Plugin exception");
|
||||
|
||||
// Locate the main entry
|
||||
PluginInfo pluginInfo = JsonConvert.DeserializeObject<PluginInfo>(File.ReadAllText(metadataFile));
|
||||
pluginInfo.Directory = subDirectory;
|
||||
|
||||
LoadPlugin(pluginInfo);
|
||||
LoadPlugin(subDirectory);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -136,15 +134,18 @@ namespace Artemis.Core.Services
|
||||
}
|
||||
|
||||
// Activate plugins after they are all loaded
|
||||
foreach (PluginInfo pluginInfo in _plugins.Where(p => p.IsEnabled))
|
||||
foreach (Plugin plugin in _plugins.Where(p => p.Entity.IsEnabled))
|
||||
{
|
||||
try
|
||||
foreach (PluginImplementation pluginImplementation in plugin.Implementations.Where(i => i.Entity.IsEnabled))
|
||||
{
|
||||
EnablePlugin(pluginInfo.Instance, !ignorePluginLock);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored, logged in EnablePlugin
|
||||
try
|
||||
{
|
||||
EnablePluginImplementation(pluginImplementation, !ignorePluginLock);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored, logged in EnablePlugin
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -164,30 +165,37 @@ namespace Artemis.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadPlugin(PluginInfo pluginInfo)
|
||||
public void LoadPlugin(DirectoryInfo pluginDirectory)
|
||||
{
|
||||
lock (_plugins)
|
||||
{
|
||||
_logger.Debug("Loading plugin {pluginInfo}", pluginInfo);
|
||||
OnPluginLoading(new PluginEventArgs(pluginInfo));
|
||||
_logger.Debug("Loading plugin from {directory}", pluginDirectory.FullName);
|
||||
|
||||
// Unload the plugin first if it is already loaded
|
||||
if (_plugins.Contains(pluginInfo))
|
||||
UnloadPlugin(pluginInfo);
|
||||
// Load the metadata
|
||||
string metadataFile = Path.Combine(pluginDirectory.FullName, "plugin.json");
|
||||
if (!File.Exists(metadataFile))
|
||||
_logger.Warning(new ArtemisPluginException("Couldn't find the plugins metadata file at " + metadataFile), "Plugin exception");
|
||||
|
||||
PluginEntity pluginEntity = _pluginRepository.GetPluginByGuid(pluginInfo.Guid);
|
||||
if (pluginEntity == null)
|
||||
pluginEntity = new PluginEntity {Id = pluginInfo.Guid, IsEnabled = true};
|
||||
// PluginInfo contains the ID which we need to move on
|
||||
PluginInfo pluginInfo = JsonConvert.DeserializeObject<PluginInfo>(File.ReadAllText(metadataFile));
|
||||
|
||||
pluginInfo.PluginEntity = pluginEntity;
|
||||
pluginInfo.IsEnabled = pluginEntity.IsEnabled;
|
||||
// Ensure the plugin is not already loaded
|
||||
if (_plugins.Any(p => p.Guid == pluginInfo.Guid))
|
||||
throw new ArtemisCoreException("Cannot load a plugin that is already loaded");
|
||||
|
||||
string mainFile = Path.Combine(pluginInfo.Directory.FullName, pluginInfo.Main);
|
||||
Plugin plugin = new Plugin(pluginInfo, pluginDirectory);
|
||||
OnPluginLoading(new PluginEventArgs(plugin));
|
||||
|
||||
// Load the entity and fall back on creating a new one
|
||||
plugin.Entity = _pluginRepository.GetPluginByGuid(pluginInfo.Guid) ?? new PluginEntity { Id = plugin.Guid, IsEnabled = true };
|
||||
|
||||
// Locate the main assembly entry
|
||||
string? mainFile = plugin.ResolveRelativePath(plugin.Info.Main);
|
||||
if (!File.Exists(mainFile))
|
||||
throw new ArtemisPluginException(pluginInfo, "Couldn't find the plugins main entry at " + mainFile);
|
||||
throw new ArtemisPluginException(plugin, "Couldn't find the plugins main entry at " + mainFile);
|
||||
|
||||
// Load the plugin, all types implementing Plugin and register them with DI
|
||||
pluginInfo.PluginLoader = PluginLoader.CreateFromAssemblyFile(mainFile, configure =>
|
||||
plugin.PluginLoader = PluginLoader.CreateFromAssemblyFile(mainFile!, configure =>
|
||||
{
|
||||
configure.IsUnloadable = true;
|
||||
configure.PreferSharedTypes = true;
|
||||
@ -195,57 +203,58 @@ namespace Artemis.Core.Services
|
||||
|
||||
try
|
||||
{
|
||||
pluginInfo.Assembly = pluginInfo.PluginLoader.LoadDefaultAssembly();
|
||||
plugin.Assembly = plugin.PluginLoader.LoadDefaultAssembly();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new ArtemisPluginException(pluginInfo, "Failed to load the plugins assembly", e);
|
||||
throw new ArtemisPluginException(plugin, "Failed to load the plugins assembly", e);
|
||||
}
|
||||
|
||||
// Get the Plugin implementation from the main assembly and if there is only one, instantiate it
|
||||
List<Type> pluginTypes;
|
||||
List<Type> implementationTypes;
|
||||
try
|
||||
{
|
||||
pluginTypes = pluginInfo.Assembly.GetTypes().Where(t => typeof(PluginImplementation).IsAssignableFrom(t)).ToList();
|
||||
implementationTypes = plugin.Assembly.GetTypes().Where(t => typeof(PluginImplementation).IsAssignableFrom(t)).ToList();
|
||||
}
|
||||
catch (ReflectionTypeLoadException e)
|
||||
{
|
||||
throw new ArtemisPluginException(pluginInfo, "Failed to initialize the plugin assembly", new AggregateException(e.LoaderExceptions));
|
||||
throw new ArtemisPluginException(plugin, "Failed to initialize the plugin assembly", new AggregateException(e.LoaderExceptions));
|
||||
}
|
||||
|
||||
if (pluginTypes.Count > 1)
|
||||
throw new ArtemisPluginException(pluginInfo, $"Plugin contains {pluginTypes.Count} implementations of Plugin, only 1 allowed");
|
||||
if (pluginTypes.Count == 0)
|
||||
throw new ArtemisPluginException(pluginInfo, "Plugin contains no implementation of Plugin");
|
||||
// Create the Ninject child kernel and load the module
|
||||
plugin.Kernel = new ChildKernel(_kernel);
|
||||
plugin.Kernel.Load(new PluginModule(pluginInfo));
|
||||
|
||||
Type pluginType = pluginTypes.Single();
|
||||
try
|
||||
if (!implementationTypes.Any())
|
||||
_logger.Warning("Plugin {plugin} contains no implementations", plugin);
|
||||
|
||||
// Create instances of each implementation and add them to the plugin
|
||||
// Construction should be simple and not contain any logic so failure at this point means the entire plugin fails
|
||||
foreach (Type implementationType in implementationTypes)
|
||||
{
|
||||
IParameter[] parameters = {
|
||||
new Parameter("PluginInfo", pluginInfo, false)
|
||||
};
|
||||
pluginInfo.Kernel = new ChildKernel(_kernel);
|
||||
pluginInfo.Kernel.Load(new PluginModule(pluginInfo));
|
||||
pluginInfo.Instance = (PluginImplementation) pluginInfo.Kernel.Get(pluginType, constraint: null, parameters: parameters);
|
||||
pluginInfo.Instance.PluginInfo = pluginInfo;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new ArtemisPluginException(pluginInfo, "Failed to instantiate the plugin", e);
|
||||
try
|
||||
{
|
||||
PluginImplementation instance = (PluginImplementation)plugin.Kernel.Get(implementationType);
|
||||
plugin.AddImplementation(instance);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new ArtemisPluginException(plugin, "Failed to load instantiate implementation", e);
|
||||
}
|
||||
}
|
||||
|
||||
_plugins.Add(pluginInfo);
|
||||
OnPluginLoaded(new PluginEventArgs(pluginInfo));
|
||||
_plugins.Add(plugin);
|
||||
OnPluginLoaded(new PluginEventArgs(plugin));
|
||||
}
|
||||
}
|
||||
|
||||
public void UnloadPlugin(PluginInfo pluginInfo)
|
||||
public void UnloadPlugin(Plugin plugin)
|
||||
{
|
||||
lock (_plugins)
|
||||
{
|
||||
try
|
||||
{
|
||||
pluginInfo.Instance.SetEnabled(false);
|
||||
plugin.SetEnabled(false);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@ -253,23 +262,24 @@ namespace Artemis.Core.Services
|
||||
}
|
||||
finally
|
||||
{
|
||||
OnPluginDisabled(new PluginEventArgs(pluginInfo));
|
||||
OnPluginDisabled(new PluginEventArgs(plugin));
|
||||
}
|
||||
|
||||
pluginInfo.Instance.Dispose();
|
||||
pluginInfo.PluginLoader.Dispose();
|
||||
pluginInfo.Kernel.Dispose();
|
||||
plugin.Dispose();
|
||||
_plugins.Remove(plugin);
|
||||
|
||||
_plugins.Remove(pluginInfo);
|
||||
|
||||
OnPluginUnloaded(new PluginEventArgs(pluginInfo));
|
||||
OnPluginUnloaded(new PluginEventArgs(plugin));
|
||||
}
|
||||
}
|
||||
|
||||
public void EnablePlugin(PluginImplementation pluginImplementation, bool isAutoEnable = false)
|
||||
#endregion
|
||||
|
||||
|
||||
#region Implementations
|
||||
|
||||
public void EnablePluginImplementation(PluginImplementation pluginImplementation, bool isAutoEnable = false)
|
||||
{
|
||||
_logger.Debug("Enabling plugin {pluginInfo}", pluginImplementation.PluginInfo);
|
||||
OnPluginEnabling(new PluginEventArgs(pluginImplementation.PluginInfo));
|
||||
_logger.Debug("Enabling plugin implementation {implementation} - {plugin}", pluginImplementation, pluginImplementation.Plugin);
|
||||
|
||||
lock (_plugins)
|
||||
{
|
||||
@ -306,10 +316,10 @@ namespace Artemis.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
OnPluginEnabled(new PluginEventArgs(pluginImplementation.PluginInfo));
|
||||
OnPluginImplementationEnabled(new PluginImplementationEventArgs(pluginImplementation));
|
||||
}
|
||||
|
||||
public void DisablePlugin(PluginImplementation pluginImplementation)
|
||||
public void DisablePluginImplementation(PluginImplementation pluginImplementation)
|
||||
{
|
||||
lock (_plugins)
|
||||
{
|
||||
@ -335,9 +345,12 @@ namespace Artemis.Core.Services
|
||||
OnPluginDisabled(new PluginEventArgs(pluginImplementation.PluginInfo));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public PluginInfo GetPluginInfo(PluginImplementation pluginImplementation)
|
||||
{
|
||||
return _plugins.FirstOrDefault(p => p.Instance == pluginImplementation);
|
||||
return _plugins.FirstOrDefault(p => p.Plugin == pluginImplementation);
|
||||
}
|
||||
|
||||
public List<PluginInfo> GetAllPluginInfo()
|
||||
@ -347,12 +360,12 @@ namespace Artemis.Core.Services
|
||||
|
||||
public List<T> GetPluginsOfType<T>() where T : PluginImplementation
|
||||
{
|
||||
return _plugins.Where(p => p.IsEnabled && p.Instance is T).Select(p => (T) p.Instance).ToList();
|
||||
return _plugins.Where(p => p.IsEnabled && p.Plugin is T).Select(p => (T) p.Plugin).ToList();
|
||||
}
|
||||
|
||||
public PluginImplementation GetPluginByAssembly(Assembly assembly)
|
||||
{
|
||||
return _plugins.FirstOrDefault(p => p.Assembly == assembly)?.Instance;
|
||||
return _plugins.FirstOrDefault(p => p.Assembly == assembly)?.Plugin;
|
||||
}
|
||||
|
||||
public PluginImplementation GetPluginByDevice(IRGBDevice rgbDevice)
|
||||
@ -362,8 +375,8 @@ namespace Artemis.Core.Services
|
||||
|
||||
public PluginImplementation GetCallingPlugin()
|
||||
{
|
||||
StackTrace stackTrace = new StackTrace(); // get call stack
|
||||
StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames)
|
||||
StackTrace stackTrace = new StackTrace(); // get call stack
|
||||
StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames)
|
||||
|
||||
foreach (StackFrame stackFrame in stackFrames)
|
||||
{
|
||||
@ -395,7 +408,7 @@ namespace Artemis.Core.Services
|
||||
if (createLockFile)
|
||||
File.Create(Path.Combine(pluginDirectory.FullName, "artemis.lock")).Close();
|
||||
}
|
||||
|
||||
|
||||
#region Events
|
||||
|
||||
public event EventHandler CopyingBuildInPlugins;
|
||||
@ -406,6 +419,9 @@ namespace Artemis.Core.Services
|
||||
public event EventHandler<PluginEventArgs> PluginEnabled;
|
||||
public event EventHandler<PluginEventArgs> PluginDisabled;
|
||||
|
||||
public event EventHandler<PluginImplementationEventArgs> PluginImplementationEnabled;
|
||||
public event EventHandler<PluginImplementationEventArgs> PluginImplementationDisabled;
|
||||
|
||||
protected virtual void OnCopyingBuildInPlugins()
|
||||
{
|
||||
CopyingBuildInPlugins?.Invoke(this, EventArgs.Empty);
|
||||
@ -441,6 +457,16 @@ namespace Artemis.Core.Services
|
||||
PluginDisabled?.Invoke(this, e);
|
||||
}
|
||||
|
||||
protected virtual void OnPluginImplementationDisabled(PluginImplementationEventArgs e)
|
||||
{
|
||||
PluginImplementationDisabled?.Invoke(this, e);
|
||||
}
|
||||
|
||||
protected virtual void OnPluginImplementationEnabled(PluginImplementationEventArgs e)
|
||||
{
|
||||
PluginImplementationEnabled?.Invoke(this, e);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -8,16 +8,16 @@ namespace Artemis.Core.Services
|
||||
{
|
||||
internal class DataModelService : IDataModelService
|
||||
{
|
||||
public DataModelService(IPluginService pluginService)
|
||||
public DataModelService(IPluginManagementService pluginManagementService)
|
||||
{
|
||||
// Add data models of already loaded plugins
|
||||
foreach (Module module in pluginService.GetPluginsOfType<Module>().Where(p => p.IsEnabled))
|
||||
foreach (Module module in pluginManagementService.GetPluginsOfType<Module>().Where(p => p.IsEnabled))
|
||||
AddModuleDataModel(module);
|
||||
foreach (BaseDataModelExpansion dataModelExpansion in pluginService.GetPluginsOfType<BaseDataModelExpansion>().Where(p => p.IsEnabled))
|
||||
foreach (BaseDataModelExpansion dataModelExpansion in pluginManagementService.GetPluginsOfType<BaseDataModelExpansion>().Where(p => p.IsEnabled))
|
||||
AddDataModelExpansionDataModel(dataModelExpansion);
|
||||
|
||||
// Add data models of new plugins when they get enabled
|
||||
pluginService.PluginEnabled += PluginServiceOnPluginEnabled;
|
||||
pluginManagementService.PluginEnabled += PluginServiceOnPluginEnabled;
|
||||
}
|
||||
|
||||
public DataModelRegistration RegisterDataModel(DataModel dataModel)
|
||||
@ -56,9 +56,9 @@ namespace Artemis.Core.Services
|
||||
|
||||
private void PluginServiceOnPluginEnabled(object sender, PluginEventArgs e)
|
||||
{
|
||||
if (e.PluginInfo.Instance is Module module)
|
||||
if (e.PluginInfo.Plugin is Module module)
|
||||
AddModuleDataModel(module);
|
||||
else if (e.PluginInfo.Instance is BaseDataModelExpansion dataModelExpansion)
|
||||
else if (e.PluginInfo.Plugin is BaseDataModelExpansion dataModelExpansion)
|
||||
AddDataModelExpansionDataModel(dataModelExpansion);
|
||||
}
|
||||
|
||||
|
||||
@ -13,19 +13,19 @@ namespace Artemis.Core.Services
|
||||
internal class ProfileService : IProfileService
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly IPluginService _pluginService;
|
||||
private readonly IPluginManagementService _pluginManagementService;
|
||||
private readonly IProfileRepository _profileRepository;
|
||||
private readonly ISurfaceService _surfaceService;
|
||||
|
||||
internal ProfileService(ILogger logger,
|
||||
IPluginService pluginService,
|
||||
IPluginManagementService pluginManagementService,
|
||||
ISurfaceService surfaceService,
|
||||
IConditionOperatorService conditionOperatorService,
|
||||
IDataBindingService dataBindingService,
|
||||
IProfileRepository profileRepository)
|
||||
{
|
||||
_logger = logger;
|
||||
_pluginService = pluginService;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
_surfaceService = surfaceService;
|
||||
_profileRepository = profileRepository;
|
||||
|
||||
@ -118,15 +118,15 @@ namespace Artemis.Core.Services
|
||||
}
|
||||
|
||||
// This could happen during activation so subscribe to it
|
||||
_pluginService.PluginEnabled += ActivatingProfilePluginToggle;
|
||||
_pluginService.PluginDisabled += ActivatingProfilePluginToggle;
|
||||
_pluginManagementService.PluginEnabled += ActivatingProfilePluginToggle;
|
||||
_pluginManagementService.PluginDisabled += ActivatingProfilePluginToggle;
|
||||
_surfaceService.SurfaceConfigurationUpdated += ActivatingProfileSurfaceUpdate;
|
||||
|
||||
await profileDescriptor.ProfileModule.ChangeActiveProfileAnimated(profile, _surfaceService.ActiveSurface);
|
||||
SaveActiveProfile(profileDescriptor.ProfileModule);
|
||||
|
||||
_pluginService.PluginEnabled -= ActivatingProfilePluginToggle;
|
||||
_pluginService.PluginDisabled -= ActivatingProfilePluginToggle;
|
||||
_pluginManagementService.PluginEnabled -= ActivatingProfilePluginToggle;
|
||||
_pluginManagementService.PluginDisabled -= ActivatingProfilePluginToggle;
|
||||
_surfaceService.SurfaceConfigurationUpdated -= ActivatingProfileSurfaceUpdate;
|
||||
|
||||
return profile;
|
||||
@ -285,7 +285,7 @@ namespace Artemis.Core.Services
|
||||
/// <param name="surface"></param>
|
||||
private void ActiveProfilesPopulateLeds(ArtemisSurface surface)
|
||||
{
|
||||
List<ProfileModule> profileModules = _pluginService.GetPluginsOfType<ProfileModule>();
|
||||
List<ProfileModule> profileModules = _pluginManagementService.GetPluginsOfType<ProfileModule>();
|
||||
foreach (ProfileModule profileModule in profileModules.Where(p => p.ActiveProfile != null).ToList())
|
||||
profileModule.ActiveProfile.PopulateLeds(surface);
|
||||
}
|
||||
|
||||
@ -12,18 +12,18 @@ namespace Artemis.Core.Services
|
||||
internal class SurfaceService : ISurfaceService
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly IPluginService _pluginService;
|
||||
private readonly IPluginManagementService _pluginManagementService;
|
||||
private readonly PluginSetting<double> _renderScaleSetting;
|
||||
private readonly IRgbService _rgbService;
|
||||
private readonly List<ArtemisSurface> _surfaceConfigurations;
|
||||
private readonly ISurfaceRepository _surfaceRepository;
|
||||
|
||||
public SurfaceService(ILogger logger, ISurfaceRepository surfaceRepository, IRgbService rgbService, IPluginService pluginService, ISettingsService settingsService)
|
||||
public SurfaceService(ILogger logger, ISurfaceRepository surfaceRepository, IRgbService rgbService, IPluginManagementService pluginManagementService, ISettingsService settingsService)
|
||||
{
|
||||
_logger = logger;
|
||||
_surfaceRepository = surfaceRepository;
|
||||
_rgbService = rgbService;
|
||||
_pluginService = pluginService;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
_surfaceConfigurations = new List<ArtemisSurface>();
|
||||
_renderScaleSetting = settingsService.GetSetting("Core.RenderScale", 0.5);
|
||||
|
||||
@ -44,7 +44,7 @@ namespace Artemis.Core.Services
|
||||
// Add all current devices
|
||||
foreach (IRGBDevice rgbDevice in _rgbService.LoadedDevices)
|
||||
{
|
||||
PluginImplementation pluginImplementation = _pluginService.GetPluginByDevice(rgbDevice);
|
||||
PluginImplementation pluginImplementation = _pluginManagementService.GetPluginByDevice(rgbDevice);
|
||||
configuration.Devices.Add(new ArtemisDevice(rgbDevice, pluginImplementation, configuration));
|
||||
}
|
||||
|
||||
@ -136,7 +136,7 @@ namespace Artemis.Core.Services
|
||||
IRGBDevice device = _rgbService.Surface.Devices.FirstOrDefault(d => d.GetDeviceIdentifier() == position.DeviceIdentifier);
|
||||
if (device != null)
|
||||
{
|
||||
PluginImplementation pluginImplementation = _pluginService.GetPluginByDevice(device);
|
||||
PluginImplementation pluginImplementation = _pluginManagementService.GetPluginByDevice(device);
|
||||
surfaceConfiguration.Devices.Add(new ArtemisDevice(device, pluginImplementation, surfaceConfiguration, position));
|
||||
}
|
||||
}
|
||||
@ -178,7 +178,7 @@ namespace Artemis.Core.Services
|
||||
DeviceEntity existingDeviceConfig = surface.SurfaceEntity.DeviceEntities.FirstOrDefault(d => d.DeviceIdentifier == deviceIdentifier);
|
||||
if (existingDeviceConfig != null)
|
||||
{
|
||||
PluginImplementation pluginImplementation = _pluginService.GetPluginByDevice(rgbDevice);
|
||||
PluginImplementation pluginImplementation = _pluginManagementService.GetPluginByDevice(rgbDevice);
|
||||
device = new ArtemisDevice(rgbDevice, pluginImplementation, surface, existingDeviceConfig);
|
||||
}
|
||||
// Fall back on creating a new device
|
||||
@ -189,7 +189,7 @@ namespace Artemis.Core.Services
|
||||
rgbDevice.DeviceInfo,
|
||||
deviceIdentifier
|
||||
);
|
||||
PluginImplementation pluginImplementation = _pluginService.GetPluginByDevice(rgbDevice);
|
||||
PluginImplementation pluginImplementation = _pluginManagementService.GetPluginByDevice(rgbDevice);
|
||||
device = new ArtemisDevice(rgbDevice, pluginImplementation, surface);
|
||||
}
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ namespace Artemis.Core
|
||||
if (Registrations.Any(r => r.ConditionOperator == conditionOperator))
|
||||
throw new ArtemisCoreException($"Condition operator store store already contains operator '{conditionOperator.Description}'");
|
||||
|
||||
registration = new ConditionOperatorRegistration(conditionOperator, conditionOperator.PluginInfo.Instance) {IsInStore = true};
|
||||
registration = new ConditionOperatorRegistration(conditionOperator, conditionOperator.PluginInfo.Plugin) {IsInStore = true};
|
||||
Registrations.Add(registration);
|
||||
}
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ namespace Artemis.Core
|
||||
if (Registrations.Any(r => r.DataBindingModifierType == modifierType))
|
||||
throw new ArtemisCoreException($"Data binding modifier type store already contains modifier '{modifierType.Name}'");
|
||||
|
||||
typeRegistration = new DataBindingModifierTypeRegistration(modifierType, modifierType.PluginInfo.Instance) { IsInStore = true };
|
||||
typeRegistration = new DataBindingModifierTypeRegistration(modifierType, modifierType.PluginInfo.Plugin) { IsInStore = true };
|
||||
Registrations.Add(typeRegistration);
|
||||
}
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ namespace Artemis.Core
|
||||
if (Registrations.Any(r => r.LayerBrushDescriptor == descriptor))
|
||||
throw new ArtemisCoreException($"Store already contains layer brush '{descriptor.DisplayName}'");
|
||||
|
||||
registration = new LayerBrushRegistration(descriptor, descriptor.LayerBrushProvider.PluginInfo.Instance) {IsInStore = true};
|
||||
registration = new LayerBrushRegistration(descriptor, descriptor.LayerBrushProvider.PluginInfo.Plugin) {IsInStore = true};
|
||||
Registrations.Add(registration);
|
||||
}
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ namespace Artemis.Core
|
||||
if (Registrations.Any(r => r.LayerEffectDescriptor == descriptor))
|
||||
throw new ArtemisCoreException($"Store already contains layer brush '{descriptor.DisplayName}'");
|
||||
|
||||
registration = new LayerEffectRegistration(descriptor, descriptor.LayerEffectProvider.PluginInfo.Instance) { IsInStore = true };
|
||||
registration = new LayerEffectRegistration(descriptor, descriptor.LayerEffectProvider.PluginInfo.Plugin) { IsInStore = true };
|
||||
Registrations.Add(registration);
|
||||
}
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ namespace Artemis.Core
|
||||
{
|
||||
public CorePluginImplementation()
|
||||
{
|
||||
Constants.CorePluginInfo.Instance = this;
|
||||
Constants.CorePluginInfo.Plugin = this;
|
||||
IsEnabled = true;
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Artemis.Storage.Entities.Plugins
|
||||
{
|
||||
@ -9,5 +10,16 @@ namespace Artemis.Storage.Entities.Plugins
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public bool IsEnabled { get; set; }
|
||||
|
||||
public List<PluginImplementationEntity> Implementations { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the configuration of a plugin implementation, each implementation has one configuration
|
||||
/// </summary>
|
||||
public class PluginImplementationEntity
|
||||
{
|
||||
public string Type { get; set; }
|
||||
public bool IsEnabled { get; set; }
|
||||
}
|
||||
}
|
||||
@ -22,7 +22,7 @@ namespace Artemis.UI.Shared
|
||||
ViewModelType = viewModelType;
|
||||
|
||||
if (PluginInfo != Constants.CorePluginInfo)
|
||||
PluginInfo.Instance.Disabled += InstanceOnDisabled;
|
||||
PluginInfo.Plugin.Disabled += InstanceOnDisabled;
|
||||
}
|
||||
|
||||
public RegistrationType RegistrationType { get; }
|
||||
@ -35,7 +35,7 @@ namespace Artemis.UI.Shared
|
||||
internal void Unsubscribe()
|
||||
{
|
||||
if (PluginInfo != Constants.CorePluginInfo)
|
||||
PluginInfo.Instance.Disabled -= InstanceOnDisabled;
|
||||
PluginInfo.Plugin.Disabled -= InstanceOnDisabled;
|
||||
}
|
||||
|
||||
private void InstanceOnDisabled(object sender, EventArgs e)
|
||||
|
||||
@ -16,7 +16,7 @@ namespace Artemis.UI.Shared
|
||||
ViewModelType = viewModelType;
|
||||
|
||||
if (PluginInfo != Constants.CorePluginInfo)
|
||||
PluginInfo.Instance.Disabled += InstanceOnDisabled;
|
||||
PluginInfo.Plugin.Disabled += InstanceOnDisabled;
|
||||
}
|
||||
|
||||
public PluginInfo PluginInfo { get; }
|
||||
@ -26,7 +26,7 @@ namespace Artemis.UI.Shared
|
||||
internal void Unsubscribe()
|
||||
{
|
||||
if (PluginInfo != Constants.CorePluginInfo)
|
||||
PluginInfo.Instance.Disabled -= InstanceOnDisabled;
|
||||
PluginInfo.Plugin.Disabled -= InstanceOnDisabled;
|
||||
}
|
||||
|
||||
private void InstanceOnDisabled(object sender, EventArgs e)
|
||||
|
||||
@ -22,14 +22,14 @@ namespace Artemis.UI.Shared.Services
|
||||
private readonly IKernel _kernel;
|
||||
private readonly IViewManager _viewManager;
|
||||
private readonly IWindowManager _windowManager;
|
||||
private readonly IPluginService _pluginService;
|
||||
private readonly IPluginManagementService _pluginManagementService;
|
||||
|
||||
public DialogService(IKernel kernel, IViewManager viewManager, IWindowManager windowManager, IPluginService pluginService)
|
||||
public DialogService(IKernel kernel, IViewManager viewManager, IWindowManager windowManager, IPluginManagementService pluginManagementService)
|
||||
{
|
||||
_kernel = kernel;
|
||||
_viewManager = viewManager;
|
||||
_windowManager = windowManager;
|
||||
_pluginService = pluginService;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
}
|
||||
|
||||
private async Task<object> ShowDialog<T>(IParameter[] parameters) where T : DialogViewModelBase
|
||||
@ -109,7 +109,7 @@ namespace Artemis.UI.Shared.Services
|
||||
|
||||
private async Task<object> ShowDialogAt<T>(string identifier, IParameter[] parameters) where T : DialogViewModelBase
|
||||
{
|
||||
PluginImplementation callingPluginImplementation = _pluginService.GetCallingPlugin();
|
||||
PluginImplementation callingPluginImplementation = _pluginManagementService.GetCallingPlugin();
|
||||
if (parameters == null) throw new ArgumentNullException(nameof(parameters));
|
||||
|
||||
if (callingPluginImplementation != null)
|
||||
|
||||
@ -11,17 +11,17 @@ namespace Artemis.UI.PropertyInput
|
||||
{
|
||||
public class BrushPropertyInputViewModel : PropertyInputViewModel<LayerBrushReference>
|
||||
{
|
||||
private readonly IPluginService _pluginService;
|
||||
private readonly IPluginManagementService _pluginManagementService;
|
||||
private BindableCollection<LayerBrushDescriptor> _descriptors;
|
||||
|
||||
public BrushPropertyInputViewModel(LayerProperty<LayerBrushReference> layerProperty,
|
||||
IProfileEditorService profileEditorService,
|
||||
IPluginService pluginService) : base(layerProperty, profileEditorService)
|
||||
IPluginManagementService pluginManagementService) : base(layerProperty, profileEditorService)
|
||||
{
|
||||
_pluginService = pluginService;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
|
||||
_pluginService.PluginEnabled += PluginServiceOnPluginLoaded;
|
||||
_pluginService.PluginDisabled += PluginServiceOnPluginLoaded;
|
||||
_pluginManagementService.PluginEnabled += PluginManagementServiceOnPluginManagementLoaded;
|
||||
_pluginManagementService.PluginDisabled += PluginManagementServiceOnPluginManagementLoaded;
|
||||
UpdateEnumValues();
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ namespace Artemis.UI.PropertyInput
|
||||
|
||||
public void UpdateEnumValues()
|
||||
{
|
||||
List<LayerBrushProvider> layerBrushProviders = _pluginService.GetPluginsOfType<LayerBrushProvider>();
|
||||
List<LayerBrushProvider> layerBrushProviders = _pluginManagementService.GetPluginsOfType<LayerBrushProvider>();
|
||||
Descriptors = new BindableCollection<LayerBrushDescriptor>(layerBrushProviders.SelectMany(l => l.LayerBrushDescriptors));
|
||||
NotifyOfPropertyChange(nameof(SelectedDescriptor));
|
||||
}
|
||||
@ -47,8 +47,8 @@ namespace Artemis.UI.PropertyInput
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
_pluginService.PluginEnabled -= PluginServiceOnPluginLoaded;
|
||||
_pluginService.PluginDisabled -= PluginServiceOnPluginLoaded;
|
||||
_pluginManagementService.PluginEnabled -= PluginManagementServiceOnPluginManagementLoaded;
|
||||
_pluginManagementService.PluginDisabled -= PluginManagementServiceOnPluginManagementLoaded;
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
@ -63,7 +63,7 @@ namespace Artemis.UI.PropertyInput
|
||||
InputValue = new LayerBrushReference(value);
|
||||
}
|
||||
|
||||
private void PluginServiceOnPluginLoaded(object sender, PluginEventArgs e)
|
||||
private void PluginManagementServiceOnPluginManagementLoaded(object sender, PluginEventArgs e)
|
||||
{
|
||||
UpdateEnumValues();
|
||||
}
|
||||
|
||||
@ -12,13 +12,13 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.LayerEffects
|
||||
{
|
||||
public class EffectsViewModel : Conductor<LayerEffectDescriptor>.Collection.AllActive
|
||||
{
|
||||
private readonly IPluginService _pluginService;
|
||||
private readonly IPluginManagementService _pluginManagementService;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private LayerEffectDescriptor _selectedLayerEffectDescriptor;
|
||||
|
||||
public EffectsViewModel(LayerPropertiesViewModel layerPropertiesViewModel, IPluginService pluginService, IProfileEditorService profileEditorService)
|
||||
public EffectsViewModel(LayerPropertiesViewModel layerPropertiesViewModel, IPluginManagementService pluginManagementService, IProfileEditorService profileEditorService)
|
||||
{
|
||||
_pluginService = pluginService;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
_profileEditorService = profileEditorService;
|
||||
LayerPropertiesViewModel = layerPropertiesViewModel;
|
||||
PropertyChanged += HandleSelectedLayerEffectChanged;
|
||||
@ -35,7 +35,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.LayerEffects
|
||||
|
||||
public void PopulateDescriptors()
|
||||
{
|
||||
List<LayerEffectProvider> layerBrushProviders = _pluginService.GetPluginsOfType<LayerEffectProvider>();
|
||||
List<LayerEffectProvider> layerBrushProviders = _pluginManagementService.GetPluginsOfType<LayerEffectProvider>();
|
||||
List<LayerEffectDescriptor> descriptors = layerBrushProviders.SelectMany(l => l.LayerEffectDescriptors).ToList();
|
||||
Items.AddRange(descriptors.Except(Items));
|
||||
Items.RemoveRange(Items.Except(descriptors));
|
||||
|
||||
@ -13,7 +13,7 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs
|
||||
public class DataModelDebugViewModel : Screen
|
||||
{
|
||||
private readonly IDataModelUIService _dataModelUIService;
|
||||
private readonly IPluginService _pluginService;
|
||||
private readonly IPluginManagementService _pluginManagementService;
|
||||
private readonly Timer _updateTimer;
|
||||
private bool _isModuleFilterEnabled;
|
||||
private DataModelPropertiesViewModel _mainDataModel;
|
||||
@ -21,10 +21,10 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs
|
||||
private string _propertySearch;
|
||||
private Module _selectedModule;
|
||||
|
||||
public DataModelDebugViewModel(IDataModelUIService dataModelUIService, IPluginService pluginService)
|
||||
public DataModelDebugViewModel(IDataModelUIService dataModelUIService, IPluginManagementService pluginManagementService)
|
||||
{
|
||||
_dataModelUIService = dataModelUIService;
|
||||
_pluginService = pluginService;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
_updateTimer = new Timer(500);
|
||||
|
||||
DisplayName = "Data model";
|
||||
@ -77,8 +77,8 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs
|
||||
GetDataModel();
|
||||
_updateTimer.Start();
|
||||
_updateTimer.Elapsed += OnUpdateTimerOnElapsed;
|
||||
_pluginService.PluginEnabled += PluginServiceOnPluginToggled;
|
||||
_pluginService.PluginDisabled += PluginServiceOnPluginToggled;
|
||||
_pluginManagementService.PluginEnabled += PluginManagementServiceOnPluginManagementToggled;
|
||||
_pluginManagementService.PluginDisabled += PluginManagementServiceOnPluginManagementToggled;
|
||||
|
||||
PopulateModules();
|
||||
|
||||
@ -89,8 +89,8 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs
|
||||
{
|
||||
_updateTimer.Stop();
|
||||
_updateTimer.Elapsed -= OnUpdateTimerOnElapsed;
|
||||
_pluginService.PluginEnabled -= PluginServiceOnPluginToggled;
|
||||
_pluginService.PluginDisabled -= PluginServiceOnPluginToggled;
|
||||
_pluginManagementService.PluginEnabled -= PluginManagementServiceOnPluginManagementToggled;
|
||||
_pluginManagementService.PluginDisabled -= PluginManagementServiceOnPluginManagementToggled;
|
||||
|
||||
base.OnDeactivate();
|
||||
}
|
||||
@ -110,14 +110,14 @@ namespace Artemis.UI.Screens.Settings.Debug.Tabs
|
||||
: _dataModelUIService.GetMainDataModelVisualization();
|
||||
}
|
||||
|
||||
private void PluginServiceOnPluginToggled(object? sender, PluginEventArgs e)
|
||||
private void PluginManagementServiceOnPluginManagementToggled(object? sender, PluginEventArgs e)
|
||||
{
|
||||
PopulateModules();
|
||||
}
|
||||
|
||||
private void PopulateModules()
|
||||
{
|
||||
Modules = _pluginService.GetPluginsOfType<Module>().Where(p => p.IsEnabled).ToList();
|
||||
Modules = _pluginManagementService.GetPluginsOfType<Module>().Where(p => p.IsEnabled).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -25,7 +25,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.General
|
||||
private List<Tuple<string, int>> _targetFrameRates;
|
||||
private readonly PluginSetting<LayerBrushReference> _defaultLayerBrushDescriptor;
|
||||
|
||||
public GeneralSettingsTabViewModel(IDialogService dialogService, IDebugService debugService, ISettingsService settingsService, IPluginService pluginService)
|
||||
public GeneralSettingsTabViewModel(IDialogService dialogService, IDebugService debugService, ISettingsService settingsService, IPluginManagementService pluginManagementService)
|
||||
{
|
||||
DisplayName = "GENERAL";
|
||||
|
||||
@ -46,7 +46,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.General
|
||||
// Anything else is kinda broken right now
|
||||
SampleSizes = new List<int> {1, 9};
|
||||
|
||||
List<LayerBrushProvider> layerBrushProviders = pluginService.GetPluginsOfType<LayerBrushProvider>();
|
||||
List<LayerBrushProvider> layerBrushProviders = pluginManagementService.GetPluginsOfType<LayerBrushProvider>();
|
||||
|
||||
LayerBrushDescriptors = new BindableCollection<LayerBrushDescriptor>(layerBrushProviders.SelectMany(l => l.LayerBrushDescriptors));
|
||||
_defaultLayerBrushDescriptor = _settingsService.GetSetting("ProfileEditor.DefaultLayerBrushDescriptor", new LayerBrushReference
|
||||
|
||||
@ -10,17 +10,17 @@ namespace Artemis.UI.Screens.Settings.Tabs.Modules
|
||||
public class ModuleOrderTabViewModel : Screen, IDropTarget
|
||||
{
|
||||
private readonly IModuleService _moduleService;
|
||||
private readonly IPluginService _pluginService;
|
||||
private readonly IPluginManagementService _pluginManagementService;
|
||||
private readonly DefaultDropHandler _defaultDropHandler;
|
||||
private readonly List<ModuleOrderModuleViewModel> _modules;
|
||||
|
||||
public ModuleOrderTabViewModel(IPluginService pluginService, IModuleService moduleService)
|
||||
public ModuleOrderTabViewModel(IPluginManagementService pluginManagementService, IModuleService moduleService)
|
||||
{
|
||||
DisplayName = "MODULE PRIORITY";
|
||||
|
||||
_pluginService = pluginService;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
_moduleService = moduleService;
|
||||
_modules = new List<ModuleOrderModuleViewModel>(pluginService.GetPluginsOfType<Module>().Select(m => new ModuleOrderModuleViewModel(m)));
|
||||
_modules = new List<ModuleOrderModuleViewModel>(pluginManagementService.GetPluginsOfType<Module>().Select(m => new ModuleOrderModuleViewModel(m)));
|
||||
_defaultDropHandler = new DefaultDropHandler();
|
||||
|
||||
NormalModules = new BindableCollection<ModuleOrderModuleViewModel>();
|
||||
|
||||
@ -9,15 +9,15 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
||||
{
|
||||
public class PluginSettingsTabViewModel : Conductor<PluginSettingsViewModel>.Collection.AllActive
|
||||
{
|
||||
private readonly IPluginService _pluginService;
|
||||
private readonly IPluginManagementService _pluginManagementService;
|
||||
private readonly ISettingsVmFactory _settingsVmFactory;
|
||||
private BindableCollection<PluginSettingsViewModel> _plugins;
|
||||
|
||||
public PluginSettingsTabViewModel(IPluginService pluginService, ISettingsVmFactory settingsVmFactory)
|
||||
public PluginSettingsTabViewModel(IPluginManagementService pluginManagementService, ISettingsVmFactory settingsVmFactory)
|
||||
{
|
||||
DisplayName = "PLUGINS";
|
||||
|
||||
_pluginService = pluginService;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
_settingsVmFactory = settingsVmFactory;
|
||||
}
|
||||
|
||||
@ -29,7 +29,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
||||
Items.Clear();
|
||||
await Task.Delay(200);
|
||||
|
||||
List<PluginSettingsViewModel> instances = _pluginService.GetAllPluginInfo().Select(p => _settingsVmFactory.CreatePluginSettingsViewModel(p.Instance)).ToList();
|
||||
List<PluginSettingsViewModel> instances = _pluginManagementService.GetAllPluginInfo().Select(p => _settingsVmFactory.CreatePluginSettingsViewModel(p.Plugin)).ToList();
|
||||
foreach (PluginSettingsViewModel pluginSettingsViewModel in instances)
|
||||
Items.Add(pluginSettingsViewModel);
|
||||
});
|
||||
|
||||
@ -26,7 +26,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
||||
{
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly ILogger _logger;
|
||||
private readonly IPluginService _pluginService;
|
||||
private readonly IPluginManagementService _pluginManagementService;
|
||||
private readonly ISnackbarMessageQueue _snackbarMessageQueue;
|
||||
private readonly IWindowManager _windowManager;
|
||||
private bool _enabling;
|
||||
@ -37,7 +37,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
||||
ILogger logger,
|
||||
IWindowManager windowManager,
|
||||
IDialogService dialogService,
|
||||
IPluginService pluginService,
|
||||
IPluginManagementService pluginManagementService,
|
||||
ISnackbarMessageQueue snackbarMessageQueue)
|
||||
{
|
||||
PluginImplementation = pluginImplementation;
|
||||
@ -46,7 +46,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
||||
_logger = logger;
|
||||
_windowManager = windowManager;
|
||||
_dialogService = dialogService;
|
||||
_pluginService = pluginService;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
_snackbarMessageQueue = snackbarMessageQueue;
|
||||
}
|
||||
|
||||
@ -183,7 +183,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
||||
|
||||
try
|
||||
{
|
||||
_pluginService.EnablePlugin(PluginImplementation);
|
||||
_pluginManagementService.EnablePluginImplementation(PluginImplementation);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -195,7 +195,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
||||
}
|
||||
}
|
||||
else
|
||||
_pluginService.DisablePlugin(PluginImplementation);
|
||||
_pluginManagementService.DisablePluginImplementation(PluginImplementation);
|
||||
|
||||
NotifyOfPropertyChange(nameof(IsEnabled));
|
||||
NotifyOfPropertyChange(nameof(CanOpenSettings));
|
||||
@ -208,7 +208,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
||||
bool restart = false;
|
||||
|
||||
// If any plugin already requires a restart, don't ask the user again
|
||||
bool restartQueued = _pluginService.GetAllPluginInfo().Any(p => p.Instance != null && !p.IsEnabled && p.Instance.IsEnabled);
|
||||
bool restartQueued = _pluginManagementService.GetAllPluginInfo().Any(p => p.Plugin != null && !p.IsEnabled && p.Plugin.IsEnabled);
|
||||
// If the plugin isn't enabled (load failed), it can be disabled without a restart
|
||||
if (!restartQueued && PluginImplementation.IsEnabled)
|
||||
{
|
||||
@ -220,7 +220,7 @@ namespace Artemis.UI.Screens.Settings.Tabs.Plugins
|
||||
);
|
||||
}
|
||||
|
||||
_pluginService.DisablePlugin(PluginImplementation);
|
||||
_pluginManagementService.DisablePluginImplementation(PluginImplementation);
|
||||
if (restart)
|
||||
{
|
||||
_logger.Debug("Restarting for device provider disable {pluginInfo}", PluginImplementation.PluginInfo);
|
||||
|
||||
@ -29,18 +29,18 @@ namespace Artemis.UI.Screens.Sidebar
|
||||
private readonly Timer _activeModulesUpdateTimer;
|
||||
private readonly IKernel _kernel;
|
||||
private readonly IModuleVmFactory _moduleVmFactory;
|
||||
private readonly IPluginService _pluginService;
|
||||
private readonly IPluginManagementService _pluginManagementService;
|
||||
private string _activeModules;
|
||||
private bool _isSidebarOpen;
|
||||
private IScreen _selectedItem;
|
||||
private BindableCollection<INavigationItem> _sidebarItems;
|
||||
private Dictionary<INavigationItem, Module> _sidebarModules;
|
||||
|
||||
public SidebarViewModel(IKernel kernel, IEventAggregator eventAggregator, IModuleVmFactory moduleVmFactory, IPluginService pluginService)
|
||||
public SidebarViewModel(IKernel kernel, IEventAggregator eventAggregator, IModuleVmFactory moduleVmFactory, IPluginManagementService pluginManagementService)
|
||||
{
|
||||
_kernel = kernel;
|
||||
_moduleVmFactory = moduleVmFactory;
|
||||
_pluginService = pluginService;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
|
||||
SidebarModules = new Dictionary<INavigationItem, Module>();
|
||||
SidebarItems = new BindableCollection<INavigationItem>();
|
||||
@ -49,8 +49,8 @@ namespace Artemis.UI.Screens.Sidebar
|
||||
_activeModulesUpdateTimer.Start();
|
||||
_activeModulesUpdateTimer.Elapsed += ActiveModulesUpdateTimerOnElapsed;
|
||||
|
||||
_pluginService.PluginEnabled += PluginServiceOnPluginEnabled;
|
||||
_pluginService.PluginDisabled += PluginServiceOnPluginDisabled;
|
||||
_pluginManagementService.PluginEnabled += PluginManagementServiceOnPluginManagementEnabled;
|
||||
_pluginManagementService.PluginDisabled += PluginManagementServiceOnPluginManagementDisabled;
|
||||
|
||||
SetupSidebar();
|
||||
eventAggregator.Subscribe(this);
|
||||
@ -96,8 +96,8 @@ namespace Artemis.UI.Screens.Sidebar
|
||||
SelectedItem?.Deactivate();
|
||||
SelectedItem = null;
|
||||
|
||||
_pluginService.PluginEnabled -= PluginServiceOnPluginEnabled;
|
||||
_pluginService.PluginDisabled -= PluginServiceOnPluginDisabled;
|
||||
_pluginManagementService.PluginEnabled -= PluginManagementServiceOnPluginManagementEnabled;
|
||||
_pluginManagementService.PluginDisabled -= PluginManagementServiceOnPluginManagementDisabled;
|
||||
|
||||
_activeModulesUpdateTimer.Stop();
|
||||
_activeModulesUpdateTimer.Elapsed -= ActiveModulesUpdateTimerOnElapsed;
|
||||
@ -118,7 +118,7 @@ namespace Artemis.UI.Screens.Sidebar
|
||||
// Add all activated modules
|
||||
SidebarItems.Add(new DividerNavigationItem());
|
||||
SidebarItems.Add(new SubheaderNavigationItem {Subheader = "Modules"});
|
||||
List<Module> modules = _pluginService.GetPluginsOfType<Module>().ToList();
|
||||
List<Module> modules = _pluginManagementService.GetPluginsOfType<Module>().ToList();
|
||||
foreach (Module module in modules)
|
||||
AddModule(module);
|
||||
|
||||
@ -210,15 +210,15 @@ namespace Artemis.UI.Screens.Sidebar
|
||||
|
||||
#region Event handlers
|
||||
|
||||
private void PluginServiceOnPluginEnabled(object sender, PluginEventArgs e)
|
||||
private void PluginManagementServiceOnPluginManagementEnabled(object sender, PluginEventArgs e)
|
||||
{
|
||||
if (e.PluginInfo.Instance is Module module)
|
||||
if (e.PluginInfo.Plugin is Module module)
|
||||
AddModule(module);
|
||||
}
|
||||
|
||||
private void PluginServiceOnPluginDisabled(object sender, PluginEventArgs e)
|
||||
private void PluginManagementServiceOnPluginManagementDisabled(object sender, PluginEventArgs e)
|
||||
{
|
||||
if (e.PluginInfo.Instance is Module module)
|
||||
if (e.PluginInfo.Plugin is Module module)
|
||||
RemoveModule(module);
|
||||
}
|
||||
|
||||
|
||||
@ -10,13 +10,13 @@ namespace Artemis.UI.Screens.Splash
|
||||
public class SplashViewModel : Screen
|
||||
{
|
||||
private readonly ICoreService _coreService;
|
||||
private readonly IPluginService _pluginService;
|
||||
private readonly IPluginManagementService _pluginManagementService;
|
||||
private string _status;
|
||||
|
||||
public SplashViewModel(ICoreService coreService, IPluginService pluginService)
|
||||
public SplashViewModel(ICoreService coreService, IPluginManagementService pluginManagementService)
|
||||
{
|
||||
_coreService = coreService;
|
||||
_pluginService = pluginService;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
Status = "Initializing Core";
|
||||
}
|
||||
|
||||
@ -37,46 +37,46 @@ namespace Artemis.UI.Screens.Splash
|
||||
protected override void OnInitialActivate()
|
||||
{
|
||||
_coreService.Initialized += OnCoreServiceOnInitialized;
|
||||
_pluginService.CopyingBuildInPlugins += OnPluginServiceOnCopyingBuildInPlugins;
|
||||
_pluginService.PluginLoading += OnPluginServiceOnPluginLoading;
|
||||
_pluginService.PluginLoaded += OnPluginServiceOnPluginLoaded;
|
||||
_pluginService.PluginEnabling += PluginServiceOnPluginEnabling;
|
||||
_pluginService.PluginEnabled += PluginServiceOnPluginEnabled;
|
||||
_pluginManagementService.CopyingBuildInPlugins += OnPluginManagementServiceOnCopyingBuildInPluginsManagement;
|
||||
_pluginManagementService.PluginLoading += OnPluginManagementServiceOnPluginManagementLoading;
|
||||
_pluginManagementService.PluginLoaded += OnPluginManagementServiceOnPluginManagementLoaded;
|
||||
_pluginManagementService.PluginEnabling += PluginManagementServiceOnPluginManagementEnabling;
|
||||
_pluginManagementService.PluginEnabled += PluginManagementServiceOnPluginManagementEnabled;
|
||||
base.OnInitialActivate();
|
||||
}
|
||||
|
||||
protected override void OnClose()
|
||||
{
|
||||
_coreService.Initialized -= OnCoreServiceOnInitialized;
|
||||
_pluginService.CopyingBuildInPlugins -= OnPluginServiceOnCopyingBuildInPlugins;
|
||||
_pluginService.PluginLoading -= OnPluginServiceOnPluginLoading;
|
||||
_pluginService.PluginLoaded -= OnPluginServiceOnPluginLoaded;
|
||||
_pluginService.PluginEnabling -= PluginServiceOnPluginEnabling;
|
||||
_pluginService.PluginEnabled -= PluginServiceOnPluginEnabled;
|
||||
_pluginManagementService.CopyingBuildInPlugins -= OnPluginManagementServiceOnCopyingBuildInPluginsManagement;
|
||||
_pluginManagementService.PluginLoading -= OnPluginManagementServiceOnPluginManagementLoading;
|
||||
_pluginManagementService.PluginLoaded -= OnPluginManagementServiceOnPluginManagementLoaded;
|
||||
_pluginManagementService.PluginEnabling -= PluginManagementServiceOnPluginManagementEnabling;
|
||||
_pluginManagementService.PluginEnabled -= PluginManagementServiceOnPluginManagementEnabled;
|
||||
base.OnClose();
|
||||
}
|
||||
|
||||
private void OnPluginServiceOnPluginLoaded(object sender, PluginEventArgs args)
|
||||
private void OnPluginManagementServiceOnPluginManagementLoaded(object sender, PluginEventArgs args)
|
||||
{
|
||||
Status = "Initializing UI";
|
||||
}
|
||||
|
||||
private void OnPluginServiceOnPluginLoading(object sender, PluginEventArgs args)
|
||||
private void OnPluginManagementServiceOnPluginManagementLoading(object sender, PluginEventArgs args)
|
||||
{
|
||||
Status = "Loading plugin: " + args.PluginInfo.Name;
|
||||
}
|
||||
|
||||
private void PluginServiceOnPluginEnabled(object sender, PluginEventArgs args)
|
||||
private void PluginManagementServiceOnPluginManagementEnabled(object sender, PluginEventArgs args)
|
||||
{
|
||||
Status = "Initializing UI";
|
||||
}
|
||||
|
||||
private void PluginServiceOnPluginEnabling(object sender, PluginEventArgs args)
|
||||
private void PluginManagementServiceOnPluginManagementEnabling(object sender, PluginEventArgs args)
|
||||
{
|
||||
Status = "Enabling plugin: " + args.PluginInfo.Name;
|
||||
}
|
||||
|
||||
private void OnPluginServiceOnCopyingBuildInPlugins(object sender, EventArgs args)
|
||||
private void OnPluginManagementServiceOnCopyingBuildInPluginsManagement(object sender, EventArgs args)
|
||||
{
|
||||
Status = "Updating built-in plugins";
|
||||
}
|
||||
|
||||
@ -13,19 +13,19 @@ namespace Artemis.UI.Services
|
||||
{
|
||||
private readonly IDataModelUIService _dataModelUIService;
|
||||
private readonly IProfileEditorService _profileEditorService;
|
||||
private readonly IPluginService _pluginService;
|
||||
private readonly IPluginManagementService _pluginManagementService;
|
||||
private bool _registeredBuiltInDataModelDisplays;
|
||||
private bool _registeredBuiltInDataModelInputs;
|
||||
private bool _registeredBuiltInPropertyEditors;
|
||||
|
||||
public RegistrationService(IDataModelUIService dataModelUIService, IProfileEditorService profileEditorService, IPluginService pluginService)
|
||||
public RegistrationService(IDataModelUIService dataModelUIService, IProfileEditorService profileEditorService, IPluginManagementService pluginManagementService)
|
||||
{
|
||||
_dataModelUIService = dataModelUIService;
|
||||
_profileEditorService = profileEditorService;
|
||||
_pluginService = pluginService;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
|
||||
LoadPluginModules();
|
||||
pluginService.PluginLoaded += PluginServiceOnPluginLoaded;
|
||||
pluginManagementService.PluginLoaded += PluginServiceOnPluginLoaded;
|
||||
}
|
||||
|
||||
public void RegisterBuiltInDataModelDisplays()
|
||||
@ -80,7 +80,7 @@ namespace Artemis.UI.Services
|
||||
|
||||
private void LoadPluginModules()
|
||||
{
|
||||
foreach (PluginInfo pluginInfo in _pluginService.GetAllPluginInfo())
|
||||
foreach (PluginInfo pluginInfo in _pluginManagementService.GetAllPluginInfo())
|
||||
pluginInfo.Kernel.Load(new[] { new PluginUIModule(pluginInfo) });
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user