Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Openrgb device updated implementation #338

Open
wants to merge 6 commits into
base: Development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions RGB.NET.Core/Ids/IdGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ public static class IdGenerator

// ReSharper disable InconsistentNaming
private static readonly HashSet<string> _registeredIds = [];
private static readonly Dictionary<Assembly, Dictionary<string, string>> _idMappings = [];
private static readonly Dictionary<Assembly, Dictionary<string, int>> _counter = [];
private static readonly Dictionary<object, Dictionary<string, string>> _idMappings = [];
private static readonly Dictionary<object, Dictionary<string, int>> _counter = [];
// ReSharper restore InconsistentNaming

#endregion
Expand All @@ -29,7 +29,7 @@ public static class IdGenerator
[MethodImpl(MethodImplOptions.NoInlining)]
public static string MakeUnique(string id) => MakeUnique(Assembly.GetCallingAssembly(), id);

internal static string MakeUnique(Assembly callingAssembly, string id)
public static string MakeUnique(object callingAssembly, string id)
{
if (!_idMappings.TryGetValue(callingAssembly, out Dictionary<string, string>? idMapping))
{
Expand Down Expand Up @@ -63,7 +63,7 @@ internal static string MakeUnique(Assembly callingAssembly, string id)
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ResetCounter() => ResetCounter(Assembly.GetCallingAssembly());

internal static void ResetCounter(Assembly callingAssembly)
public static void ResetCounter(object callingAssembly)
{
if (_counter.TryGetValue(callingAssembly, out Dictionary<string, int>? counter))
counter.Clear();
Expand Down
19 changes: 19 additions & 0 deletions RGB.NET.Devices.OpenRGB/Abstract/AbstractOpenRGBDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,23 @@ protected AbstractOpenRGBDevice(TDeviceInfo info, IUpdateQueue updateQueue)
{ }

#endregion

#region Methods

private bool Equals(AbstractOpenRGBDevice<TDeviceInfo> other)
{
return DeviceInfo.DeviceName == other.DeviceInfo.DeviceName;
}

public override bool Equals(object? obj)
{
return ReferenceEquals(this, obj) || (obj is AbstractOpenRGBDevice<TDeviceInfo> other && Equals(other));
}

public override int GetHashCode()
{
return DeviceInfo.DeviceName.GetHashCode();
}

#endregion
}
14 changes: 12 additions & 2 deletions RGB.NET.Devices.OpenRGB/Abstract/OpenRGBDeviceInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,24 @@ public class OpenRGBDeviceInfo : IRGBDeviceInfo
/// Initializes a new instance of <see cref="OpenRGBDeviceInfo"/>.
/// </summary>
/// <param name="openRGBDevice">The OpenRGB device to extract information from.</param>
internal OpenRGBDeviceInfo(OpenRGBDevice openRGBDevice)
/// <param name="splitId">If this is a zone or segment, specify the name</param>
internal OpenRGBDeviceInfo(OpenRGBDevice openRGBDevice, string? splitId = null)
{
this.OpenRGBDevice = openRGBDevice;

DeviceType = Helper.GetRgbNetDeviceType(openRGBDevice.Type);
Manufacturer = Helper.GetVendorName(openRGBDevice);
Model = Helper.GetModelName(openRGBDevice);
DeviceName = DeviceHelper.CreateDeviceName(Manufacturer, Model);
string model = Manufacturer + " " + Model;
string id = string.IsNullOrWhiteSpace(openRGBDevice.Serial) ? openRGBDevice.Location : openRGBDevice.Serial;
if (string.IsNullOrWhiteSpace(id)) // this device is 99% unpluggable
{
DeviceName = IdGenerator.MakeUnique(typeof(OpenRGBDeviceProvider), Manufacturer + " " + Model);
}
else
{
DeviceName = model + " #" + Helper.HashAndShorten(id) + (splitId != null ? $" {splitId}" : null);
}
}

#endregion
Expand Down
4 changes: 2 additions & 2 deletions RGB.NET.Devices.OpenRGB/Generic/OpenRGBUpdateQueue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public sealed class OpenRGBUpdateQueue : UpdateQueue

private readonly int _deviceId;

private readonly OpenRgbClient _openRGB;
private readonly IOpenRgbClient _openRGB;
private readonly OpenRGBColor[] _colors;

#endregion
Expand All @@ -32,7 +32,7 @@ public sealed class OpenRGBUpdateQueue : UpdateQueue
/// <param name="deviceId">The index used to identify the device.</param>
/// <param name="client">The OpenRGB client used to send updates to the OpenRGB server.</param>
/// <param name="device">The OpenRGB Device containing device-specific information.</param>
public OpenRGBUpdateQueue(IDeviceUpdateTrigger updateTrigger, int deviceId, OpenRgbClient client, OpenRGBDevice device)
public OpenRGBUpdateQueue(IDeviceUpdateTrigger updateTrigger, int deviceId, IOpenRgbClient client, OpenRGBDevice device)
: base(updateTrigger)
{
this._deviceId = deviceId;
Expand Down
23 changes: 22 additions & 1 deletion RGB.NET.Devices.OpenRGB/Helper.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using OpenRGB.NET;
using System;
using System.Security.Cryptography;
using System.Text;
using OpenRGB.NET;
using RGB.NET.Core;
using OpenRGBDevice = OpenRGB.NET.Device;

Expand Down Expand Up @@ -53,4 +56,22 @@ public static string GetVendorName(OpenRGBDevice openRGBDevice) => string.IsNull
public static string GetModelName(OpenRGBDevice openRGBDevice) => string.IsNullOrWhiteSpace(openRGBDevice.Vendor)
? openRGBDevice.Name
: openRGBDevice.Name.Replace(openRGBDevice.Vendor, "").Trim();
/**
* Shortens given input into 8 character string
*/
internal static string HashAndShorten(string input)
{
using SHA256 sha256Hash = SHA256.Create();
byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
// Take the first 4 bytes of the hash
byte[] shortenedBytes = new byte[4];
Array.Copy(bytes, shortenedBytes, 4);
// Convert the bytes to a string
StringBuilder shortenedHash = new();
foreach (byte b in shortenedBytes)
{
shortenedHash.Append(b.ToString("X2"));
}
return shortenedHash.ToString();
}
}
22 changes: 22 additions & 0 deletions RGB.NET.Devices.OpenRGB/OpenRGBClientWrapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.Collections.Generic;
using OpenRGB.NET;
using RGB.NET.Core;

namespace RGB.NET.Devices.OpenRGB;

public class OpenRGBClientWrapper
{
public OpenRgbClient OpenRgbClient { get; }

public List<IRGBDevice> Devices { get; } = new();

public OpenRGBClientWrapper(OpenRgbClient openRgbClient)
{
OpenRgbClient = openRgbClient;
}

public void Dispose()
{
OpenRgbClient.Dispose();
}
}
144 changes: 93 additions & 51 deletions RGB.NET.Devices.OpenRGB/OpenRGBDeviceProvider.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using OpenRGB.NET;
using RGB.NET.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRGB.NET;
using OpenRgbDevice = OpenRGB.NET.Device;

namespace RGB.NET.Devices.OpenRGB;

Expand All @@ -17,7 +18,7 @@ public sealed class OpenRGBDeviceProvider : AbstractRGBDeviceProvider
// ReSharper disable once InconsistentNaming
private static readonly object _lock = new();

private readonly List<OpenRgbClient> _clients = [];
private readonly List<OpenRGBClientWrapper> _clients = [];

private static OpenRGBDeviceProvider? _instance;

Expand Down Expand Up @@ -84,7 +85,9 @@ protected override void InitializeSDK()
try
{
OpenRgbClient openRgb = new(ip: deviceDefinition.Ip, port: deviceDefinition.Port, name: deviceDefinition.ClientName, autoConnect: true);
_clients.Add(openRgb);
OpenRGBClientWrapper wrapper = new(openRgb);
openRgb.DeviceListUpdated += (_, _) => RefreshClient(wrapper);
_clients.Add(wrapper);
deviceDefinition.Connected = true;
}
catch (Exception e)
Expand All @@ -95,67 +98,104 @@ protected override void InitializeSDK()
}
}
}

private void RefreshClient(OpenRGBClientWrapper openRgbClient)
{
List<IRGBDevice> currentDevices = new(openRgbClient.Devices);
List<IRGBDevice> newDevices = GetOrgbClientDevices(openRgbClient.OpenRgbClient)
.SelectMany((device, i) => SplitDevice(device, i, openRgbClient.OpenRgbClient)).ToList();

foreach (IRGBDevice rgbDevice in currentDevices.Except(newDevices))
{
RemoveDevice(rgbDevice);
openRgbClient.Devices.Remove(rgbDevice);
}
foreach (IRGBDevice rgbDevice in newDevices)
{
openRgbClient.Devices.Add(rgbDevice);
AddDevice(rgbDevice);
}
}

/// <inheritdoc />
protected override IEnumerable<IRGBDevice> LoadDevices()
{
foreach (OpenRgbClient? openRgb in _clients)
return _clients.SelectMany(LoadClientDevices);
}

private IEnumerable<IRGBDevice> LoadClientDevices(OpenRGBClientWrapper client)
{
List<IRGBDevice> devices = GetOrgbClientDevices(client.OpenRgbClient)
.SelectMany((device, i) => SplitDevice(device, i, client.OpenRgbClient))
.ToList();
client.Devices.AddRange(devices);
return devices;
}

private IEnumerable<OpenRgbDevice> GetOrgbClientDevices(IOpenRgbClient openRgb)
{
int deviceCount = openRgb.GetControllerCount();

for (int i = 0; i < deviceCount; i++)
{
int deviceCount = openRgb.GetControllerCount();
OpenRgbDevice device = openRgb.GetControllerData(i);

for (int i = 0; i < deviceCount; i++)
int directModeIndex = Array.FindIndex(device.Modes, d => d.Name == "Direct");
if (directModeIndex != -1)
{
//set the device to direct mode if it has it
openRgb.UpdateMode(i, directModeIndex);
}
else if (!ForceAddAllDevices)
{
Device device = openRgb.GetControllerData(i);
//if direct mode does not exist
//and if we're not forcing, continue to the next device.
continue;
}

int directModeIndex = Array.FindIndex(device.Modes, d => d.Name == "Direct");
if (directModeIndex != -1)
{
//set the device to direct mode if it has it
openRgb.UpdateMode(i, directModeIndex);
}
else if (!ForceAddAllDevices)
{
//if direct mode does not exist
//and if we're not forcing, continue to the next device.
continue;
}
if (device.Zones.Length == 0)
continue;
if (device.Zones.All(z => z.LedCount == 0))
continue;

if (device.Zones.Length == 0)
continue;
if (device.Zones.All(z => z.LedCount == 0))
continue;
yield return device;
}
}

OpenRGBUpdateQueue updateQueue = new(GetUpdateTrigger(), i, openRgb, device);
private IEnumerable<IRGBDevice> SplitDevice(OpenRgbDevice device, int i, IOpenRgbClient openRgb)
{
IDeviceUpdateTrigger clientUpdateTrigger = GetUpdateTrigger();
OpenRGBUpdateQueue updateQueue = new(clientUpdateTrigger, i, openRgb, device);

bool anyZoneHasSegments = device.Zones.Any(z => z.Segments.Length > 0);
bool splitDeviceByZones = anyZoneHasSegments || PerZoneDeviceFlag.HasFlag(Helper.GetRgbNetDeviceType(device.Type));
bool anyZoneHasSegments = device.Zones.Any(z => z.Segments.Length > 0);
bool splitDeviceByZones = anyZoneHasSegments || PerZoneDeviceFlag.HasFlag(Helper.GetRgbNetDeviceType(device.Type));

if (!splitDeviceByZones)
{
yield return new OpenRGBGenericDevice(new OpenRGBDeviceInfo(device), updateQueue);
continue;
}
if (!splitDeviceByZones)
{
yield return new OpenRGBGenericDevice(new OpenRGBDeviceInfo(device), updateQueue);
yield break;
}

int totalLedCount = 0;
int totalLedCount = 0;

foreach (Zone zone in device.Zones)
{
if (zone.LedCount <= 0)
continue;

foreach (Zone zone in device.Zones)
if (zone.Segments.Length <= 0)
{
string zoneId = zone.Name;
yield return new OpenRGBZoneDevice(new OpenRGBDeviceInfo(device, zoneId), totalLedCount, zone, updateQueue);
totalLedCount += (int)zone.LedCount;
}
else
{
foreach (Segment segment in zone.Segments)
{
if (zone.LedCount <= 0)
continue;

if (zone.Segments.Length <= 0)
{
yield return new OpenRGBZoneDevice(new OpenRGBDeviceInfo(device), totalLedCount, zone, updateQueue);
totalLedCount += (int)zone.LedCount;
}
else
{
foreach (Segment segment in zone.Segments)
{
yield return new OpenRGBSegmentDevice(new OpenRGBDeviceInfo(device), totalLedCount, segment, updateQueue);
totalLedCount += (int)segment.LedCount;
}
}
string zoneId = segment.Name;
yield return new OpenRGBSegmentDevice(new OpenRGBDeviceInfo(device, zoneId), totalLedCount, segment, updateQueue);
totalLedCount += (int)segment.LedCount;
}
}
}
Expand All @@ -168,15 +208,17 @@ protected override void Dispose(bool disposing)
{
base.Dispose(disposing);

foreach (OpenRgbClient client in _clients)
foreach (OpenRGBClientWrapper wrapper in _clients)
{
try { client.Dispose(); }
try { wrapper.Dispose(); }
catch { /* at least we tried */ }
}

_clients.Clear();
DeviceDefinitions.Clear();

IdGenerator.ResetCounter(typeof(OpenRGBDeviceProvider));

_instance = null;
}
}
Expand Down