1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-31 01:42:02 +00:00

Devices - Updated for RGB.NET changes

This commit is contained in:
Robert 2021-02-14 15:51:41 +01:00
parent c70e7d0c00
commit 7ccc9c54fb
7 changed files with 176 additions and 98 deletions

View File

@ -38,7 +38,7 @@ namespace Artemis.Core
Leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly(); Leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
LedIds = new ReadOnlyDictionary<LedId, ArtemisLed>(Leds.ToDictionary(l => l.RgbLed.Id, l => l)); LedIds = new ReadOnlyDictionary<LedId, ArtemisLed>(Leds.ToDictionary(l => l.RgbLed.Id, l => l));
LoadBestLayout(); ApplyKeyboardLayout();
ApplyToEntity(); ApplyToEntity();
CalculateRenderProperties(); CalculateRenderProperties();
} }
@ -56,7 +56,8 @@ namespace Artemis.Core
Leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly(); Leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly();
LedIds = new ReadOnlyDictionary<LedId, ArtemisLed>(Leds.ToDictionary(l => l.RgbLed.Id, l => l)); LedIds = new ReadOnlyDictionary<LedId, ArtemisLed>(Leds.ToDictionary(l => l.RgbLed.Id, l => l));
LoadBestLayout();
ApplyKeyboardLayout();
} }
/// <summary> /// <summary>
@ -229,12 +230,12 @@ namespace Artemis.Core
/// Gets or sets the physical layout of the device e.g. ISO or ANSI. /// Gets or sets the physical layout of the device e.g. ISO or ANSI.
/// <para>Only applicable to keyboards</para> /// <para>Only applicable to keyboards</para>
/// </summary> /// </summary>
public string? PhysicalLayout public KeyboardLayoutType PhysicalLayout
{ {
get => DeviceEntity.PhysicalLayout; get => (KeyboardLayoutType) DeviceEntity.PhysicalLayout;
set set
{ {
DeviceEntity.PhysicalLayout = value; DeviceEntity.PhysicalLayout = (int) value;
OnPropertyChanged(nameof(PhysicalLayout)); OnPropertyChanged(nameof(PhysicalLayout));
} }
} }
@ -296,8 +297,8 @@ namespace Artemis.Core
{ {
// Take out invalid file name chars, may not be perfect but neither are you // Take out invalid file name chars, may not be perfect but neither are you
string fileName = System.IO.Path.GetInvalidFileNameChars().Aggregate(RgbDevice.DeviceInfo.Model, (current, c) => current.Replace(c, '-')); string fileName = System.IO.Path.GetInvalidFileNameChars().Aggregate(RgbDevice.DeviceInfo.Model, (current, c) => current.Replace(c, '-'));
if (PhysicalLayout != null) if (RgbDevice is IKeyboard)
fileName = $"{fileName}-{PhysicalLayout.ToUpper()}"; fileName = $"{fileName}-{PhysicalLayout.ToString().ToUpper()}";
if (includeExtension) if (includeExtension)
fileName = $"{fileName}.xml"; fileName = $"{fileName}.xml";
@ -309,9 +310,7 @@ namespace Artemis.Core
/// </summary> /// </summary>
public void LoadBestLayout() public void LoadBestLayout()
{ {
// If supported, detect the device layout so that we can load the correct one
if (DeviceProvider.CanDetectLogicalLayout || DeviceProvider.CanDetectPhysicalLayout && RgbDevice is IKeyboard)
DeviceProvider.DetectDeviceLayout(this);
// Look for a user layout // Look for a user layout
// ... here // ... here
@ -325,11 +324,23 @@ namespace Artemis.Core
ApplyLayout(deviceProviderLayout); ApplyLayout(deviceProviderLayout);
} }
private void ApplyKeyboardLayout()
{
if (!(RgbDevice is IKeyboard keyboard))
return;
// If supported, detect the device layout so that we can load the correct one
if (DeviceProvider.CanDetectLogicalLayout )
LogicalLayout = DeviceProvider.GetLogicalLayout(keyboard);
if (DeviceProvider.CanDetectPhysicalLayout)
PhysicalLayout = (KeyboardLayoutType) keyboard.DeviceInfo.Layout;
}
/// <summary> /// <summary>
/// Applies the provided layout to the device /// Applies the provided layout to the device
/// </summary> /// </summary>
/// <param name="layout">The layout to apply</param> /// <param name="layout">The layout to apply</param>
public void ApplyLayout(ArtemisLayout layout) internal void ApplyLayout(ArtemisLayout layout)
{ {
if (layout.IsValid) if (layout.IsValid)
layout.RgbLayout!.ApplyTo(RgbDevice); layout.RgbLayout!.ApplyTo(RgbDevice);

View File

@ -0,0 +1,41 @@
// ReSharper disable InconsistentNaming
namespace Artemis.Core
{
// Copied from RGB.NET to avoid needing to reference RGB.NET
/// <summary>
/// Represents a physical layout type for a keyboard
/// </summary>
public enum KeyboardLayoutType
{
/// <summary>
/// An unknown layout type
/// </summary>
Unknown = 0,
/// <summary>
/// The ANSI layout type, often used in the US (uses a short enter)
/// </summary>
ANSI = 1,
/// <summary>
/// The ISO layout type, often used in the EU (uses a tall enter)
/// </summary>
ISO = 2,
/// <summary>
/// The JIS layout type, often used in Japan (based on ISO)
/// </summary>
JIS = 3,
/// <summary>
/// The ABNT layout type, often used in Brazil/Portugal (based on ISO)
/// </summary>
ABNT = 4,
/// <summary>
/// The KS layout type, often used in South Korea
/// </summary>
KS = 5
}
}

View File

@ -36,7 +36,7 @@ namespace Artemis.Core.DeviceProviders
/// <summary> /// <summary>
/// A boolean indicating whether this device provider detects the physical layout of connected keyboards. /// A boolean indicating whether this device provider detects the physical layout of connected keyboards.
/// <para> /// <para>
/// Note: <see cref="DetectDeviceLayout" /> is only called when this or <see cref="CanDetectLogicalLayout" /> /// Note: <see cref="GetLogicalLayout" /> is only called when this or <see cref="CanDetectLogicalLayout" />
/// is <see langword="true" />. /// is <see langword="true" />.
/// </para> /// </para>
/// </summary> /// </summary>
@ -45,7 +45,7 @@ namespace Artemis.Core.DeviceProviders
/// <summary> /// <summary>
/// A boolean indicating whether this device provider detects the logical layout of connected keyboards /// A boolean indicating whether this device provider detects the logical layout of connected keyboards
/// <para> /// <para>
/// Note: <see cref="DetectDeviceLayout" /> is only called when this or <see cref="CanDetectPhysicalLayout" /> /// Note: <see cref="GetLogicalLayout" /> is only called when this or <see cref="CanDetectPhysicalLayout" />
/// is <see langword="true" />. /// is <see langword="true" />.
/// </para> /// </para>
/// </summary> /// </summary>
@ -77,12 +77,13 @@ namespace Artemis.Core.DeviceProviders
/// <summary> /// <summary>
/// Called when a specific RGB device's logical and physical layout must be detected /// Called when a specific RGB device's logical and physical layout must be detected
/// <para> /// <para>
/// Note: Only called when <see cref="CanDetectPhysicalLayout" /> or <see cref="CanDetectLogicalLayout" /> is <see langword="true" />. /// Note: Only called when <see cref="CanDetectLogicalLayout" /> is <see langword="true" />.
/// </para> /// </para>
/// </summary> /// </summary>
/// <param name="rgbDevice">The device to detect the layout for, always a keyboard</param> /// <param name="keyboard">The device to detect the layout for, always a keyboard</param>
public virtual void DetectDeviceLayout(ArtemisDevice rgbDevice) public virtual string GetLogicalLayout(IKeyboard keyboard)
{ {
throw new NotImplementedException("Device provider does not support detecting logical layouts (don't call base.GetLogicalLayout())");
} }
} }
} }

View File

@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Artemis.Core.DeviceProviders;
using RGB.NET.Core; using RGB.NET.Core;
namespace Artemis.Core.Services namespace Artemis.Core.Services
@ -56,6 +55,11 @@ namespace Artemis.Core.Services
/// </summary> /// </summary>
event EventHandler<DeviceEventArgs> DeviceReloaded; event EventHandler<DeviceEventArgs> DeviceReloaded;
/// <summary>
/// Occurs when a single device was removed
/// </summary>
event EventHandler<DeviceEventArgs> DeviceRemoved;
/// <summary> /// <summary>
/// Recalculates the LED group used by the <see cref="BitmapBrush" /> /// Recalculates the LED group used by the <see cref="BitmapBrush" />
/// </summary> /// </summary>

View File

@ -51,8 +51,10 @@ namespace Artemis.Core.Services
{ {
try try
{ {
// Device provider may have been attached before..? List<IRGBDevice> toRemove = deviceProvider.Devices.Where(d => Surface.Devices.Contains(d)).ToList();
Surface.Detach(deviceProvider.Devices); Surface.Detach(deviceProvider.Devices);
foreach (IRGBDevice rgbDevice in toRemove)
OnDeviceRemoved(new DeviceEventArgs(rgbDevice));
deviceProvider.Initialize(RGBDeviceType.All, true); deviceProvider.Initialize(RGBDeviceType.All, true);
Surface.Attach(deviceProvider.Devices); Surface.Attach(deviceProvider.Devices);
@ -111,6 +113,7 @@ namespace Artemis.Core.Services
public event EventHandler<DeviceEventArgs>? DeviceLoaded; public event EventHandler<DeviceEventArgs>? DeviceLoaded;
public event EventHandler<DeviceEventArgs>? DeviceReloaded; public event EventHandler<DeviceEventArgs>? DeviceReloaded;
public event EventHandler<DeviceEventArgs> DeviceRemoved;
public void UpdateSurfaceLedGroup(ArtemisSurface? artemisSurface) public void UpdateSurfaceLedGroup(ArtemisSurface? artemisSurface)
{ {
@ -147,6 +150,11 @@ namespace Artemis.Core.Services
DeviceReloaded?.Invoke(this, e); DeviceReloaded?.Invoke(this, e);
} }
protected virtual void OnDeviceRemoved(DeviceEventArgs e)
{
DeviceRemoved?.Invoke(this, e);
}
#endregion #endregion
} }
} }

View File

@ -32,8 +32,88 @@ namespace Artemis.Core.Services
LoadFromRepository(); LoadFromRepository();
_rgbService.DeviceLoaded += RgbServiceOnDeviceLoaded; _rgbService.DeviceLoaded += RgbServiceOnDeviceLoaded;
_rgbService.DeviceRemoved += RgbServiceOnDeviceRemoved;
} }
#region Repository
private void LoadFromRepository()
{
List<SurfaceEntity> configs = _surfaceRepository.GetAll();
foreach (SurfaceEntity surfaceEntity in configs)
{
// Create the surface entity
ArtemisSurface surfaceConfiguration = new(_rgbService.Surface, surfaceEntity);
foreach (DeviceEntity position in surfaceEntity.DeviceEntities)
{
IRGBDevice? device = _rgbService.Surface.Devices.FirstOrDefault(d => d.GetDeviceIdentifier() == position.DeviceIdentifier);
if (device != null)
{
DeviceProvider deviceProvider = _pluginManagementService.GetDeviceProviderByDevice(device);
surfaceConfiguration.Devices.Add(new ArtemisDevice(device, deviceProvider, surfaceConfiguration, position));
}
}
// Finally, add the surface config to the collection
lock (_surfaceConfigurations)
{
_surfaceConfigurations.Add(surfaceConfiguration);
}
}
// When all surface configs are loaded, apply the active surface config
ArtemisSurface? active = SurfaceConfigurations.FirstOrDefault(c => c.IsActive);
if (active != null)
{
SetActiveSurfaceConfiguration(active);
}
else
{
active = SurfaceConfigurations.FirstOrDefault();
if (active != null)
SetActiveSurfaceConfiguration(active);
else
SetActiveSurfaceConfiguration(CreateSurfaceConfiguration("Default"));
}
}
#endregion
#region Utilities
private void AddDeviceIfMissing(IRGBDevice rgbDevice, ArtemisSurface surface)
{
string deviceIdentifier = rgbDevice.GetDeviceIdentifier();
ArtemisDevice? device = surface.Devices.FirstOrDefault(d => d.DeviceEntity.DeviceIdentifier == deviceIdentifier);
if (device != null)
return;
// Find an existing device config and use that
DeviceEntity? existingDeviceConfig = surface.SurfaceEntity.DeviceEntities.FirstOrDefault(d => d.DeviceIdentifier == deviceIdentifier);
if (existingDeviceConfig != null)
{
DeviceProvider deviceProvider = _pluginManagementService.GetDeviceProviderByDevice(rgbDevice);
device = new ArtemisDevice(rgbDevice, deviceProvider, surface, existingDeviceConfig);
}
// Fall back on creating a new device
else
{
_logger.Information(
"No device config found for {deviceInfo}, device hash: {deviceHashCode}. Adding a new entry.",
rgbDevice.DeviceInfo,
deviceIdentifier
);
DeviceProvider deviceProvider = _pluginManagementService.GetDeviceProviderByDevice(rgbDevice);
device = new ArtemisDevice(rgbDevice, deviceProvider, surface);
}
surface.Devices.Add(device);
}
#endregion
public ArtemisSurface ActiveSurface { get; private set; } public ArtemisSurface ActiveSurface { get; private set; }
public ReadOnlyCollection<ArtemisSurface> SurfaceConfigurations => _surfaceConfigurations.AsReadOnly(); public ReadOnlyCollection<ArtemisSurface> SurfaceConfigurations => _surfaceConfigurations.AsReadOnly();
@ -97,14 +177,12 @@ namespace Artemis.Core.Services
{ {
surface.ApplyToEntity(); surface.ApplyToEntity();
if (includeDevices) if (includeDevices)
{
foreach (ArtemisDevice deviceConfiguration in surface.Devices) foreach (ArtemisDevice deviceConfiguration in surface.Devices)
{ {
deviceConfiguration.ApplyToEntity(); deviceConfiguration.ApplyToEntity();
if (surface.IsActive) if (surface.IsActive)
deviceConfiguration.ApplyToRgbDevice(); deviceConfiguration.ApplyToRgbDevice();
} }
}
surface.UpdateLedMap(); surface.UpdateLedMap();
@ -126,82 +204,6 @@ namespace Artemis.Core.Services
} }
} }
#region Repository
private void LoadFromRepository()
{
List<SurfaceEntity> configs = _surfaceRepository.GetAll();
foreach (SurfaceEntity surfaceEntity in configs)
{
// Create the surface entity
ArtemisSurface surfaceConfiguration = new(_rgbService.Surface, surfaceEntity);
foreach (DeviceEntity position in surfaceEntity.DeviceEntities)
{
IRGBDevice? device = _rgbService.Surface.Devices.FirstOrDefault(d => d.GetDeviceIdentifier() == position.DeviceIdentifier);
if (device != null)
{
DeviceProvider deviceProvider = _pluginManagementService.GetDeviceProviderByDevice(device);
surfaceConfiguration.Devices.Add(new ArtemisDevice(device, deviceProvider, surfaceConfiguration, position));
}
}
// Finally, add the surface config to the collection
lock (_surfaceConfigurations)
{
_surfaceConfigurations.Add(surfaceConfiguration);
}
}
// When all surface configs are loaded, apply the active surface config
ArtemisSurface? active = SurfaceConfigurations.FirstOrDefault(c => c.IsActive);
if (active != null)
SetActiveSurfaceConfiguration(active);
else
{
active = SurfaceConfigurations.FirstOrDefault();
if (active != null)
SetActiveSurfaceConfiguration(active);
else
SetActiveSurfaceConfiguration(CreateSurfaceConfiguration("Default"));
}
}
#endregion
#region Utilities
private void AddDeviceIfMissing(IRGBDevice rgbDevice, ArtemisSurface surface)
{
string deviceIdentifier = rgbDevice.GetDeviceIdentifier();
ArtemisDevice? device = surface.Devices.FirstOrDefault(d => d.DeviceEntity.DeviceIdentifier == deviceIdentifier);
if (device != null)
return;
// Find an existing device config and use that
DeviceEntity? existingDeviceConfig = surface.SurfaceEntity.DeviceEntities.FirstOrDefault(d => d.DeviceIdentifier == deviceIdentifier);
if (existingDeviceConfig != null)
{
DeviceProvider deviceProvider = _pluginManagementService.GetDeviceProviderByDevice(rgbDevice);
device = new ArtemisDevice(rgbDevice, deviceProvider, surface, existingDeviceConfig);
}
// Fall back on creating a new device
else
{
_logger.Information(
"No device config found for {deviceInfo}, device hash: {deviceHashCode}. Adding a new entry.",
rgbDevice.DeviceInfo,
deviceIdentifier
);
DeviceProvider deviceProvider = _pluginManagementService.GetDeviceProviderByDevice(rgbDevice);
device = new ArtemisDevice(rgbDevice, deviceProvider, surface);
}
surface.Devices.Add(device);
}
#endregion
#region AutoLayout #region AutoLayout
public void AutoArrange(ArtemisSurface? artemisSurface = null) public void AutoArrange(ArtemisSurface? artemisSurface = null)
@ -209,7 +211,7 @@ namespace Artemis.Core.Services
artemisSurface ??= ActiveSurface; artemisSurface ??= ActiveSurface;
if (!artemisSurface.Devices.Any()) if (!artemisSurface.Devices.Any())
return; return;
SurfaceArrangement surfaceArrangement = SurfaceArrangement.GetDefaultArrangement(); SurfaceArrangement surfaceArrangement = SurfaceArrangement.GetDefaultArrangement();
surfaceArrangement.Arrange(artemisSurface); surfaceArrangement.Arrange(artemisSurface);
UpdateSurfaceConfiguration(artemisSurface, true); UpdateSurfaceConfiguration(artemisSurface, true);
@ -230,6 +232,17 @@ namespace Artemis.Core.Services
UpdateSurfaceConfiguration(ActiveSurface, true); UpdateSurfaceConfiguration(ActiveSurface, true);
} }
private void RgbServiceOnDeviceRemoved(object? sender, DeviceEventArgs e)
{
lock (_surfaceConfigurations)
{
foreach (ArtemisSurface surfaceConfiguration in _surfaceConfigurations)
surfaceConfiguration.Devices.RemoveAll(d => d.RgbDevice == e.Device);
}
UpdateSurfaceConfiguration(ActiveSurface, true);
}
#endregion #endregion
#region Events #region Events

View File

@ -20,7 +20,7 @@ namespace Artemis.Storage.Entities.Surface
public double BlueScale { get; set; } public double BlueScale { get; set; }
public bool IsEnabled { get; set; } public bool IsEnabled { get; set; }
public string PhysicalLayout { get; set; } public int PhysicalLayout { get; set; }
public string LogicalLayout { get; set; } public string LogicalLayout { get; set; }
public List<DeviceInputIdentifierEntity> InputIdentifiers { get; set; } public List<DeviceInputIdentifierEntity> InputIdentifiers { get; set; }