1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00
2019-10-22 22:52:02 +02:00

228 lines
8.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Artemis.Core.Events;
using Artemis.Core.Exceptions;
using Artemis.Core.Models.Surface;
using Artemis.Core.Services.Interfaces;
using Artemis.Storage.Repositories.Interfaces;
using RGB.NET.Core;
using Serilog;
namespace Artemis.Core.Services.Storage
{
public class SurfaceService : ISurfaceService
{
private readonly ILogger _logger;
private readonly IRgbService _rgbService;
private readonly List<SurfaceConfiguration> _surfaceConfigurations;
private readonly ISurfaceRepository _surfaceRepository;
private SurfaceConfiguration _activeSurfaceConfiguration;
public SurfaceService(ILogger logger, ISurfaceRepository surfaceRepository, IRgbService rgbService)
{
_logger = logger;
_surfaceRepository = surfaceRepository;
_rgbService = rgbService;
_surfaceConfigurations = new List<SurfaceConfiguration>();
LoadFromRepository();
_rgbService.DeviceLoaded += RgbServiceOnDeviceLoaded;
}
public SurfaceConfiguration ActiveSurfaceConfiguration
{
get => _activeSurfaceConfiguration;
set
{
if (_activeSurfaceConfiguration == value)
return;
_activeSurfaceConfiguration = value;
lock (_surfaceConfigurations)
{
// Mark only the new value as active
foreach (var surfaceConfiguration in _surfaceConfigurations)
surfaceConfiguration.IsActive = false;
_activeSurfaceConfiguration.IsActive = true;
SaveToRepository(_surfaceConfigurations, true);
}
// Apply the active surface configuration to the devices
if (ActiveSurfaceConfiguration != null)
{
foreach (var deviceConfiguration in ActiveSurfaceConfiguration.DeviceConfigurations)
deviceConfiguration.ApplyToDevice();
}
// Update the RGB service's graphics decorator to work with the new surface configuration
_rgbService.GraphicsDecorator.UpdateBitmap();
OnActiveSurfaceConfigurationChanged(new SurfaceConfigurationEventArgs(_activeSurfaceConfiguration));
}
}
public ReadOnlyCollection<SurfaceConfiguration> SurfaceConfigurations
{
get
{
lock (_surfaceConfigurations)
{
return _surfaceConfigurations.AsReadOnly();
}
}
}
public SurfaceConfiguration CreateSurfaceConfiguration(string name)
{
// Create a blank config
var configuration = new SurfaceConfiguration(name);
// Add all current devices
foreach (var rgbDevice in _rgbService.LoadedDevices)
{
var deviceId = GetDeviceId(rgbDevice);
configuration.DeviceConfigurations.Add(new SurfaceDeviceConfiguration(rgbDevice, deviceId, configuration));
}
lock (_surfaceConfigurations)
{
_surfaceRepository.Add(configuration.SurfaceEntity);
SaveToRepository(configuration, true);
return configuration;
}
}
public void DeleteSurfaceConfiguration(SurfaceConfiguration surfaceConfiguration)
{
if (surfaceConfiguration == ActiveSurfaceConfiguration)
throw new ArtemisCoreException($"Cannot delete surface configuration '{surfaceConfiguration.Name}' because it is active.");
lock (_surfaceConfigurations)
{
surfaceConfiguration.Destroy();
_surfaceConfigurations.Remove(surfaceConfiguration);
_surfaceRepository.Remove(surfaceConfiguration.SurfaceEntity);
_surfaceRepository.Save();
}
}
#region Event handlers
private void RgbServiceOnDeviceLoaded(object sender, DeviceEventArgs e)
{
lock (_surfaceConfigurations)
{
foreach (var surfaceConfiguration in _surfaceConfigurations)
MatchDeviceConfiguration(e.Device, surfaceConfiguration);
}
foreach (var deviceConfiguration in ActiveSurfaceConfiguration.DeviceConfigurations)
deviceConfiguration.ApplyToDevice();
}
#endregion
#region Repository
private void LoadFromRepository()
{
var configs = _surfaceRepository.GetAll();
foreach (var surfaceEntity in configs)
{
// Create the surface configuration
var surfaceConfiguration = new SurfaceConfiguration(surfaceEntity);
// For each loaded device, match a device configuration
var devices = _rgbService.LoadedDevices;
foreach (var rgbDevice in devices)
MatchDeviceConfiguration(rgbDevice, surfaceConfiguration);
// Finally, add the surface config to the collection
lock (_surfaceConfigurations)
{
_surfaceConfigurations.Add(surfaceConfiguration);
}
}
// When all surface configs are loaded, apply the active surface config
var active = SurfaceConfigurations.FirstOrDefault(c => c.IsActive);
if (active != null)
ActiveSurfaceConfiguration = active;
}
public void SaveToRepository(List<SurfaceConfiguration> surfaceConfigurations, bool includeDevices)
{
foreach (var surfaceConfiguration in surfaceConfigurations)
{
surfaceConfiguration.ApplyToEntity();
if (!includeDevices)
{
foreach (var deviceConfiguration in surfaceConfiguration.DeviceConfigurations)
deviceConfiguration.ApplyToEntity();
}
}
_surfaceRepository.Save();
}
public void SaveToRepository(SurfaceConfiguration surfaceConfiguration, bool includeDevices)
{
surfaceConfiguration.ApplyToEntity();
if (includeDevices)
{
foreach (var deviceConfiguration in surfaceConfiguration.DeviceConfigurations)
deviceConfiguration.ApplyToEntity();
}
_surfaceRepository.Save();
}
#endregion
#region Utilities
private void MatchDeviceConfiguration(IRGBDevice rgbDevice, SurfaceConfiguration surfaceConfiguration)
{
var deviceId = GetDeviceId(rgbDevice);
var deviceConfig = surfaceConfiguration.DeviceConfigurations.FirstOrDefault(d => d.DeviceName == rgbDevice.DeviceInfo.DeviceName &&
d.DeviceModel == rgbDevice.DeviceInfo.Model &&
d.DeviceManufacturer == rgbDevice.DeviceInfo.Manufacturer &&
d.DeviceId == deviceId);
if (deviceConfig == null)
{
_logger.Information("No active surface config found for {deviceInfo}, device ID: {deviceId}. Adding a new entry.", rgbDevice.DeviceInfo, deviceId);
deviceConfig = new SurfaceDeviceConfiguration(rgbDevice, deviceId, surfaceConfiguration);
surfaceConfiguration.DeviceConfigurations.Add(deviceConfig);
}
deviceConfig.Device = rgbDevice;
deviceConfig.ApplyToDevice();
}
private int GetDeviceId(IRGBDevice rgbDevice)
{
return _rgbService.LoadedDevices
.Where(d => d.DeviceInfo.DeviceName == rgbDevice.DeviceInfo.DeviceName &&
d.DeviceInfo.Model == rgbDevice.DeviceInfo.Model &&
d.DeviceInfo.Manufacturer == rgbDevice.DeviceInfo.Manufacturer)
.ToList()
.IndexOf(rgbDevice) + 1;
}
#endregion
#region Events
public event EventHandler<SurfaceConfigurationEventArgs> ActiveSurfaceConfigurationChanged;
protected virtual void OnActiveSurfaceConfigurationChanged(SurfaceConfigurationEventArgs e)
{
ActiveSurfaceConfigurationChanged?.Invoke(this, e);
}
#endregion
}
}