diff --git a/src/Artemis.Core/Models/Surface/ArtemisDevice.cs b/src/Artemis.Core/Models/Surface/ArtemisDevice.cs index 9339739d0..0317d99fa 100644 --- a/src/Artemis.Core/Models/Surface/ArtemisDevice.cs +++ b/src/Artemis.Core/Models/Surface/ArtemisDevice.cs @@ -5,6 +5,7 @@ using System.Linq; using Artemis.Core.DeviceProviders; using Artemis.Storage.Entities.Surface; using RGB.NET.Core; +using RGB.NET.Layout; using SkiaSharp; namespace Artemis.Core @@ -31,14 +32,13 @@ namespace Artemis.Core GreenScale = 1; BlueScale = 1; IsEnabled = true; - - deviceProvider.DeviceLayoutPaths.TryGetValue(rgbDevice, out string? layoutPath); - LayoutPath = layoutPath; - + InputIdentifiers = new List(); Leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly(); LedIds = new ReadOnlyDictionary(Leds.ToDictionary(l => l.RgbLed.Id, l => l)); + + LoadBestLayout(); ApplyToEntity(); CalculateRenderProperties(); } @@ -49,16 +49,14 @@ namespace Artemis.Core RgbDevice = rgbDevice; DeviceProvider = deviceProvider; Surface = surface; - - deviceProvider.DeviceLayoutPaths.TryGetValue(rgbDevice, out string? layoutPath); - LayoutPath = layoutPath; - + InputIdentifiers = new List(); foreach (DeviceInputIdentifierEntity identifierEntity in DeviceEntity.InputIdentifiers) InputIdentifiers.Add(new ArtemisDeviceInputIdentifier(identifierEntity.InputProvider, identifierEntity.Identifier)); Leds = rgbDevice.Select(l => new ArtemisLed(l, this)).ToList().AsReadOnly(); LedIds = new ReadOnlyDictionary(Leds.ToDictionary(l => l.RgbLed.Id, l => l)); + LoadBestLayout(); } /// @@ -227,11 +225,6 @@ namespace Artemis.Core } } - /// - /// Gets the path to where the layout of the device was (attempted to be) loaded from - /// - public string? LayoutPath { get; internal set; } - /// /// Gets the layout of the device expanded with Artemis-specific data /// @@ -266,6 +259,15 @@ namespace Artemis.Core return artemisLed; } + public void LoadBestLayout() + { + ArtemisLayout artemisLayout = DeviceProvider.LoadLayout(RgbDevice); + if (artemisLayout.IsValid) + artemisLayout.DeviceLayout!.ApplyTo(RgbDevice); + + Layout = artemisLayout; + } + internal void ApplyToEntity() { // Other properties are computed diff --git a/src/Artemis.Core/Models/Surface/ArtemisLayout.cs b/src/Artemis.Core/Models/Surface/ArtemisLayout.cs index 64dc6409a..cf61d8752 100644 --- a/src/Artemis.Core/Models/Surface/ArtemisLayout.cs +++ b/src/Artemis.Core/Models/Surface/ArtemisLayout.cs @@ -1,10 +1,57 @@ using System; +using RGB.NET.Layout; namespace Artemis.Core { + /// + /// Represents a device layout decorated with extra Artemis-specific data + /// public class ArtemisLayout { - public ArtemisDevice Device { get; set; } - public Uri Image { get; set; } + /// + /// Creates a new instance of the class + /// + /// The path of the layout XML file + public ArtemisLayout(string filePath) + { + FilePath = filePath; + DeviceLayout = DeviceLayout.Load(FilePath); + IsValid = DeviceLayout != null; + } + + /// + /// Gets the file path the layout was (attempted to be) loaded from + /// + public string FilePath { get; } + + /// + /// Gets the RGB.NET device layout + /// + public DeviceLayout? DeviceLayout { get; } + + /// + /// Gets a boolean indicating whether a valid layout was loaded + /// + public bool IsValid { get; } + + /// + /// Gets the device this image is applied to + /// + public ArtemisDevice? Device { get; internal set; } + + /// + /// Gets or sets the physical layout of the device. Only applicable to keyboards + /// + public string? PhysicalLayout { get; set; } + + /// + /// Gets or sets the logical layout of the device. Only applicable to keyboards + /// + public string? LogicalLayout { get; set; } + + /// + /// Gets or sets the image of the device + /// + public Uri? Image { get; set; } } } \ No newline at end of file diff --git a/src/Artemis.Core/Plugins/DeviceProviders/DeviceProvider.cs b/src/Artemis.Core/Plugins/DeviceProviders/DeviceProvider.cs index 84b276192..9ae9f0e20 100644 --- a/src/Artemis.Core/Plugins/DeviceProviders/DeviceProvider.cs +++ b/src/Artemis.Core/Plugins/DeviceProviders/DeviceProvider.cs @@ -1,6 +1,6 @@ using System; -using System.Collections.Generic; using System.IO; +using System.Linq; using Ninject; using RGB.NET.Core; using Serilog; @@ -34,7 +34,15 @@ namespace Artemis.Core.DeviceProviders [Inject] public ILogger? Logger { get; set; } - internal Dictionary DeviceLayoutPaths { get; set; } = new(); + /// + /// A boolean indicating whether this device provider detects the physical layout of connected keyboards + /// + public bool CanDetectPhysicalLayout { get; protected set; } + + /// + /// A boolean indicating whether this device provider detects the logical layout of connected keyboards + /// + public bool CanDetectLogicalLayout { get; protected set; } /// public override void Disable() @@ -43,31 +51,37 @@ namespace Artemis.Core.DeviceProviders } /// + /// Loads a layout for the specified device and wraps it in an /// - /// - /// - /// - protected void ResolveAbsolutePath(Type type, object sender, ResolvePathEventArgs e) + /// The device to load the layout for + /// The resulting Artemis layout + public virtual ArtemisLayout LoadLayout(IRGBDevice rgbDevice) { - if (sender.GetType() == type || sender.GetType().IsGenericType(type)) - { - // Start from the plugin directory - if (e.RelativePart != null && e.FileName != null) - e.FinalPath = Path.Combine(Plugin.Directory.FullName, e.RelativePart, e.FileName); - else if (e.RelativePath != null) - e.FinalPath = Path.Combine(Plugin.Directory.FullName, e.RelativePath); + // Take out invalid file name chars, may not be perfect but neither are you + string model = Path.GetInvalidFileNameChars().Aggregate(rgbDevice.DeviceInfo.Model, (current, c) => current.Replace(c, '-')); + string layoutDir = Path.Combine(Plugin.Directory.FullName, "Layouts"); + string filePath; + // if (rgbDevice.DeviceInfo is IPhysicalLayoutDeviceInfo) + // { + // filePath = Path.Combine( + // layoutDir, + // rgbDevice.DeviceInfo.Manufacturer, + // rgbDevice.DeviceInfo.DeviceType.ToString(), + // model, + // keyboard.DeviceInfo. + // ) + ".xml"; + // } + // else + // { + filePath = Path.Combine( + layoutDir, + rgbDevice.DeviceInfo.Manufacturer, + rgbDevice.DeviceInfo.DeviceType.ToString(), + model + ) + ".xml"; + // } - IRGBDevice device = (IRGBDevice) sender; - IRGBDeviceInfo deviceInfo = device.DeviceInfo; - if (e.FileName != null && !File.Exists(e.FinalPath)) - { - Logger?.Information("Couldn't find a layout for device {deviceName}, model {deviceModel} at {filePath}", - deviceInfo.DeviceName, deviceInfo.Model, e.FinalPath); - } - - if (e.FileName != null) - DeviceLayoutPaths[device] = e.FinalPath; - } + return new ArtemisLayout(filePath); } } } \ No newline at end of file diff --git a/src/Artemis.Core/Services/Interfaces/IRgbService.cs b/src/Artemis.Core/Services/Interfaces/IRgbService.cs index 6e50576fa..8e8769d56 100644 --- a/src/Artemis.Core/Services/Interfaces/IRgbService.cs +++ b/src/Artemis.Core/Services/Interfaces/IRgbService.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Artemis.Core.DeviceProviders; using RGB.NET.Core; namespace Artemis.Core.Services diff --git a/src/Artemis.Core/Services/RgbService.cs b/src/Artemis.Core/Services/RgbService.cs index 8d7d05fc7..c1f2bd5b7 100644 --- a/src/Artemis.Core/Services/RgbService.cs +++ b/src/Artemis.Core/Services/RgbService.cs @@ -71,8 +71,7 @@ namespace Artemis.Core.Services foreach (IRGBDevice surfaceDevice in deviceProvider.Devices) { - _logger.Debug("Device provider {deviceProvider} added {deviceName}", - deviceProvider.GetType().Name, surfaceDevice.DeviceInfo?.DeviceName); + _logger.Debug("Device provider {deviceProvider} added {deviceName}", deviceProvider.GetType().Name, surfaceDevice.DeviceInfo?.DeviceName); if (!_loadedDevices.Contains(surfaceDevice)) { _loadedDevices.Add(surfaceDevice); diff --git a/src/Artemis.UI/Screens/Settings/Debug/DeviceDebugView.xaml b/src/Artemis.UI/Screens/Settings/Debug/DeviceDebugView.xaml index 6ab2f00bd..3c4010319 100644 --- a/src/Artemis.UI/Screens/Settings/Debug/DeviceDebugView.xaml +++ b/src/Artemis.UI/Screens/Settings/Debug/DeviceDebugView.xaml @@ -112,24 +112,6 @@ - - - - - - - - - - Lighting support - - - - - @@ -160,7 +142,7 @@ Device image @@ -220,25 +202,7 @@ - - - - - - - - - - - Syncback supported - - - - - + @@ -251,7 +215,7 @@ Layout file path