1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2026-01-01 02:03:32 +00:00

Devices - Add device layout loading

This commit is contained in:
Robert 2021-02-10 22:45:28 +01:00
parent 7792b662e0
commit e1121afdf9
6 changed files with 107 additions and 80 deletions

View File

@ -5,6 +5,7 @@ using System.Linq;
using Artemis.Core.DeviceProviders; using Artemis.Core.DeviceProviders;
using Artemis.Storage.Entities.Surface; using Artemis.Storage.Entities.Surface;
using RGB.NET.Core; using RGB.NET.Core;
using RGB.NET.Layout;
using SkiaSharp; using SkiaSharp;
namespace Artemis.Core namespace Artemis.Core
@ -32,13 +33,12 @@ namespace Artemis.Core
BlueScale = 1; BlueScale = 1;
IsEnabled = true; IsEnabled = true;
deviceProvider.DeviceLayoutPaths.TryGetValue(rgbDevice, out string? layoutPath);
LayoutPath = layoutPath;
InputIdentifiers = new List<ArtemisDeviceInputIdentifier>(); InputIdentifiers = new List<ArtemisDeviceInputIdentifier>();
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();
ApplyToEntity(); ApplyToEntity();
CalculateRenderProperties(); CalculateRenderProperties();
} }
@ -50,15 +50,13 @@ namespace Artemis.Core
DeviceProvider = deviceProvider; DeviceProvider = deviceProvider;
Surface = surface; Surface = surface;
deviceProvider.DeviceLayoutPaths.TryGetValue(rgbDevice, out string? layoutPath);
LayoutPath = layoutPath;
InputIdentifiers = new List<ArtemisDeviceInputIdentifier>(); InputIdentifiers = new List<ArtemisDeviceInputIdentifier>();
foreach (DeviceInputIdentifierEntity identifierEntity in DeviceEntity.InputIdentifiers) foreach (DeviceInputIdentifierEntity identifierEntity in DeviceEntity.InputIdentifiers)
InputIdentifiers.Add(new ArtemisDeviceInputIdentifier(identifierEntity.InputProvider, identifierEntity.Identifier)); InputIdentifiers.Add(new ArtemisDeviceInputIdentifier(identifierEntity.InputProvider, identifierEntity.Identifier));
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();
} }
/// <summary> /// <summary>
@ -227,11 +225,6 @@ namespace Artemis.Core
} }
} }
/// <summary>
/// Gets the path to where the layout of the device was (attempted to be) loaded from
/// </summary>
public string? LayoutPath { get; internal set; }
/// <summary> /// <summary>
/// Gets the layout of the device expanded with Artemis-specific data /// Gets the layout of the device expanded with Artemis-specific data
/// </summary> /// </summary>
@ -266,6 +259,15 @@ namespace Artemis.Core
return artemisLed; return artemisLed;
} }
public void LoadBestLayout()
{
ArtemisLayout artemisLayout = DeviceProvider.LoadLayout(RgbDevice);
if (artemisLayout.IsValid)
artemisLayout.DeviceLayout!.ApplyTo(RgbDevice);
Layout = artemisLayout;
}
internal void ApplyToEntity() internal void ApplyToEntity()
{ {
// Other properties are computed // Other properties are computed

View File

@ -1,10 +1,57 @@
using System; using System;
using RGB.NET.Layout;
namespace Artemis.Core namespace Artemis.Core
{ {
/// <summary>
/// Represents a device layout decorated with extra Artemis-specific data
/// </summary>
public class ArtemisLayout public class ArtemisLayout
{ {
public ArtemisDevice Device { get; set; } /// <summary>
public Uri Image { get; set; } /// Creates a new instance of the <see cref="ArtemisLayout" /> class
/// </summary>
/// <param name="filePath">The path of the layout XML file</param>
public ArtemisLayout(string filePath)
{
FilePath = filePath;
DeviceLayout = DeviceLayout.Load(FilePath);
IsValid = DeviceLayout != null;
}
/// <summary>
/// Gets the file path the layout was (attempted to be) loaded from
/// </summary>
public string FilePath { get; }
/// <summary>
/// Gets the RGB.NET device layout
/// </summary>
public DeviceLayout? DeviceLayout { get; }
/// <summary>
/// Gets a boolean indicating whether a valid layout was loaded
/// </summary>
public bool IsValid { get; }
/// <summary>
/// Gets the device this image is applied to
/// </summary>
public ArtemisDevice? Device { get; internal set; }
/// <summary>
/// Gets or sets the physical layout of the device. Only applicable to keyboards
/// </summary>
public string? PhysicalLayout { get; set; }
/// <summary>
/// Gets or sets the logical layout of the device. Only applicable to keyboards
/// </summary>
public string? LogicalLayout { get; set; }
/// <summary>
/// Gets or sets the image of the device
/// </summary>
public Uri? Image { get; set; }
} }
} }

View File

@ -1,6 +1,6 @@
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using Ninject; using Ninject;
using RGB.NET.Core; using RGB.NET.Core;
using Serilog; using Serilog;
@ -34,7 +34,15 @@ namespace Artemis.Core.DeviceProviders
[Inject] [Inject]
public ILogger? Logger { get; set; } public ILogger? Logger { get; set; }
internal Dictionary<IRGBDevice, string> DeviceLayoutPaths { get; set; } = new(); /// <summary>
/// A boolean indicating whether this device provider detects the physical layout of connected keyboards
/// </summary>
public bool CanDetectPhysicalLayout { get; protected set; }
/// <summary>
/// A boolean indicating whether this device provider detects the logical layout of connected keyboards
/// </summary>
public bool CanDetectLogicalLayout { get; protected set; }
/// <inheritdoc /> /// <inheritdoc />
public override void Disable() public override void Disable()
@ -43,31 +51,37 @@ namespace Artemis.Core.DeviceProviders
} }
/// <summary> /// <summary>
/// Loads a layout for the specified device and wraps it in an <see cref="ArtemisLayout" />
/// </summary> /// </summary>
/// <param name="type"></param> /// <param name="rgbDevice">The device to load the layout for</param>
/// <param name="sender"></param> /// <returns>The resulting Artemis layout</returns>
/// <param name="e"></param> public virtual ArtemisLayout LoadLayout(IRGBDevice rgbDevice)
protected void ResolveAbsolutePath(Type type, object sender, ResolvePathEventArgs e)
{ {
if (sender.GetType() == type || sender.GetType().IsGenericType(type)) // 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, '-'));
// Start from the plugin directory string layoutDir = Path.Combine(Plugin.Directory.FullName, "Layouts");
if (e.RelativePart != null && e.FileName != null) string filePath;
e.FinalPath = Path.Combine(Plugin.Directory.FullName, e.RelativePart, e.FileName); // if (rgbDevice.DeviceInfo is IPhysicalLayoutDeviceInfo)
else if (e.RelativePath != null) // {
e.FinalPath = Path.Combine(Plugin.Directory.FullName, e.RelativePath); // 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; return new ArtemisLayout(filePath);
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;
}
} }
} }
} }

View File

@ -1,5 +1,6 @@
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

View File

@ -71,8 +71,7 @@ namespace Artemis.Core.Services
foreach (IRGBDevice surfaceDevice in deviceProvider.Devices) foreach (IRGBDevice surfaceDevice in deviceProvider.Devices)
{ {
_logger.Debug("Device provider {deviceProvider} added {deviceName}", _logger.Debug("Device provider {deviceProvider} added {deviceName}", deviceProvider.GetType().Name, surfaceDevice.DeviceInfo?.DeviceName);
deviceProvider.GetType().Name, surfaceDevice.DeviceInfo?.DeviceName);
if (!_loadedDevices.Contains(surfaceDevice)) if (!_loadedDevices.Contains(surfaceDevice))
{ {
_loadedDevices.Add(surfaceDevice); _loadedDevices.Add(surfaceDevice);

View File

@ -112,24 +112,6 @@
</Grid> </Grid>
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" /> <Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Lighting support</TextBlock>
<TextBlock Style="{StaticResource MaterialDesignTextBlock}"
Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}"
TextWrapping="Wrap"
Text="{Binding Device.RgbDevice.DeviceInfo.Lighting}" />
</StackPanel>
</Grid>
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition /> <RowDefinition />
@ -160,7 +142,7 @@
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Device image</TextBlock> <TextBlock Style="{StaticResource MaterialDesignTextBlock}">Device image</TextBlock>
<TextBox Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}" <TextBox Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}"
TextWrapping="Wrap" TextWrapping="Wrap"
Text="{Binding Device.RgbDevice.DeviceInfo.Image, Mode=OneWay}" Text="{Binding Device.Layout.Image, Mode=OneWay}"
IsReadOnly="True" /> IsReadOnly="True" />
</StackPanel> </StackPanel>
</Grid> </Grid>
@ -221,24 +203,6 @@
</Grid> </Grid>
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" /> <Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Syncback supported</TextBlock>
<TextBlock Style="{StaticResource MaterialDesignTextBlock}"
Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}"
TextWrapping="Wrap"
Text="{Binding Device.RgbDevice.DeviceInfo.SupportsSyncBack}" />
</StackPanel>
</Grid>
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition /> <RowDefinition />
@ -251,7 +215,7 @@
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Layout file path</TextBlock> <TextBlock Style="{StaticResource MaterialDesignTextBlock}">Layout file path</TextBlock>
<TextBox Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}" <TextBox Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}"
TextWrapping="Wrap" TextWrapping="Wrap"
Text="{Binding Device.LayoutPath, Mode=OneWay}" Text="{Binding Device.Layout.FilePath, Mode=OneWay}"
IsReadOnly="True" /> IsReadOnly="True" />
</StackPanel> </StackPanel>
</Grid> </Grid>