Skip to content

Commit

Permalink
Merge pull request #17 from diogotr7/feature/chroma-reader
Browse files Browse the repository at this point in the history
Replace old RazerSdkWrapper with RazerSdkReader
  • Loading branch information
diogotr7 committed Aug 20, 2023
2 parents e2c1b2a + eab0631 commit c1bcb03
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@

<ItemGroup>
<PackageReference Include="ArtemisRGB.UI.Shared" IncludeAssets="compile;build;buildTransitive" Version="1.2023.727.9" />
</ItemGroup>

<ItemGroup>
<Reference Include="RazerSdkWrapper" />
<PackageReference Include="RazerSdkReader" Version="1.5.0" />
</ItemGroup>

<Target Name="DownloadChromaSdk" BeforeTargets="PrepareForBuild">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,11 @@ public static class DefaultChromaLedMap
public static readonly LedId[,] Mousepad =
{
{
LedId.Mousepad20,
LedId.Mousepad19,
LedId.Mousepad18,
LedId.Mousepad17,
LedId.Mousepad16,
LedId.Mousepad15,
LedId.Mousepad14,
LedId.Mousepad13,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,23 @@
using SkiaSharp;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Xml.Linq;

namespace Artemis.Plugins.LayerBrushes.Chroma.LayerBrushes;

public class ChromaLayerBrush : PerLedLayerBrush<ChromaPropertyGroup>
{
private readonly ChromaService _chroma;
private readonly PluginSetting<Dictionary<RzDeviceType, LedId[,]>> _keyMapSetting;
private readonly ConcurrentDictionary<LedId, SKColor> _colors;
private readonly Dictionary<LedId, SKColor> _colors;
private readonly object _lock;

public ChromaLayerBrush(ChromaService chroma, PluginSettings pluginSettings)
{
_chroma = chroma;
_keyMapSetting = pluginSettings.GetSetting("ChromaLedArray", DefaultChromaLedMap.Clone());
_keyMapSetting = pluginSettings.GetSetting("ChromaKeymap", DefaultChromaLedMap.Clone());
_colors = new();
_lock = new();
}

private double forceRefreshAppListTimer;
Expand All @@ -39,11 +42,14 @@ private void OnMatrixUpdated(object? sender, RzDeviceType e)
SKColor[,] matrix = _chroma.Matrices[e];
var dict = _keyMapSetting.Value[e];

for (int i = 0; i < matrix.GetLength(0); i++)
lock (_lock)
{
for (int j = 0; j < matrix.GetLength(1); j++)
for (var i = 0; i < matrix.GetLength(0); i++)
{
_colors[dict[i, j]] = matrix[i, j];
for (var j = 0; j < matrix.GetLength(1); j++)
{
_colors[dict[i, j]] = matrix[i, j];
}
}
}
}
Expand All @@ -70,12 +76,15 @@ public override SKColor GetColor(ArtemisLed led, SKPoint renderPoint)
if (string.IsNullOrWhiteSpace(_chroma.CurrentApp) || _chroma.CurrentApp.Contains("Artemis.UI"))
return SKColor.Empty;

if (_colors.TryGetValue(led.RgbLed.Id, out SKColor color))
return ProcessColor(color);

//According to razer docs, chromaLink1 is the "catchall" ledId. If an LED doesn't have a mapping, use this color.
if (Properties.UseDefaultLed.CurrentValue && _colors.TryGetValue(LedId.LedStripe1, out var chromaLink1))
return ProcessColor(chromaLink1);
lock (_lock)
{
if (_colors.TryGetValue(led.RgbLed.Id, out var color))
return ProcessColor(color);

//According to razer docs, chromaLink1 is the "catchall" ledId. If an LED doesn't have a mapping, use this color.
if (Properties.UseDefaultLed.CurrentValue && _colors.TryGetValue(LedId.LedStripe1, out var chromaLink1))
return ProcessColor(chromaLink1);
}

return SKColor.Empty;
}
Expand Down
12 changes: 7 additions & 5 deletions src/Artemis.Plugins.LayerBrushes.Chroma/Module/ChromaModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Artemis.Plugins.LayerBrushes.Chroma.Module;

Expand All @@ -32,6 +33,7 @@ public override void Enable()
{
_chroma.MatrixUpdated += UpdateMatrix;
_chroma.AppListUpdated += UpdateAppList;
UpdateAppList(null, EventArgs.Empty);
try
{
DataModel.PriorityList = _registry.GetRazerSdkInfo().PriorityList;
Expand Down Expand Up @@ -59,15 +61,15 @@ public override void Update(double deltaTime)
private void UpdateAppList(object? sender, EventArgs e)
{
DataModel.CurrentApplication = _chroma.CurrentApp;
DataModel.ApplicationList = _chroma.Apps;
DataModel.PidList = _chroma.Pids;
DataModel.ApplicationList = _chroma.Apps.ToList();
DataModel.PidList = _chroma.Pids.ToList();
}

private void UpdateMatrix(object? sender, RzDeviceType rzDeviceType)
{
lock (_lock)
{
if (!_chroma.Matrices.TryGetValue(rzDeviceType, out SKColor[,]? colors))
if (!_chroma.Matrices.TryGetValue(rzDeviceType, out var colors))
return;

if (!_deviceTypeCache.TryGetValue(rzDeviceType, out var deviceDataModel))
Expand All @@ -76,9 +78,9 @@ private void UpdateMatrix(object? sender, RzDeviceType rzDeviceType)
_deviceTypeCache.Add(rzDeviceType, deviceDataModel);
}

for (int row = 0; row < colors.GetLength(0); row++)
for (var row = 0; row < colors.GetLength(0); row++)
{
for (int col = 0; col < colors.GetLength(1); col++)
for (var col = 0; col < colors.GetLength(1); col++)
{
var ledId = DefaultChromaLedMap.DeviceTypes[rzDeviceType][row, col];
if (ledId == LedId.Invalid)
Expand Down
Binary file not shown.
159 changes: 87 additions & 72 deletions src/Artemis.Plugins.LayerBrushes.Chroma/Services/ChromaService.cs
Original file line number Diff line number Diff line change
@@ -1,129 +1,144 @@
using Artemis.Core.Services;
using RazerSdkWrapper;
using RazerSdkWrapper.Data;
using Serilog;
using SkiaSharp;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using Artemis.Core;
using RazerSdkReader;
using RazerSdkReader.Structures;

namespace Artemis.Plugins.LayerBrushes.Chroma.Services;

public class ChromaService : IPluginService, IDisposable
{
private readonly ILogger _logger;
private readonly RzSdkManager _manager;
private readonly ChromaReader _reader;
private readonly Profiler _profiler;
private readonly Dictionary<RzDeviceType, string> _enumNames;

public event EventHandler<RzDeviceType>? MatrixUpdated;
public event EventHandler? AppListUpdated;

public string? CurrentApp { get; private set; } = string.Empty;
public int? CurrentAppId { get; private set; } = null;
public string? CurrentApp { get; private set; } = null;
public List<string> Apps { get; } = new();
public List<int> Pids { get; } = new();
public ConcurrentDictionary<RzDeviceType, SKColor[,]> Matrices { get; } = new();

public ChromaService(ILogger logger)
public ChromaService(ILogger logger, Plugin plugin)
{
_logger = logger;

_logger.Verbose("Starting RzSDKManager...");
_manager = new RzSdkManager()
{
AppListEnabled = true,
MousepadEnabled = true,
MouseEnabled = true,
KeypadEnabled = true,
KeyboardEnabled = true,
HeadsetEnabled = true,
ChromaLinkEnabled = true
};
_logger.Verbose("Started RzSdkManager successfully");
_manager.DataUpdated += OnDataUpdated;
_logger.Verbose("Starting RazerSdkReader...");
_profiler = plugin.GetProfiler("Chroma Service");

_enumNames = Enum.GetValues<RzDeviceType>().ToDictionary(t => t, t => $"Update {Enum.GetName(typeof(RzDeviceType), t) ?? throw new Exception()}");

_reader = new();
_reader.KeyboardUpdated += RazerEmulatorReaderOnKeyboardUpdated;
_reader.MouseUpdated += RazerEmulatorReaderOnMouseUpdated;
_reader.MousepadUpdated += RazerEmulatorReaderOnMousepadUpdated;
_reader.KeypadUpdated += RazerEmulatorReaderOnKeypadUpdated;
_reader.HeadsetUpdated += RazerEmulatorReaderOnHeadsetUpdated;
_reader.ChromaLinkUpdated += RazerEmulatorReaderOnChromaLinkUpdated;
_reader.AppDataUpdated += RazerEmulatorReaderOnAppDataUpdated;
_reader.Start();
_logger.Verbose("Started RazerSdkReader successfully");

UpdateAppList(true);
}

internal void UpdateAppList(bool forced = false)
private void RazerEmulatorReaderOnAppDataUpdated(object? sender, in ChromaAppData e)
{
if (CurrentApp == null && !forced)
return;
UpdateAppListData(in e);
}

RzAppListDataProvider applist = _manager.GetDataProvider<RzAppListDataProvider>();
applist.Update();
UpdateAppListData(applist);
private void RazerEmulatorReaderOnChromaLinkUpdated(object? sender, in ChromaLink e)
{
UpdateMatrix(RzDeviceType.ChromaLink,in e);
}

private void OnDataUpdated(object? sender, EventArgs e)
private void RazerEmulatorReaderOnHeadsetUpdated(object? sender, in ChromaHeadset e)
{
if (sender is not AbstractDataProvider provider)
return;
UpdateMatrix(RzDeviceType.Headset,in e);
}

provider.Update();
private void RazerEmulatorReaderOnKeypadUpdated(object? sender, in ChromaKeypad e)
{
UpdateMatrix(RzDeviceType.Keypad,in e);
}

if (provider is RzAppListDataProvider app)
{
UpdateAppListData(app);
_logger.Verbose("Updated AppList: CurrentApp: {currentApp} | Apps: {apps} | Pids: {pids}", CurrentApp ?? "None", Apps, Pids);
}
else if (provider is AbstractColorDataProvider colorProvider)
{
UpdateMatrix(colorProvider);
_logger.Verbose("Updated {provider}. Zone zero: {color}", _deviceTypeDict[colorProvider.GetType()], colorProvider.GetZoneColor(0));
}
private void RazerEmulatorReaderOnMousepadUpdated(object? sender, in ChromaMousepad e)
{
UpdateMatrix(RzDeviceType.Mousepad,in e);
}

private void UpdateMatrix(AbstractColorDataProvider colorProvider)
private void RazerEmulatorReaderOnMouseUpdated(object? sender, in ChromaMouse e)
{
RzDeviceType matrixDeviceType = _deviceTypeDict[colorProvider.GetType()];
GridSize grid = colorProvider.Grids[0];
UpdateMatrix(RzDeviceType.Mouse,in e);
}

SKColor[,] matrix = Matrices.GetOrAdd(matrixDeviceType, static (id,g) => new SKColor[g.Height, g.Width], grid);
private void RazerEmulatorReaderOnKeyboardUpdated(object? sender, in ChromaKeyboard e)
{
UpdateMatrix(RzDeviceType.Keyboard, e);
}

for (int i = 0; i < grid.Height; i++)
internal void UpdateAppList(bool forced = false)
{
//TODO: Is this needed anymore?
return;
}

private void UpdateMatrix<T>(RzDeviceType deviceType, in T data) where T : unmanaged, IColorProvider
{
var profilerName = _enumNames[deviceType];

_profiler.StartMeasurement(profilerName);
var matrix = Matrices.GetOrAdd(deviceType, static (id, t) => new SKColor[t.Height, t.Width], data);

for (var i = 0; i < data.Height; i++)
{
for (int j = 0; j < grid.Width; j++)
for (var j = 0; j < data.Width; j++)
{
(byte r, byte g, byte b) = colorProvider.GetZoneColor((int)(i * grid.Width + j));
matrix[i, j] = new SKColor(r, g, b);
// ReSharper disable once PossiblyImpureMethodCallOnReadonlyVariable
var clr = data.GetColor(i * data.Width + j);
matrix[i, j] = new SKColor(clr.R, clr.G, clr.B);
}
}

MatrixUpdated?.Invoke(this, matrixDeviceType);
MatrixUpdated?.Invoke(this, deviceType);
_profiler.StopMeasurement(profilerName);
}

private void UpdateAppListData(RzAppListDataProvider app)
private void UpdateAppListData(in ChromaAppData app)
{
Apps.Clear();
Pids.Clear();
CurrentApp = app.CurrentAppExecutable;
for (int i = 0; i < app.AppCount; i++)
CurrentAppId = app.CurrentAppId == 0 ? null : (int)app.CurrentAppId;
CurrentApp = null;
for (var i = 0; i < app.AppCount; i++)
{
Apps.Add(app.GetExecutableName(i));
Pids.Add(app.GetPid(i));
Apps.Add(app.AppInfo[i].AppName);
Pids.Add((int)app.AppInfo[i].AppId);

if (app.AppInfo[i].AppId == app.CurrentAppId)
CurrentApp = app.AppInfo[i].AppName;
}

AppListUpdated?.Invoke(this, EventArgs.Empty);
_logger.Verbose("Updated Chroma app list");
}

private readonly Dictionary<Type, RzDeviceType> _deviceTypeDict = new()
{
[typeof(RzMousepadDataProvider)] = RzDeviceType.Mousepad,
[typeof(RzMouseDataProvider)] = RzDeviceType.Mouse,
[typeof(RzKeypadDataProvider)] = RzDeviceType.Keypad,
[typeof(RzKeyboardDataProvider)] = RzDeviceType.Keyboard,
[typeof(RzHeadsetDataProvider)] = RzDeviceType.Headset,
[typeof(RzChromaLinkDataProvider)] = RzDeviceType.ChromaLink
};

#region IDisposable
public void Dispose()
{
_manager.DataUpdated -= OnDataUpdated;
//TODO: disposing this throws this:
//System.ApplicationException: Object synchronization method was called from an unsynchronized block of code.
//idk what to do about it
//_manager?.Dispose();
GC.SuppressFinalize(this);
_reader.KeyboardUpdated -= RazerEmulatorReaderOnKeyboardUpdated;
_reader.MouseUpdated -= RazerEmulatorReaderOnMouseUpdated;
_reader.MousepadUpdated -= RazerEmulatorReaderOnMousepadUpdated;
_reader.KeypadUpdated -= RazerEmulatorReaderOnKeypadUpdated;
_reader.HeadsetUpdated -= RazerEmulatorReaderOnHeadsetUpdated;
_reader.ChromaLinkUpdated -= RazerEmulatorReaderOnChromaLinkUpdated;
_reader.AppDataUpdated -= RazerEmulatorReaderOnAppDataUpdated;
_reader.Dispose();
}
#endregion
}
}

0 comments on commit c1bcb03

Please sign in to comment.