diff --git a/src/Artemis.Plugins.LayerBrushes.Chroma/Artemis.Plugins.LayerBrushes.Chroma.csproj b/src/Artemis.Plugins.LayerBrushes.Chroma/Artemis.Plugins.LayerBrushes.Chroma.csproj index ba4fd68..efcb4d8 100644 --- a/src/Artemis.Plugins.LayerBrushes.Chroma/Artemis.Plugins.LayerBrushes.Chroma.csproj +++ b/src/Artemis.Plugins.LayerBrushes.Chroma/Artemis.Plugins.LayerBrushes.Chroma.csproj @@ -8,10 +8,7 @@ - - - - + diff --git a/src/Artemis.Plugins.LayerBrushes.Chroma/DefaultChromaLedMap.cs b/src/Artemis.Plugins.LayerBrushes.Chroma/DefaultChromaLedMap.cs index cefa1f9..9c82ae5 100644 --- a/src/Artemis.Plugins.LayerBrushes.Chroma/DefaultChromaLedMap.cs +++ b/src/Artemis.Plugins.LayerBrushes.Chroma/DefaultChromaLedMap.cs @@ -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, diff --git a/src/Artemis.Plugins.LayerBrushes.Chroma/LayerBrushes/ChromaLayerBrush.cs b/src/Artemis.Plugins.LayerBrushes.Chroma/LayerBrushes/ChromaLayerBrush.cs index fc79c13..2a77bc3 100644 --- a/src/Artemis.Plugins.LayerBrushes.Chroma/LayerBrushes/ChromaLayerBrush.cs +++ b/src/Artemis.Plugins.LayerBrushes.Chroma/LayerBrushes/ChromaLayerBrush.cs @@ -6,6 +6,7 @@ using SkiaSharp; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Xml.Linq; namespace Artemis.Plugins.LayerBrushes.Chroma.LayerBrushes; @@ -13,13 +14,15 @@ public class ChromaLayerBrush : PerLedLayerBrush { private readonly ChromaService _chroma; private readonly PluginSetting> _keyMapSetting; - private readonly ConcurrentDictionary _colors; + private readonly Dictionary _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; @@ -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]; + } } } } @@ -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; } diff --git a/src/Artemis.Plugins.LayerBrushes.Chroma/Module/ChromaModule.cs b/src/Artemis.Plugins.LayerBrushes.Chroma/Module/ChromaModule.cs index 6aade3b..9f188b7 100644 --- a/src/Artemis.Plugins.LayerBrushes.Chroma/Module/ChromaModule.cs +++ b/src/Artemis.Plugins.LayerBrushes.Chroma/Module/ChromaModule.cs @@ -6,6 +6,7 @@ using SkiaSharp; using System; using System.Collections.Generic; +using System.Linq; namespace Artemis.Plugins.LayerBrushes.Chroma.Module; @@ -32,6 +33,7 @@ public override void Enable() { _chroma.MatrixUpdated += UpdateMatrix; _chroma.AppListUpdated += UpdateAppList; + UpdateAppList(null, EventArgs.Empty); try { DataModel.PriorityList = _registry.GetRazerSdkInfo().PriorityList; @@ -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)) @@ -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) diff --git a/src/Artemis.Plugins.LayerBrushes.Chroma/RazerSdkWrapper.dll b/src/Artemis.Plugins.LayerBrushes.Chroma/RazerSdkWrapper.dll deleted file mode 100644 index 05a75eb..0000000 Binary files a/src/Artemis.Plugins.LayerBrushes.Chroma/RazerSdkWrapper.dll and /dev/null differ diff --git a/src/Artemis.Plugins.LayerBrushes.Chroma/Services/ChromaService.cs b/src/Artemis.Plugins.LayerBrushes.Chroma/Services/ChromaService.cs index c7285ca..7340335 100644 --- a/src/Artemis.Plugins.LayerBrushes.Chroma/Services/ChromaService.cs +++ b/src/Artemis.Plugins.LayerBrushes.Chroma/Services/ChromaService.cs @@ -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 _enumNames; public event EventHandler? 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 Apps { get; } = new(); public List Pids { get; } = new(); public ConcurrentDictionary 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().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(); - 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(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 _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 -} +} \ No newline at end of file