diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index dd005ce..c4091ba 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -11,16 +11,19 @@ on:
jobs:
build:
- runs-on: windows-2022
+ runs-on: windows-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup .NET
- uses: actions/setup-dotnet@v1
+ uses: actions/setup-dotnet@v3
with:
- dotnet-version: 7.0.x
+ dotnet-version: |
+ 8.0.x
+ 7.0.x
+ 6.0.x
- name: Git Semantic Version
id: versioning
uses: PaulHatch/semantic-version@v4.0.3
@@ -33,12 +36,6 @@ jobs:
run: dotnet build --no-restore --configuration Release /p:Version=${{ steps.versioning.outputs.version }}
- name: Test
run: dotnet test --no-build --verbosity normal --configuration Release
- - name: Upload a Build Artifact NET5
- uses: actions/upload-artifact@v2.2.4
- with:
- name: RGB.NET-NET5
- path: bin/net5.0/RGB.NET.*.dll
- if-no-files-found: error
- name: Upload a Build Artifact NET6
uses: actions/upload-artifact@v2.2.4
with:
@@ -51,6 +48,12 @@ jobs:
name: RGB.NET-NET7
path: bin/net7.0/RGB.NET.*.dll
if-no-files-found: error
+ - name: Upload a Build Artifact NET8
+ uses: actions/upload-artifact@v2.2.4
+ with:
+ name: RGB.NET-NET8
+ path: bin/net8.0/RGB.NET.*.dll
+ if-no-files-found: error
- name: Upload Nuget Build Artifact
uses: actions/upload-artifact@v2.2.4
with:
@@ -59,3 +62,11 @@ jobs:
if-no-files-found: error
- name: Nuget Push
run: dotnet nuget push **\*.nupkg --skip-duplicate --api-key ${{ secrets.NUGET_TOKEN }} --source https://api.nuget.org/v3/index.json
+ - name: Symbols Push
+ run: dotnet nuget push **\*.snupkg --skip-duplicate --api-key ${{ secrets.NUGET_TOKEN }} --source https://api.nuget.org/v3/index.json
+ - name: Create Tag
+ uses: mathieudutour/github-tag-action@v6.1
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ custom_tag: ${{ steps.versioning.outputs.version }}
+ tag_prefix: v
diff --git a/.github/workflows/pr_verify.yml b/.github/workflows/pr_verify.yml
index b47d33e..d556fa2 100644
--- a/.github/workflows/pr_verify.yml
+++ b/.github/workflows/pr_verify.yml
@@ -7,14 +7,17 @@ on:
jobs:
build:
- runs-on: windows-2022
+ runs-on: windows-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Setup .NET
- uses: actions/setup-dotnet@v1
+ uses: actions/setup-dotnet@v3
with:
- dotnet-version: 7.0.x
+ dotnet-version: |
+ 8.0.x
+ 7.0.x
+ 6.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index f5e9cce..f6e3df3 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -10,16 +10,19 @@ on:
jobs:
build:
- runs-on: windows-2022
+ runs-on: windows-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup .NET
- uses: actions/setup-dotnet@v1
+ uses: actions/setup-dotnet@v3
with:
- dotnet-version: 7.0.x
+ dotnet-version: |
+ 8.0.x
+ 7.0.x
+ 6.0.x
- name: Git Semantic Version
id: versioning
uses: PaulHatch/semantic-version@v4.0.3
@@ -32,12 +35,6 @@ jobs:
run: dotnet build --no-restore --configuration Release /p:Version=${{ steps.versioning.outputs.version }}
- name: Test
run: dotnet test --no-build --verbosity normal --configuration Release
- - name: Upload a Build Artifact NET5
- uses: actions/upload-artifact@v2.2.4
- with:
- name: RGB.NET-NET5
- path: bin/net5.0/RGB.NET.*.dll
- if-no-files-found: error
- name: Upload a Build Artifact NET6
uses: actions/upload-artifact@v2.2.4
with:
@@ -50,6 +47,12 @@ jobs:
name: RGB.NET-NET7
path: bin/net7.0/RGB.NET.*.dll
if-no-files-found: error
+ - name: Upload a Build Artifact NET8
+ uses: actions/upload-artifact@v2.2.4
+ with:
+ name: RGB.NET-NET8
+ path: bin/net8.0/RGB.NET.*.dll
+ if-no-files-found: error
- name: Upload Nuget Build Artifact
uses: actions/upload-artifact@v2.2.4
with:
@@ -61,6 +64,6 @@ jobs:
with:
tag_name: ${{ steps.versioning.outputs.version_tag }}
generate_release_notes: true
- files: bin/net7.0/RGB.NET.*.dll
+ files: bin/net8.0/RGB.NET.*.dll
- name: Nuget Push
run: dotnet nuget push **\*.nupkg --skip-duplicate --api-key ${{ secrets.NUGET_TOKEN }} --source https://api.nuget.org/v3/index.json
diff --git a/RGB.NET.Core/Color/Behaviors/DefaultColorBehavior.cs b/RGB.NET.Core/Color/Behaviors/DefaultColorBehavior.cs
index 6942325..c1859c2 100644
--- a/RGB.NET.Core/Color/Behaviors/DefaultColorBehavior.cs
+++ b/RGB.NET.Core/Color/Behaviors/DefaultColorBehavior.cs
@@ -6,7 +6,7 @@ namespace RGB.NET.Core;
///
/// Represents the default-behavior for the work with colors.
///
-public class DefaultColorBehavior : IColorBehavior
+public sealed class DefaultColorBehavior : IColorBehavior
{
#region Methods
@@ -14,7 +14,7 @@ public class DefaultColorBehavior : IColorBehavior
/// Converts the individual byte values of this to a human-readable string.
///
/// A string that contains the individual byte values of this . For example "[A: 255, R: 255, G: 0, B: 0]".
- public virtual string ToString(in Color color) => $"[A: {color.GetA()}, R: {color.GetR()}, G: {color.GetG()}, B: {color.GetB()}]";
+ public string ToString(in Color color) => $"[A: {color.GetA()}, R: {color.GetR()}, G: {color.GetG()}, B: {color.GetB()}]";
///
/// Tests whether the specified object is a and is equivalent to this .
@@ -22,28 +22,31 @@ public class DefaultColorBehavior : IColorBehavior
/// The color to test.
/// The object to test.
/// true if is a equivalent to this ; otherwise, false.
- public virtual bool Equals(in Color color, object? obj)
- {
- if (obj is not Color color2) return false;
-
- return color.A.EqualsInTolerance(color2.A)
- && color.R.EqualsInTolerance(color2.R)
- && color.G.EqualsInTolerance(color2.G)
- && color.B.EqualsInTolerance(color2.B);
- }
+ public bool Equals(in Color color, object? obj) => obj is Color color2 && Equals(color, color2);
+
+ ///
+ /// Tests whether the specified object is a and is equivalent to this .
+ ///
+ /// The first color to test.
+ /// The second color to test.
+ /// true if equivalent to this ; otherwise, false.
+ public bool Equals(in Color color, in Color color2) => color.A.EqualsInTolerance(color2.A)
+ && color.R.EqualsInTolerance(color2.R)
+ && color.G.EqualsInTolerance(color2.G)
+ && color.B.EqualsInTolerance(color2.B);
///
/// Returns a hash code for this .
///
/// An integer value that specifies the hash code for this .
- public virtual int GetHashCode(in Color color) => HashCode.Combine(color.A, color.R, color.G, color.B);
+ public int GetHashCode(in Color color) => HashCode.Combine(color.A, color.R, color.G, color.B);
///
/// Blends a over this color.
///
/// The to to blend over.
/// The to blend.
- public virtual Color Blend(in Color baseColor, in Color blendColor)
+ public Color Blend(in Color baseColor, in Color blendColor)
{
if (blendColor.A.EqualsInTolerance(0)) return baseColor;
diff --git a/RGB.NET.Core/Color/Behaviors/IColorBehavior.cs b/RGB.NET.Core/Color/Behaviors/IColorBehavior.cs
index 29b6614..f365f37 100644
--- a/RGB.NET.Core/Color/Behaviors/IColorBehavior.cs
+++ b/RGB.NET.Core/Color/Behaviors/IColorBehavior.cs
@@ -20,6 +20,14 @@ public interface IColorBehavior
/// true if is a equivalent to this ; otherwise, false.
bool Equals(in Color color, object? obj);
+ ///
+ /// Tests whether the specified object is a and is equivalent to this .
+ ///
+ /// The first color to test.
+ /// The second color to test.
+ /// true if equivalent to this ; otherwise, false.
+ bool Equals(in Color color, in Color color2);
+
///
/// Returns a hash code for this .
///
diff --git a/RGB.NET.Core/Color/Color.cs b/RGB.NET.Core/Color/Color.cs
index ae775d3..c786502 100644
--- a/RGB.NET.Core/Color/Color.cs
+++ b/RGB.NET.Core/Color/Color.cs
@@ -11,7 +11,7 @@ namespace RGB.NET.Core;
/// Represents an ARGB (alpha, red, green, blue) color.
///
[DebuggerDisplay("[A: {A}, R: {R}, G: {G}, B: {B}]")]
-public readonly struct Color
+public readonly struct Color : IEquatable
{
#region Constants
@@ -196,6 +196,13 @@ public readonly struct Color
/// true if is a equivalent to this ; otherwise, false.
public override bool Equals(object? obj) => Behavior.Equals(this, obj);
+ ///
+ /// Tests whether the specified is equivalent to this , as defined by the current .
+ ///
+ /// The color to test.
+ /// true if is equivalent to this ; otherwise, false.
+ public bool Equals(Color other) => Behavior.Equals(this, other);
+
///
/// Returns a hash code for this , as defined by the current .
///
diff --git a/RGB.NET.Core/Decorators/AbstractDecorateable.cs b/RGB.NET.Core/Decorators/AbstractDecorateable.cs
index 5312eab..706aa45 100644
--- a/RGB.NET.Core/Decorators/AbstractDecorateable.cs
+++ b/RGB.NET.Core/Decorators/AbstractDecorateable.cs
@@ -11,7 +11,7 @@ public abstract class AbstractDecoratable : AbstractBindable, IDecoratable
{
#region Properties & Fields
- private readonly List _decorators = new();
+ private readonly List _decorators = [];
///
public IReadOnlyList Decorators { get; }
diff --git a/RGB.NET.Core/Decorators/AbstractDecorator.cs b/RGB.NET.Core/Decorators/AbstractDecorator.cs
index 159fb4b..2043ef6 100644
--- a/RGB.NET.Core/Decorators/AbstractDecorator.cs
+++ b/RGB.NET.Core/Decorators/AbstractDecorator.cs
@@ -29,7 +29,7 @@ public abstract class AbstractDecorator : AbstractBindable, IDecorator
///
/// Gets a readonly-list of all this decorator is attached to.
///
- protected List DecoratedObjects { get; } = new();
+ protected List DecoratedObjects { get; } = [];
#endregion
@@ -46,14 +46,14 @@ public abstract class AbstractDecorator : AbstractBindable, IDecorator
///
protected virtual void Detach()
{
- List decoratables = new(DecoratedObjects);
+ List decoratables = [..DecoratedObjects];
foreach (IDecoratable decoratable in decoratables)
{
IEnumerable types = decoratable.GetType().GetInterfaces().Where(t => t.IsGenericType
&& (t.Name == typeof(IDecoratable<>).Name)
&& t.GenericTypeArguments[0].IsInstanceOfType(this));
foreach (Type decoratableType in types)
- decoratableType.GetMethod(nameof(IDecoratable.RemoveDecorator))?.Invoke(decoratable, new object[] { this });
+ decoratableType.GetMethod(nameof(IDecoratable.RemoveDecorator))?.Invoke(decoratable, [this]);
}
}
diff --git a/RGB.NET.Core/Decorators/IDecoratable.cs b/RGB.NET.Core/Decorators/IDecoratable.cs
index 5fddf47..413b698 100644
--- a/RGB.NET.Core/Decorators/IDecoratable.cs
+++ b/RGB.NET.Core/Decorators/IDecoratable.cs
@@ -6,8 +6,7 @@ namespace RGB.NET.Core;
///
/// Represents a basic decoratable.
///
-public interface IDecoratable : INotifyPropertyChanged
-{ }
+public interface IDecoratable : INotifyPropertyChanged;
///
///
diff --git a/RGB.NET.Core/Decorators/ILedGroupDecorator.cs b/RGB.NET.Core/Decorators/ILedGroupDecorator.cs
index 051ca9d..51bd302 100644
--- a/RGB.NET.Core/Decorators/ILedGroupDecorator.cs
+++ b/RGB.NET.Core/Decorators/ILedGroupDecorator.cs
@@ -4,5 +4,4 @@
///
/// Represents a basic decorator decorating a .
///
-public interface ILedGroupDecorator : IDecorator
-{ }
\ No newline at end of file
+public interface ILedGroupDecorator : IDecorator;
\ No newline at end of file
diff --git a/RGB.NET.Core/Devices/AbstractRGBDevice.cs b/RGB.NET.Core/Devices/AbstractRGBDevice.cs
index 1457e0a..9e3572b 100644
--- a/RGB.NET.Core/Devices/AbstractRGBDevice.cs
+++ b/RGB.NET.Core/Devices/AbstractRGBDevice.cs
@@ -2,9 +2,12 @@
// ReSharper disable UnusedMember.Global
// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+using System;
+using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
+using System.Runtime.CompilerServices;
namespace RGB.NET.Core;
@@ -50,7 +53,7 @@ public abstract class AbstractRGBDevice : Placeable, IRGBDevice
/// Gets a dictionary containing all of the .
///
- protected Dictionary LedMapping { get; } = new();
+ protected Dictionary LedMapping { get; } = [];
///
/// Gets the update queue used to update this device.
@@ -84,6 +87,8 @@ public abstract class AbstractRGBDevice : Placeable, IRGBDevice : Placeable, IRGBDevice ledsToUpdate = GetLedsToUpdate(flushLeds).ToList();
-
- foreach (Led led in ledsToUpdate)
- led.Update();
-
- UpdateLeds(ledsToUpdate);
+ UpdateLeds(GetLedsToUpdate(flushLeds));
}
///
@@ -110,7 +110,7 @@ public abstract class AbstractRGBDevice : Placeable, IRGBDevice
/// Forces all LEDs to be treated as dirty.
/// The collection LEDs to update.
- protected virtual IEnumerable GetLedsToUpdate(bool flushLeds) => ((RequiresFlush || flushLeds) ? LedMapping.Values : LedMapping.Values.Where(x => x.IsDirty)).Where(led => led.RequestedColor?.A > 0);
+ protected virtual IEnumerable GetLedsToUpdate(bool flushLeds) => ((RequiresFlush || flushLeds || UpdateQueue.RequiresFlush) ? LedMapping.Values : LedMapping.Values.Where(x => x.IsDirty)).Where(led => led.RequestedColor?.A > 0);
///
/// Gets an enumerable of a custom data and color tuple for the specified leds.
@@ -121,45 +121,55 @@ public abstract class AbstractRGBDevice : Placeable, IRGBDevice
/// The enumerable of leds to convert.
/// The enumerable of custom data and color tuples for the specified leds.
- protected virtual IEnumerable<(object key, Color color)> GetUpdateData(IEnumerable leds)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ protected (object key, Color color) GetUpdateData(Led led)
{
- if (ColorCorrections.Count > 0)
- {
- foreach (Led led in leds)
- {
- Color color = led.Color;
- object key = led.CustomData ?? led.Id;
+ Color color = led.Color;
+ object key = led.CustomData ?? led.Id;
- foreach (IColorCorrection colorCorrection in ColorCorrections)
- colorCorrection.ApplyTo(ref color);
+ // ReSharper disable once ForCanBeConvertedToForeach - This causes an allocation that's not really needed here
+ for (int i = 0; i < ColorCorrections.Count; i++)
+ ColorCorrections[i].ApplyTo(ref color);
- yield return (key, color);
- }
- }
- else
- {
- foreach (Led led in leds)
- {
- Color color = led.Color;
- object key = led.CustomData ?? led.Id;
-
- yield return (key, color);
- }
- }
+ return (key, color);
}
///
/// Sends all the updated to the device.
///
- protected virtual void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate));
+ protected virtual void UpdateLeds(IEnumerable ledsToUpdate)
+ {
+ (object key, Color color)[] buffer = ArrayPool<(object, Color)>.Shared.Rent(LedMapping.Count);
+
+ int counter = 0;
+ foreach (Led led in ledsToUpdate)
+ {
+ led.Update();
+
+ buffer[counter] = GetUpdateData(led);
+ ++counter;
+ }
+
+ UpdateQueue.SetData(new ReadOnlySpan<(object, Color)>(buffer)[..counter]);
+
+ ArrayPool<(object, Color)>.Shared.Return(buffer);
+ }
///
public virtual void Dispose()
{
- try { UpdateQueue.Dispose(); } catch { /* :( */ }
+ try
+ {
+ UpdateQueue.RemoveReferencingObject(this);
+ if (!UpdateQueue.HasActiveReferences())
+ UpdateQueue.Dispose();
+ }
+ catch { /* :( */ }
try { LedMapping.Clear(); } catch { /* this really shouldn't happen */ }
IdGenerator.ResetCounter(GetType().Assembly);
+
+ GC.SuppressFinalize(this);
}
///
diff --git a/RGB.NET.Core/Devices/AbstractRGBDeviceProvider.cs b/RGB.NET.Core/Devices/AbstractRGBDeviceProvider.cs
index ae66ca0..ff2f7df 100644
--- a/RGB.NET.Core/Devices/AbstractRGBDeviceProvider.cs
+++ b/RGB.NET.Core/Devices/AbstractRGBDeviceProvider.cs
@@ -12,6 +12,8 @@ public abstract class AbstractRGBDeviceProvider : IRGBDeviceProvider
{
#region Properties & Fields
+ private bool _isDisposed = false;
+
private readonly double _defaultUpdateRateHardLimit;
///
@@ -20,14 +22,19 @@ public abstract class AbstractRGBDeviceProvider : IRGBDeviceProvider
///
public bool ThrowsExceptions { get; protected set; }
+ ///
+ /// The list of devices managed by this device-provider.
+ ///
+ protected List InternalDevices { get; } = [];
+
///
- public virtual IEnumerable Devices { get; protected set; } = Enumerable.Empty();
+ public virtual IReadOnlyList Devices => new ReadOnlyCollection(InternalDevices);
///
/// Gets the dictionary containing the registered update triggers.
/// Normally should be used to access them.
///
- protected Dictionary UpdateTriggerMapping { get; } = new();
+ protected Dictionary UpdateTriggerMapping { get; } = [];
///
public IReadOnlyList<(int id, IDeviceUpdateTrigger trigger)> UpdateTriggers => new ReadOnlyCollection<(int id, IDeviceUpdateTrigger trigger)>(UpdateTriggerMapping.Select(x => (x.Key, x.Value)).ToList());
@@ -39,6 +46,9 @@ public abstract class AbstractRGBDeviceProvider : IRGBDeviceProvider
///
public event EventHandler? Exception;
+ ///
+ public event EventHandler? DevicesChanged;
+
#endregion
#region Constructors
@@ -52,6 +62,8 @@ public abstract class AbstractRGBDeviceProvider : IRGBDeviceProvider
this._defaultUpdateRateHardLimit = defaultUpdateRateHardLimit;
}
+ ~AbstractRGBDeviceProvider() => Dispose(false);
+
#endregion
#region Methods
@@ -59,6 +71,8 @@ public abstract class AbstractRGBDeviceProvider : IRGBDeviceProvider
///
public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false)
{
+ if (_isDisposed) throw new ObjectDisposedException(GetType().FullName);
+
ThrowsExceptions = throwExceptions;
try
@@ -67,7 +81,8 @@ public abstract class AbstractRGBDeviceProvider : IRGBDeviceProvider
InitializeSDK();
- Devices = new ReadOnlyCollection(GetLoadedDevices(loadFilter).ToList());
+ foreach (IRGBDevice device in GetLoadedDevices(loadFilter))
+ AddDevice(device);
foreach (IDeviceUpdateTrigger updateTrigger in UpdateTriggerMapping.Values)
updateTrigger.Start();
@@ -99,7 +114,9 @@ public abstract class AbstractRGBDeviceProvider : IRGBDeviceProvider
/// The filtered collection of loaded devices.
protected virtual IEnumerable GetLoadedDevices(RGBDeviceType loadFilter)
{
- List devices = new();
+ if (_isDisposed) throw new ObjectDisposedException(GetType().FullName);
+
+ List devices = [];
foreach (IRGBDevice device in LoadDevices())
{
try
@@ -143,6 +160,8 @@ public abstract class AbstractRGBDeviceProvider : IRGBDeviceProvider
/// The update trigger mapped to the specified id.
protected virtual IDeviceUpdateTrigger GetUpdateTrigger(int id = -1, double? updateRateHardLimit = null)
{
+ if (_isDisposed) throw new ObjectDisposedException(GetType().FullName);
+
if (!UpdateTriggerMapping.TryGetValue(id, out IDeviceUpdateTrigger? updaeTrigger))
UpdateTriggerMapping[id] = (updaeTrigger = CreateUpdateTrigger(id, updateRateHardLimit ?? _defaultUpdateRateHardLimit));
@@ -162,23 +181,61 @@ public abstract class AbstractRGBDeviceProvider : IRGBDeviceProvider
///
protected virtual void Reset()
{
+ if (_isDisposed) throw new ObjectDisposedException(GetType().FullName);
+
foreach (IDeviceUpdateTrigger updateTrigger in UpdateTriggerMapping.Values)
updateTrigger.Dispose();
foreach (IRGBDevice device in Devices)
device.Dispose();
- Devices = Enumerable.Empty();
+ List devices = [..InternalDevices];
+ foreach (IRGBDevice device in devices)
+ RemoveDevice(device);
+
UpdateTriggerMapping.Clear();
IsInitialized = false;
}
+ ///
+ /// Adds the provided device to the list of managed devices.
+ ///
+ /// The device to add.
+ /// true if the device was added successfully; otherwise false.
+ protected virtual bool AddDevice(IRGBDevice device)
+ {
+ if (_isDisposed) throw new ObjectDisposedException(GetType().FullName);
+
+ if (InternalDevices.Contains(device)) return false;
+
+ InternalDevices.Add(device);
+ try { OnDevicesChanged(DevicesChangedEventArgs.CreateDevicesAddedArgs(device)); } catch { /* we don't want to throw due to bad event handlers */ }
+
+ return true;
+ }
+
+ ///
+ /// Removes the provided device from the list of managed devices.
+ ///
+ /// The device to remove.
+ /// true if the device was removed successfully; otherwise false.
+ protected virtual bool RemoveDevice(IRGBDevice device)
+ {
+ if (_isDisposed) throw new ObjectDisposedException(GetType().FullName);
+
+ if (!InternalDevices.Remove(device)) return false;
+
+ try { OnDevicesChanged(DevicesChangedEventArgs.CreateDevicesRemovedArgs(device)); } catch { /* we don't want to throw due to bad event handlers */ }
+
+ return true;
+ }
+
///
/// Triggers the -event and throws the specified exception if is true and it is not overriden in the event.
///
/// The exception to throw.
/// Indicates if the exception is critical for device provider to work correctly.
- protected virtual void Throw(Exception ex, bool isCritical = false)
+ public virtual void Throw(Exception ex, bool isCritical = false)
{
ExceptionEventArgs args = new(ex, isCritical, ThrowsExceptions);
try { OnException(args); } catch { /* we don't want to throw due to bad event handlers */ }
@@ -188,18 +245,38 @@ public abstract class AbstractRGBDeviceProvider : IRGBDeviceProvider
}
///
- /// Throws the event.
+ /// Throws the .event.
///
/// The parameters passed to the event.
protected virtual void OnException(ExceptionEventArgs args) => Exception?.Invoke(this, args);
+ ///
+ /// Throws the -event.
+ ///
+ /// The parameters passed to the event.
+ protected virtual void OnDevicesChanged(DevicesChangedEventArgs args) => DevicesChanged?.Invoke(this, args);
+
///
- public virtual void Dispose()
+ public void Dispose()
{
- Reset();
+ if (_isDisposed) return;
+
+ try
+ {
+ Dispose(true);
+ }
+ catch { /* don't throw in dispose! */ }
GC.SuppressFinalize(this);
+
+ _isDisposed = true;
}
+ ///
+ /// Disposes the object and frees all resources.
+ ///
+ /// true if explicitely called through the Dispose-Method, false if called by the destructor.
+ protected virtual void Dispose(bool disposing) => Reset();
+
#endregion
}
\ No newline at end of file
diff --git a/RGB.NET.Core/Devices/IRGBDeviceProvider.cs b/RGB.NET.Core/Devices/IRGBDeviceProvider.cs
index 48edc4d..6e22d12 100644
--- a/RGB.NET.Core/Devices/IRGBDeviceProvider.cs
+++ b/RGB.NET.Core/Devices/IRGBDeviceProvider.cs
@@ -20,12 +20,16 @@ public interface IRGBDeviceProvider : IDisposable
///
/// Indicates if exceptions in the device provider are thrown or silently ignored.
///
+ ///
+ /// This should only be set to true for debugging/development purposes.
+ /// Production code should use the -Event to handle exceptions.
+ ///
bool ThrowsExceptions { get; }
///
/// Gets a collection of loaded by this .
///
- IEnumerable Devices { get; }
+ IReadOnlyList Devices { get; }
///
/// Gets a collection registered to this device provider.
@@ -41,6 +45,11 @@ public interface IRGBDeviceProvider : IDisposable
///
event EventHandler? Exception;
+ ///
+ /// Occures when the devices provided by this device provider changed.
+ ///
+ event EventHandler? DevicesChanged;
+
#endregion
#region Methods
diff --git a/RGB.NET.Core/Devices/RGBDeviceType.cs b/RGB.NET.Core/Devices/RGBDeviceType.cs
index 88e4f82..57be106 100644
--- a/RGB.NET.Core/Devices/RGBDeviceType.cs
+++ b/RGB.NET.Core/Devices/RGBDeviceType.cs
@@ -93,6 +93,11 @@ public enum RGBDeviceType
///
LedController = 1 << 15,
+ ///
+ /// Represents a game controller.
+ ///
+ GameController = 1 << 16,
+
///
/// Represents a device where the type is not known or not present in the list.
///
diff --git a/RGB.NET.Core/Devices/TypeInterfaces/ICooler.cs b/RGB.NET.Core/Devices/TypeInterfaces/ICooler.cs
index 1e1eb2f..da7c2a0 100644
--- a/RGB.NET.Core/Devices/TypeInterfaces/ICooler.cs
+++ b/RGB.NET.Core/Devices/TypeInterfaces/ICooler.cs
@@ -3,5 +3,4 @@
///
/// Represents a cooler-device
///
-public interface ICooler : IRGBDevice
-{ }
\ No newline at end of file
+public interface ICooler : IRGBDevice;
\ No newline at end of file
diff --git a/RGB.NET.Core/Devices/TypeInterfaces/IDRAM.cs b/RGB.NET.Core/Devices/TypeInterfaces/IDRAM.cs
index 3bb4c23..a395d91 100644
--- a/RGB.NET.Core/Devices/TypeInterfaces/IDRAM.cs
+++ b/RGB.NET.Core/Devices/TypeInterfaces/IDRAM.cs
@@ -3,5 +3,4 @@
///
/// Represents a DRAM-device
///
-public interface IDRAM : IRGBDevice
-{ }
\ No newline at end of file
+public interface IDRAM : IRGBDevice;
\ No newline at end of file
diff --git a/RGB.NET.Core/Devices/TypeInterfaces/IFan.cs b/RGB.NET.Core/Devices/TypeInterfaces/IFan.cs
index 9f0c803..fd11b08 100644
--- a/RGB.NET.Core/Devices/TypeInterfaces/IFan.cs
+++ b/RGB.NET.Core/Devices/TypeInterfaces/IFan.cs
@@ -3,5 +3,4 @@
///
/// represents a fan-device
///
-public interface IFan : IRGBDevice
-{ }
\ No newline at end of file
+public interface IFan : IRGBDevice;
\ No newline at end of file
diff --git a/RGB.NET.Core/Devices/TypeInterfaces/IGameController.cs b/RGB.NET.Core/Devices/TypeInterfaces/IGameController.cs
new file mode 100644
index 0000000..ebfe6a1
--- /dev/null
+++ b/RGB.NET.Core/Devices/TypeInterfaces/IGameController.cs
@@ -0,0 +1,6 @@
+namespace RGB.NET.Core;
+
+///
+/// Represents a gamecontroller-device
+///
+public interface IGameController: IRGBDevice;
\ No newline at end of file
diff --git a/RGB.NET.Core/Devices/TypeInterfaces/IGraphicsCard.cs b/RGB.NET.Core/Devices/TypeInterfaces/IGraphicsCard.cs
index 372ec09..9d58944 100644
--- a/RGB.NET.Core/Devices/TypeInterfaces/IGraphicsCard.cs
+++ b/RGB.NET.Core/Devices/TypeInterfaces/IGraphicsCard.cs
@@ -3,5 +3,4 @@
///
/// Represents a graphics-card-device
///
-public interface IGraphicsCard : IRGBDevice
-{ }
\ No newline at end of file
+public interface IGraphicsCard : IRGBDevice;
\ No newline at end of file
diff --git a/RGB.NET.Core/Devices/TypeInterfaces/IHeadset.cs b/RGB.NET.Core/Devices/TypeInterfaces/IHeadset.cs
index 0256cd5..fea115e 100644
--- a/RGB.NET.Core/Devices/TypeInterfaces/IHeadset.cs
+++ b/RGB.NET.Core/Devices/TypeInterfaces/IHeadset.cs
@@ -3,5 +3,4 @@
///
/// Represents a headset-device
///
-public interface IHeadset : IRGBDevice
-{ }
\ No newline at end of file
+public interface IHeadset : IRGBDevice;
\ No newline at end of file
diff --git a/RGB.NET.Core/Devices/TypeInterfaces/IHeadsetStand.cs b/RGB.NET.Core/Devices/TypeInterfaces/IHeadsetStand.cs
index 537c856..afc31c7 100644
--- a/RGB.NET.Core/Devices/TypeInterfaces/IHeadsetStand.cs
+++ b/RGB.NET.Core/Devices/TypeInterfaces/IHeadsetStand.cs
@@ -3,5 +3,4 @@
///
/// Represents a headset-stand-device
///
-public interface IHeadsetStand : IRGBDevice
-{ }
\ No newline at end of file
+public interface IHeadsetStand : IRGBDevice;
\ No newline at end of file
diff --git a/RGB.NET.Core/Devices/TypeInterfaces/IKeypad.cs b/RGB.NET.Core/Devices/TypeInterfaces/IKeypad.cs
index 2a65233..ff6a970 100644
--- a/RGB.NET.Core/Devices/TypeInterfaces/IKeypad.cs
+++ b/RGB.NET.Core/Devices/TypeInterfaces/IKeypad.cs
@@ -3,5 +3,4 @@
///
/// Represents a keypad-device
///
-public interface IKeypad : IRGBDevice
-{ }
\ No newline at end of file
+public interface IKeypad : IRGBDevice;
\ No newline at end of file
diff --git a/RGB.NET.Core/Devices/TypeInterfaces/ILedMatrix.cs b/RGB.NET.Core/Devices/TypeInterfaces/ILedMatrix.cs
index b0f401e..48d029b 100644
--- a/RGB.NET.Core/Devices/TypeInterfaces/ILedMatrix.cs
+++ b/RGB.NET.Core/Devices/TypeInterfaces/ILedMatrix.cs
@@ -3,5 +3,4 @@
///
/// Represents a led-matrix-device
///
-public interface ILedMatrix : IRGBDevice
-{ }
\ No newline at end of file
+public interface ILedMatrix : IRGBDevice;
\ No newline at end of file
diff --git a/RGB.NET.Core/Devices/TypeInterfaces/ILedStripe.cs b/RGB.NET.Core/Devices/TypeInterfaces/ILedStripe.cs
index 4bb5fd8..355cd28 100644
--- a/RGB.NET.Core/Devices/TypeInterfaces/ILedStripe.cs
+++ b/RGB.NET.Core/Devices/TypeInterfaces/ILedStripe.cs
@@ -3,5 +3,4 @@
///
/// Represents a led-stripe-device
///
-public interface ILedStripe : IRGBDevice
-{ }
\ No newline at end of file
+public interface ILedStripe : IRGBDevice;
\ No newline at end of file
diff --git a/RGB.NET.Core/Devices/TypeInterfaces/IMainboard.cs b/RGB.NET.Core/Devices/TypeInterfaces/IMainboard.cs
index 10af8f4..5e7b270 100644
--- a/RGB.NET.Core/Devices/TypeInterfaces/IMainboard.cs
+++ b/RGB.NET.Core/Devices/TypeInterfaces/IMainboard.cs
@@ -3,5 +3,4 @@
///
/// Represents a mainboard-device
///
-public interface IMainboard : IRGBDevice
-{ }
\ No newline at end of file
+public interface IMainboard : IRGBDevice;
\ No newline at end of file
diff --git a/RGB.NET.Core/Devices/TypeInterfaces/IMouse.cs b/RGB.NET.Core/Devices/TypeInterfaces/IMouse.cs
index 76e62e2..d045976 100644
--- a/RGB.NET.Core/Devices/TypeInterfaces/IMouse.cs
+++ b/RGB.NET.Core/Devices/TypeInterfaces/IMouse.cs
@@ -3,5 +3,4 @@
///
/// Represents a mouse-device
///
-public interface IMouse : IRGBDevice
-{ }
\ No newline at end of file
+public interface IMouse : IRGBDevice;
\ No newline at end of file
diff --git a/RGB.NET.Core/Devices/TypeInterfaces/IMousepad.cs b/RGB.NET.Core/Devices/TypeInterfaces/IMousepad.cs
index c89b254..af87521 100644
--- a/RGB.NET.Core/Devices/TypeInterfaces/IMousepad.cs
+++ b/RGB.NET.Core/Devices/TypeInterfaces/IMousepad.cs
@@ -3,5 +3,4 @@
///
/// Represents a mousepad-device
///
-public interface IMousepad : IRGBDevice
-{ }
\ No newline at end of file
+public interface IMousepad : IRGBDevice;
\ No newline at end of file
diff --git a/RGB.NET.Core/Devices/TypeInterfaces/ISpeaker.cs b/RGB.NET.Core/Devices/TypeInterfaces/ISpeaker.cs
index cde47e4..226d6a8 100644
--- a/RGB.NET.Core/Devices/TypeInterfaces/ISpeaker.cs
+++ b/RGB.NET.Core/Devices/TypeInterfaces/ISpeaker.cs
@@ -3,5 +3,4 @@
///
/// Represents a speaker-device
///
-public interface ISpeaker : IRGBDevice
-{ }
\ No newline at end of file
+public interface ISpeaker : IRGBDevice;
\ No newline at end of file
diff --git a/RGB.NET.Core/Devices/TypeInterfaces/IUnknownDevice.cs b/RGB.NET.Core/Devices/TypeInterfaces/IUnknownDevice.cs
index 1d136ad..a037453 100644
--- a/RGB.NET.Core/Devices/TypeInterfaces/IUnknownDevice.cs
+++ b/RGB.NET.Core/Devices/TypeInterfaces/IUnknownDevice.cs
@@ -3,5 +3,4 @@
///
/// Represents a device with unkown or not specified type.
///
-public interface IUnknownDevice : IRGBDevice
-{ }
\ No newline at end of file
+public interface IUnknownDevice : IRGBDevice;
\ No newline at end of file
diff --git a/RGB.NET.Core/Events/DevicesChangedEventArgs.cs b/RGB.NET.Core/Events/DevicesChangedEventArgs.cs
new file mode 100644
index 0000000..5a856e5
--- /dev/null
+++ b/RGB.NET.Core/Events/DevicesChangedEventArgs.cs
@@ -0,0 +1,27 @@
+using System;
+
+namespace RGB.NET.Core;
+
+public sealed class DevicesChangedEventArgs(IRGBDevice device, DevicesChangedEventArgs.DevicesChangedAction action)
+ : EventArgs
+{
+ #region Properties & Fields
+
+ public IRGBDevice Device { get; } = device;
+ public DevicesChangedAction Action { get; } = action;
+
+ #endregion
+
+ #region Methods
+
+ public static DevicesChangedEventArgs CreateDevicesAddedArgs(IRGBDevice addedDevice) => new(addedDevice, DevicesChangedAction.Added);
+ public static DevicesChangedEventArgs CreateDevicesRemovedArgs(IRGBDevice removedDevice) => new(removedDevice, DevicesChangedAction.Removed);
+
+ #endregion
+
+ public enum DevicesChangedAction
+ {
+ Added,
+ Removed
+ }
+}
\ No newline at end of file
diff --git a/RGB.NET.Core/Events/UpdatedEventArgs.cs b/RGB.NET.Core/Events/UpdatedEventArgs.cs
index b4251d4..467e503 100644
--- a/RGB.NET.Core/Events/UpdatedEventArgs.cs
+++ b/RGB.NET.Core/Events/UpdatedEventArgs.cs
@@ -6,5 +6,4 @@ namespace RGB.NET.Core;
///
/// Represents the information supplied with an -event.
///
-public class UpdatedEventArgs : EventArgs
-{ }
\ No newline at end of file
+public class UpdatedEventArgs : EventArgs;
\ No newline at end of file
diff --git a/RGB.NET.Core/Events/UpdatingEventArgs.cs b/RGB.NET.Core/Events/UpdatingEventArgs.cs
index 47df4af..d39ea74 100644
--- a/RGB.NET.Core/Events/UpdatingEventArgs.cs
+++ b/RGB.NET.Core/Events/UpdatingEventArgs.cs
@@ -26,7 +26,7 @@ public class UpdatingEventArgs : EventArgs
///
/// Gets the custom-data provided by the trigger for this update.
///
- public CustomUpdateData CustomData { get; }
+ public ICustomUpdateData CustomData { get; }
#endregion
@@ -39,7 +39,7 @@ public class UpdatingEventArgs : EventArgs
/// The elapsed time (in seconds) since the last update.
/// The trigger causing this update.
/// The custom-data provided by the trigger for this update.
- public UpdatingEventArgs(double deltaTime, IUpdateTrigger? trigger, CustomUpdateData customData)
+ public UpdatingEventArgs(double deltaTime, IUpdateTrigger? trigger, ICustomUpdateData customData)
{
this.DeltaTime = deltaTime;
this.Trigger = trigger;
diff --git a/RGB.NET.Core/Extensions/RectangleExtensions.cs b/RGB.NET.Core/Extensions/RectangleExtensions.cs
index 68fec32..c97256f 100644
--- a/RGB.NET.Core/Extensions/RectangleExtensions.cs
+++ b/RGB.NET.Core/Extensions/RectangleExtensions.cs
@@ -151,12 +151,13 @@ public static class RectangleExtensions
/// A array of containing the new locations of the corners of the original rectangle.
public static Point[] Rotate(this in Rectangle rect, in Rotation rotation, in Point origin = new())
{
- Point[] points = {
- rect.Location, // top left
- new(rect.Location.X + rect.Size.Width, rect.Location.Y), // top right
- new(rect.Location.X + rect.Size.Width, rect.Location.Y + rect.Size.Height), // bottom right
- new(rect.Location.X, rect.Location.Y + rect.Size.Height), // bottom right
- };
+ Point[] points =
+ [
+ rect.Location, // top left
+ new Point(rect.Location.X + rect.Size.Width, rect.Location.Y), // top right
+ new Point(rect.Location.X + rect.Size.Width, rect.Location.Y + rect.Size.Height), // bottom right
+ new Point(rect.Location.X, rect.Location.Y + rect.Size.Height), // bottom right
+ ];
float sin = MathF.Sin(rotation.Radians);
float cos = MathF.Cos(rotation.Radians);
diff --git a/RGB.NET.Core/Extensions/ReferenceCountingExtension.cs b/RGB.NET.Core/Extensions/ReferenceCountingExtension.cs
new file mode 100644
index 0000000..58039eb
--- /dev/null
+++ b/RGB.NET.Core/Extensions/ReferenceCountingExtension.cs
@@ -0,0 +1,6 @@
+namespace RGB.NET.Core;
+
+public static class ReferenceCountingExtension
+{
+ public static bool HasActiveReferences(this IReferenceCounting target) => target.ActiveReferenceCount > 0;
+}
\ No newline at end of file
diff --git a/RGB.NET.Core/Groups/AbstractLedGroup.cs b/RGB.NET.Core/Groups/AbstractLedGroup.cs
index 6569dac..7135a21 100644
--- a/RGB.NET.Core/Groups/AbstractLedGroup.cs
+++ b/RGB.NET.Core/Groups/AbstractLedGroup.cs
@@ -1,5 +1,7 @@
-using System.Collections;
+using System;
+using System.Collections;
using System.Collections.Generic;
+using System.Linq;
namespace RGB.NET.Core;
@@ -51,11 +53,23 @@ public abstract class AbstractLedGroup : AbstractDecoratable
///
public virtual void OnDetach() { }
+ ///
+ public virtual IList ToList() => GetLeds().ToList();
+
///
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
///
public IEnumerator GetEnumerator() => GetLeds().GetEnumerator();
+ ///
+ IDisposable? ILedGroup.ToListUnsafe(out IList leds) => ToListUnsafe(out leds);
+
+ protected virtual IDisposable? ToListUnsafe(out IList leds)
+ {
+ leds = ToList();
+ return null;
+ }
+
#endregion
}
\ No newline at end of file
diff --git a/RGB.NET.Core/Groups/ILedGroup.cs b/RGB.NET.Core/Groups/ILedGroup.cs
index 88b5b97..1970afc 100644
--- a/RGB.NET.Core/Groups/ILedGroup.cs
+++ b/RGB.NET.Core/Groups/ILedGroup.cs
@@ -1,6 +1,7 @@
// ReSharper disable UnusedMemberInSuper.Global
// ReSharper disable UnusedMember.Global
+using System;
using System.Collections.Generic;
namespace RGB.NET.Core;
@@ -39,4 +40,12 @@ public interface ILedGroup : IDecoratable, IEnumerable
/// Called when the is detached from the .
///
void OnDetach();
+
+ ///
+ /// Returns a list containing all in this group.
+ ///
+ /// A list containing all in this group.
+ IList ToList();
+
+ internal IDisposable? ToListUnsafe(out IList leds);
}
\ No newline at end of file
diff --git a/RGB.NET.Core/Groups/ListLedGroup.cs b/RGB.NET.Core/Groups/ListLedGroup.cs
index a33fc56..4bca2fb 100644
--- a/RGB.NET.Core/Groups/ListLedGroup.cs
+++ b/RGB.NET.Core/Groups/ListLedGroup.cs
@@ -1,7 +1,9 @@
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable UnusedMember.Global
+using System;
using System.Collections.Generic;
+using System.Threading;
namespace RGB.NET.Core;
@@ -9,14 +11,16 @@ namespace RGB.NET.Core;
///
/// Represents a ledgroup containing arbitrary .
///
-public class ListLedGroup : AbstractLedGroup
+public sealed class ListLedGroup : AbstractLedGroup
{
#region Properties & Fields
+ private readonly ActionDisposable _unlockDisposable;
+
///
/// Gets the list containing the of this .
///
- protected IList GroupLeds { get; } = new List();
+ private readonly IList _groupLeds = new List();
#endregion
@@ -29,7 +33,9 @@ public class ListLedGroup : AbstractLedGroup
/// Specifies the surface to attach this group to or null if the group should not be attached on creation.
public ListLedGroup(RGBSurface? surface)
: base(surface)
- { }
+ {
+ _unlockDisposable = new ActionDisposable(Unlock);
+ }
///
///
@@ -40,6 +46,8 @@ public class ListLedGroup : AbstractLedGroup
public ListLedGroup(RGBSurface? surface, IEnumerable leds)
: base(surface)
{
+ _unlockDisposable = new ActionDisposable(Unlock);
+
AddLeds(leds);
}
@@ -52,6 +60,8 @@ public class ListLedGroup : AbstractLedGroup
public ListLedGroup(RGBSurface? surface, params Led[] leds)
: base(surface)
{
+ _unlockDisposable = new ActionDisposable(Unlock);
+
AddLeds(leds);
}
@@ -71,10 +81,10 @@ public class ListLedGroup : AbstractLedGroup
/// The to add.
public void AddLeds(IEnumerable leds)
{
- lock (GroupLeds)
+ lock (_groupLeds)
foreach (Led led in leds)
if (!ContainsLed(led))
- GroupLeds.Add(led);
+ _groupLeds.Add(led);
}
///
@@ -89,9 +99,9 @@ public class ListLedGroup : AbstractLedGroup
/// The to remove.
public void RemoveLeds(IEnumerable leds)
{
- lock (GroupLeds)
+ lock (_groupLeds)
foreach (Led led in leds)
- GroupLeds.Remove(led);
+ _groupLeds.Remove(led);
}
///
@@ -101,8 +111,8 @@ public class ListLedGroup : AbstractLedGroup
/// true if the LED is contained by this ledgroup; otherwise, false.
public bool ContainsLed(Led led)
{
- lock (GroupLeds)
- return GroupLeds.Contains(led);
+ lock (_groupLeds)
+ return _groupLeds.Contains(led);
}
///
@@ -111,10 +121,10 @@ public class ListLedGroup : AbstractLedGroup
/// The ledgroup to merge.
public void MergeLeds(ILedGroup groupToMerge)
{
- lock (GroupLeds)
+ lock (_groupLeds)
foreach (Led led in groupToMerge)
- if (!GroupLeds.Contains(led))
- GroupLeds.Add(led);
+ if (!_groupLeds.Contains(led))
+ _groupLeds.Add(led);
}
///
@@ -122,11 +132,27 @@ public class ListLedGroup : AbstractLedGroup
/// Gets a list containing the from this group.
///
/// The list containing the .
- protected override IEnumerable GetLeds()
+ protected override IEnumerable GetLeds() => ToList();
+
+ ///
+ ///
+ /// Gets a list containing the from this group.
+ ///
+ /// The list containing the .
+ public override IList ToList()
{
- lock (GroupLeds)
- return new List(GroupLeds);
+ lock (_groupLeds)
+ return new List(_groupLeds);
}
+ protected override IDisposable ToListUnsafe(out IList leds)
+ {
+ Monitor.Enter(_groupLeds);
+ leds = _groupLeds;
+ return _unlockDisposable;
+ }
+
+ private void Unlock() => Monitor.Exit(_groupLeds);
+
#endregion
}
\ No newline at end of file
diff --git a/RGB.NET.Core/Helper/TimerHelper.cs b/RGB.NET.Core/Helper/TimerHelper.cs
index 432170b..e2742ab 100644
--- a/RGB.NET.Core/Helper/TimerHelper.cs
+++ b/RGB.NET.Core/Helper/TimerHelper.cs
@@ -46,7 +46,7 @@ public static class TimerHelper
}
// ReSharper disable once InconsistentNaming
- private static readonly HashSet _timerLeases = new();
+ private static readonly HashSet _timerLeases = [];
#endregion
@@ -143,7 +143,7 @@ public static class TimerHelper
///
public static void DisposeAllHighResolutionTimerRequests()
{
- List timerLeases = new(_timerLeases);
+ List timerLeases = [.._timerLeases];
foreach (HighResolutionTimerDisposable timer in timerLeases)
timer.Dispose();
}
diff --git a/RGB.NET.Core/Ids/IdGenerator.cs b/RGB.NET.Core/Ids/IdGenerator.cs
index 99beaa6..f9bf217 100644
--- a/RGB.NET.Core/Ids/IdGenerator.cs
+++ b/RGB.NET.Core/Ids/IdGenerator.cs
@@ -12,9 +12,9 @@ public static class IdGenerator
#region Properties & Fields
// ReSharper disable InconsistentNaming
- private static readonly HashSet _registeredIds = new();
- private static readonly Dictionary> _idMappings = new();
- private static readonly Dictionary> _counter = new();
+ private static readonly HashSet _registeredIds = [];
+ private static readonly Dictionary> _idMappings = [];
+ private static readonly Dictionary> _counter = [];
// ReSharper restore InconsistentNaming
#endregion
@@ -33,8 +33,8 @@ public static class IdGenerator
{
if (!_idMappings.TryGetValue(callingAssembly, out Dictionary? idMapping))
{
- _idMappings.Add(callingAssembly, idMapping = new Dictionary());
- _counter.Add(callingAssembly, new Dictionary());
+ _idMappings.Add(callingAssembly, idMapping = []);
+ _counter.Add(callingAssembly, []);
}
Dictionary counterMapping = _counter[callingAssembly];
@@ -50,8 +50,7 @@ public static class IdGenerator
idMapping.Add(id, mappedId);
}
- if (!counterMapping.ContainsKey(mappedId))
- counterMapping.Add(mappedId, 0);
+ counterMapping.TryAdd(mappedId, 0);
int counter = ++counterMapping[mappedId];
return counter <= 1 ? mappedId : $"{mappedId} ({counter})";
diff --git a/RGB.NET.Core/Leds/Led.cs b/RGB.NET.Core/Leds/Led.cs
index ad2e3f9..2fb05ea 100644
--- a/RGB.NET.Core/Leds/Led.cs
+++ b/RGB.NET.Core/Leds/Led.cs
@@ -9,7 +9,7 @@ namespace RGB.NET.Core;
/// Represents a single LED of a RGB-device.
///
[DebuggerDisplay("{Id} {Color}")]
-public class Led : Placeable
+public sealed class Led : Placeable
{
#region Properties & Fields
diff --git a/RGB.NET.Core/Leds/LedId.cs b/RGB.NET.Core/Leds/LedId.cs
index dff98a5..a0b12c9 100644
--- a/RGB.NET.Core/Leds/LedId.cs
+++ b/RGB.NET.Core/Leds/LedId.cs
@@ -372,6 +372,14 @@ public enum LedId
Keyboard_Custom127 = 0x0000707F,
Keyboard_Custom128 = 0x00007080,
+ Keyboard_IndicatorNumLock = 0x00008001,
+ Keyboard_IndicatorCapsLock = 0x00008002,
+ Keyboard_IndicatorScrollLock = 0x00008003,
+ Keyboard_IndicatorWinLock = 0x00008004,
+ Keyboard_IndicatorPower = 0x00008005,
+ Keyboard_IndicatorMuted = 0x00008006,
+ Keyboard_IndicatorMacro = 0x00008007,
+
/*### Mouse ###*/
Mouse1 = 0x00100001,
Mouse2 = 0x00100002,
@@ -6286,6 +6294,136 @@ public enum LedId
Cooler127 = 0x00D0007F,
Cooler128 = 0x00D00080,
+ /*### GameController ###*/
+ GameController1 = 0x00E00001,
+ GameController2 = 0x00E00002,
+ GameController3 = 0x00E00003,
+ GameController4 = 0x00E00004,
+ GameController5 = 0x00E00005,
+ GameController6 = 0x00E00006,
+ GameController7 = 0x00E00007,
+ GameController8 = 0x00E00008,
+ GameController9 = 0x00E00009,
+ GameController10 = 0x00E0000A,
+ GameController11 = 0x00E0000B,
+ GameController12 = 0x00E0000C,
+ GameController13 = 0x00E0000D,
+ GameController14 = 0x00E0000E,
+ GameController15 = 0x00E0000F,
+ GameController16 = 0x00E00010,
+ GameController17 = 0x00E00011,
+ GameController18 = 0x00E00012,
+ GameController19 = 0x00E00013,
+ GameController20 = 0x00E00014,
+ GameController21 = 0x00E00015,
+ GameController22 = 0x00E00016,
+ GameController23 = 0x00E00017,
+ GameController24 = 0x00E00018,
+ GameController25 = 0x00E00019,
+ GameController26 = 0x00E0001A,
+ GameController27 = 0x00E0001B,
+ GameController28 = 0x00E0001C,
+ GameController29 = 0x00E0001D,
+ GameController30 = 0x00E0001E,
+ GameController31 = 0x00E0001F,
+ GameController32 = 0x00E00020,
+ GameController33 = 0x00E00021,
+ GameController34 = 0x00E00022,
+ GameController35 = 0x00E00023,
+ GameController36 = 0x00E00024,
+ GameController37 = 0x00E00025,
+ GameController38 = 0x00E00026,
+ GameController39 = 0x00E00027,
+ GameController40 = 0x00E00028,
+ GameController41 = 0x00E00029,
+ GameController42 = 0x00E0002A,
+ GameController43 = 0x00E0002B,
+ GameController44 = 0x00E0002C,
+ GameController45 = 0x00E0002D,
+ GameController46 = 0x00E0002E,
+ GameController47 = 0x00E0002F,
+ GameController48 = 0x00E00030,
+ GameController49 = 0x00E00031,
+ GameController50 = 0x00E00032,
+ GameController51 = 0x00E00033,
+ GameController52 = 0x00E00034,
+ GameController53 = 0x00E00035,
+ GameController54 = 0x00E00036,
+ GameController55 = 0x00E00037,
+ GameController56 = 0x00E00038,
+ GameController57 = 0x00E00039,
+ GameController58 = 0x00E0003A,
+ GameController59 = 0x00E0003B,
+ GameController60 = 0x00E0003C,
+ GameController61 = 0x00E0003D,
+ GameController62 = 0x00E0003E,
+ GameController63 = 0x00E0003F,
+ GameController64 = 0x00E00040,
+ GameController65 = 0x00E00041,
+ GameController66 = 0x00E00042,
+ GameController67 = 0x00E00043,
+ GameController68 = 0x00E00044,
+ GameController69 = 0x00E00045,
+ GameController70 = 0x00E00046,
+ GameController71 = 0x00E00047,
+ GameController72 = 0x00E00048,
+ GameController73 = 0x00E00049,
+ GameController74 = 0x00E0004A,
+ GameController75 = 0x00E0004B,
+ GameController76 = 0x00E0004C,
+ GameController77 = 0x00E0004D,
+ GameController78 = 0x00E0004E,
+ GameController79 = 0x00E0004F,
+ GameController80 = 0x00E00050,
+ GameController81 = 0x00E00051,
+ GameController82 = 0x00E00052,
+ GameController83 = 0x00E00053,
+ GameController84 = 0x00E00054,
+ GameController85 = 0x00E00055,
+ GameController86 = 0x00E00056,
+ GameController87 = 0x00E00057,
+ GameController88 = 0x00E00058,
+ GameController89 = 0x00E00059,
+ GameController90 = 0x00E0005A,
+ GameController91 = 0x00E0005B,
+ GameController92 = 0x00E0005C,
+ GameController93 = 0x00E0005D,
+ GameController94 = 0x00E0005E,
+ GameController95 = 0x00E0005F,
+ GameController96 = 0x00E00060,
+ GameController97 = 0x00E00061,
+ GameController98 = 0x00E00062,
+ GameController99 = 0x00E00063,
+ GameController100 = 0x00E00064,
+ GameController101 = 0x00E00065,
+ GameController102 = 0x00E00066,
+ GameController103 = 0x00E00067,
+ GameController104 = 0x00E00068,
+ GameController105 = 0x00E00069,
+ GameController106 = 0x00E0006A,
+ GameController107 = 0x00E0006B,
+ GameController108 = 0x00E0006C,
+ GameController109 = 0x00E0006D,
+ GameController110 = 0x00E0006E,
+ GameController111 = 0x00E0006F,
+ GameController112 = 0x00E00070,
+ GameController113 = 0x00E00071,
+ GameController114 = 0x00E00072,
+ GameController115 = 0x00E00073,
+ GameController116 = 0x00E00074,
+ GameController117 = 0x00E00075,
+ GameController118 = 0x00E00076,
+ GameController119 = 0x00E00077,
+ GameController120 = 0x00E00078,
+ GameController121 = 0x00E00079,
+ GameController122 = 0x00E0007A,
+ GameController123 = 0x00E0007B,
+ GameController124 = 0x00E0007C,
+ GameController125 = 0x00E0007D,
+ GameController126 = 0x00E0007E,
+ GameController127 = 0x00E0007F,
+ GameController128 = 0x00E00080,
+
/*### Custom ###*/
Custom1 = 0x0FE00001,
Custom2 = 0x0FE00002,
diff --git a/RGB.NET.Core/Leds/LedMapping.cs b/RGB.NET.Core/Leds/LedMapping.cs
index e2866d3..a296bbe 100644
--- a/RGB.NET.Core/Leds/LedMapping.cs
+++ b/RGB.NET.Core/Leds/LedMapping.cs
@@ -8,13 +8,19 @@ namespace RGB.NET.Core;
/// Represents a mapping from to a custom identifier.
///
/// The identifier the is mapped to.
-public class LedMapping : IEnumerable<(LedId ledId, T mapping)>
+public sealed class LedMapping : IEnumerable<(LedId ledId, T mapping)>
where T : notnull
{
+ #region Constants
+
+ public static LedMapping Empty { get; } = [];
+
+ #endregion
+
#region Properties & Fields
- private readonly Dictionary _mapping = new();
- private readonly Dictionary _reverseMapping = new();
+ private readonly Dictionary _mapping = [];
+ private readonly Dictionary _reverseMapping = [];
///
/// Gets the number of entries in this mapping.
diff --git a/RGB.NET.Core/MVVM/AbstractBindable.cs b/RGB.NET.Core/MVVM/AbstractBindable.cs
index c58c1ae..26ac0b5 100644
--- a/RGB.NET.Core/MVVM/AbstractBindable.cs
+++ b/RGB.NET.Core/MVVM/AbstractBindable.cs
@@ -1,4 +1,5 @@
-using System.ComponentModel;
+using System.Collections.Generic;
+using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace RGB.NET.Core;
@@ -26,9 +27,9 @@ public abstract class AbstractBindable : IBindable
/// Type of the property.
/// Reference to the backing-filed.
/// Value to apply.
- /// true if the value needs to be updated; otherweise false.
+ /// true if the value needs to be updated; otherwise false.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- protected virtual bool RequiresUpdate(ref T storage, T value) => !Equals(storage, value);
+ protected bool RequiresUpdate(ref T storage, T value) => !EqualityComparer.Default.Equals(storage, value);
///
/// Checks if the property already matches the desired value and updates it if not.
@@ -39,7 +40,7 @@ public abstract class AbstractBindable : IBindable
/// Name of the property used to notify listeners. This value is optional
/// and can be provided automatically when invoked from compilers that support .
/// true if the value was changed, false if the existing value matched the desired value.
- protected virtual bool SetProperty(ref T storage, T value, [CallerMemberName] string? propertyName = null)
+ protected bool SetProperty(ref T storage, T value, [CallerMemberName] string? propertyName = null)
{
if (!RequiresUpdate(ref storage, value)) return false;
@@ -54,7 +55,7 @@ public abstract class AbstractBindable : IBindable
///
/// Name of the property used to notify listeners. This value is optional
/// and can be provided automatically when invoked from compilers that support .
- protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
+ protected void OnPropertyChanged([CallerMemberName] string? propertyName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
#endregion
diff --git a/RGB.NET.Core/MVVM/IBindable.cs b/RGB.NET.Core/MVVM/IBindable.cs
index 34a861d..9719288 100644
--- a/RGB.NET.Core/MVVM/IBindable.cs
+++ b/RGB.NET.Core/MVVM/IBindable.cs
@@ -5,6 +5,4 @@ namespace RGB.NET.Core;
///
/// Represents a basic bindable class which notifies when a property value changes.
///
-public interface IBindable : INotifyPropertyChanged
-{
-}
\ No newline at end of file
+public interface IBindable : INotifyPropertyChanged;
\ No newline at end of file
diff --git a/RGB.NET.Core/Misc/AbstractReferenceCounting.cs b/RGB.NET.Core/Misc/AbstractReferenceCounting.cs
new file mode 100644
index 0000000..f55c56a
--- /dev/null
+++ b/RGB.NET.Core/Misc/AbstractReferenceCounting.cs
@@ -0,0 +1,40 @@
+using System.Collections.Generic;
+
+namespace RGB.NET.Core;
+
+public abstract class AbstractReferenceCounting : IReferenceCounting
+{
+ #region Properties & Fields
+
+ private readonly HashSet
protected virtual void OnLocationChanged()
{
- LocationChanged?.Invoke(this, new EventArgs());
+ LocationChanged?.Invoke(this, EventArgs.Empty);
UpdateActualPlaceableData();
}
@@ -220,7 +220,7 @@ public class Placeable : AbstractBindable, IPlaceable
///
protected virtual void OnSizeChanged()
{
- SizeChanged?.Invoke(this, new EventArgs());
+ SizeChanged?.Invoke(this, EventArgs.Empty);
UpdateActualPlaceableData();
}
@@ -229,7 +229,7 @@ public class Placeable : AbstractBindable, IPlaceable
///
protected virtual void OnScaleChanged()
{
- ScaleChanged?.Invoke(this, new EventArgs());
+ ScaleChanged?.Invoke(this, EventArgs.Empty);
UpdateActualPlaceableData();
}
@@ -238,24 +238,24 @@ public class Placeable : AbstractBindable, IPlaceable
///
protected virtual void OnRotationChanged()
{
- RotationChanged?.Invoke(this, new EventArgs());
+ RotationChanged?.Invoke(this, EventArgs.Empty);
UpdateActualPlaceableData();
}
///
/// Called when the property was changed.
///
- protected virtual void OnActualLocationChanged() => ActualLocationChanged?.Invoke(this, new EventArgs());
+ protected virtual void OnActualLocationChanged() => ActualLocationChanged?.Invoke(this, EventArgs.Empty);
///
/// Called when the property was changed.
///
- protected virtual void OnActualSizeChanged() => ActualSizeChanged?.Invoke(this, new EventArgs());
+ protected virtual void OnActualSizeChanged() => ActualSizeChanged?.Invoke(this, EventArgs.Empty);
///
/// Called when the property was changed.
///
- protected virtual void OnBoundaryChanged() => BoundaryChanged?.Invoke(this, new EventArgs());
+ protected virtual void OnBoundaryChanged() => BoundaryChanged?.Invoke(this, EventArgs.Empty);
#endregion
}
\ No newline at end of file
diff --git a/RGB.NET.Core/Positioning/Point.cs b/RGB.NET.Core/Positioning/Point.cs
index e2f3d97..e92c65f 100644
--- a/RGB.NET.Core/Positioning/Point.cs
+++ b/RGB.NET.Core/Positioning/Point.cs
@@ -10,7 +10,7 @@ namespace RGB.NET.Core;
/// Represents a point consisting of a X- and a Y-position.
///
[DebuggerDisplay("[X: {X}, Y: {Y}]")]
-public readonly struct Point
+public readonly struct Point : IEquatable
{
#region Constants
@@ -59,18 +59,20 @@ public readonly struct Point
/// A string that contains the and of this . For example "[X: 100, Y: 20]".
public override string ToString() => $"[X: {X}, Y: {Y}]";
+ ///
+ /// Tests whether the specified is equivalent to this .
+ ///
+ /// The point to test.
+ /// true if is equivalent to this ; otherwise, false.
+ public bool Equals(Point other) => ((float.IsNaN(X) && float.IsNaN(other.X)) || X.EqualsInTolerance(other.X))
+ && ((float.IsNaN(Y) && float.IsNaN(other.Y)) || Y.EqualsInTolerance(other.Y));
+
///
/// Tests whether the specified object is a and is equivalent to this .
///
/// The object to test.
/// true if is a equivalent to this ; otherwise, false.
- public override bool Equals(object? obj)
- {
- if (obj is not Point comparePoint) return false;
-
- return ((float.IsNaN(X) && float.IsNaN(comparePoint.X)) || X.EqualsInTolerance(comparePoint.X))
- && ((float.IsNaN(Y) && float.IsNaN(comparePoint.Y)) || Y.EqualsInTolerance(comparePoint.Y));
- }
+ public override bool Equals(object? obj) => obj is Point other && Equals(other);
///
/// Returns a hash code for this .
diff --git a/RGB.NET.Core/Positioning/Rectangle.cs b/RGB.NET.Core/Positioning/Rectangle.cs
index a178989..095a210 100644
--- a/RGB.NET.Core/Positioning/Rectangle.cs
+++ b/RGB.NET.Core/Positioning/Rectangle.cs
@@ -12,7 +12,7 @@ namespace RGB.NET.Core;
/// Represents a rectangle defined by it's position and it's size.
///
[DebuggerDisplay("[Location: {Location}, Size: {Size}]")]
-public readonly struct Rectangle
+public readonly struct Rectangle : IEquatable
{
#region Properties & Fields
@@ -57,7 +57,8 @@ public readonly struct Rectangle
/// Initializes a new instance of the class using the (0,0) and the specified .
///
/// The size of of this .
- public Rectangle(Size size) : this(new Point(), size)
+ public Rectangle(Size size)
+ : this(new Point(), size)
{ }
///
@@ -120,15 +121,13 @@ public readonly struct Rectangle
public Rectangle(params Point[] points)
: this(points.AsEnumerable())
{ }
-
- ///
+
///
/// Initializes a new instance of the class using the specified list of .
/// The and is calculated to contain all points provided as parameters.
///
/// The list of used to calculate the and .
public Rectangle(IEnumerable points)
- : this()
{
bool hasPoint = false;
float posX = float.MaxValue;
@@ -145,13 +144,37 @@ public readonly struct Rectangle
posY2 = Math.Max(posY2, point.Y);
}
- (Point location, Size size) = hasPoint ? InitializeFromPoints(new Point(posX, posY), new Point(posX2, posY2)) : InitializeFromPoints(new Point(0, 0), new Point(0, 0));
+ (Point location, Size size) = hasPoint ? InitializeFromPoints(new Point(posX, posY), new Point(posX2, posY2))
+ : InitializeFromPoints(new Point(0, 0), new Point(0, 0));
Location = location;
Size = size;
Center = new Point(Location.X + (Size.Width / 2.0f), Location.Y + (Size.Height / 2.0f));
}
+ internal Rectangle(IList leds)
+ {
+ float posX = float.MaxValue;
+ float posY = float.MaxValue;
+ float posX2 = float.MinValue;
+ float posY2 = float.MinValue;
+
+ // ReSharper disable once ForCanBeConvertedToForeach
+ for (int i = 0; i < leds.Count; i++)
+ {
+ Rectangle rectangle = leds[i].AbsoluteBoundary;
+ posX = Math.Min(posX, rectangle.Location.X);
+ posY = Math.Min(posY, rectangle.Location.Y);
+ posX2 = Math.Max(posX2, rectangle.Location.X + rectangle.Size.Width);
+ posY2 = Math.Max(posY2, rectangle.Location.Y + rectangle.Size.Height);
+ }
+
+ (Point location, Size size) = leds.Count > 0 ? InitializeFromPoints(new Point(posX, posY), new Point(posX2, posY2)) : InitializeFromPoints(new Point(0, 0), new Point(0, 0));
+ Location = location;
+ Size = size;
+ Center = new Point(Location.X + (Size.Width / 2.0f), Location.Y + (Size.Height / 2.0f));
+ }
+
#endregion
#region Methods
@@ -172,35 +195,25 @@ public readonly struct Rectangle
/// A string that contains the and of this . For example "[Location: [X: 100, Y: 10], Size: [Width: 20, Height: [40]]".
public override string ToString() => $"[Location: {Location}, Size: {Size}]";
+ ///
+ /// Tests whether the specified is equivalent to this .
+ ///
+ /// The rectangle to test.
+ /// true if is equivalent to this ; otherwise, false.
+ public bool Equals(Rectangle other) => (Location == other.Location) && (Size == other.Size);
+
///
/// Tests whether the specified object is a and is equivalent to this .
///
/// The object to test.
/// true if is a equivalent to this ; otherwise, false.
- public override bool Equals(object? obj)
- {
- if (obj is not Rectangle compareRect)
- return false;
-
- if (GetType() != compareRect.GetType())
- return false;
-
- return (Location == compareRect.Location) && (Size == compareRect.Size);
- }
+ public override bool Equals(object? obj) => obj is Rectangle other && Equals(other);
///
/// Returns a hash code for this .
///
/// An integer value that specifies the hash code for this .
- public override int GetHashCode()
- {
- unchecked
- {
- int hashCode = Location.GetHashCode();
- hashCode = (hashCode * 397) ^ Size.GetHashCode();
- return hashCode;
- }
- }
+ public override int GetHashCode() => HashCode.Combine(Location, Size);
#endregion
diff --git a/RGB.NET.Core/Positioning/Rotation.cs b/RGB.NET.Core/Positioning/Rotation.cs
index 58903b7..e204b75 100644
--- a/RGB.NET.Core/Positioning/Rotation.cs
+++ b/RGB.NET.Core/Positioning/Rotation.cs
@@ -10,7 +10,7 @@ namespace RGB.NET.Core;
/// Represents an angular rotation.
///
[DebuggerDisplay("[{" + nameof(Degrees) + "}°]")]
-public readonly struct Rotation
+public readonly struct Rotation : IEquatable
{
#region Constants
diff --git a/RGB.NET.Core/Positioning/Scale.cs b/RGB.NET.Core/Positioning/Scale.cs
index 8c88406..18644e6 100644
--- a/RGB.NET.Core/Positioning/Scale.cs
+++ b/RGB.NET.Core/Positioning/Scale.cs
@@ -1,6 +1,7 @@
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable UnusedMember.Global
+using System;
using System.Diagnostics;
namespace RGB.NET.Core;
@@ -9,7 +10,7 @@ namespace RGB.NET.Core;
/// Represents a scaling.
///
[DebuggerDisplay("[Horizontal: {Horizontal}, Vertical: {Vertical}]")]
-public readonly struct Scale
+public readonly struct Scale : IEquatable
{
#region Properties & Fields
@@ -49,6 +50,12 @@ public readonly struct Scale
#region Methods
+ ///
+ /// Converts the and value of this to a human-readable string.
+ ///
+ /// A string that contains the and value of this . For example "[Horizontal: 1, Vertical: 0.5]".
+ public override string ToString() => $"[Horizontal: {Horizontal}, Vertical: {Vertical}]\"";
+
///
/// Tests whether the specified is equivalent to this .
///
@@ -67,7 +74,7 @@ public readonly struct Scale
/// Returns a hash code for this .
///
/// An integer value that specifies the hash code for this .
- public override int GetHashCode() { unchecked { return (Horizontal.GetHashCode() * 397) ^ Vertical.GetHashCode(); } }
+ public override int GetHashCode() => HashCode.Combine(Horizontal, Vertical);
///
/// Deconstructs the scale into the horizontal and vertical value.
diff --git a/RGB.NET.Core/Positioning/Size.cs b/RGB.NET.Core/Positioning/Size.cs
index daba2ff..1a9a6d6 100644
--- a/RGB.NET.Core/Positioning/Size.cs
+++ b/RGB.NET.Core/Positioning/Size.cs
@@ -1,6 +1,7 @@
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable UnusedMember.Global
+using System;
using System.Diagnostics;
namespace RGB.NET.Core;
@@ -9,7 +10,7 @@ namespace RGB.NET.Core;
/// Represents a size consisting of a width and a height.
///
[DebuggerDisplay("[Width: {Width}, Height: {Height}]")]
-public readonly struct Size
+public readonly struct Size : IEquatable
{
#region Constants
@@ -67,33 +68,26 @@ public readonly struct Size
/// A string that contains the and of this . For example "[Width: 100, Height: 20]".
public override string ToString() => $"[Width: {Width}, Height: {Height}]";
+ ///
+ /// Tests whether the specified is equivalent to this .
+ ///
+ /// The size to test.
+ /// true if is equivalent to this ; otherwise, false.
+ public bool Equals(Size other) => ((float.IsNaN(Width) && float.IsNaN(other.Width)) || Width.EqualsInTolerance(other.Width))
+ && ((float.IsNaN(Height) && float.IsNaN(other.Height)) || Height.EqualsInTolerance(other.Height));
+
///
/// Tests whether the specified object is a and is equivalent to this .
///
/// The object to test.
/// true if is a equivalent to this ; otherwise, false.
- public override bool Equals(object? obj)
- {
- if (obj is not Size size) return false;
-
- (float width, float height) = size;
- return ((float.IsNaN(Width) && float.IsNaN(width)) || Width.EqualsInTolerance(width))
- && ((float.IsNaN(Height) && float.IsNaN(height)) || Height.EqualsInTolerance(height));
- }
+ public override bool Equals(object? obj) => obj is Size other && Equals(other);
///
/// Returns a hash code for this .
///
/// An integer value that specifies the hash code for this .
- public override int GetHashCode()
- {
- unchecked
- {
- int hashCode = Width.GetHashCode();
- hashCode = (hashCode * 397) ^ Height.GetHashCode();
- return hashCode;
- }
- }
+ public override int GetHashCode() => HashCode.Combine(Width, Height);
///
/// Deconstructs the size into the width and height value.
diff --git a/RGB.NET.Core/README.md b/RGB.NET.Core/README.md
index d31978b..b07d190 100644
--- a/RGB.NET.Core/README.md
+++ b/RGB.NET.Core/README.md
@@ -17,7 +17,7 @@ surface.AlignDevices();
surface.RegisterUpdateTrigger(new TimerUpdateTrigger());
```
-## Basis Rendering
+## Basic Rendering
```csharp
// Create a led-group containing all leds on the surface
ILedGroup allLeds = new ListLedGroup(surface, surface.Leds);
diff --git a/RGB.NET.Core/RGB.NET.Core.csproj b/RGB.NET.Core/RGB.NET.Core.csproj
index 6357388..1022bf0 100644
--- a/RGB.NET.Core/RGB.NET.Core.csproj
+++ b/RGB.NET.Core/RGB.NET.Core.csproj
@@ -1,6 +1,6 @@
- net7.0;net6.0;net5.0
+ net8.0;net7.0;net6.0
latest
enable
@@ -41,7 +41,7 @@
- $(DefineConstants);TRACE;DEBUG
+ TRACE;DEBUG
true
false
@@ -49,7 +49,7 @@
true
$(NoWarn);CS1591;CS1572;CS1573
- $(DefineConstants);RELEASE
+ RELEASE
diff --git a/RGB.NET.Core/RGB.NET.Core.csproj.DotSettings b/RGB.NET.Core/RGB.NET.Core.csproj.DotSettings
index bf7655f..7f9a6e2 100644
--- a/RGB.NET.Core/RGB.NET.Core.csproj.DotSettings
+++ b/RGB.NET.Core/RGB.NET.Core.csproj.DotSettings
@@ -16,6 +16,7 @@
True
True
True
+ True
True
True
True
diff --git a/RGB.NET.Core/RGBSurface.cs b/RGB.NET.Core/RGBSurface.cs
index f8ec437..5c3387f 100644
--- a/RGB.NET.Core/RGBSurface.cs
+++ b/RGB.NET.Core/RGBSurface.cs
@@ -22,7 +22,7 @@ public sealed class RGBSurface : AbstractBindable, IDisposable
private readonly IList _devices = new List();
private readonly IList _updateTriggers = new List();
- private readonly List _ledGroups = new();
+ private readonly List _ledGroups = [];
///
/// Gets a readonly list containing all loaded .
@@ -132,11 +132,12 @@ public sealed class RGBSurface : AbstractBindable, IDisposable
/// Perform a full update for all devices. Updates only dirty by default, or all , if flushLeds is set to true.
///
/// Specifies whether all , (including clean ones) should be updated.
- public void Update(bool flushLeds = false) => Update(null, new CustomUpdateData((CustomUpdateDataIndex.FLUSH_LEDS, flushLeds)));
+ //public void Update(bool flushLeds = false) => Update(null, new CustomUpdateData((CustomUpdateDataIndex.FLUSH_LEDS, flushLeds)));
+ public void Update(bool flushLeds = false) => Update(null, flushLeds ? DefaultCustomUpdateData.FLUSH : DefaultCustomUpdateData.NO_FLUSH);
- private void Update(object? updateTrigger, CustomUpdateData customData) => Update(updateTrigger as IUpdateTrigger, customData);
+ private void Update(object? updateTrigger, ICustomUpdateData customData) => Update(updateTrigger as IUpdateTrigger, customData);
- private void Update(IUpdateTrigger? updateTrigger, CustomUpdateData customData)
+ private void Update(IUpdateTrigger? updateTrigger, ICustomUpdateData customData)
{
try
{
@@ -149,19 +150,25 @@ public sealed class RGBSurface : AbstractBindable, IDisposable
{
OnUpdating(updateTrigger, customData);
+ // ReSharper disable ForCanBeConvertedToForeach - 'for' has a performance benefit (no enumerator allocation) here and since 'Update' is considered a hot path it's optimized
if (render)
lock (_ledGroups)
{
// Render brushes
- foreach (ILedGroup ledGroup in _ledGroups)
- try { Render(ledGroup); }
+ for (int i = 0; i < _ledGroups.Count; i++)
+ {
+ try { Render(_ledGroups[i]); }
catch (Exception ex) { OnException(ex); }
+ }
}
if (updateDevices)
- foreach (IRGBDevice device in _devices)
- try { device.Update(flushLeds); }
+ for (int i = 0; i < _devices.Count; i++)
+ {
+ try { _devices[i].Update(flushLeds); }
catch (Exception ex) { OnException(ex); }
+ }
+ // ReSharper restore ForCanBeConvertedToForeach
OnUpdated();
}
@@ -177,7 +184,7 @@ public sealed class RGBSurface : AbstractBindable, IDisposable
{
List devices;
lock (Devices)
- devices = new List(_devices);
+ devices = [.._devices];
foreach (IRGBDevice device in devices)
try { Detach(device); }
@@ -197,29 +204,31 @@ public sealed class RGBSurface : AbstractBindable, IDisposable
/// Thrown if the of the Brush is not valid.
private void Render(ILedGroup ledGroup)
{
- IList leds = ledGroup.ToList();
IBrush? brush = ledGroup.Brush;
if ((brush == null) || !brush.IsEnabled) return;
- IEnumerable<(RenderTarget renderTarget, Color color)> render;
- switch (brush.CalculationMode)
+ using (ledGroup.ToListUnsafe(out IList leds))
{
- case RenderMode.Relative:
- Rectangle brushRectangle = new(leds.Select(led => led.AbsoluteBoundary));
- Point offset = new(-brushRectangle.Location.X, -brushRectangle.Location.Y);
- brushRectangle = brushRectangle.SetLocation(new Point(0, 0));
- render = brush.Render(brushRectangle, leds.Select(led => new RenderTarget(led, led.AbsoluteBoundary.Translate(offset))));
- break;
- case RenderMode.Absolute:
- render = brush.Render(Boundary, leds.Select(led => new RenderTarget(led, led.AbsoluteBoundary)));
- break;
- default:
- throw new ArgumentException($"The CalculationMode '{brush.CalculationMode}' is not valid.");
- }
+ IEnumerable<(RenderTarget renderTarget, Color color)> render;
+ switch (brush.CalculationMode)
+ {
+ case RenderMode.Relative:
+ Rectangle brushRectangle = new(leds);
+ Point offset = new(-brushRectangle.Location.X, -brushRectangle.Location.Y);
+ brushRectangle = brushRectangle.SetLocation(new Point(0, 0));
+ render = brush.Render(brushRectangle, leds.Select(led => new RenderTarget(led, led.AbsoluteBoundary.Translate(offset))));
+ break;
+ case RenderMode.Absolute:
+ render = brush.Render(Boundary, leds.Select(led => new RenderTarget(led, led.AbsoluteBoundary)));
+ break;
+ default:
+ throw new ArgumentException($"The CalculationMode '{brush.CalculationMode}' is not valid.");
+ }
- foreach ((RenderTarget renderTarget, Color c) in render)
- renderTarget.Led.Color = c;
+ foreach ((RenderTarget renderTarget, Color c) in render)
+ renderTarget.Led.Color = c;
+ }
}
///
@@ -358,7 +367,7 @@ public sealed class RGBSurface : AbstractBindable, IDisposable
///
/// Handles the needed event-calls before updating.
///
- private void OnUpdating(IUpdateTrigger? trigger, CustomUpdateData customData)
+ private void OnUpdating(IUpdateTrigger? trigger, ICustomUpdateData customData)
{
try
{
diff --git a/RGB.NET.Core/Rendering/Brushes/AbstractBrush.cs b/RGB.NET.Core/Rendering/Brushes/AbstractBrush.cs
index 553e53b..bc39b5d 100644
--- a/RGB.NET.Core/Rendering/Brushes/AbstractBrush.cs
+++ b/RGB.NET.Core/Rendering/Brushes/AbstractBrush.cs
@@ -74,9 +74,13 @@ public abstract class AbstractBrush : AbstractDecoratable, IBru
if (Decorators.Count == 0) return;
lock (Decorators)
- foreach (IBrushDecorator decorator in Decorators)
+ // ReSharper disable once ForCanBeConvertedToForeach - Sadly this does not get optimized reliably and causes allocations if foreached
+ for (int i = 0; i < Decorators.Count; i++)
+ {
+ IBrushDecorator decorator = Decorators[i];
if (decorator.IsEnabled)
decorator.ManipulateColor(rectangle, renderTarget, ref color);
+ }
}
///
diff --git a/RGB.NET.Core/Rendering/Brushes/SolidColorBrush.cs b/RGB.NET.Core/Rendering/Brushes/SolidColorBrush.cs
index 4175db1..02f8e2d 100644
--- a/RGB.NET.Core/Rendering/Brushes/SolidColorBrush.cs
+++ b/RGB.NET.Core/Rendering/Brushes/SolidColorBrush.cs
@@ -7,7 +7,7 @@ namespace RGB.NET.Core;
///
/// Represents a brush drawing only a single color.
///
-public class SolidColorBrush : AbstractBrush
+public sealed class SolidColorBrush : AbstractBrush
{
#region Properties & Fields
@@ -32,6 +32,8 @@ public class SolidColorBrush : AbstractBrush
public SolidColorBrush(Color color)
{
this.Color = color;
+
+ CalculationMode = RenderMode.Absolute;
}
#endregion
diff --git a/RGB.NET.Core/Rendering/Brushes/TextureBrush.cs b/RGB.NET.Core/Rendering/Brushes/TextureBrush.cs
index 4a2de6e..41280cd 100644
--- a/RGB.NET.Core/Rendering/Brushes/TextureBrush.cs
+++ b/RGB.NET.Core/Rendering/Brushes/TextureBrush.cs
@@ -4,7 +4,7 @@
///
/// Represents a brush drawing a texture.
///
-public class TextureBrush : AbstractBrush
+public sealed class TextureBrush : AbstractBrush
{
#region Properties & Fields
diff --git a/RGB.NET.Core/Rendering/Textures/EmptyTexture.cs b/RGB.NET.Core/Rendering/Textures/EmptyTexture.cs
index 588b62b..7aca9b7 100644
--- a/RGB.NET.Core/Rendering/Textures/EmptyTexture.cs
+++ b/RGB.NET.Core/Rendering/Textures/EmptyTexture.cs
@@ -1,6 +1,6 @@
namespace RGB.NET.Core;
-internal class EmptyTexture : ITexture
+internal sealed class EmptyTexture : ITexture
{
#region Properties & Fields
diff --git a/RGB.NET.Core/Rendering/Textures/PixelTexture.cs b/RGB.NET.Core/Rendering/Textures/PixelTexture.cs
index 3672e2c..170d2d5 100644
--- a/RGB.NET.Core/Rendering/Textures/PixelTexture.cs
+++ b/RGB.NET.Core/Rendering/Textures/PixelTexture.cs
@@ -1,5 +1,6 @@
-using System;
-using System.Buffers;
+// ReSharper disable MemberCanBePrivate.Global
+
+using System;
using System.Runtime.CompilerServices;
namespace RGB.NET.Core;
@@ -12,16 +13,22 @@ namespace RGB.NET.Core;
public abstract class PixelTexture : ITexture
where T : unmanaged
{
- #region Constants
-
- private const int STACK_ALLOC_LIMIT = 1024;
-
- #endregion
-
#region Properties & Fields
- private readonly int _dataPerPixel;
- private readonly int _stride;
+ ///
+ /// Gets the underlying pixel data.
+ ///
+ protected abstract ReadOnlySpan Data { get; }
+
+ ///
+ /// Gets the amount of data-entries per pixel.
+ ///
+ protected int DataPerPixel { get; }
+
+ ///
+ /// Gets the stride of the data.
+ ///
+ protected int Stride { get; }
///
/// Gets or sets the sampler used to get the color of a region.
@@ -31,11 +38,6 @@ public abstract class PixelTexture : ITexture
///
public Size Size { get; }
- ///
- /// Gets the underlying pixel data.
- ///
- protected abstract ReadOnlySpan Data { get; }
-
///
public virtual Color this[in Point point]
{
@@ -85,31 +87,12 @@ public abstract class PixelTexture : ITexture
if ((width == 0) || (height == 0)) return Color.Transparent;
if ((width == 1) && (height == 1)) return GetColor(GetPixelData(x, y));
- int bufferSize = width * height * _dataPerPixel;
- if (bufferSize <= STACK_ALLOC_LIMIT)
- {
- Span buffer = stackalloc T[bufferSize];
- GetRegionData(x, y, width, height, buffer);
+ SamplerInfo samplerInfo = new(x, y, width, height, Stride, DataPerPixel, Data);
- Span pixelData = stackalloc T[_dataPerPixel];
- Sampler.Sample(new SamplerInfo(width, height, buffer), pixelData);
+ Span pixelData = stackalloc T[DataPerPixel];
+ Sampler.Sample(samplerInfo, pixelData);
- return GetColor(pixelData);
- }
- else
- {
- T[] rent = ArrayPool.Shared.Rent(bufferSize);
-
- Span buffer = new Span(rent)[..bufferSize];
- GetRegionData(x, y, width, height, buffer);
-
- Span pixelData = stackalloc T[_dataPerPixel];
- Sampler.Sample(new SamplerInfo(width, height, buffer), pixelData);
-
- ArrayPool.Shared.Return(rent);
-
- return GetColor(pixelData);
- }
+ return GetColor(pixelData);
}
}
@@ -127,8 +110,8 @@ public abstract class PixelTexture : ITexture
/// The stride of the data or -1 if the width should be used.
public PixelTexture(int with, int height, int dataPerPixel, ISampler sampler, int stride = -1)
{
- this._stride = stride == -1 ? with : stride;
- this._dataPerPixel = dataPerPixel;
+ this.Stride = stride == -1 ? with : stride;
+ this.DataPerPixel = dataPerPixel;
this.Sampler = sampler;
Size = new Size(with, height);
@@ -152,27 +135,7 @@ public abstract class PixelTexture : ITexture
/// The y-location.
/// The pixel-data on the specified location.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- protected virtual ReadOnlySpan GetPixelData(int x, int y) => Data.Slice((y * _stride) + x, _dataPerPixel);
-
- ///
- /// Writes the pixel-data of the specified region to the passed buffer.
- ///
- /// The x-location of the region to get the data for.
- /// The y-location of the region to get the data for.
- /// The width of the region to get the data for.
- /// The height of the region to get the data for.
- /// The buffer to write the data to.
- protected virtual void GetRegionData(int x, int y, int width, int height, in Span buffer)
- {
- int dataWidth = width * _dataPerPixel;
- ReadOnlySpan data = Data;
- for (int i = 0; i < height; i++)
- {
- ReadOnlySpan dataSlice = data.Slice((((y + i) * _stride) + x) * _dataPerPixel, dataWidth);
- Span destination = buffer.Slice(i * dataWidth, dataWidth);
- dataSlice.CopyTo(destination);
- }
- }
+ private ReadOnlySpan GetPixelData(int x, int y) => Data.Slice((y * Stride) + x, DataPerPixel);
#endregion
}
@@ -225,6 +188,7 @@ public sealed class PixelTexture : PixelTexture
#region Methods
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
protected override Color GetColor(in ReadOnlySpan pixel) => pixel[0];
#endregion
diff --git a/RGB.NET.Core/Rendering/Textures/Sampler/AverageColorSampler.cs b/RGB.NET.Core/Rendering/Textures/Sampler/AverageColorSampler.cs
index f93d212..9ba2cb0 100644
--- a/RGB.NET.Core/Rendering/Textures/Sampler/AverageColorSampler.cs
+++ b/RGB.NET.Core/Rendering/Textures/Sampler/AverageColorSampler.cs
@@ -1,6 +1,5 @@
using System;
using System.Numerics;
-using System.Runtime.InteropServices;
namespace RGB.NET.Core;
@@ -10,7 +9,7 @@ namespace RGB.NET.Core;
///
/// Averages all components (A, R, G, B) of the colors separately which isn't ideal in cases where multiple different colors are combined.
///
-public class AverageColorSampler : ISampler
+public sealed class AverageColorSampler : ISampler
{
#region Constants
@@ -30,20 +29,35 @@ public class AverageColorSampler : ISampler
float a = 0, r = 0, g = 0, b = 0;
- if (Vector.IsHardwareAccelerated && (info.Data.Length >= Vector.Count))
+ if (Vector.IsHardwareAccelerated && (info.Height > 1) && (info.Width >= ELEMENTS_PER_VECTOR))
{
- int chunks = info.Data.Length / ELEMENTS_PER_VECTOR;
- int missingElements = info.Data.Length - (chunks * ELEMENTS_PER_VECTOR);
+ int chunks = info.Width / ELEMENTS_PER_VECTOR;
+ int missingElements = info.Width - (chunks * ELEMENTS_PER_VECTOR);
Vector sum = Vector.Zero;
- fixed (Color* colorPtr = &MemoryMarshal.GetReference(info.Data))
+ for (int y = 0; y < info.Height; y++)
{
- Color* current = colorPtr;
- for (int i = 0; i < chunks; i++)
+ ReadOnlySpan data = info[y];
+
+ fixed (Color* colorPtr = data)
{
- sum = Vector.Add(sum, *(Vector*)current);
- current += ELEMENTS_PER_VECTOR;
+ Color* current = colorPtr;
+ for (int i = 0; i < chunks; i++)
+ {
+ sum = Vector.Add(sum, *(Vector*)current);
+ current += ELEMENTS_PER_VECTOR;
+ }
+ }
+
+ for (int i = 0; i < missingElements; i++)
+ {
+ Color color = data[^(i + 1)];
+
+ a += color.A;
+ r += color.R;
+ g += color.G;
+ b += color.B;
}
}
@@ -54,26 +68,17 @@ public class AverageColorSampler : ISampler
g += sum[i + 2];
b += sum[i + 3];
}
-
- for (int i = 0; i < missingElements; i++)
- {
- Color color = info.Data[^(i + 1)];
-
- a += color.A;
- r += color.R;
- g += color.G;
- b += color.B;
- }
}
else
{
- foreach (Color color in info.Data)
- {
- a += color.A;
- r += color.R;
- g += color.G;
- b += color.B;
- }
+ for (int y = 0; y < info.Height; y++)
+ foreach (Color color in info[y])
+ {
+ a += color.A;
+ r += color.R;
+ g += color.G;
+ b += color.B;
+ }
}
pixelData[0] = new Color(a / count, r / count, g / count, b / count);
diff --git a/RGB.NET.Core/Rendering/Textures/Sampler/SamplerInfo.cs b/RGB.NET.Core/Rendering/Textures/Sampler/SamplerInfo.cs
index ab7a0a1..bf59c93 100644
--- a/RGB.NET.Core/Rendering/Textures/Sampler/SamplerInfo.cs
+++ b/RGB.NET.Core/Rendering/Textures/Sampler/SamplerInfo.cs
@@ -10,20 +10,29 @@ public readonly ref struct SamplerInfo
{
#region Properties & Fields
+ private readonly ReadOnlySpan _data;
+ private readonly int _x;
+ private readonly int _y;
+ private readonly int _stride;
+ private readonly int _dataPerPixel;
+ private readonly int _dataWidth;
+
///
/// Gets the width of the region the data comes from.
///
- public int Width { get; }
+ public readonly int Width;
///
/// Gets the height of region the data comes from.
///
- public int Height { get; }
+ public readonly int Height;
///
- /// Gets the data to sample.
+ /// Gets the data for the requested row.
///
- public ReadOnlySpan Data { get; }
+ /// The row to get the data for.
+ /// A readonly span containing the data of the row.
+ public ReadOnlySpan this[int row] => _data.Slice((((_y + row) * _stride) + _x) * _dataPerPixel, _dataWidth);
#endregion
@@ -35,11 +44,17 @@ public readonly ref struct SamplerInfo
/// The width of the region the data comes from.
/// The height of region the data comes from.
/// The data to sample.
- public SamplerInfo(int width, int height, ReadOnlySpan data)
+ public SamplerInfo(int x, int y, int width, int height, int stride, int dataPerPixel, in ReadOnlySpan data)
{
+ this._x = x;
+ this._y = y;
+ this._data = data;
+ this._stride = stride;
+ this._dataPerPixel = dataPerPixel;
this.Width = width;
this.Height = height;
- this.Data = data;
+
+ _dataWidth = width * dataPerPixel;
}
#endregion
diff --git a/RGB.NET.Core/Update/CustomUpdateData.cs b/RGB.NET.Core/Update/CustomUpdateData.cs
index 88f734a..736723a 100644
--- a/RGB.NET.Core/Update/CustomUpdateData.cs
+++ b/RGB.NET.Core/Update/CustomUpdateData.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
namespace RGB.NET.Core;
@@ -34,11 +35,24 @@ public static class CustomUpdateDataIndex
///
/// Represents a set of custom data, each indexed by a string-key.
///
-public class CustomUpdateData
+public interface ICustomUpdateData
+{
+ ///
+ /// Gets the value for a specific key.
+ ///
+ /// The key of the value.
+ /// The value represented by the specified key.
+ object? this[string key] { get; }
+}
+
+///
+/// Represents a set of custom data, each indexed by a string-key.
+///
+public sealed class CustomUpdateData : ICustomUpdateData
{
#region Properties & Fields
- private Dictionary _data = new();
+ private readonly Dictionary _data = [];
#endregion
@@ -51,8 +65,8 @@ public class CustomUpdateData
/// The value represented by the specified key.
public object? this[string key]
{
- get => _data.TryGetValue(key.ToUpperInvariant(), out object? data) ? data : default;
- set => _data[key.ToUpperInvariant()] = value;
+ get => _data.TryGetValue(key, out object? data) ? data : default;
+ set => _data[key] = value;
}
#endregion
@@ -77,3 +91,39 @@ public class CustomUpdateData
#endregion
}
+
+internal sealed class DefaultCustomUpdateData : ICustomUpdateData
+{
+ #region Constants
+
+ public static readonly DefaultCustomUpdateData FLUSH = new(true);
+ public static readonly DefaultCustomUpdateData NO_FLUSH = new(false);
+
+ #endregion
+
+ #region Properties & Fields
+
+ private readonly bool _flushLeds;
+
+ public object? this[string key]
+ {
+ get
+ {
+ if (string.Equals(key, CustomUpdateDataIndex.FLUSH_LEDS, StringComparison.Ordinal))
+ return _flushLeds;
+
+ return null;
+ }
+ }
+
+ #endregion
+
+ #region Constructors
+
+ private DefaultCustomUpdateData(bool flushLeds)
+ {
+ this._flushLeds = flushLeds;
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Core/Update/Devices/DeviceUpdateTrigger.cs b/RGB.NET.Core/Update/Devices/DeviceUpdateTrigger.cs
index 5d357b6..a45ae6c 100644
--- a/RGB.NET.Core/Update/Devices/DeviceUpdateTrigger.cs
+++ b/RGB.NET.Core/Update/Devices/DeviceUpdateTrigger.cs
@@ -1,5 +1,6 @@
// ReSharper disable MemberCanBePrivate.Global
+using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
@@ -132,7 +133,7 @@ public class DeviceUpdateTrigger : AbstractUpdateTrigger, IDeviceUpdateTrigger
///
/// Stops the trigger.
///
- public async void Stop()
+ public virtual async void Stop()
{
if (!IsRunning) return;
@@ -140,7 +141,9 @@ public class DeviceUpdateTrigger : AbstractUpdateTrigger, IDeviceUpdateTrigger
UpdateTokenSource?.Cancel();
if (UpdateTask != null)
- await UpdateTask;
+ try { await UpdateTask.ConfigureAwait(false); }
+ catch (TaskCanceledException) { }
+ catch (OperationCanceledException) { }
UpdateTask?.Dispose();
UpdateTask = null;
@@ -156,11 +159,13 @@ public class DeviceUpdateTrigger : AbstractUpdateTrigger, IDeviceUpdateTrigger
using (TimerHelper.RequestHighResolutionTimer())
while (!UpdateToken.IsCancellationRequested)
if (HasDataEvent.WaitOne(Timeout))
- LastUpdateTime = TimerHelper.Execute(() => OnUpdate(), UpdateFrequency * 1000);
+ LastUpdateTime = TimerHelper.Execute(TimerExecute, UpdateFrequency * 1000);
else if ((HeartbeatTimer > 0) && (LastUpdateTimestamp > 0) && (TimerHelper.GetElapsedTime(LastUpdateTimestamp) > HeartbeatTimer))
OnUpdate(new CustomUpdateData().Heartbeat());
}
+ private void TimerExecute() => OnUpdate();
+
protected override void OnUpdate(CustomUpdateData? updateData = null)
{
base.OnUpdate(updateData);
@@ -178,7 +183,12 @@ public class DeviceUpdateTrigger : AbstractUpdateTrigger, IDeviceUpdateTrigger
}
///
- public override void Dispose() => Stop();
+ public override void Dispose()
+ {
+ Stop();
+
+ GC.SuppressFinalize(this);
+ }
#endregion
}
\ No newline at end of file
diff --git a/RGB.NET.Core/Update/Devices/IUpdateQueue.cs b/RGB.NET.Core/Update/Devices/IUpdateQueue.cs
index 3a0f63a..03a3e65 100644
--- a/RGB.NET.Core/Update/Devices/IUpdateQueue.cs
+++ b/RGB.NET.Core/Update/Devices/IUpdateQueue.cs
@@ -1,5 +1,4 @@
using System;
-using System.Collections.Generic;
namespace RGB.NET.Core;
@@ -8,15 +7,20 @@ namespace RGB.NET.Core;
///
/// The identifier used to identify the data processed by this queue.
/// The type of the data processed by this queue.
-public interface IUpdateQueue : IDisposable
+public interface IUpdateQueue : IReferenceCounting, IDisposable
where TIdentifier : notnull
{
+ ///
+ /// Gets a bool indicating if the queue requires a flush of all data due to an internal error.
+ ///
+ bool RequiresFlush { get; }
+
///
/// Sets or merges the provided data set in the current dataset and notifies the trigger that there is new data available.
///
/// The set of data.
// ReSharper disable once MemberCanBeProtected.Global
- void SetData(IEnumerable<(TIdentifier, TData)> dataSet);
+ void SetData(ReadOnlySpan<(TIdentifier, TData)> dataSet);
///
/// Resets the current data set.
@@ -27,5 +31,4 @@ public interface IUpdateQueue : IDisposable
///
/// Represents a generic update queue processing -data using -identifiers.
///
-public interface IUpdateQueue : IUpdateQueue
/// The type of the key used to identify some data.
/// The type of the data.
-public abstract class UpdateQueue : IUpdateQueue
+public abstract class UpdateQueue : AbstractReferenceCounting, IUpdateQueue
where TIdentifier : notnull
{
#region Properties & Fields
private readonly object _dataLock = new();
private readonly IDeviceUpdateTrigger _updateTrigger;
- private readonly Dictionary _currentDataSet = new();
+ private readonly Dictionary _currentDataSet = [];
+
+ ///
+ public bool RequiresFlush { get; private set; }
#endregion
@@ -62,7 +64,7 @@ public abstract class UpdateQueue : IUpdateQueue.Shared.Return(dataSet);
}
@@ -78,17 +80,16 @@ public abstract class UpdateQueue : IUpdateQueue
/// The set of data that needs to be updated.
- protected abstract void Update(in ReadOnlySpan<(TIdentifier key, TData color)> dataSet);
+ protected abstract bool Update(in ReadOnlySpan<(TIdentifier key, TData color)> dataSet);
///
/// Sets or merges the provided data set in the current dataset and notifies the trigger that there is new data available.
///
/// The set of data.
// ReSharper disable once MemberCanBeProtected.Global
- public virtual void SetData(IEnumerable<(TIdentifier, TData)> dataSet)
+ public virtual void SetData(ReadOnlySpan<(TIdentifier, TData)> data)
{
- IList<(TIdentifier, TData)> data = dataSet.ToList();
- if (data.Count == 0) return;
+ if (data.Length == 0) return;
lock (_dataLock)
{
diff --git a/RGB.NET.Core/Update/ManualUpdateTrigger.cs b/RGB.NET.Core/Update/ManualUpdateTrigger.cs
index 67e8ca4..5cd4235 100644
--- a/RGB.NET.Core/Update/ManualUpdateTrigger.cs
+++ b/RGB.NET.Core/Update/ManualUpdateTrigger.cs
@@ -83,12 +83,12 @@ public sealed class ManualUpdateTrigger : AbstractUpdateTrigger
OnStartup();
while (!UpdateToken.IsCancellationRequested)
- {
if (_mutex.WaitOne(100))
- LastUpdateTime = TimerHelper.Execute(() => OnUpdate(_customUpdateData));
- }
+ LastUpdateTime = TimerHelper.Execute(TimerExecute);
}
+ private void TimerExecute() => OnUpdate(_customUpdateData);
+
///
public override void Dispose() => Stop();
diff --git a/RGB.NET.Core/Update/TimerUpdateTrigger.cs b/RGB.NET.Core/Update/TimerUpdateTrigger.cs
index 14a7e9f..6b94b3f 100644
--- a/RGB.NET.Core/Update/TimerUpdateTrigger.cs
+++ b/RGB.NET.Core/Update/TimerUpdateTrigger.cs
@@ -10,7 +10,7 @@ namespace RGB.NET.Core;
///
/// Represents an update trigger that triggers in a set interval.
///
-public class TimerUpdateTrigger : AbstractUpdateTrigger
+public sealed class TimerUpdateTrigger : AbstractUpdateTrigger
{
#region Properties & Fields
@@ -21,17 +21,17 @@ public class TimerUpdateTrigger : AbstractUpdateTrigger
///
/// Gets or sets the update loop of this trigger.
///
- protected Task? UpdateTask { get; set; }
+ private Task? _updateTask;
///
- /// Gets or sets the cancellation token source used to create the cancellation token checked by the .
+ /// Gets or sets the cancellation token source used to create the cancellation token checked by the .
///
- protected CancellationTokenSource? UpdateTokenSource { get; set; }
+ private CancellationTokenSource? _updateTokenSource;
///
- /// Gets or sets the cancellation token checked by the .
+ /// Gets or sets the cancellation token checked by the .
///
- protected CancellationToken UpdateToken { get; set; }
+ private CancellationToken _updateToken;
private double _updateFrequency = 1.0 / 30.0;
///
@@ -88,11 +88,11 @@ public class TimerUpdateTrigger : AbstractUpdateTrigger
{
lock (_lock)
{
- if (UpdateTask == null)
+ if (_updateTask == null)
{
- UpdateTokenSource?.Dispose();
- UpdateTokenSource = new CancellationTokenSource();
- UpdateTask = Task.Factory.StartNew(UpdateLoop, (UpdateToken = UpdateTokenSource.Token), TaskCreationOptions.LongRunning, TaskScheduler.Default);
+ _updateTokenSource?.Dispose();
+ _updateTokenSource = new CancellationTokenSource();
+ _updateTask = Task.Factory.StartNew(UpdateLoop, (_updateToken = _updateTokenSource.Token), TaskCreationOptions.LongRunning, TaskScheduler.Default);
}
}
}
@@ -104,13 +104,13 @@ public class TimerUpdateTrigger : AbstractUpdateTrigger
{
lock (_lock)
{
- if (UpdateTask != null)
+ if (_updateTask != null)
{
- UpdateTokenSource?.Cancel();
+ _updateTokenSource?.Cancel();
try
{
// ReSharper disable once MethodSupportsCancellation
- UpdateTask.Wait();
+ _updateTask.Wait();
}
catch (AggregateException)
{
@@ -118,8 +118,8 @@ public class TimerUpdateTrigger : AbstractUpdateTrigger
}
finally
{
- UpdateTask.Dispose();
- UpdateTask = null;
+ _updateTask.Dispose();
+ _updateTask = null;
}
}
}
@@ -130,16 +130,16 @@ public class TimerUpdateTrigger : AbstractUpdateTrigger
OnStartup();
using (TimerHelper.RequestHighResolutionTimer())
- while (!UpdateToken.IsCancellationRequested)
- LastUpdateTime = TimerHelper.Execute(() => OnUpdate(_customUpdateData), UpdateFrequency * 1000);
-
+ while (!_updateToken.IsCancellationRequested)
+ LastUpdateTime = TimerHelper.Execute(TimerExecute, UpdateFrequency * 1000);
}
+ private void TimerExecute() => OnUpdate(_customUpdateData);
+
///
public override void Dispose()
{
Stop();
- GC.SuppressFinalize(this);
}
#endregion
diff --git a/RGB.NET.Devices.Asus/AsusDeviceProvider.cs b/RGB.NET.Devices.Asus/AsusDeviceProvider.cs
index 2e09b52..805db68 100644
--- a/RGB.NET.Devices.Asus/AsusDeviceProvider.cs
+++ b/RGB.NET.Devices.Asus/AsusDeviceProvider.cs
@@ -12,15 +12,25 @@ namespace RGB.NET.Devices.Asus;
///
/// Represents a device provider responsible for Cooler Master devices.
///
-public class AsusDeviceProvider : AbstractRGBDeviceProvider
+public sealed class AsusDeviceProvider : AbstractRGBDeviceProvider
{
#region Properties & Fields
+ // ReSharper disable once InconsistentNaming
+ private static readonly object _lock = new();
+
private static AsusDeviceProvider? _instance;
///
/// Gets the singleton instance.
///
- public static AsusDeviceProvider Instance => _instance ?? new AsusDeviceProvider();
+ public static AsusDeviceProvider Instance
+ {
+ get
+ {
+ lock (_lock)
+ return _instance ?? new AsusDeviceProvider();
+ }
+ }
private IAuraSdk2? _sdk;
private IAuraSyncDeviceCollection? _devices; //HACK DarthAffe 05.04.2021: Due to some researches this might fix the access violation in the asus-sdk
@@ -35,8 +45,11 @@ public class AsusDeviceProvider : AbstractRGBDeviceProvider
/// Thrown if this constructor is called even if there is already an instance of this class.
public AsusDeviceProvider()
{
- if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(AsusDeviceProvider)}");
- _instance = this;
+ lock (_lock)
+ {
+ if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(AsusDeviceProvider)}");
+ _instance = this;
+ }
}
#endregion
@@ -60,6 +73,7 @@ public class AsusDeviceProvider : AbstractRGBDeviceProvider
for (int i = 0; i < _devices.Count; i++)
{
IAuraSyncDevice device = _devices[i];
+
yield return (AsusDeviceType)device.Type switch
{
AsusDeviceType.MB_RGB => new AsusMainboardRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Mainboard, device, WMIHelper.GetMainboardInfo()?.model ?? device.Name), GetUpdateTrigger()),
@@ -68,26 +82,30 @@ public class AsusDeviceProvider : AbstractRGBDeviceProvider
AsusDeviceType.HEADSET_RGB => new AsusHeadsetRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Headset, device), GetUpdateTrigger()),
AsusDeviceType.DRAM_RGB => new AsusDramRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.DRAM, device), GetUpdateTrigger()),
AsusDeviceType.KEYBOARD_RGB => new AsusKeyboardRGBDevice(new AsusKeyboardRGBDeviceInfo(device), LedMappings.KeyboardMapping, GetUpdateTrigger()),
+ AsusDeviceType.KEYBOARD_5ZONE_RGB => new AsusKeyboardRGBDevice(new AsusKeyboardRGBDeviceInfo(device), null, GetUpdateTrigger()),
AsusDeviceType.NB_KB_RGB => new AsusKeyboardRGBDevice(new AsusKeyboardRGBDeviceInfo(device), LedMappings.KeyboardMapping, GetUpdateTrigger()),
AsusDeviceType.NB_KB_4ZONE_RGB => new AsusKeyboardRGBDevice(new AsusKeyboardRGBDeviceInfo(device), null, GetUpdateTrigger()),
AsusDeviceType.MOUSE_RGB => new AsusMouseRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Mouse, device), GetUpdateTrigger()),
- _ => new AsusUnspecifiedRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Unknown, device), LedId.Custom1, GetUpdateTrigger())
+ AsusDeviceType.TERMINAL_RGB => new AsusUnspecifiedRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.LedController, device), LedId.Custom1, GetUpdateTrigger()),
+ _ => new AsusUnspecifiedRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Unknown, device), LedId.Unknown1, GetUpdateTrigger())
};
}
}
///
- public override void Dispose()
+ protected override void Dispose(bool disposing)
{
- base.Dispose();
+ lock (_lock)
+ {
+ base.Dispose(disposing);
- try { _sdk?.ReleaseControl(0); }
- catch { /* at least we tried */ }
+ try { _sdk?.ReleaseControl(0); }
+ catch { /* at least we tried */ }
- _devices = null;
- _sdk = null;
-
- GC.SuppressFinalize(this);
+ _devices = null;
+ _sdk = null;
+ _instance = null;
+ }
}
#endregion
diff --git a/RGB.NET.Devices.Asus/Enum/AsusDeviceType.cs b/RGB.NET.Devices.Asus/Enum/AsusDeviceType.cs
index ad529ed..bb9a2be 100644
--- a/RGB.NET.Devices.Asus/Enum/AsusDeviceType.cs
+++ b/RGB.NET.Devices.Asus/Enum/AsusDeviceType.cs
@@ -16,9 +16,12 @@ internal enum AsusDeviceType : uint
EXTERNAL_BLUE_RAY_RGB = 0x61000,
DRAM_RGB = 0x70000,
KEYBOARD_RGB = 0x80000,
+ KEYBOARD_5ZONE_RGB = 0x80001,
NB_KB_RGB = 0x81000,
NB_KB_4ZONE_RGB = 0x81001,
MOUSE_RGB = 0x90000,
CHASSIS_RGB = 0xB0000,
- PROJECTOR_RGB = 0xC0000
+ PROJECTOR_RGB = 0xC0000,
+ WATERCOOLER_RGB = 0xD1000,
+ TERMINAL_RGB = 0xE0000
}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Asus/Generic/AsusUnspecifiedRGBDevice.cs b/RGB.NET.Devices.Asus/Generic/AsusUnspecifiedRGBDevice.cs
index bb40578..6d20952 100644
--- a/RGB.NET.Devices.Asus/Generic/AsusUnspecifiedRGBDevice.cs
+++ b/RGB.NET.Devices.Asus/Generic/AsusUnspecifiedRGBDevice.cs
@@ -4,9 +4,9 @@ namespace RGB.NET.Devices.Asus;
///
///
-/// Represents a Asus headset.
+/// Represents a Asus device that is otherwise not handled by a more specific helper.
///
-public class AsusUnspecifiedRGBDevice : AsusRGBDevice, IUnknownDevice
+public sealed class AsusUnspecifiedRGBDevice : AsusRGBDevice, IUnknownDevice
{
#region Properties & Fields
@@ -18,9 +18,9 @@ public class AsusUnspecifiedRGBDevice : AsusRGBDevice, IUnkno
///
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
- /// The specific information provided by Asus for the headset.
+ /// The specific information provided by Asus for the device.
/// The ledId of the first led of this device. All other leds are created by incrementing this base-id by 1.
/// The update trigger used to update this device.
internal AsusUnspecifiedRGBDevice(AsusRGBDeviceInfo info, LedId baseLedId, IDeviceUpdateTrigger updateTrigger)
diff --git a/RGB.NET.Devices.Asus/Generic/AsusUpdateQueue.cs b/RGB.NET.Devices.Asus/Generic/AsusUpdateQueue.cs
index 6de33fa..2f40ec6 100644
--- a/RGB.NET.Devices.Asus/Generic/AsusUpdateQueue.cs
+++ b/RGB.NET.Devices.Asus/Generic/AsusUpdateQueue.cs
@@ -8,7 +8,7 @@ namespace RGB.NET.Devices.Asus;
///
/// Represents the update-queue performing updates for asus devices.
///
-public class AsusUpdateQueue : UpdateQueue
+public sealed class AsusUpdateQueue : UpdateQueue
{
#region Properties & Fields
@@ -17,7 +17,7 @@ public class AsusUpdateQueue : UpdateQueue
///
/// The device to be updated.
///
- protected IAuraSyncDevice Device { get; }
+ private readonly IAuraSyncDevice _device;
#endregion
@@ -31,7 +31,7 @@ public class AsusUpdateQueue : UpdateQueue
public AsusUpdateQueue(IDeviceUpdateTrigger updateTrigger, IAuraSyncDevice device)
: base(updateTrigger)
{
- this.Device = device;
+ this._device = device;
this._lights = new IAuraRgbLight[device.Lights.Count];
for (int i = 0; i < device.Lights.Count; i++)
@@ -43,14 +43,14 @@ public class AsusUpdateQueue : UpdateQueue
#region Methods
///
- protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet)
+ protected override bool Update(in ReadOnlySpan<(object key, Color color)> dataSet)
{
try
{
- if ((Device.Type == (uint)AsusDeviceType.KEYBOARD_RGB) || (Device.Type == (uint)AsusDeviceType.NB_KB_RGB))
+ if ((_device.Type == (uint)AsusDeviceType.KEYBOARD_RGB) || (_device.Type == (uint)AsusDeviceType.NB_KB_RGB))
{
- if (Device is not IAuraSyncKeyboard keyboard)
- return;
+ if (_device is not IAuraSyncKeyboard keyboard)
+ return true;
foreach ((object customData, Color value) in dataSet)
{
@@ -87,12 +87,17 @@ public class AsusUpdateQueue : UpdateQueue
}
}
- Device.Apply();
- }
- catch
- { /* "The server threw an exception." seems to be a thing here ... */
- }
- }
+ _device.Apply();
+ return true;
+ }
+ catch (Exception ex)
+ {
+ AsusDeviceProvider.Instance.Throw(ex);
+ }
+
+ return false;
+ }
+
#endregion
}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Asus/Generic/IAsusRGBDevice.cs b/RGB.NET.Devices.Asus/Generic/IAsusRGBDevice.cs
index cb7d4a9..027c83a 100644
--- a/RGB.NET.Devices.Asus/Generic/IAsusRGBDevice.cs
+++ b/RGB.NET.Devices.Asus/Generic/IAsusRGBDevice.cs
@@ -5,5 +5,4 @@ namespace RGB.NET.Devices.Asus;
///
/// Represents a asus RGB-device.
///
-public interface IAsusRGBDevice : IRGBDevice
-{ }
\ No newline at end of file
+public interface IAsusRGBDevice : IRGBDevice;
\ No newline at end of file
diff --git a/RGB.NET.Devices.Asus/GraphicsCard/AsusGraphicsCardRGBDevice.cs b/RGB.NET.Devices.Asus/GraphicsCard/AsusGraphicsCardRGBDevice.cs
index 15c2383..1debf59 100644
--- a/RGB.NET.Devices.Asus/GraphicsCard/AsusGraphicsCardRGBDevice.cs
+++ b/RGB.NET.Devices.Asus/GraphicsCard/AsusGraphicsCardRGBDevice.cs
@@ -6,7 +6,7 @@ namespace RGB.NET.Devices.Asus;
///
/// Represents a Asus graphicsCard.
///
-public class AsusGraphicsCardRGBDevice : AsusRGBDevice, IGraphicsCard
+public sealed class AsusGraphicsCardRGBDevice : AsusRGBDevice, IGraphicsCard
{
#region Constructors
diff --git a/RGB.NET.Devices.Asus/Headset/AsusHeadsetRGBDevice.cs b/RGB.NET.Devices.Asus/Headset/AsusHeadsetRGBDevice.cs
index 71f9e10..516dab6 100644
--- a/RGB.NET.Devices.Asus/Headset/AsusHeadsetRGBDevice.cs
+++ b/RGB.NET.Devices.Asus/Headset/AsusHeadsetRGBDevice.cs
@@ -6,7 +6,7 @@ namespace RGB.NET.Devices.Asus;
///
/// Represents a Asus headset.
///
-public class AsusHeadsetRGBDevice : AsusRGBDevice, IHeadset
+public sealed class AsusHeadsetRGBDevice : AsusRGBDevice, IHeadset
{
#region Constructors
diff --git a/RGB.NET.Devices.Asus/Helper/WMIHelper.cs b/RGB.NET.Devices.Asus/Helper/WMIHelper.cs
index 5aa49c7..482f3a3 100644
--- a/RGB.NET.Devices.Asus/Helper/WMIHelper.cs
+++ b/RGB.NET.Devices.Asus/Helper/WMIHelper.cs
@@ -43,7 +43,7 @@ internal static class WMIHelper
if ((_systemModelInfo == null) && (_systemModelSearcher != null))
foreach (ManagementBaseObject managementBaseObject in _systemModelSearcher.Get())
{
- _systemModelInfo = managementBaseObject["Model"]?.ToString();
+ _systemModelInfo = managementBaseObject["Model"].ToString();
break;
}
@@ -57,7 +57,7 @@ internal static class WMIHelper
if (!_mainboardInfo.HasValue && (_mainboardSearcher != null))
foreach (ManagementBaseObject managementBaseObject in _mainboardSearcher.Get())
{
- _mainboardInfo = (managementBaseObject["Manufacturer"]?.ToString() ?? string.Empty, managementBaseObject["Product"]?.ToString() ?? string.Empty);
+ _mainboardInfo = (managementBaseObject["Manufacturer"].ToString() ?? string.Empty, managementBaseObject["Product"].ToString() ?? string.Empty);
break;
}
@@ -71,7 +71,7 @@ internal static class WMIHelper
if ((_graphicsCardInfo == null) && (_graphicsCardSearcher != null))
foreach (ManagementBaseObject managementBaseObject in _graphicsCardSearcher.Get())
{
- _graphicsCardInfo = managementBaseObject["Name"]?.ToString();
+ _graphicsCardInfo = managementBaseObject["Name"].ToString();
break;
}
diff --git a/RGB.NET.Devices.Asus/Keyboard/AsusKeyboardLedMapping.cs b/RGB.NET.Devices.Asus/Keyboard/AsusKeyboardLedMapping.cs
index 9eb8d1f..298dd61 100644
--- a/RGB.NET.Devices.Asus/Keyboard/AsusKeyboardLedMapping.cs
+++ b/RGB.NET.Devices.Asus/Keyboard/AsusKeyboardLedMapping.cs
@@ -188,4 +188,49 @@ public static class LedMappings
{ LedId.Keyboard_Custom59, 131 },
{ LedId.Keyboard_Custom60, 133 },
};
+
+ ///
+ /// A LED mapping containing extra lights for the ROG Strix G15 (2021)
+ ///
+ ///
+ ///
+ /// ASUS notebooks have extra lights under wide keys like space and backspace, these do not appear as keys on the device.
+ /// Instead they only appear in the Lights enumerable, this mapping maps the matching keys to the index of these lights.
+ /// There are also some keys which do not use the default key scan code mappings for LEDs, and instead rely on lights.
+ ///
+ /// You may add more of these by further populating .
+ ///
+ public static LedMapping ROGStrixG15 { get; } = new()
+ {
+ { LedId.Keyboard_Custom71, 4 }, //Mic Mute
+ { LedId.Keyboard_Custom72, 5 }, //Fan
+ { LedId.Keyboard_Custom73, 6 }, //ROG Logo
+ //{ LedId.Keyboard_Function, 127 }, //commented out because adding a mapping fails if a mapping already exists for a key, even if it is incorrect for this device
+ //use Keyboard_Custom36 in the default mapping to get the Fn key on this laptop
+
+ { LedId.Keyboard_Custom52, 55 }, //backspace extra LEDs (x2) - these are named to match the appropriate LEDs in the previous ROG Zephyrus mapping
+ { LedId.Keyboard_Custom53, 57 },
+ { LedId.Keyboard_Custom54, 97 }, //enter extra LEDs (x2)
+ { LedId.Keyboard_Custom55, 99 },
+ { LedId.Keyboard_Custom56, 118 }, //right shift extra LEDs (x2)
+ { LedId.Keyboard_Custom57, 120 },
+ { LedId.Keyboard_Custom58, 130 }, //space bar extra LEDs (x3)
+ { LedId.Keyboard_Custom59, 131 }, //this one specifically is also exposed as Custom7 (AsusLedID.KEY_NOCONVERT) in the main map
+ { LedId.Keyboard_Custom60, 133 },
+
+ { LedId.Keyboard_MediaVolumeDown, 2 },
+ { LedId.Keyboard_MediaVolumeUp, 3 },
+ { LedId.Keyboard_MediaPlay, 58 },
+ { LedId.Keyboard_MediaStop, 79 },
+ { LedId.Keyboard_MediaPreviousTrack, 100 },
+ { LedId.Keyboard_MediaNextTrack, 121 },
+
+ { LedId.LedStripe1, 174 }, //front LED strip; yes, these are in reverse order, since the SDK exposes them from right to left
+ { LedId.LedStripe2, 173 },
+ { LedId.LedStripe3, 172 },
+ { LedId.LedStripe4, 171 },
+ { LedId.LedStripe5, 170 },
+ { LedId.LedStripe6, 169 },
+
+ };
}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Asus/Keyboard/AsusKeyboardRGBDevice.cs b/RGB.NET.Devices.Asus/Keyboard/AsusKeyboardRGBDevice.cs
index 86f64aa..1200429 100644
--- a/RGB.NET.Devices.Asus/Keyboard/AsusKeyboardRGBDevice.cs
+++ b/RGB.NET.Devices.Asus/Keyboard/AsusKeyboardRGBDevice.cs
@@ -20,13 +20,13 @@ public record AsusKeyboardExtraMapping(Regex Regex, LedMapping LedMapping);
///
/// Represents a Asus keyboard.
///
-public class AsusKeyboardRGBDevice : AsusRGBDevice, IKeyboard
+public sealed class AsusKeyboardRGBDevice : AsusRGBDevice, IKeyboard
{
#region Properties & Fields
private readonly LedMapping? _ledMapping;
- private readonly Dictionary _ledAsusLed = new();
- private readonly Dictionary _ledAsusLights = new();
+ private readonly Dictionary _ledAsusLed = [];
+ private readonly Dictionary _ledAsusLights = [];
IKeyboardDeviceInfo IKeyboard.DeviceInfo => DeviceInfo;
@@ -35,10 +35,11 @@ public class AsusKeyboardRGBDevice : AsusRGBDevice, I
/// Note: These LED mappings should be based on light indexes.
///
// ReSharper disable once InconsistentNaming
- public static readonly List ExtraLedMappings = new()
- {
- new AsusKeyboardExtraMapping(new Regex("(ROG Zephyrus Duo 15).*?"), LedMappings.ROGZephyrusDuo15)
- };
+ public static readonly List ExtraLedMappings =
+ [
+ new AsusKeyboardExtraMapping(new Regex("(ROG Zephyrus Duo 15).*?"), LedMappings.ROGZephyrusDuo15),
+ new AsusKeyboardExtraMapping(new Regex("(ROG Strix G513QM).*?"), LedMappings.ROGStrixG15)
+ ];
#endregion
@@ -65,7 +66,7 @@ public class AsusKeyboardRGBDevice : AsusRGBDevice, I
private void InitializeLayout()
{
- if (DeviceInfo.Device.Type != (uint)AsusDeviceType.NB_KB_4ZONE_RGB)
+ if ((DeviceInfo.Device.Type != (uint)AsusDeviceType.NB_KB_4ZONE_RGB) && (DeviceInfo.Device.Type !=(uint)AsusDeviceType.KEYBOARD_5ZONE_RGB))
{
int pos = 0;
int unknownLed = (int)LedId.Unknown1;
diff --git a/RGB.NET.Devices.Asus/Keyboard/AsusKeyboardRGBDeviceInfo.cs b/RGB.NET.Devices.Asus/Keyboard/AsusKeyboardRGBDeviceInfo.cs
index 4173271..3afb50c 100644
--- a/RGB.NET.Devices.Asus/Keyboard/AsusKeyboardRGBDeviceInfo.cs
+++ b/RGB.NET.Devices.Asus/Keyboard/AsusKeyboardRGBDeviceInfo.cs
@@ -7,7 +7,7 @@ namespace RGB.NET.Devices.Asus;
///
/// Represents a generic information for a .
///
-public class AsusKeyboardRGBDeviceInfo : AsusRGBDeviceInfo, IKeyboardDeviceInfo
+public sealed class AsusKeyboardRGBDeviceInfo : AsusRGBDeviceInfo, IKeyboardDeviceInfo
{
#region Properties & Fields
@@ -15,7 +15,7 @@ public class AsusKeyboardRGBDeviceInfo : AsusRGBDeviceInfo, IKeyboardDeviceInfo
/// The ASUS SDK returns useless names for notebook keyboards, possibly for others as well.
/// Keep a list of those and rely on to get the real model
///
- private static readonly List GENERIC_DEVICE_NAMES = new() { "NotebookKeyboard" };
+ private static readonly List GENERIC_DEVICE_NAMES = ["NotebookKeyboard"];
///
public KeyboardLayoutType Layout => KeyboardLayoutType.Unknown;
diff --git a/RGB.NET.Devices.Asus/Mainboard/AsusMainboardRGBDevice.cs b/RGB.NET.Devices.Asus/Mainboard/AsusMainboardRGBDevice.cs
index 2f92bb6..137ae90 100644
--- a/RGB.NET.Devices.Asus/Mainboard/AsusMainboardRGBDevice.cs
+++ b/RGB.NET.Devices.Asus/Mainboard/AsusMainboardRGBDevice.cs
@@ -6,7 +6,7 @@ namespace RGB.NET.Devices.Asus;
///
/// Represents a Asus mainboard.
///
-public class AsusMainboardRGBDevice : AsusRGBDevice, IMainboard
+public sealed class AsusMainboardRGBDevice : AsusRGBDevice, IMainboard
{
#region Constructors
diff --git a/RGB.NET.Devices.Asus/Mouse/AsusMouseRGBDevice.cs b/RGB.NET.Devices.Asus/Mouse/AsusMouseRGBDevice.cs
index 3db166a..e4ae049 100644
--- a/RGB.NET.Devices.Asus/Mouse/AsusMouseRGBDevice.cs
+++ b/RGB.NET.Devices.Asus/Mouse/AsusMouseRGBDevice.cs
@@ -6,7 +6,7 @@ namespace RGB.NET.Devices.Asus;
///
/// Represents a Asus mouse.
///
-public class AsusMouseRGBDevice : AsusRGBDevice, IMouse
+public sealed class AsusMouseRGBDevice : AsusRGBDevice, IMouse
{
#region Constructors
diff --git a/RGB.NET.Devices.Asus/RGB.NET.Devices.Asus.csproj b/RGB.NET.Devices.Asus/RGB.NET.Devices.Asus.csproj
index b4ac280..ecf4ea7 100644
--- a/RGB.NET.Devices.Asus/RGB.NET.Devices.Asus.csproj
+++ b/RGB.NET.Devices.Asus/RGB.NET.Devices.Asus.csproj
@@ -1,6 +1,6 @@
- net7.0;net6.0;net5.0
+ net8.0;net7.0;net6.0
latest
enable
@@ -40,7 +40,7 @@
- $(DefineConstants);TRACE;DEBUG
+ TRACE;DEBUG
true
false
@@ -48,7 +48,7 @@
true
$(NoWarn);CS1591;CS1572;CS1573
- $(DefineConstants);RELEASE
+ RELEASE
@@ -57,21 +57,7 @@
-
-
-
-
- <_PackageFiles Include="$(OutputPath)\net6.0\Interop.AuraServiceLib.dll">
- None
- lib\net6.0\
-
-
-
-
- <_PackageFiles Include="$(OutputPath)\net5.0\Interop.AuraServiceLib.dll">
- None
- lib\net5.0\
-
+
diff --git a/RGB.NET.Devices.CoolerMaster/Attributes/DeviceTypeAttribute.cs b/RGB.NET.Devices.CoolerMaster/Attributes/DeviceTypeAttribute.cs
index 8aad300..07245cb 100644
--- a/RGB.NET.Devices.CoolerMaster/Attributes/DeviceTypeAttribute.cs
+++ b/RGB.NET.Devices.CoolerMaster/Attributes/DeviceTypeAttribute.cs
@@ -8,7 +8,7 @@ namespace RGB.NET.Devices.CoolerMaster;
/// Specifies the of a field.
///
[AttributeUsage(AttributeTargets.Field)]
-public class DeviceTypeAttribute : Attribute
+public sealed class DeviceTypeAttribute : Attribute
{
#region Properties & Fields
diff --git a/RGB.NET.Devices.CoolerMaster/CoolerMasterDeviceProvider.cs b/RGB.NET.Devices.CoolerMaster/CoolerMasterDeviceProvider.cs
index 280e520..cecc41d 100644
--- a/RGB.NET.Devices.CoolerMaster/CoolerMasterDeviceProvider.cs
+++ b/RGB.NET.Devices.CoolerMaster/CoolerMasterDeviceProvider.cs
@@ -13,27 +13,37 @@ namespace RGB.NET.Devices.CoolerMaster;
///
/// Represents a device provider responsible for Cooler Master devices.
///
-public class CoolerMasterDeviceProvider : AbstractRGBDeviceProvider
+public sealed class CoolerMasterDeviceProvider : AbstractRGBDeviceProvider
{
#region Properties & Fields
+ // ReSharper disable once InconsistentNaming
+ private static readonly object _lock = new();
+
private static CoolerMasterDeviceProvider? _instance;
///
/// Gets the singleton instance.
///
- public static CoolerMasterDeviceProvider Instance => _instance ?? new CoolerMasterDeviceProvider();
+ public static CoolerMasterDeviceProvider Instance
+ {
+ get
+ {
+ lock (_lock)
+ return _instance ?? new CoolerMasterDeviceProvider();
+ }
+ }
///
/// Gets a modifiable list of paths used to find the native SDK-dlls for x86 applications.
/// The first match will be used.
///
- public static List PossibleX86NativePaths { get; } = new() { "x86/CMSDK.dll" };
+ public static List PossibleX86NativePaths { get; } = ["x86/CMSDK.dll"];
///
/// Gets a modifiable list of paths used to find the native SDK-dlls for x64 applications.
/// The first match will be used.
///
- public static List PossibleX64NativePaths { get; } = new() { "x64/CMSDK.dll" };
+ public static List PossibleX64NativePaths { get; } = ["x64/CMSDK.dll"];
#endregion
@@ -45,8 +55,11 @@ public class CoolerMasterDeviceProvider : AbstractRGBDeviceProvider
/// Thrown if this constructor is called even if there is already an instance of this class.
public CoolerMasterDeviceProvider()
{
- if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(CoolerMasterDeviceProvider)}");
- _instance = this;
+ lock (_lock)
+ {
+ if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(CoolerMasterDeviceProvider)}");
+ _instance = this;
+ }
}
#endregion
@@ -94,12 +107,17 @@ public class CoolerMasterDeviceProvider : AbstractRGBDeviceProvider
}
///
- public override void Dispose()
+ protected override void Dispose(bool disposing)
{
- base.Dispose();
+ lock (_lock)
+ {
+ base.Dispose(disposing);
- try { _CoolerMasterSDK.Reload(); }
- catch { /* Unlucky.. */ }
+ try { _CoolerMasterSDK.Reload(); }
+ catch { /* Unlucky.. */ }
+
+ _instance = null;
+ }
}
#endregion
diff --git a/RGB.NET.Devices.CoolerMaster/Enum/CoolerMasterDevicesIndexes.cs b/RGB.NET.Devices.CoolerMaster/Enum/CoolerMasterDevicesIndexes.cs
index f528ccf..66eb53b 100644
--- a/RGB.NET.Devices.CoolerMaster/Enum/CoolerMasterDevicesIndexes.cs
+++ b/RGB.NET.Devices.CoolerMaster/Enum/CoolerMasterDevicesIndexes.cs
@@ -4,8 +4,6 @@
using System.ComponentModel;
using RGB.NET.Core;
-#pragma warning disable 1591 // Missing XML comment for publicly visible type or member
-
namespace RGB.NET.Devices.CoolerMaster;
///
diff --git a/RGB.NET.Devices.CoolerMaster/Enum/CoolerMasterEffects.cs b/RGB.NET.Devices.CoolerMaster/Enum/CoolerMasterEffects.cs
deleted file mode 100644
index b9fcaa1..0000000
--- a/RGB.NET.Devices.CoolerMaster/Enum/CoolerMasterEffects.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-// ReSharper disable InconsistentNaming
-// ReSharper disable UnusedMember.Global
-
-#pragma warning disable 1591 // Missing XML comment for publicly visible type or member
-
-namespace RGB.NET.Devices.CoolerMaster;
-
-///
-/// Contains a list of available effects.
-///
-public enum CoolerMasterEffects
-{
- FullOn = 0,
- Breath = 1,
- BreathCycle = 2,
- Single = 3,
- Wave = 4,
- Ripple = 5,
- Cross = 6,
- Rain = 7,
- Star = 8,
- Snake = 9,
- Rec = 10,
-
- Spectrum = 11,
- RapidFire = 12,
- Indicator = 13, //mouse Effect
- FireBall = 14,
- WaterRipple = 15,
- ReactivePunch = 16,
- Snowing = 17,
- HeartBeat = 18,
- ReactiveTornade = 19,
-
- Multi1 = 0xE0,
- Multi2 = 0xE1,
- Multi3 = 0xE2,
- Multi4 = 0xE3,
- Off = 0xFE
-}
\ No newline at end of file
diff --git a/RGB.NET.Devices.CoolerMaster/Generic/CoolerMasterRGBDevice.cs b/RGB.NET.Devices.CoolerMaster/Generic/CoolerMasterRGBDevice.cs
index b44a90c..f5d2fad 100644
--- a/RGB.NET.Devices.CoolerMaster/Generic/CoolerMasterRGBDevice.cs
+++ b/RGB.NET.Devices.CoolerMaster/Generic/CoolerMasterRGBDevice.cs
@@ -33,6 +33,8 @@ public abstract class CoolerMasterRGBDevice : AbstractRGBDevice
/// Represents the update-queue performing updates for cooler master devices.
///
-public class CoolerMasterUpdateQueue : UpdateQueue
+public sealed class CoolerMasterUpdateQueue : UpdateQueue
{
#region Properties & Fields
@@ -37,15 +37,26 @@ public class CoolerMasterUpdateQueue : UpdateQueue
#region Methods
///
- protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet)
+ protected override bool Update(in ReadOnlySpan<(object key, Color color)> dataSet)
{
- foreach ((object key, Color color) in dataSet)
+ try
{
- (int row, int column) = ((int, int))key;
- _deviceMatrix.KeyColor[row, column] = new _CoolerMasterKeyColor(color.GetR(), color.GetG(), color.GetB());
+ foreach ((object key, Color color) in dataSet)
+ {
+ (int row, int column) = ((int, int))key;
+ _deviceMatrix.KeyColor[row, column] = new _CoolerMasterKeyColor(color.GetR(), color.GetG(), color.GetB());
+ }
+
+ _CoolerMasterSDK.SetAllLedColor(_deviceMatrix, _deviceIndex);
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ CoolerMasterDeviceProvider.Instance.Throw(ex);
}
- _CoolerMasterSDK.SetAllLedColor(_deviceMatrix, _deviceIndex);
+ return false;
}
#endregion
diff --git a/RGB.NET.Devices.CoolerMaster/Generic/ICoolerMasterRGBDevice.cs b/RGB.NET.Devices.CoolerMaster/Generic/ICoolerMasterRGBDevice.cs
index 5cf66bb..8c1fb92 100644
--- a/RGB.NET.Devices.CoolerMaster/Generic/ICoolerMasterRGBDevice.cs
+++ b/RGB.NET.Devices.CoolerMaster/Generic/ICoolerMasterRGBDevice.cs
@@ -5,5 +5,4 @@ namespace RGB.NET.Devices.CoolerMaster;
///
/// Represents a CoolerMaster RGB-device.
///
-public interface ICoolerMasterRGBDevice : IRGBDevice
-{ }
\ No newline at end of file
+public interface ICoolerMasterRGBDevice : IRGBDevice;
\ No newline at end of file
diff --git a/RGB.NET.Devices.CoolerMaster/Keyboard/CoolerMasterKeyboardRGBDevice.cs b/RGB.NET.Devices.CoolerMaster/Keyboard/CoolerMasterKeyboardRGBDevice.cs
index 29b1e3c..1d03191 100644
--- a/RGB.NET.Devices.CoolerMaster/Keyboard/CoolerMasterKeyboardRGBDevice.cs
+++ b/RGB.NET.Devices.CoolerMaster/Keyboard/CoolerMasterKeyboardRGBDevice.cs
@@ -7,7 +7,7 @@ namespace RGB.NET.Devices.CoolerMaster;
///
/// Represents a CoolerMaster keyboard.
///
-public class CoolerMasterKeyboardRGBDevice : CoolerMasterRGBDevice, IKeyboard
+public sealed class CoolerMasterKeyboardRGBDevice : CoolerMasterRGBDevice, IKeyboard
{
#region Properties & Fields
diff --git a/RGB.NET.Devices.CoolerMaster/Keyboard/CoolerMasterKeyboardRGBDeviceInfo.cs b/RGB.NET.Devices.CoolerMaster/Keyboard/CoolerMasterKeyboardRGBDeviceInfo.cs
index df9fec9..591a62f 100644
--- a/RGB.NET.Devices.CoolerMaster/Keyboard/CoolerMasterKeyboardRGBDeviceInfo.cs
+++ b/RGB.NET.Devices.CoolerMaster/Keyboard/CoolerMasterKeyboardRGBDeviceInfo.cs
@@ -5,7 +5,7 @@ namespace RGB.NET.Devices.CoolerMaster;
///
/// Represents a generic information for a .
///
-public class CoolerMasterKeyboardRGBDeviceInfo : CoolerMasterRGBDeviceInfo, IKeyboardDeviceInfo
+public sealed class CoolerMasterKeyboardRGBDeviceInfo : CoolerMasterRGBDeviceInfo, IKeyboardDeviceInfo
{
#region Properties & Fields
diff --git a/RGB.NET.Devices.CoolerMaster/Mouse/CoolerMasterMouseRGBDevice.cs b/RGB.NET.Devices.CoolerMaster/Mouse/CoolerMasterMouseRGBDevice.cs
index 16ba91c..53e4522 100644
--- a/RGB.NET.Devices.CoolerMaster/Mouse/CoolerMasterMouseRGBDevice.cs
+++ b/RGB.NET.Devices.CoolerMaster/Mouse/CoolerMasterMouseRGBDevice.cs
@@ -7,7 +7,7 @@ namespace RGB.NET.Devices.CoolerMaster;
///
/// Represents a CoolerMaster mouse.
///
-public class CoolerMasterMouseRGBDevice : CoolerMasterRGBDevice, IMouse
+public sealed class CoolerMasterMouseRGBDevice : CoolerMasterRGBDevice, IMouse
{
#region Constructors
diff --git a/RGB.NET.Devices.CoolerMaster/Mouse/CoolerMasterMouseRGBDeviceInfo.cs b/RGB.NET.Devices.CoolerMaster/Mouse/CoolerMasterMouseRGBDeviceInfo.cs
index 14f6b0e..2698216 100644
--- a/RGB.NET.Devices.CoolerMaster/Mouse/CoolerMasterMouseRGBDeviceInfo.cs
+++ b/RGB.NET.Devices.CoolerMaster/Mouse/CoolerMasterMouseRGBDeviceInfo.cs
@@ -6,7 +6,7 @@ namespace RGB.NET.Devices.CoolerMaster;
///
/// Represents a generic information for a .
///
-public class CoolerMasterMouseRGBDeviceInfo : CoolerMasterRGBDeviceInfo
+public sealed class CoolerMasterMouseRGBDeviceInfo : CoolerMasterRGBDeviceInfo
{
#region Constructors
diff --git a/RGB.NET.Devices.CoolerMaster/Native/_CoolerMasterSDK.cs b/RGB.NET.Devices.CoolerMaster/Native/_CoolerMasterSDK.cs
index 6b51c39..6be82b0 100644
--- a/RGB.NET.Devices.CoolerMaster/Native/_CoolerMasterSDK.cs
+++ b/RGB.NET.Devices.CoolerMaster/Native/_CoolerMasterSDK.cs
@@ -16,14 +16,14 @@ internal static class _CoolerMasterSDK
{
#region Libary Management
- private static IntPtr _handle = IntPtr.Zero;
+ private static nint _handle = 0;
///
/// Reloads the SDK.
///
internal static void Reload()
{
- if (_handle != IntPtr.Zero)
+ if (_handle != 0)
{
foreach (CoolerMasterDevicesIndexes index in Enum.GetValues(typeof(CoolerMasterDevicesIndexes)))
EnableLedControl(false, index);
@@ -34,7 +34,7 @@ internal static class _CoolerMasterSDK
private static void LoadCMSDK()
{
- if (_handle != IntPtr.Zero) return;
+ if (_handle != 0) return;
// HACK: Load library at runtime to support both, x86 and x64 with one managed dll
List possiblePathList = (Environment.Is64BitProcess ? CoolerMasterDeviceProvider.PossibleX64NativePaths : CoolerMasterDeviceProvider.PossibleX86NativePaths)
@@ -47,7 +47,7 @@ internal static class _CoolerMasterSDK
#if NET6_0
if (_handle == IntPtr.Zero) throw new RGBDeviceException($"CoolerMaster LoadLibrary failed with error code {Marshal.GetLastPInvokeError()}");
#else
- if (_handle == IntPtr.Zero) throw new RGBDeviceException($"CoolerMaster LoadLibrary failed with error code {Marshal.GetLastWin32Error()}");
+ if (_handle == 0) throw new RGBDeviceException($"CoolerMaster LoadLibrary failed with error code {Marshal.GetLastWin32Error()}");
#endif
_getSDKVersionPointer = (GetSDKVersionPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_handle, "GetCM_SDK_DllVer"), typeof(GetSDKVersionPointer));
@@ -62,7 +62,7 @@ internal static class _CoolerMasterSDK
internal static void UnloadCMSDK()
{
- if (_handle == IntPtr.Zero) return;
+ if (_handle == 0) return;
_getSDKVersionPointer = null;
_setControlDevicenPointer = null;
@@ -74,14 +74,14 @@ internal static class _CoolerMasterSDK
_setAllLedColorPointer = null;
NativeLibrary.Free(_handle);
- _handle = IntPtr.Zero;
+ _handle = 0;
}
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
- private static extern IntPtr LoadLibrary(string dllToLoad);
+ private static extern nint LoadLibrary(string dllToLoad);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
- private static extern IntPtr GetProcAddress(IntPtr dllHandle, string name);
+ private static extern nint GetProcAddress(nint dllHandle, string name);
#endregion
diff --git a/RGB.NET.Devices.CoolerMaster/RGB.NET.Devices.CoolerMaster.csproj b/RGB.NET.Devices.CoolerMaster/RGB.NET.Devices.CoolerMaster.csproj
index d4812ed..73017c6 100644
--- a/RGB.NET.Devices.CoolerMaster/RGB.NET.Devices.CoolerMaster.csproj
+++ b/RGB.NET.Devices.CoolerMaster/RGB.NET.Devices.CoolerMaster.csproj
@@ -1,6 +1,6 @@
- net7.0;net6.0;net5.0
+ net8.0;net7.0;net6.0
latest
enable
@@ -40,7 +40,7 @@
- $(DefineConstants);TRACE;DEBUG
+ TRACE;DEBUG
true
false
@@ -48,7 +48,7 @@
true
$(NoWarn);CS1591;CS1572;CS1573
- $(DefineConstants);RELEASE
+ RELEASE
diff --git a/RGB.NET.Devices.Corsair/Cooler/CorsairCoolerRGBDevice.cs b/RGB.NET.Devices.Corsair/Cooler/CorsairCoolerRGBDevice.cs
new file mode 100644
index 0000000..e92a731
--- /dev/null
+++ b/RGB.NET.Devices.Corsair/Cooler/CorsairCoolerRGBDevice.cs
@@ -0,0 +1,34 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using RGB.NET.Core;
+using System.Collections.Generic;
+
+namespace RGB.NET.Devices.Corsair;
+
+///
+///
+/// Represents a corsair cooler.
+///
+public sealed class CorsairCoolerRGBDevice : CorsairRGBDevice, ICooler
+{
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The specific information provided by CUE for the cooler.
+ /// The queue used to update this device.
+ internal CorsairCoolerRGBDevice(CorsairCoolerRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
+ : base(info, updateQueue)
+ { }
+
+ #endregion
+
+ #region Methods
+
+ protected override LedMapping CreateMapping(IEnumerable ids) => LedMappings.CreateCoolerMapping(ids);
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Cooler/CorsairCoolerRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair/Cooler/CorsairCoolerRGBDeviceInfo.cs
new file mode 100644
index 0000000..96333b4
--- /dev/null
+++ b/RGB.NET.Devices.Corsair/Cooler/CorsairCoolerRGBDeviceInfo.cs
@@ -0,0 +1,28 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using RGB.NET.Core;
+using RGB.NET.Devices.Corsair.Native;
+
+namespace RGB.NET.Devices.Corsair;
+
+///
+///
+/// Represents a generic information for a .
+///
+public sealed class CorsairCoolerRGBDeviceInfo : CorsairRGBDeviceInfo
+{
+ #region Constructors
+
+ ///
+ internal CorsairCoolerRGBDeviceInfo(_CorsairDeviceInfo nativeInfo, int ledCount, int ledOffset)
+ : base(RGBDeviceType.Cooler, nativeInfo, ledCount, ledOffset)
+ { }
+
+ ///
+ internal CorsairCoolerRGBDeviceInfo(_CorsairDeviceInfo nativeInfo, int ledCount, int ledOffset, string modelName)
+ : base(RGBDeviceType.Cooler, nativeInfo, ledCount, ledOffset, modelName)
+ { }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/CorsairDeviceProvider.cs b/RGB.NET.Devices.Corsair/CorsairDeviceProvider.cs
index 7acd75e..4dba9ea 100644
--- a/RGB.NET.Devices.Corsair/CorsairDeviceProvider.cs
+++ b/RGB.NET.Devices.Corsair/CorsairDeviceProvider.cs
@@ -3,8 +3,7 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.InteropServices;
+using System.Threading;
using RGB.NET.Core;
using RGB.NET.Devices.Corsair.Native;
@@ -14,37 +13,72 @@ namespace RGB.NET.Devices.Corsair;
///
/// Represents a device provider responsible for corsair (CUE) devices.
///
-public class CorsairDeviceProvider : AbstractRGBDeviceProvider
+public sealed class CorsairDeviceProvider : AbstractRGBDeviceProvider
{
#region Properties & Fields
+ // ReSharper disable once InconsistentNaming
+ private static readonly object _lock = new();
+
private static CorsairDeviceProvider? _instance;
///
/// Gets the singleton instance.
///
- public static CorsairDeviceProvider Instance => _instance ?? new CorsairDeviceProvider();
+ public static CorsairDeviceProvider Instance
+ {
+ get
+ {
+ lock (_lock)
+ return _instance ?? new CorsairDeviceProvider();
+ }
+ }
///
/// Gets a modifiable list of paths used to find the native SDK-dlls for x86 applications.
/// The first match will be used.
///
- public static List PossibleX86NativePaths { get; } = new() { "x86/CUESDK.dll", "x86/CUESDK_2019.dll", "x86/CUESDK_2017.dll", "x86/CUESDK_2015.dll", "x86/CUESDK_2013.dll" };
+ public static List PossibleX86NativePaths { get; } = ["x86/iCUESDK.dll", "x86/CUESDK_2019.dll"];
///
/// Gets a modifiable list of paths used to find the native SDK-dlls for x64 applications.
/// The first match will be used.
///
- public static List PossibleX64NativePaths { get; } = new() { "x64/CUESDK.dll", "x64/CUESDK.x64_2019.dll", "x64/CUESDK.x64_2017.dll", "x64/CUESDK_2019.dll", "x64/CUESDK_2017.dll", "x64/CUESDK_2015.dll", "x64/CUESDK_2013.dll" };
+ public static List PossibleX64NativePaths { get; } = ["x64/iCUESDK.dll", "x64/iCUESDK.x64_2019.dll", "x64/CUESDK.dll", "x64/CUESDK.x64_2019.dll"];
///
- /// Gets the protocol details for the current SDK-connection.
+ /// Gets or sets the timeout used when connecting to the SDK.
///
- public CorsairProtocolDetails? ProtocolDetails { get; private set; }
+ public static TimeSpan ConnectionTimeout { get; set; } = TimeSpan.FromMilliseconds(500);
///
- /// Gets the last error documented by CUE.
+ /// Gets or sets a bool indicating if exclusive request should be requested through the iCUE-SDK.
///
- public static CorsairError LastError => _CUESDK.CorsairGetLastError();
+ public static bool ExclusiveAccess { get; set; } = false;
+
+ ///
+ /// Gets the details for the current SDK-session.
+ ///
+ public CorsairSessionDetails SessionDetails { get; private set; } = new();
+
+ private CorsairSessionState _sessionState = CorsairSessionState.Invalid;
+ public CorsairSessionState SessionState
+ {
+ get => _sessionState;
+ private set
+ {
+ _sessionState = value;
+
+ try { SessionStateChanged?.Invoke(this, SessionState); }
+ catch { /* catch faulty event-handlers*/ }
+ }
+ }
+
+ #endregion
+
+ #region Events
+
+ // ReSharper disable once UnassignedField.Global
+ public EventHandler? SessionStateChanged;
#endregion
@@ -56,35 +90,56 @@ public class CorsairDeviceProvider : AbstractRGBDeviceProvider
/// Thrown if this constructor is called even if there is already an instance of this class.
public CorsairDeviceProvider()
{
- if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(CorsairDeviceProvider)}");
- _instance = this;
+ lock (_lock)
+ {
+ if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(CorsairDeviceProvider)}");
+ _instance = this;
+ }
}
#endregion
#region Methods
- ///
protected override void InitializeSDK()
{
_CUESDK.Reload();
- ProtocolDetails = new CorsairProtocolDetails(_CUESDK.CorsairPerformProtocolHandshake());
+ using ManualResetEventSlim waitEvent = new(false);
- CorsairError error = LastError;
- if (error != CorsairError.Success)
- Throw(new CUEException(error), true);
+ void OnInitializeSessionStateChanged(object? sender, CorsairSessionState state)
+ {
+ if (state == CorsairSessionState.Connected)
+ // ReSharper disable once AccessToDisposedClosure
+ waitEvent.Set();
+ }
- if (ProtocolDetails.BreakingChanges)
- Throw(new RGBDeviceException("The SDK currently used isn't compatible with the installed version of CUE.\r\n"
- + $"CUE-Version: {ProtocolDetails.ServerVersion} (Protocol {ProtocolDetails.ServerProtocolVersion})\r\n"
- + $"SDK-Version: {ProtocolDetails.SdkVersion} (Protocol {ProtocolDetails.SdkProtocolVersion})"), true);
+ try
+ {
+ _CUESDK.SessionStateChanged += OnSessionStateChanged;
+ _CUESDK.SessionStateChanged += OnInitializeSessionStateChanged;
- // DarthAffe 02.02.2021: 127 is iCUE
- if (!_CUESDK.CorsairSetLayerPriority(128))
- Throw(new CUEException(LastError));
+ CorsairError errorCode = _CUESDK.CorsairConnect();
+ if (errorCode != CorsairError.Success)
+ Throw(new RGBDeviceException($"Failed to initialized Corsair-SDK. (ErrorCode: {errorCode})"));
+
+ if (!waitEvent.Wait(ConnectionTimeout))
+ Throw(new RGBDeviceException($"Failed to initialized Corsair-SDK. (Timeout - Current connection state: {_CUESDK.SesionState})"));
+
+ _CUESDK.CorsairGetSessionDetails(out _CorsairSessionDetails? details);
+ if (errorCode != CorsairError.Success)
+ Throw(new RGBDeviceException($"Failed to get session details. (ErrorCode: {errorCode})"));
+
+ SessionDetails = new CorsairSessionDetails(details!);
+ }
+ finally
+ {
+ _CUESDK.SessionStateChanged -= OnInitializeSessionStateChanged;
+ }
}
+ private void OnSessionStateChanged(object? sender, CorsairSessionState state) => SessionState = state;
+
///
protected override IEnumerable LoadDevices()
{
@@ -97,119 +152,190 @@ public class CorsairDeviceProvider : AbstractRGBDeviceProvider
private IEnumerable LoadCorsairDevices()
{
- int deviceCount = _CUESDK.CorsairGetDeviceCount();
- for (int i = 0; i < deviceCount; i++)
+ CorsairError error = _CUESDK.CorsairGetDevices(new _CorsairDeviceFilter(CorsairDeviceType.All), out _CorsairDeviceInfo[] devices);
+ if (error != CorsairError.Success)
+ Throw(new RGBDeviceException($"Failed to load devices. (ErrorCode: {error})"));
+
+ foreach (_CorsairDeviceInfo device in devices)
{
- _CorsairDeviceInfo nativeDeviceInfo = (_CorsairDeviceInfo)Marshal.PtrToStructure(_CUESDK.CorsairGetDeviceInfo(i), typeof(_CorsairDeviceInfo))!;
- if (!((CorsairDeviceCaps)nativeDeviceInfo.capsMask).HasFlag(CorsairDeviceCaps.Lighting))
- continue; // Everything that doesn't support lighting control is useless
+ if (string.IsNullOrWhiteSpace(device.id)) continue;
- CorsairDeviceUpdateQueue updateQueue = new(GetUpdateTrigger(), i);
- switch (nativeDeviceInfo.type)
+ error = _CUESDK.CorsairRequestControl(device.id, ExclusiveAccess ? CorsairAccessLevel.ExclusiveLightingControl : CorsairAccessLevel.Shared);
+ if (error != CorsairError.Success)
+ Throw(new RGBDeviceException($"Failed to take control of device '{device.id}'. (ErrorCode: {error})"));
+
+ CorsairDeviceUpdateQueue updateQueue = new(GetUpdateTrigger(), device);
+
+ int channelLedCount = 0;
+ for (int i = 0; i < device.channelCount; i++)
{
- case CorsairDeviceType.Keyboard:
- yield return new CorsairKeyboardRGBDevice(new CorsairKeyboardRGBDeviceInfo(i, nativeDeviceInfo), updateQueue);
- break;
+ Console.WriteLine($"Channel {i}/{device.channelCount}");
+ channelLedCount += _CUESDK.ReadDevicePropertySimpleInt32(device.id!, CorsairDevicePropertyId.ChannelLedCount, (uint)i);
+ }
- case CorsairDeviceType.Mouse:
- yield return new CorsairMouseRGBDevice(new CorsairMouseRGBDeviceInfo(i, nativeDeviceInfo), updateQueue);
- break;
+ int deviceLedCount = device.ledCount - channelLedCount;
+ if (deviceLedCount > 0)
+ switch (device.type)
+ {
+ case CorsairDeviceType.Keyboard:
+ yield return new CorsairKeyboardRGBDevice(new CorsairKeyboardRGBDeviceInfo(device, deviceLedCount, 0), updateQueue);
+ break;
- case CorsairDeviceType.Headset:
- yield return new CorsairHeadsetRGBDevice(new CorsairHeadsetRGBDeviceInfo(i, nativeDeviceInfo), updateQueue);
- break;
+ case CorsairDeviceType.Mouse:
+ yield return new CorsairMouseRGBDevice(new CorsairMouseRGBDeviceInfo(device, deviceLedCount, 0), updateQueue);
+ break;
- case CorsairDeviceType.Mousepad:
- yield return new CorsairMousepadRGBDevice(new CorsairMousepadRGBDeviceInfo(i, nativeDeviceInfo), updateQueue);
- break;
+ case CorsairDeviceType.Headset:
+ yield return new CorsairHeadsetRGBDevice(new CorsairHeadsetRGBDeviceInfo(device, deviceLedCount, 0), updateQueue);
+ break;
- case CorsairDeviceType.HeadsetStand:
- yield return new CorsairHeadsetStandRGBDevice(new CorsairHeadsetStandRGBDeviceInfo(i, nativeDeviceInfo), updateQueue);
- break;
+ case CorsairDeviceType.Mousemat:
+ yield return new CorsairMousepadRGBDevice(new CorsairMousepadRGBDeviceInfo(device, deviceLedCount, 0), updateQueue);
+ break;
- case CorsairDeviceType.MemoryModule:
- yield return new CorsairMemoryRGBDevice(new CorsairMemoryRGBDeviceInfo(i, nativeDeviceInfo), updateQueue);
- break;
+ case CorsairDeviceType.HeadsetStand:
+ yield return new CorsairHeadsetStandRGBDevice(new CorsairHeadsetStandRGBDeviceInfo(device, deviceLedCount, 0), updateQueue);
+ break;
- case CorsairDeviceType.Mainboard:
- yield return new CorsairMainboardRGBDevice(new CorsairMainboardRGBDeviceInfo(i, nativeDeviceInfo), updateQueue);
- break;
+ case CorsairDeviceType.MemoryModule:
+ yield return new CorsairMemoryRGBDevice(new CorsairMemoryRGBDeviceInfo(device, deviceLedCount, 0), updateQueue);
+ break;
- case CorsairDeviceType.GraphicsCard:
- yield return new CorsairGraphicsCardRGBDevice(new CorsairGraphicsCardRGBDeviceInfo(i, nativeDeviceInfo), updateQueue);
- break;
+ case CorsairDeviceType.Motherboard:
+ yield return new CorsairMainboardRGBDevice(new CorsairMainboardRGBDeviceInfo(device, deviceLedCount, 0), updateQueue);
+ break;
- case CorsairDeviceType.Touchbar:
- yield return new CorsairTouchbarRGBDevice(new CorsairTouchbarRGBDeviceInfo(i, nativeDeviceInfo), updateQueue);
- break;
+ case CorsairDeviceType.GraphicsCard:
+ yield return new CorsairGraphicsCardRGBDevice(new CorsairGraphicsCardRGBDeviceInfo(device, deviceLedCount, 0), updateQueue);
+ break;
- case CorsairDeviceType.Cooler:
- case CorsairDeviceType.CommanderPro:
- case CorsairDeviceType.LightningNodePro:
- List<_CorsairChannelInfo> channels = GetChannels(nativeDeviceInfo).ToList();
- int channelsLedCount = channels.Sum(x => x.totalLedsCount);
- int deviceLedCount = nativeDeviceInfo.ledsCount - channelsLedCount;
+ case CorsairDeviceType.Touchbar:
+ yield return new CorsairTouchbarRGBDevice(new CorsairTouchbarRGBDeviceInfo(device, deviceLedCount, 0), updateQueue);
+ break;
- if (deviceLedCount > 0)
- yield return new CorsairCustomRGBDevice(new CorsairCustomRGBDeviceInfo(i, nativeDeviceInfo, deviceLedCount), updateQueue);
+ case CorsairDeviceType.Cooler:
+ yield return new CorsairCoolerRGBDevice(new CorsairCoolerRGBDeviceInfo(device, deviceLedCount, 0), updateQueue);
+ break;
- int ledOffset = deviceLedCount;
- foreach (_CorsairChannelInfo channelInfo in channels)
+ case CorsairDeviceType.GameController:
+ yield return new CorsairGameControllerRGBDevice(new CorsairGameControllerRGBDeviceInfo(device, deviceLedCount, 0), updateQueue);
+ break;
+
+ case CorsairDeviceType.FanLedController:
+ case CorsairDeviceType.LedController:
+ case CorsairDeviceType.Unknown:
+ yield return new CorsairUnknownRGBDevice(new CorsairUnknownRGBDeviceInfo(device, deviceLedCount, 0), updateQueue);
+ break;
+
+ default:
+ Throw(new RGBDeviceException("Unknown Device-Type"));
+ break;
+ }
+
+ int offset = deviceLedCount;
+ for (int i = 0; i < device.channelCount; i++)
+ {
+ int deviceCount = _CUESDK.ReadDevicePropertySimpleInt32(device.id!, CorsairDevicePropertyId.ChannelDeviceCount, (uint)i);
+ if (deviceCount <= 0) continue; // DarthAffe 10.02.2023: There seem to be an issue in the SDK where it reports empty channels and fails when getting ledCounts and device types from them
+
+ int[] ledCounts = _CUESDK.ReadDevicePropertySimpleInt32Array(device.id!, CorsairDevicePropertyId.ChannelDeviceLedCountArray, (uint)i);
+ int[] deviceTypes = _CUESDK.ReadDevicePropertySimpleInt32Array(device.id!, CorsairDevicePropertyId.ChannelDeviceTypeArray, (uint)i);
+
+ for (int j = 0; j < deviceCount; j++)
+ {
+ CorsairChannelDeviceType deviceType = (CorsairChannelDeviceType)deviceTypes[j];
+ int ledCount = ledCounts[j];
+
+ switch (deviceType)
{
- int channelDeviceInfoStructSize = Marshal.SizeOf(typeof(_CorsairChannelDeviceInfo));
- IntPtr channelDeviceInfoPtr = channelInfo.devices;
- for (int device = 0; (device < channelInfo.devicesCount) && (ledOffset < nativeDeviceInfo.ledsCount); device++)
- {
- _CorsairChannelDeviceInfo channelDeviceInfo = (_CorsairChannelDeviceInfo)Marshal.PtrToStructure(channelDeviceInfoPtr, typeof(_CorsairChannelDeviceInfo))!;
+ case CorsairChannelDeviceType.FanHD:
+ yield return new CorsairFanRGBDevice(new CorsairFanRGBDeviceInfo(device, ledCount, offset, "HD Fan"), updateQueue);
+ break;
- yield return new CorsairCustomRGBDevice(new CorsairCustomRGBDeviceInfo(i, nativeDeviceInfo, channelDeviceInfo, ledOffset), updateQueue);
+ case CorsairChannelDeviceType.FanSP:
+ yield return new CorsairFanRGBDevice(new CorsairFanRGBDeviceInfo(device, ledCount, offset, "SP Fan"), updateQueue);
+ break;
- ledOffset += channelDeviceInfo.deviceLedCount;
- channelDeviceInfoPtr = new IntPtr(channelDeviceInfoPtr.ToInt64() + channelDeviceInfoStructSize);
- }
+ case CorsairChannelDeviceType.FanLL:
+ yield return new CorsairFanRGBDevice(new CorsairFanRGBDeviceInfo(device, ledCount, offset, "LL Fan"), updateQueue);
+ break;
+
+ case CorsairChannelDeviceType.FanML:
+ yield return new CorsairFanRGBDevice(new CorsairFanRGBDeviceInfo(device, ledCount, offset, "ML Fan"), updateQueue);
+ break;
+
+ case CorsairChannelDeviceType.FanQL:
+ yield return new CorsairFanRGBDevice(new CorsairFanRGBDeviceInfo(device, ledCount, offset, "QL Fan"), updateQueue);
+ break;
+
+ case CorsairChannelDeviceType.FanQX:
+ yield return new CorsairFanRGBDevice(new CorsairFanRGBDeviceInfo(device, ledCount, offset, "QX Fan"), updateQueue);
+ break;
+
+ case CorsairChannelDeviceType.EightLedSeriesFan:
+ yield return new CorsairFanRGBDevice(new CorsairFanRGBDeviceInfo(device, ledCount, offset, "8-Led-Series Fan Fan"), updateQueue);
+ break;
+
+ case CorsairChannelDeviceType.DAP:
+ yield return new CorsairFanRGBDevice(new CorsairFanRGBDeviceInfo(device, ledCount, offset, "DAP Fan"), updateQueue);
+ break;
+
+ case CorsairChannelDeviceType.Pump:
+ yield return new CorsairCoolerRGBDevice(new CorsairCoolerRGBDeviceInfo(device, ledCount, offset, "Pump"), updateQueue);
+ break;
+
+ case CorsairChannelDeviceType.WaterBlock:
+ yield return new CorsairCoolerRGBDevice(new CorsairCoolerRGBDeviceInfo(device, ledCount, offset, "Water Block"), updateQueue);
+ break;
+
+ case CorsairChannelDeviceType.Strip:
+ string modelName = "LED Strip";
+
+ // LS100 Led Strips are reported as one big strip if configured in monitor mode in iCUE, 138 LEDs for dual monitor, 84 for single
+ if ((device.model == "LS100 Starter Kit") && (ledCount == 138))
+ modelName = "LS100 LED Strip (dual monitor)";
+ else if ((device.model == "LS100 Starter Kit") && (ledCount == 84))
+ modelName = "LS100 LED Strip (single monitor)";
+ // Any other value means an "External LED Strip" in iCUE, these are reported per-strip, 15 for short strips, 27 for long
+ else if ((device.model == "LS100 Starter Kit") && (ledCount == 15))
+ modelName = "LS100 LED Strip (short)";
+ else if ((device.model == "LS100 Starter Kit") && (ledCount == 27))
+ modelName = "LS100 LED Strip (long)";
+
+ yield return new CorsairLedStripRGBDevice(new CorsairLedStripRGBDeviceInfo(device, ledCount, offset, modelName), updateQueue);
+ break;
+
+ case CorsairChannelDeviceType.DRAM:
+ yield return new CorsairMemoryRGBDevice(new CorsairMemoryRGBDeviceInfo(device, ledCount, offset, "DRAM"), updateQueue);
+ break;
+
+ default:
+ Throw(new RGBDeviceException("Unknown Device-Type"));
+ break;
}
- break;
- default:
- Throw(new RGBDeviceException("Unknown Device-Type"));
- break;
+ offset += ledCount;
+ }
}
}
}
- private static IEnumerable<_CorsairChannelInfo> GetChannels(_CorsairDeviceInfo deviceInfo)
+ ///
+ protected override void Dispose(bool disposing)
{
- _CorsairChannelsInfo? channelsInfo = deviceInfo.channels;
- if (channelsInfo == null) yield break;
-
- IntPtr channelInfoPtr = channelsInfo.channels;
- for (int channel = 0; channel < channelsInfo.channelsCount; channel++)
+ lock (_lock)
{
- yield return (_CorsairChannelInfo)Marshal.PtrToStructure(channelInfoPtr, typeof(_CorsairChannelInfo))!;
+ base.Dispose(disposing);
- int channelInfoStructSize = Marshal.SizeOf(typeof(_CorsairChannelInfo));
- channelInfoPtr = new IntPtr(channelInfoPtr.ToInt64() + channelInfoStructSize);
+ try { _CUESDK.CorsairDisconnect(); }
+ catch { /* at least we tried */ }
+
+ try { _CUESDK.UnloadCUESDK(); }
+ catch { /* at least we tried */ }
+
+ _instance = null;
}
}
- ///
- protected override void Reset()
- {
- ProtocolDetails = null;
-
- base.Reset();
- }
-
- ///
- public override void Dispose()
- {
- base.Dispose();
-
- try { _CUESDK.UnloadCUESDK(); }
- catch { /* at least we tried */ }
-
- GC.SuppressFinalize(this);
- }
-
#endregion
}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Enum/CorsairAccessLevel.cs b/RGB.NET.Devices.Corsair/Enum/CorsairAccessLevel.cs
new file mode 100644
index 0000000..33a87e0
--- /dev/null
+++ b/RGB.NET.Devices.Corsair/Enum/CorsairAccessLevel.cs
@@ -0,0 +1,30 @@
+// ReSharper disable InconsistentNaming
+// ReSharper disable UnusedMember.Global
+
+namespace RGB.NET.Devices.Corsair;
+
+///
+/// iCUE-SDK: Represents an SDK access level.
+///
+public enum CorsairAccessLevel
+{
+ ///
+ /// iCUE-SDK: shared mode (default)
+ ///
+ Shared = 0,
+
+ ///
+ /// iCUE-SDK: exclusive lightings, but shared events
+ ///
+ ExclusiveLightingControl = 1,
+
+ ///
+ /// iCUE-SDK: exclusive key events, but shared lightings
+ ///
+ ExclusiveKeyEventsListening = 2,
+
+ ///
+ /// iCUE-SDK: exclusive mode
+ ///
+ ExclusiveLightingControlAndKeyEventsListening = 3
+};
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Enum/CorsairChannelDeviceType.cs b/RGB.NET.Devices.Corsair/Enum/CorsairChannelDeviceType.cs
index 8c89470..afadf30 100644
--- a/RGB.NET.Devices.Corsair/Enum/CorsairChannelDeviceType.cs
+++ b/RGB.NET.Devices.Corsair/Enum/CorsairChannelDeviceType.cs
@@ -1,13 +1,10 @@
// ReSharper disable InconsistentNaming
// ReSharper disable UnusedMember.Global
-
-#pragma warning disable 1591 // Missing XML comment for publicly visible type or member
-
namespace RGB.NET.Devices.Corsair;
///
-/// Contains a list of available corsair channel device types.
+/// iCUE-SDK: Contains a list of available corsair channel device types.
///
public enum CorsairChannelDeviceType
{
@@ -16,10 +13,12 @@ public enum CorsairChannelDeviceType
FanSP = 2,
FanLL = 3,
FanML = 4,
- Strip = 5,
- DAP = 6,
- Pump = 7,
- FanQL = 8,
- WaterBlock = 9,
- EightLedSeriesFan = 10 // Previously called FanSPPRO
+ FanQL = 5,
+ EightLedSeriesFan = 6,
+ Strip = 7,
+ DAP = 8,
+ Pump = 9,
+ DRAM = 10,
+ WaterBlock = 11,
+ FanQX = 12,
};
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Enum/CorsairDataType.cs b/RGB.NET.Devices.Corsair/Enum/CorsairDataType.cs
new file mode 100644
index 0000000..e9bf894
--- /dev/null
+++ b/RGB.NET.Devices.Corsair/Enum/CorsairDataType.cs
@@ -0,0 +1,47 @@
+namespace RGB.NET.Devices.Corsair;
+
+///
+/// iCUE-SDK: contains list of available property types
+///
+public enum CorsairDataType
+{
+ ///
+ /// iCUE-SDK: for property of type Boolean
+ ///
+ Boolean = 0,
+
+ ///
+ /// iCUE-SDK: for property of type Int32 or Enumeration
+ ///
+ Int32 = 1,
+
+ ///
+ /// iCUE-SDK: for property of type Float64
+ ///
+ Float64 = 2,
+
+ ///
+ /// iCUE-SDK: for property of type String
+ ///
+ String = 3,
+
+ ///
+ /// iCUE-SDK: for array of Boolean
+ ///
+ BooleanArray = 16,
+
+ ///
+ /// iCUE-SDK: for array of Int32
+ ///
+ Int32Array = 17,
+
+ ///
+ /// iCUE-SDK: for array of Float64
+ ///
+ Float64Array = 18,
+
+ ///
+ /// iCUE-SDK: for array of String
+ ///
+ StringArray = 19
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Enum/CorsairDevicePropertyId.cs b/RGB.NET.Devices.Corsair/Enum/CorsairDevicePropertyId.cs
new file mode 100644
index 0000000..0646355
--- /dev/null
+++ b/RGB.NET.Devices.Corsair/Enum/CorsairDevicePropertyId.cs
@@ -0,0 +1,77 @@
+namespace RGB.NET.Devices.Corsair;
+
+///
+/// iCUE-SDK: contains list of properties identifiers which can be read from device
+///
+public enum CorsairDevicePropertyId
+{
+ ///
+ /// iCUE-SDK: dummy value
+ ///
+ Invalid = 0,
+
+ ///
+ /// iCUE-SDK: array of CorsairDevicePropertyId members supported by device
+ ///
+ PropertyArray = 1,
+
+ ///
+ /// iCUE-SDK: indicates Mic state (On or Off); used for headset, headset stand
+ ///
+ MicEnabled = 2,
+
+ ///
+ /// iCUE-SDK: indicates Surround Sound state (On or Off); used for headset, headset stand
+ ///
+ SurroundSoundEnabled = 3,
+
+ ///
+ /// iCUE-SDK: indicates Sidetone state (On or Off); used for headset (where applicable)
+ ///
+ SidetoneEnabled = 4,
+
+ ///
+ /// iCUE-SDK: the number of active equalizer preset (integer, 1 - 5); used for headset, headset stand
+ ///
+ EqualizerPreset = 5,
+
+ ///
+ /// iCUE-SDK: keyboard physical layout (see CorsairPhysicalLayout for valid values); used for keyboard
+ ///
+ PhysicalLayout = 6,
+
+ ///
+ /// iCUE-SDK: keyboard logical layout (see CorsairLogicalLayout for valid values); used for keyboard
+ ///
+ LogicalLayout = 7,
+
+ ///
+ /// iCUE-SDK: array of programmable G, M or S keys on device
+ ///
+ MacroKeyArray = 8,
+
+ ///
+ /// iCUE-SDK: battery level (0 - 100); used for wireless devices
+ ///
+ BatteryLevel = 9,
+
+ ///
+ /// iCUE-SDK: total number of LEDs connected to the channel
+ ///
+ ChannelLedCount = 10,
+
+ ///
+ /// iCUE-SDK: number of LED-devices (fans, strips, etc.) connected to the channel which is controlled by the DIY device
+ ///
+ ChannelDeviceCount = 11,
+
+ ///
+ /// iCUE-SDK: array of integers, each element describes the number of LEDs controlled by the channel device
+ ///
+ ChannelDeviceLedCountArray = 12,
+
+ ///
+ /// iCUE-SDK: array of CorsairChannelDeviceType members, each element describes the type of the channel device
+ ///
+ ChannelDeviceTypeArray = 13
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Enum/CorsairDeviceType.cs b/RGB.NET.Devices.Corsair/Enum/CorsairDeviceType.cs
index a409c5d..9e78403 100644
--- a/RGB.NET.Devices.Corsair/Enum/CorsairDeviceType.cs
+++ b/RGB.NET.Devices.Corsair/Enum/CorsairDeviceType.cs
@@ -1,27 +1,88 @@
// ReSharper disable InconsistentNaming
// ReSharper disable UnusedMember.Global
-
-#pragma warning disable 1591 // Missing XML comment for publicly visible type or member
+using System;
namespace RGB.NET.Devices.Corsair;
///
-/// Contains a list of available corsair device types.
+/// iCUE-SDK: Contains a list of available corsair device types.
///
-public enum CorsairDeviceType
+[Flags]
+public enum CorsairDeviceType : uint
{
- Unknown = 0,
- Mouse = 1,
- Keyboard = 2,
- Headset = 3,
- Mousepad = 4,
- HeadsetStand = 5,
- CommanderPro = 6,
- LightningNodePro = 7,
- MemoryModule = 8,
- Cooler = 9,
- Mainboard = 10,
- GraphicsCard = 11,
- Touchbar = 12
+ ///
+ /// iCUE-SDK: for unknown/invalid devices
+ ///
+ Unknown = 0x0000,
+
+ ///
+ /// iCUE-SDK: for keyboards
+ ///
+ Keyboard = 0x0001,
+
+ ///
+ /// iCUE-SDK: for mice
+ ///
+ Mouse = 0x0002,
+
+ ///
+ /// iCUE-SDK: for mousemats
+ ///
+ Mousemat = 0x0004,
+
+ ///
+ /// iCUE-SDK: for headsets
+ ///
+ Headset = 0x0008,
+
+ ///
+ /// iCUE-SDK: for headset stands
+ ///
+ HeadsetStand = 0x0010,
+
+ ///
+ /// iCUE-SDK: for DIY-devices like Commander PRO
+ ///
+ FanLedController = 0x0020,
+
+ ///
+ /// iCUE-SDK: for DIY-devices like Lighting Node PRO
+ ///
+ LedController = 0x0040,
+
+ ///
+ /// iCUE-SDK: for memory modules
+ ///
+ MemoryModule = 0x0080,
+
+ ///
+ /// iCUE-SDK: for coolers
+ ///
+ Cooler = 0x0100,
+
+ ///
+ /// iCUE-SDK: for motherboards
+ ///
+ Motherboard = 0x0200,
+
+ ///
+ /// iCUE-SDK: for graphics cards
+ ///
+ GraphicsCard = 0x0400,
+
+ ///
+ /// iCUE-SDK: for touchbars
+ ///
+ Touchbar = 0x0800,
+
+ ///
+ /// iCUE-SDK: for game controllers
+ ///
+ GameController = 0x1000,
+
+ ///
+ /// iCUE-SDK: for all devices
+ ///
+ All = 0xFFFFFFFF
};
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Enum/CorsairError.cs b/RGB.NET.Devices.Corsair/Enum/CorsairError.cs
index 977c2cf..d2fb672 100644
--- a/RGB.NET.Devices.Corsair/Enum/CorsairError.cs
+++ b/RGB.NET.Devices.Corsair/Enum/CorsairError.cs
@@ -4,38 +4,47 @@
namespace RGB.NET.Devices.Corsair;
///
-/// Shared list of all errors which could happen during calling of Corsair* functions.
+/// iCUE-SDK: Shared list of all errors which could happen during calling of Corsair* functions.
///
public enum CorsairError
{
///
- /// If previously called function completed successfully.
+ /// iCUE-SDK: if previously called function completed successfully
///
- Success,
+ Success = 0,
///
- /// CUE is not running or was shut down or third-party control is disabled in CUE settings. (runtime error)
+ /// iCUE-SDK: if iCUE is not running or was shut down or third-party control is disabled in iCUE settings (runtime error), or if developer did not call CorsairConnect after calling CorsairDisconnect or on app start (developer error)
///
- ServerNotFound,
+ NotConnected = 1,
///
- /// If some other client has or took over exclusive control. (runtime error)
+ /// iCUE-SDK: if some other client has or took over exclusive control (runtime error)
///
- NoControl,
+ NoControl = 2,
///
- /// If developer did not perform protocol handshake. (developer error)
+ /// iCUE-SDK: if developer is calling the function that is not supported by the server (either because protocol has broken by server or client or because the function is new and server is too old. Check CorsairSessionDetails for details) (developer error)
///
- ProtocolHandshakeMissing,
+ IncompatibleProtocol = 3,
///
- /// If developer is calling the function that is not supported by the server (either because protocol has broken by server or client or because the function is new and server is too old.
- /// Check CorsairProtocolDetails for details). (developer error)
+ /// iCUE-SDK: if developer supplied invalid arguments to the function (for specifics look at function descriptions) (developer error)
///
- IncompatibleProtocol,
+ InvalidArguments = 4,
///
- /// If developer supplied invalid arguments to the function (for specifics look at function descriptions). (developer error)
+ /// iCUE-SDK: if developer is calling the function that is not allowed due to current state (reading improper properties from device, or setting callback when it has already been set) (developer error)
///
- InvalidArguments
+ InvalidOperation = 5,
+
+ ///
+ /// iCUE-SDK: if invalid device id has been supplied as an argument to the function (when device id refers to disconnected device) (runtime error)
+ ///
+ DeviceNotFound = 6,
+
+ ///
+ /// iCUE-SDK: if specific functionality (key interception) is disabled in iCUE settings (runtime error)
+ ///
+ NotAllowed = 7
};
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Enum/CorsairLedGroup.cs b/RGB.NET.Devices.Corsair/Enum/CorsairLedGroup.cs
new file mode 100644
index 0000000..58b7079
--- /dev/null
+++ b/RGB.NET.Devices.Corsair/Enum/CorsairLedGroup.cs
@@ -0,0 +1,89 @@
+// ReSharper disable InconsistentNaming
+
+namespace RGB.NET.Devices.Corsair;
+
+///
+/// iCUE-SDK: contains a list of led groups. Led group is used as a part of led identifier
+///
+public enum CorsairLedGroup
+{
+ ///
+ /// iCUE-SDK: for keyboard leds
+ ///
+ Keyboard = 0,
+
+ ///
+ /// iCUE-SDK: for keyboard leds on G keys
+ ///
+ KeyboardGKeys = 1,
+
+ ///
+ /// iCUE-SDK: for keyboard lighting pipe leds
+ ///
+ KeyboardEdge = 2,
+
+ ///
+ /// iCUE-SDK: for vendor specific keyboard leds (ProfileSwitch, DialRing, etc.)
+ ///
+ KeyboardOem = 3,
+
+ ///
+ /// iCUE-SDK: for mouse leds
+ ///
+ Mouse = 4,
+
+ ///
+ /// iCUE-SDK: for mousemat leds
+ ///
+ Mousemat = 5,
+
+ ///
+ /// iCUE-SDK: for headset leds
+ ///
+ Headset = 6,
+
+ ///
+ /// iCUE-SDK: for headset stand leds
+ ///
+ HeadsetStand = 7,
+
+ ///
+ /// iCUE-SDK: for memory module leds
+ ///
+ MemoryModule = 8,
+
+ ///
+ /// iCUE-SDK: for motherboard leds
+ ///
+ Motherboard = 9,
+
+ ///
+ /// iCUE-SDK: for graphics card leds
+ ///
+ GraphicsCard = 10,
+
+ ///
+ /// iCUE-SDK: for leds on the first channel of DIY devices and coolers
+ ///
+ DIY_Channel1 = 11,
+
+ ///
+ /// iCUE-SDK: for leds on the second channel of DIY devices and coolers
+ ///
+ DIY_Channel2 = 12,
+
+ ///
+ /// iCUE-SDK: for leds on the third channel of DIY devices and coolers
+ ///
+ DIY_Channel3 = 13,
+
+ ///
+ /// iCUE-SDK: for touchbar leds
+ ///
+ Touchbar = 14,
+
+ ///
+ /// iCUE-SDK: for game controller leds
+ ///
+ GameController = 15
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Enum/CorsairLedIdKeyboard.cs b/RGB.NET.Devices.Corsair/Enum/CorsairLedIdKeyboard.cs
new file mode 100644
index 0000000..3b5ad52
--- /dev/null
+++ b/RGB.NET.Devices.Corsair/Enum/CorsairLedIdKeyboard.cs
@@ -0,0 +1,142 @@
+// ReSharper disable InconsistentNaming
+// ReSharper disable UnusedMember.Global
+#pragma warning disable 1591
+
+namespace RGB.NET.Devices.Corsair;
+
+///
+/// iCUE-SDK: contains a list of keyboard leds that belong to CLG_Keyboard group
+///
+public enum CorsairLedIdKeyboard
+{
+ Invalid = 0,
+ Escape = 1,
+ F1 = 2,
+ F2 = 3,
+ F3 = 4,
+ F4 = 5,
+ F5 = 6,
+ F6 = 7,
+ F7 = 8,
+ F8 = 9,
+ F9 = 10,
+ F10 = 11,
+ F11 = 12,
+ F12 = 13,
+ GraveAccentAndTilde = 14,
+ One = 15,
+ Two = 16,
+ Three = 17,
+ Four = 18,
+ Five = 19,
+ Six = 20,
+ Seven = 21,
+ Eight = 22,
+ Nine = 23,
+ Zero = 24,
+ MinusAndUnderscore = 25,
+ EqualsAndPlus = 26,
+ Backspace = 27,
+ Tab = 28,
+ Q = 29,
+ W = 30,
+ E = 31,
+ R = 32,
+ T = 33,
+ Y = 34,
+ U = 35,
+ I = 36,
+ O = 37,
+ P = 38,
+ BracketLeft = 39,
+ BracketRight = 40,
+ CapsLock = 41,
+ A = 42,
+ S = 43,
+ D = 44,
+ F = 45,
+ G = 46,
+ H = 47,
+ J = 48,
+ K = 49,
+ L = 50,
+ SemicolonAndColon = 51,
+ ApostropheAndDoubleQuote = 52,
+ Backslash = 53,
+ Enter = 54,
+ LeftShift = 55,
+ NonUsBackslash = 56,
+ Z = 57,
+ X = 58,
+ C = 59,
+ V = 60,
+ B = 61,
+ N = 62,
+ M = 63,
+ CommaAndLessThan = 64,
+ PeriodAndBiggerThan = 65,
+ SlashAndQuestionMark = 66,
+ RightShift = 67,
+ LeftCtrl = 68,
+ LeftGui = 69,
+ LeftAlt = 70,
+ Space = 71,
+ RightAlt = 72,
+ RightGui = 73,
+ Application = 74,
+ RightCtrl = 75,
+ LedProgramming = 76,
+ Lang1 = 77,
+ Lang2 = 78,
+ International1 = 79,
+ International2 = 80,
+ International3 = 81,
+ International4 = 82,
+ International5 = 83,
+ PrintScreen = 84,
+ ScrollLock = 85,
+ PauseBreak = 86,
+ Insert = 87,
+ Home = 88,
+ PageUp = 89,
+ Delete = 90,
+ End = 91,
+ PageDown = 92,
+ UpArrow = 93,
+ LeftArrow = 94,
+ DownArrow = 95,
+ RightArrow = 96,
+ NonUsTilde = 97,
+ Brightness = 98,
+ WinLock = 99,
+ Mute = 100,
+ Stop = 101,
+ ScanPreviousTrack = 102,
+ PlayPause = 103,
+ ScanNextTrack = 104,
+ NumLock = 105,
+ KeypadSlash = 106,
+ KeypadAsterisk = 107,
+ KeypadMinus = 108,
+ Keypad7 = 109,
+ Keypad8 = 110,
+ Keypad9 = 111,
+ KeypadPlus = 112,
+ Keypad4 = 113,
+ Keypad5 = 114,
+ Keypad6 = 115,
+ Keypad1 = 116,
+ Keypad2 = 117,
+ Keypad3 = 118,
+ KeypadComma = 119,
+ KeypadEnter = 120,
+ Keypad0 = 121,
+ KeypadPeriodAndDelete = 122,
+ VolumeUp = 123,
+ VolumeDown = 124,
+ MR = 125,
+ M1 = 126,
+ M2 = 127,
+ M3 = 128,
+ Fn = 129
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Enum/CorsairLogicalKeyboardLayout.cs b/RGB.NET.Devices.Corsair/Enum/CorsairLogicalKeyboardLayout.cs
index ebc4e1b..d5325bb 100644
--- a/RGB.NET.Devices.Corsair/Enum/CorsairLogicalKeyboardLayout.cs
+++ b/RGB.NET.Devices.Corsair/Enum/CorsairLogicalKeyboardLayout.cs
@@ -1,14 +1,14 @@
// ReSharper disable InconsistentNaming
// ReSharper disable UnusedMember.Global
-#pragma warning disable 1591
namespace RGB.NET.Devices.Corsair;
///
-/// Contains a list of available logical layouts for corsair keyboards.
+/// iCUE-SDK: Contains a list of available logical layouts for corsair keyboards.
///
public enum CorsairLogicalKeyboardLayout
{
+ Invalid = 0,
US_Int = 1,
NA = 2,
EU = 3,
diff --git a/RGB.NET.Devices.Corsair/Enum/CorsairPhysicalKeyboardLayout.cs b/RGB.NET.Devices.Corsair/Enum/CorsairPhysicalKeyboardLayout.cs
index 9f5c1c3..f02cd6c 100644
--- a/RGB.NET.Devices.Corsair/Enum/CorsairPhysicalKeyboardLayout.cs
+++ b/RGB.NET.Devices.Corsair/Enum/CorsairPhysicalKeyboardLayout.cs
@@ -4,32 +4,14 @@
namespace RGB.NET.Devices.Corsair;
///
-/// Contains a list of available physical layouts for corsair keyboards.
+/// iCUE-SDK: Contains a list of available physical layouts for corsair keyboards.
///
public enum CorsairPhysicalKeyboardLayout
{
- ///
- /// US-Keyboard
- ///
+ Invalid = 0,
US = 1,
-
- ///
- /// UK-Keyboard
- ///
UK = 2,
-
- ///
- /// BR-Keyboard
- ///
- BR = 3,
-
- ///
- /// JP-Keyboard
- ///
- JP = 4,
-
- ///
- /// KR-Keyboard
- ///
- KR = 5
+ JP = 3,
+ KR = 4,
+ BR = 5
}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Enum/CorsairPropertyFlag.cs b/RGB.NET.Devices.Corsair/Enum/CorsairPropertyFlag.cs
new file mode 100644
index 0000000..f0e4506
--- /dev/null
+++ b/RGB.NET.Devices.Corsair/Enum/CorsairPropertyFlag.cs
@@ -0,0 +1,30 @@
+using System;
+
+namespace RGB.NET.Devices.Corsair;
+
+///
+/// iCUE-SDK: contains list of operations that can be applied to the property
+///
+[Flags]
+public enum CorsairPropertyFlag
+{
+ ///
+ /// -
+ ///
+ None = 0x00,
+
+ ///
+ /// iCUE-SDK: describes readable property
+ ///
+ CanRead = 0x01,
+
+ ///
+ /// iCUE-SDK: describes writable property
+ ///
+ CanWrite = 0x02,
+
+ ///
+ /// iCUE-SDK: if flag is set, then index should be used to read/write multiple properties that share the same property identifier
+ ///
+ Indexed = 0x04
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Enum/CorsairSessionState.cs b/RGB.NET.Devices.Corsair/Enum/CorsairSessionState.cs
new file mode 100644
index 0000000..c78dce1
--- /dev/null
+++ b/RGB.NET.Devices.Corsair/Enum/CorsairSessionState.cs
@@ -0,0 +1,45 @@
+// ReSharper disable InconsistentNaming
+// ReSharper disable UnusedMember.Global
+
+namespace RGB.NET.Devices.Corsair;
+
+///
+/// iCUE-SDK: contains a list of all possible session states
+///
+public enum CorsairSessionState
+{
+ ///
+ /// iCUE-SDK: dummy value
+ ///
+ Invalid = 0,
+
+ ///
+ /// iCUE-SDK: client not initialized or client closed connection (initial state)
+ ///
+ Closed = 1,
+
+ ///
+ /// iCUE-SDK: client initiated connection but not connected yet
+ ///
+ Connecting = 2,
+
+ ///
+ /// iCUE-SDK: server did not respond, sdk will try again
+ ///
+ Timeout = 3,
+
+ ///
+ /// iCUE-SDK: server did not allow connection
+ ///
+ ConnectionRefused = 4,
+
+ ///
+ /// iCUE-SDK: server closed connection
+ ///
+ ConnectionLost = 5,
+
+ ///
+ /// iCUE-SDK: successfully connected
+ ///
+ Connected = 6
+};
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Exceptions/CUEException.cs b/RGB.NET.Devices.Corsair/Exceptions/CUEException.cs
index aca2994..902860f 100644
--- a/RGB.NET.Devices.Corsair/Exceptions/CUEException.cs
+++ b/RGB.NET.Devices.Corsair/Exceptions/CUEException.cs
@@ -9,7 +9,7 @@ namespace RGB.NET.Devices.Corsair;
///
/// Represents an exception thrown by the CUE.
///
-public class CUEException : ApplicationException
+public sealed class CUEException : ApplicationException
{
#region Properties & Fields
diff --git a/RGB.NET.Devices.Corsair/Fan/CorsairFanRGBDevice.cs b/RGB.NET.Devices.Corsair/Fan/CorsairFanRGBDevice.cs
new file mode 100644
index 0000000..eb91492
--- /dev/null
+++ b/RGB.NET.Devices.Corsair/Fan/CorsairFanRGBDevice.cs
@@ -0,0 +1,34 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using RGB.NET.Core;
+using System.Collections.Generic;
+
+namespace RGB.NET.Devices.Corsair;
+
+///
+///
+/// Represents a corsair fan.
+///
+public sealed class CorsairFanRGBDevice : CorsairRGBDevice, IFan
+{
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The specific information provided by CUE for the fan.
+ /// The queue used to update this device.
+ internal CorsairFanRGBDevice(CorsairFanRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
+ : base(info, updateQueue)
+ { }
+
+ #endregion
+
+ #region Methods
+
+ protected override LedMapping CreateMapping(IEnumerable ids) => LedMappings.CreateFanMapping(ids);
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Fan/CorsairFanRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair/Fan/CorsairFanRGBDeviceInfo.cs
new file mode 100644
index 0000000..35124d0
--- /dev/null
+++ b/RGB.NET.Devices.Corsair/Fan/CorsairFanRGBDeviceInfo.cs
@@ -0,0 +1,28 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using RGB.NET.Core;
+using RGB.NET.Devices.Corsair.Native;
+
+namespace RGB.NET.Devices.Corsair;
+
+///
+///
+/// Represents a generic information for a .
+///
+public sealed class CorsairFanRGBDeviceInfo : CorsairRGBDeviceInfo
+{
+ #region Constructors
+
+ ///
+ internal CorsairFanRGBDeviceInfo(_CorsairDeviceInfo nativeInfo, int ledCount, int ledOffset)
+ : base(RGBDeviceType.Fan, nativeInfo, ledCount, ledOffset)
+ { }
+
+ ///
+ internal CorsairFanRGBDeviceInfo(_CorsairDeviceInfo nativeInfo, int ledCount, int ledOffset, string modelName)
+ : base(RGBDeviceType.Fan, nativeInfo, ledCount, ledOffset, modelName)
+ { }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/GameController/CorsairGameControllerRGBDevice.cs b/RGB.NET.Devices.Corsair/GameController/CorsairGameControllerRGBDevice.cs
new file mode 100644
index 0000000..2c4234d
--- /dev/null
+++ b/RGB.NET.Devices.Corsair/GameController/CorsairGameControllerRGBDevice.cs
@@ -0,0 +1,34 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using RGB.NET.Core;
+using System.Collections.Generic;
+
+namespace RGB.NET.Devices.Corsair;
+
+///
+///
+/// Represents a corsair gamecontroller.
+///
+public sealed class CorsairGameControllerRGBDevice : CorsairRGBDevice, IGameController
+{
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The specific information provided by CUE for the gamecontroller
+ /// The queue used to update this device.
+ internal CorsairGameControllerRGBDevice(CorsairGameControllerRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
+ : base(info, updateQueue)
+ { }
+
+ #endregion
+
+ #region Methods
+
+ protected override LedMapping CreateMapping(IEnumerable ids) => LedMappings.CreateGameControllerMapping(ids);
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/GameController/CorsairGameControllerRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair/GameController/CorsairGameControllerRGBDeviceInfo.cs
new file mode 100644
index 0000000..5d968d7
--- /dev/null
+++ b/RGB.NET.Devices.Corsair/GameController/CorsairGameControllerRGBDeviceInfo.cs
@@ -0,0 +1,20 @@
+using RGB.NET.Core;
+using RGB.NET.Devices.Corsair.Native;
+
+namespace RGB.NET.Devices.Corsair;
+
+///
+///
+/// Represents a generic information for a .
+///
+public sealed class CorsairGameControllerRGBDeviceInfo : CorsairRGBDeviceInfo
+{
+ #region Constructors
+
+ ///
+ internal CorsairGameControllerRGBDeviceInfo(_CorsairDeviceInfo nativeInfo, int ledCount, int ledOffset)
+ : base(RGBDeviceType.GameController, nativeInfo, ledCount, ledOffset)
+ { }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Generic/CorsairDeviceUpdateQueue.cs b/RGB.NET.Devices.Corsair/Generic/CorsairDeviceUpdateQueue.cs
index 408e907..be3a3bf 100644
--- a/RGB.NET.Devices.Corsair/Generic/CorsairDeviceUpdateQueue.cs
+++ b/RGB.NET.Devices.Corsair/Generic/CorsairDeviceUpdateQueue.cs
@@ -9,11 +9,14 @@ namespace RGB.NET.Devices.Corsair;
///
/// Represents the update-queue performing updates for corsair devices.
///
-public class CorsairDeviceUpdateQueue : UpdateQueue
+public sealed class CorsairDeviceUpdateQueue : UpdateQueue
{
#region Properties & Fields
- private int _deviceIndex;
+ private bool _isDisposed = false;
+
+ private readonly _CorsairDeviceInfo _device;
+ private readonly nint _colorPtr;
#endregion
@@ -24,10 +27,12 @@ public class CorsairDeviceUpdateQueue : UpdateQueue
///
/// The update trigger used by this queue.
/// The index used to identify the device.
- public CorsairDeviceUpdateQueue(IDeviceUpdateTrigger updateTrigger, int deviceIndex)
+ internal CorsairDeviceUpdateQueue(IDeviceUpdateTrigger updateTrigger, _CorsairDeviceInfo device)
: base(updateTrigger)
{
- this._deviceIndex = deviceIndex;
+ this._device = device;
+
+ _colorPtr = Marshal.AllocHGlobal(Marshal.SizeOf<_CorsairLedColor>() * device.ledCount);
}
#endregion
@@ -35,28 +40,42 @@ public class CorsairDeviceUpdateQueue : UpdateQueue
#region Methods
///
- protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet)
+ protected override unsafe bool Update(in ReadOnlySpan<(object key, Color color)> dataSet)
{
- int structSize = Marshal.SizeOf(typeof(_CorsairLedColor));
- IntPtr ptr = Marshal.AllocHGlobal(structSize * dataSet.Length);
- IntPtr addPtr = new(ptr.ToInt64());
- foreach ((object key, Color color) in dataSet)
+ try
{
- _CorsairLedColor corsairColor = new()
- {
- ledId = (int)key,
- r = color.GetR(),
- g = color.GetG(),
- b = color.GetB()
- };
+ if (_isDisposed) throw new ObjectDisposedException(nameof(CorsairDeviceUpdateQueue));
+ if (!_CUESDK.IsConnected) return false;
- Marshal.StructureToPtr(corsairColor, addPtr, false);
- addPtr = new IntPtr(addPtr.ToInt64() + structSize);
+ Span<_CorsairLedColor> colors = new((void*)_colorPtr, dataSet.Length);
+ for (int i = 0; i < colors.Length; i++)
+ {
+ (object id, Color color) = dataSet[i];
+ (byte a, byte r, byte g, byte b) = color.GetRGBBytes();
+ colors[i] = new _CorsairLedColor((CorsairLedId)id, r, g, b, a);
+ }
+
+ CorsairError error = _CUESDK.CorsairSetLedColors(_device.id!, dataSet.Length, _colorPtr);
+ if (error != CorsairError.Success)
+ throw new RGBDeviceException($"Failed to update device '{_device.id}'. (ErrorCode: {error})");
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ CorsairDeviceProvider.Instance.Throw(ex);
}
- _CUESDK.CorsairSetLedsColorsBufferByDeviceIndex(_deviceIndex, dataSet.Length, ptr);
- _CUESDK.CorsairSetLedsColorsFlushBuffer();
- Marshal.FreeHGlobal(ptr);
+ return false;
+ }
+
+ ///
+ public override void Dispose()
+ {
+ base.Dispose();
+
+ _isDisposed = true;
+ Marshal.FreeHGlobal(_colorPtr);
}
#endregion
diff --git a/RGB.NET.Devices.Corsair/Generic/CorsairLedId.cs b/RGB.NET.Devices.Corsair/Generic/CorsairLedId.cs
new file mode 100644
index 0000000..e8c5c5b
--- /dev/null
+++ b/RGB.NET.Devices.Corsair/Generic/CorsairLedId.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace RGB.NET.Devices.Corsair;
+
+[StructLayout(LayoutKind.Sequential)]
+public readonly struct CorsairLedId : IComparable, IEquatable
+{
+ #region Properties & Fields
+
+ public readonly uint Id;
+
+ public CorsairLedGroup Group => (CorsairLedGroup)(Id >> 16);
+ public uint Index => Id & 0x0000FFFF;
+
+ #endregion
+
+ #region Constructors
+
+ public CorsairLedId(uint id)
+ {
+ this.Id = id;
+ }
+
+ public CorsairLedId(CorsairLedGroup group, CorsairLedIdKeyboard id)
+ : this(group, (int)id)
+ { }
+
+ public CorsairLedId(CorsairLedGroup group, int index)
+ {
+ Id = (((uint)group) << 16) | (uint)index;
+ }
+
+ #endregion
+
+ #region Methods
+
+ public int CompareTo(CorsairLedId other) => Id.CompareTo(other.Id);
+
+ public bool Equals(CorsairLedId other) => Id == other.Id;
+
+ public override bool Equals(object? obj) => obj is CorsairLedId other && Equals(other);
+
+ public override int GetHashCode() => Id.GetHashCode();
+
+ public static bool operator ==(CorsairLedId left, CorsairLedId right) => left.Id == right.Id;
+ public static bool operator !=(CorsairLedId left, CorsairLedId right) => !(left == right);
+ public static bool operator <(CorsairLedId left, CorsairLedId right) => left.Id < right.Id;
+ public static bool operator <=(CorsairLedId left, CorsairLedId right) => left.Id <= right.Id;
+ public static bool operator >(CorsairLedId left, CorsairLedId right) => left.Id > right.Id;
+ public static bool operator >=(CorsairLedId left, CorsairLedId right) => left.Id >= right.Id;
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Generic/CorsairProtocolDetails.cs b/RGB.NET.Devices.Corsair/Generic/CorsairProtocolDetails.cs
index e764e08..afca46b 100644
--- a/RGB.NET.Devices.Corsair/Generic/CorsairProtocolDetails.cs
+++ b/RGB.NET.Devices.Corsair/Generic/CorsairProtocolDetails.cs
@@ -1,64 +1,36 @@
// ReSharper disable MemberCanBePrivate.Global
-// ReSharper disable UnusedAutoPropertyAccessor.Global
-using System;
-using System.Runtime.InteropServices;
using RGB.NET.Devices.Corsair.Native;
namespace RGB.NET.Devices.Corsair;
///
-/// Managed wrapper for CorsairProtocolDetails.
+/// Represents version information for the Corsair-SDK
///
-public class CorsairProtocolDetails
+public sealed class CorsairSessionDetails
{
#region Properties & Fields
- ///
- /// String containing version of SDK(like "1.0.0.1").
- /// Always contains valid value even if there was no CUE found.
- ///
- public string? SdkVersion { get; }
-
- ///
- /// String containing version of CUE(like "1.0.0.1") or NULL if CUE was not found.
- ///
- public string? ServerVersion { get; }
-
- ///
- /// Integer that specifies version of protocol that is implemented by current SDK.
- /// Numbering starts from 1.
- /// Always contains valid value even if there was no CUE found.
- ///
- public int SdkProtocolVersion { get; }
-
- ///
- /// Integer that specifies version of protocol that is implemented by CUE.
- /// Numbering starts from 1.
- /// If CUE was not found then this value will be 0.
- ///
- public int ServerProtocolVersion { get; }
-
- ///
- /// Boolean that specifies if there were breaking changes between version of protocol implemented by server and client.
- ///
- public bool BreakingChanges { get; }
+ public string ClientVersion { get; }
+ public string ServerVersion { get; }
+ public string ServerHostVersion { get; }
#endregion
#region Constructors
- ///
- /// Internal constructor of managed CorsairProtocolDetails.
- ///
- /// The native CorsairProtocolDetails-struct
- internal CorsairProtocolDetails(_CorsairProtocolDetails nativeDetails)
+ internal CorsairSessionDetails()
{
- this.SdkVersion = nativeDetails.sdkVersion == IntPtr.Zero ? null : Marshal.PtrToStringAnsi(nativeDetails.sdkVersion);
- this.ServerVersion = nativeDetails.serverVersion == IntPtr.Zero ? null : Marshal.PtrToStringAnsi(nativeDetails.serverVersion);
- this.SdkProtocolVersion = nativeDetails.sdkProtocolVersion;
- this.ServerProtocolVersion = nativeDetails.serverProtocolVersion;
- this.BreakingChanges = nativeDetails.breakingChanges != 0;
+ ClientVersion = string.Empty;
+ ServerVersion = string.Empty;
+ ServerHostVersion = string.Empty;
+ }
+
+ internal CorsairSessionDetails(_CorsairSessionDetails nativeDetails)
+ {
+ this.ClientVersion = nativeDetails.clientVersion.ToString();
+ this.ServerVersion = nativeDetails.serverVersion.ToString();
+ this.ServerHostVersion = nativeDetails.serverHostVersion.ToString();
}
#endregion
diff --git a/RGB.NET.Devices.Corsair/Generic/CorsairRGBDevice.cs b/RGB.NET.Devices.Corsair/Generic/CorsairRGBDevice.cs
index 57912a5..9fcbca6 100644
--- a/RGB.NET.Devices.Corsair/Generic/CorsairRGBDevice.cs
+++ b/RGB.NET.Devices.Corsair/Generic/CorsairRGBDevice.cs
@@ -1,5 +1,5 @@
-using System;
-using System.Runtime.InteropServices;
+using System.Collections.Generic;
+using System.Linq;
using RGB.NET.Core;
using RGB.NET.Devices.Corsair.Native;
@@ -17,7 +17,7 @@ public abstract class CorsairRGBDevice : AbstractRGBDevice
/// Gets the mapping of to used to update the LEDs of this device.
///
- protected LedMapping Mapping { get; }
+ protected LedMapping Mapping { get; private set; } = LedMapping.Empty;
#endregion
@@ -29,48 +29,56 @@ public abstract class CorsairRGBDevice : AbstractRGBDeviceThe generic information provided by CUE for the device.
/// The mapping to used to update the LEDs of this device.
/// The queue used to update this device.
- protected CorsairRGBDevice(TDeviceInfo info, LedMapping mapping, CorsairDeviceUpdateQueue updateQueue)
+ protected CorsairRGBDevice(TDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
: base(info, updateQueue)
- {
- this.Mapping = mapping;
- }
+ { }
#endregion
#region Methods
void ICorsairRGBDevice.Initialize() => InitializeLayout();
-
+
///
/// Initializes the LEDs of the device based on the data provided by the SDK.
///
protected virtual void InitializeLayout()
{
- _CorsairLedPositions? nativeLedPositions = (_CorsairLedPositions?)Marshal.PtrToStructure(_CUESDK.CorsairGetLedPositionsByDeviceIndex(DeviceInfo.CorsairDeviceIndex), typeof(_CorsairLedPositions));
- if (nativeLedPositions == null) return;
+ CorsairError error = _CUESDK.CorsairGetLedPositions(DeviceInfo.DeviceId, out _CorsairLedPosition[] ledPositions);
+ if (error != CorsairError.Success)
+ throw new RGBDeviceException($"Failed to load device '{DeviceInfo.DeviceId}'. (ErrorCode: {error})");
- int structSize = Marshal.SizeOf(typeof(_CorsairLedPosition));
- IntPtr ptr = nativeLedPositions.pLedPosition;
+ List<_CorsairLedPosition> deviceLeds = ledPositions.Skip(DeviceInfo.LedOffset).Take(DeviceInfo.LedCount).ToList();
- for (int i = 0; i < nativeLedPositions.numberOfLed; i++)
+ Mapping = CreateMapping(deviceLeds.Select(x => new CorsairLedId(x.id)));
+
+ foreach (_CorsairLedPosition ledPosition in deviceLeds)
{
- _CorsairLedPosition? ledPosition = (_CorsairLedPosition?)Marshal.PtrToStructure(ptr, typeof(_CorsairLedPosition));
- if (ledPosition == null)
- {
- ptr = new IntPtr(ptr.ToInt64() + structSize);
- continue;
- }
-
- LedId ledId = Mapping.TryGetValue(ledPosition.LedId, out LedId id) ? id : LedId.Invalid;
+ LedId ledId = Mapping.TryGetValue(new CorsairLedId(ledPosition.id), out LedId id) ? id : LedId.Invalid;
Rectangle rectangle = ledPosition.ToRectangle();
AddLed(ledId, rectangle.Location, rectangle.Size);
-
- ptr = new IntPtr(ptr.ToInt64() + structSize);
}
+
+ if (DeviceInfo.LedOffset > 0)
+ FixOffsetDeviceLayout();
}
+ ///
+ /// Fixes the locations for devices split by offset by aligning them to the top left.
+ ///
+ protected virtual void FixOffsetDeviceLayout()
+ {
+ float minX = this.Min(x => x.Location.X);
+ float minY = this.Min(x => x.Location.Y);
+
+ foreach (Led led in this)
+ led.Location = led.Location.Translate(-minX, -minY);
+ }
+
+ protected abstract LedMapping CreateMapping(IEnumerable ids);
+
///
- protected override object GetLedCustomData(LedId ledId) => Mapping.TryGetValue(ledId, out CorsairLedId corsairLedId) ? corsairLedId : CorsairLedId.Invalid;
+ protected override object GetLedCustomData(LedId ledId) => Mapping.TryGetValue(ledId, out CorsairLedId corsairLedId) ? corsairLedId : new CorsairLedId(0);
#endregion
}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Generic/CorsairRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair/Generic/CorsairRGBDeviceInfo.cs
index 27c882d..6137b95 100644
--- a/RGB.NET.Devices.Corsair/Generic/CorsairRGBDeviceInfo.cs
+++ b/RGB.NET.Devices.Corsair/Generic/CorsairRGBDeviceInfo.cs
@@ -1,6 +1,4 @@
-using System;
-using System.Runtime.InteropServices;
-using System.Text.RegularExpressions;
+using System.Text.RegularExpressions;
using RGB.NET.Core;
using RGB.NET.Devices.Corsair.Native;
@@ -19,11 +17,6 @@ public class CorsairRGBDeviceInfo : IRGBDeviceInfo
///
public CorsairDeviceType CorsairDeviceType { get; }
- ///
- /// Gets the index of the .
- ///
- public int CorsairDeviceIndex { get; }
-
///
public RGBDeviceType DeviceType { get; }
@@ -44,11 +37,16 @@ public class CorsairRGBDeviceInfo : IRGBDeviceInfo
///
public object? LayoutMetadata { get; set; }
+
+ ///
+ /// Gets the amount of LEDs this device contains.
+ ///
+ public int LedCount { get; }
///
- /// Gets a flag that describes device capabilities. ()
+ /// Gets the offset used to access the LEDs of this device.
///
- public CorsairDeviceCaps CapsMask { get; }
+ internal int LedOffset { get; }
#endregion
@@ -60,14 +58,14 @@ public class CorsairRGBDeviceInfo : IRGBDeviceInfo
/// The index of the .
/// The type of the .
/// The native -struct
- internal CorsairRGBDeviceInfo(int deviceIndex, RGBDeviceType deviceType, _CorsairDeviceInfo nativeInfo)
+ internal CorsairRGBDeviceInfo(RGBDeviceType deviceType, _CorsairDeviceInfo nativeInfo, int ledCount, int ledOffset)
{
- this.CorsairDeviceIndex = deviceIndex;
this.DeviceType = deviceType;
this.CorsairDeviceType = nativeInfo.type;
- this.Model = nativeInfo.model == IntPtr.Zero ? string.Empty : Regex.Replace(Marshal.PtrToStringAnsi(nativeInfo.model) ?? string.Empty, " ?DEMO", string.Empty, RegexOptions.IgnoreCase);
- this.DeviceId = nativeInfo.deviceId ?? string.Empty;
- this.CapsMask = (CorsairDeviceCaps)nativeInfo.capsMask;
+ this.Model = nativeInfo.model == null ? string.Empty : Regex.Replace(nativeInfo.model ?? string.Empty, " ?DEMO", string.Empty, RegexOptions.IgnoreCase);
+ this.DeviceId = nativeInfo.id ?? string.Empty;
+ this.LedCount = ledCount;
+ this.LedOffset = ledOffset;
DeviceName = DeviceHelper.CreateDeviceName(Manufacturer, Model);
}
@@ -79,14 +77,14 @@ public class CorsairRGBDeviceInfo : IRGBDeviceInfo
/// The type of the .
/// The native -struct
/// The name of the device-model (overwrites the one provided with the device info).
- internal CorsairRGBDeviceInfo(int deviceIndex, RGBDeviceType deviceType, _CorsairDeviceInfo nativeInfo, string modelName)
+ internal CorsairRGBDeviceInfo(RGBDeviceType deviceType, _CorsairDeviceInfo nativeInfo, int ledCount, int ledOffset, string modelName)
{
- this.CorsairDeviceIndex = deviceIndex;
this.DeviceType = deviceType;
this.CorsairDeviceType = nativeInfo.type;
this.Model = modelName;
- this.DeviceId = nativeInfo.deviceId ?? string.Empty;
- this.CapsMask = (CorsairDeviceCaps)nativeInfo.capsMask;
+ this.DeviceId = nativeInfo.id ?? string.Empty;
+ this.LedCount = ledCount;
+ this.LedOffset = ledOffset;
DeviceName = DeviceHelper.CreateDeviceName(Manufacturer, Model);
}
diff --git a/RGB.NET.Devices.Corsair/Generic/LedMappings.cs b/RGB.NET.Devices.Corsair/Generic/LedMappings.cs
index 911e58f..58e9937 100644
--- a/RGB.NET.Devices.Corsair/Generic/LedMappings.cs
+++ b/RGB.NET.Devices.Corsair/Generic/LedMappings.cs
@@ -1,302 +1,212 @@
-using RGB.NET.Core;
+using System.Collections.Generic;
+using System.Linq;
+using RGB.NET.Core;
namespace RGB.NET.Devices.Corsair;
///
/// Contains mappings for to .
///
-public static class LedMappings
+internal static class LedMappings
{
- static LedMappings()
+ #region Constants
+
+ // ReSharper disable once InconsistentNaming
+ private static LedMapping KEYBOARD_MAPPING => new()
{
- for (int i = 0; i <= (CorsairLedId.GPU50 - CorsairLedId.GPU1); i++)
- GraphicsCard.Add(LedId.GraphicsCard1 + i, CorsairLedId.GPU1 + i);
+ { LedId.Invalid, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Invalid) },
+ { LedId.Keyboard_Escape, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Escape) },
+ { LedId.Keyboard_F1, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.F1) },
+ { LedId.Keyboard_F2, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.F2) },
+ { LedId.Keyboard_F3, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.F3) },
+ { LedId.Keyboard_F4, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.F4) },
+ { LedId.Keyboard_F5, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.F5) },
+ { LedId.Keyboard_F6, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.F6) },
+ { LedId.Keyboard_F7, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.F7) },
+ { LedId.Keyboard_F8, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.F8) },
+ { LedId.Keyboard_F9, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.F9) },
+ { LedId.Keyboard_F10, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.F10) },
+ { LedId.Keyboard_F11, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.F11) },
+ { LedId.Keyboard_GraveAccentAndTilde, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.GraveAccentAndTilde) },
+ { LedId.Keyboard_1, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.One) },
+ { LedId.Keyboard_2, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Two) },
+ { LedId.Keyboard_3, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Three) },
+ { LedId.Keyboard_4, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Four) },
+ { LedId.Keyboard_5, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Five) },
+ { LedId.Keyboard_6, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Six) },
+ { LedId.Keyboard_7, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Seven) },
+ { LedId.Keyboard_8, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Eight) },
+ { LedId.Keyboard_9, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Nine) },
+ { LedId.Keyboard_0, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Zero) },
+ { LedId.Keyboard_MinusAndUnderscore, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.MinusAndUnderscore) },
+ { LedId.Keyboard_Tab, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Tab) },
+ { LedId.Keyboard_Q, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Q) },
+ { LedId.Keyboard_W, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.W) },
+ { LedId.Keyboard_E, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.E) },
+ { LedId.Keyboard_R, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.R) },
+ { LedId.Keyboard_T, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.T) },
+ { LedId.Keyboard_Y, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Y) },
+ { LedId.Keyboard_U, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.U) },
+ { LedId.Keyboard_I, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.I) },
+ { LedId.Keyboard_O, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.O) },
+ { LedId.Keyboard_P, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.P) },
+ { LedId.Keyboard_BracketLeft, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.BracketLeft) },
+ { LedId.Keyboard_CapsLock, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.CapsLock) },
+ { LedId.Keyboard_A, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.A) },
+ { LedId.Keyboard_S, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.S) },
+ { LedId.Keyboard_D, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.D) },
+ { LedId.Keyboard_F, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.F) },
+ { LedId.Keyboard_G, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.G) },
+ { LedId.Keyboard_H, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.H) },
+ { LedId.Keyboard_J, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.J) },
+ { LedId.Keyboard_K, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.K) },
+ { LedId.Keyboard_L, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.L) },
+ { LedId.Keyboard_SemicolonAndColon, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.SemicolonAndColon) },
+ { LedId.Keyboard_ApostropheAndDoubleQuote, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.ApostropheAndDoubleQuote) },
+ { LedId.Keyboard_LeftShift, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.LeftShift) },
+ { LedId.Keyboard_NonUsBackslash, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.NonUsBackslash) },
+ { LedId.Keyboard_Z, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Z) },
+ { LedId.Keyboard_X, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.X) },
+ { LedId.Keyboard_C, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.C) },
+ { LedId.Keyboard_V, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.V) },
+ { LedId.Keyboard_B, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.B) },
+ { LedId.Keyboard_N, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.N) },
+ { LedId.Keyboard_M, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.M) },
+ { LedId.Keyboard_CommaAndLessThan, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.CommaAndLessThan) },
+ { LedId.Keyboard_PeriodAndBiggerThan, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.PeriodAndBiggerThan) },
+ { LedId.Keyboard_SlashAndQuestionMark, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.SlashAndQuestionMark) },
+ { LedId.Keyboard_LeftCtrl, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.LeftCtrl) },
+ { LedId.Keyboard_LeftGui, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.LeftGui) },
+ { LedId.Keyboard_LeftAlt, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.LeftAlt) },
+ { LedId.Keyboard_Lang2, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Lang2) },
+ { LedId.Keyboard_Space, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Space) },
+ { LedId.Keyboard_Lang1, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Lang1) },
+ { LedId.Keyboard_International2, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.International2) },
+ { LedId.Keyboard_RightAlt, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.RightAlt) },
+ { LedId.Keyboard_RightGui, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.RightGui) },
+ { LedId.Keyboard_Application, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Application) },
+ { LedId.Keyboard_Brightness, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Brightness) },
+ { LedId.Keyboard_F12, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.F12) },
+ { LedId.Keyboard_PrintScreen, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.PrintScreen) },
+ { LedId.Keyboard_ScrollLock, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.ScrollLock) },
+ { LedId.Keyboard_PauseBreak, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.PauseBreak) },
+ { LedId.Keyboard_Insert, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Insert) },
+ { LedId.Keyboard_Home, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Home) },
+ { LedId.Keyboard_PageUp, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.PageUp) },
+ { LedId.Keyboard_BracketRight, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.BracketRight) },
+ { LedId.Keyboard_Backslash, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Backslash) },
+ { LedId.Keyboard_NonUsTilde, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.NonUsTilde) },
+ { LedId.Keyboard_Enter, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Enter) },
+ { LedId.Keyboard_International1, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.International1) },
+ { LedId.Keyboard_EqualsAndPlus, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.EqualsAndPlus) },
+ { LedId.Keyboard_International3, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.International3) },
+ { LedId.Keyboard_Backspace, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Backspace) },
+ { LedId.Keyboard_Delete, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Delete) },
+ { LedId.Keyboard_End, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.End) },
+ { LedId.Keyboard_PageDown, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.PageDown) },
+ { LedId.Keyboard_RightShift, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.RightShift) },
+ { LedId.Keyboard_RightCtrl, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.RightCtrl) },
+ { LedId.Keyboard_ArrowUp, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.UpArrow) },
+ { LedId.Keyboard_ArrowLeft, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.LeftArrow) },
+ { LedId.Keyboard_ArrowDown, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.DownArrow) },
+ { LedId.Keyboard_ArrowRight, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.RightArrow) },
+ { LedId.Keyboard_WinLock, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.WinLock) },
+ { LedId.Keyboard_MediaMute, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Mute) },
+ { LedId.Keyboard_MediaStop, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Stop) },
+ { LedId.Keyboard_MediaPreviousTrack, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.ScanPreviousTrack) },
+ { LedId.Keyboard_MediaPlay, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.PlayPause) },
+ { LedId.Keyboard_MediaNextTrack, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.ScanNextTrack) },
+ { LedId.Keyboard_NumLock, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.NumLock) },
+ { LedId.Keyboard_NumSlash, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.KeypadSlash) },
+ { LedId.Keyboard_NumAsterisk, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.KeypadAsterisk) },
+ { LedId.Keyboard_NumMinus, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.KeypadMinus) },
+ { LedId.Keyboard_NumPlus, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.KeypadPlus) },
+ { LedId.Keyboard_NumEnter, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.KeypadEnter) },
+ { LedId.Keyboard_Num7, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Keypad7) },
+ { LedId.Keyboard_Num8, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Keypad8) },
+ { LedId.Keyboard_Num9, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Keypad9) },
+ { LedId.Keyboard_NumComma, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.KeypadComma) },
+ { LedId.Keyboard_Num4, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Keypad4) },
+ { LedId.Keyboard_Num5, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Keypad5) },
+ { LedId.Keyboard_Num6, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Keypad6) },
+ { LedId.Keyboard_Num1, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Keypad1) },
+ { LedId.Keyboard_Num2, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Keypad2) },
+ { LedId.Keyboard_Num3, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Keypad3) },
+ { LedId.Keyboard_Num0, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Keypad0) },
+ { LedId.Keyboard_NumPeriodAndDelete, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.KeypadPeriodAndDelete) },
+ { LedId.Keyboard_MediaVolumeUp, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.VolumeUp) },
+ { LedId.Keyboard_MediaVolumeDown, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.VolumeDown) },
+ { LedId.Keyboard_MacroRecording, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.MR) },
+ { LedId.Keyboard_Macro1, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.M1) },
+ { LedId.Keyboard_Macro2, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.M2) },
+ { LedId.Keyboard_Macro3, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.M3) },
+ { LedId.Keyboard_International5, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.International5) },
+ { LedId.Keyboard_International4, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.International4) },
+ { LedId.Keyboard_LedProgramming, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.LedProgramming) },
+ { LedId.Keyboard_Function, new CorsairLedId(CorsairLedGroup.Keyboard, CorsairLedIdKeyboard.Fn) }
+ };
- for (int i = 0; i <= (CorsairLedId.HeadsetStandZone9 - CorsairLedId.HeadsetStandZone1); i++)
- HeadsetStand.Add(LedId.HeadsetStand1 + i, CorsairLedId.HeadsetStandZone1 + i);
+ #endregion
- for (int i = 0; i <= (CorsairLedId.Mainboard100 - CorsairLedId.Mainboard1); i++)
- Mainboard.Add(LedId.Mainboard1 + i, CorsairLedId.Mainboard1 + i);
+ #region Methods
- for (int i = 0; i <= (CorsairLedId.DRAM12 - CorsairLedId.DRAM1); i++)
- Memory.Add(LedId.DRAM1 + i, CorsairLedId.DRAM1 + i);
+ internal static LedMapping CreateFanMapping(IEnumerable ids) => CreateMapping(ids, LedId.Fan1);
+ internal static LedMapping CreateCoolerMapping(IEnumerable ids) => CreateMapping(ids, LedId.Cooler1);
+ internal static LedMapping CreateLedStripMapping(IEnumerable ids) => CreateMapping(ids, LedId.LedStripe1);
+ internal static LedMapping CreateGraphicsCardMapping(IEnumerable ids) => CreateMapping(ids, LedId.GraphicsCard1);
+ internal static LedMapping CreateHeadsetStandMapping(IEnumerable ids) => CreateMapping(ids, LedId.HeadsetStand1);
+ internal static LedMapping CreateMainboardMapping(IEnumerable ids) => CreateMapping(ids, LedId.Mainboard1);
+ internal static LedMapping CreateMemoryMapping(IEnumerable ids) => CreateMapping(ids, LedId.DRAM1);
+ internal static LedMapping CreateMousepadMapping(IEnumerable ids) => CreateMapping(ids, LedId.Mousepad1);
+ internal static LedMapping CreateHeadsetMapping(IEnumerable ids) => CreateMapping(ids, LedId.Headset1);
+ internal static LedMapping CreateMouseMapping(IEnumerable ids) => CreateMapping(ids, LedId.Mouse1);
+ internal static LedMapping CreateGameControllerMapping(IEnumerable ids) => CreateMapping(ids, LedId.GameController1);
+ internal static LedMapping CreateUnknownMapping(IEnumerable ids) => CreateMapping(ids, LedId.Unknown1);
- for (int i = 0; i <= (CorsairLedId.Zone15 - CorsairLedId.Zone1); i++)
- Mousepad.Add(LedId.Mousepad1 + i, CorsairLedId.Zone1 + i);
+ internal static LedMapping CreateMapping(IEnumerable ids, LedId referenceId)
+ {
+ LedMapping mapping = [];
+ int counter = 0;
+ foreach (CorsairLedId corsairLedId in ids.OrderBy(x => x))
+ mapping.Add(referenceId + counter++, corsairLedId);
- for (int i = 0; i <= (CorsairLedId.OemLed100 - CorsairLedId.OemLed1); i++)
- Keyboard.Add(LedId.Custom1 + i, CorsairLedId.OemLed1 + i);
-
- for (int i = 0; i <= (CorsairLedId.OemLed250 - CorsairLedId.OemLed101); i++)
- Keyboard.Add(LedId.Custom101 + i, CorsairLedId.OemLed101 + i);
+ return mapping;
}
- ///
- /// Gets the mapping for graphics cards.
- ///
- public static LedMapping GraphicsCard { get; } = new();
-
- ///
- /// Gets the mapping for headsets.
- ///
- public static LedMapping HeadsetStand { get; } = new();
-
- ///
- /// Gets the mapping for mainboards.
- ///
- public static LedMapping Mainboard { get; } = new();
-
- ///
- /// Gets the mapping for memory.
- ///
- public static LedMapping Memory { get; } = new();
-
- ///
- /// Gets the mapping for mousepads.
- ///
- public static LedMapping Mousepad { get; } = new();
-
- ///
- /// Gets the mapping for headsets.
- ///
- public static LedMapping Headset { get; } = new()
+ internal static LedMapping CreateKeyboardMapping(IEnumerable ids)
{
- { LedId.Headset1, CorsairLedId.LeftLogo },
- { LedId.Headset2, CorsairLedId.RightLogo },
- };
+ Dictionary groupCounter = new()
+ {
+ [CorsairLedGroup.KeyboardOem] = 0,
+ [CorsairLedGroup.KeyboardGKeys] = 0,
+ [CorsairLedGroup.KeyboardEdge] = 0,
+ [CorsairLedGroup.Keyboard] = 0 // Workaround for unknown keys
+ };
- ///
- /// Gets the mapping for mice.
- ///
- public static LedMapping Mouse { get; } = new()
- {
- { LedId.Mouse1, CorsairLedId.B1 },
- { LedId.Mouse2, CorsairLedId.B2 },
- { LedId.Mouse3, CorsairLedId.B3 },
- { LedId.Mouse4, CorsairLedId.B4 },
- { LedId.Mouse5, CorsairLedId.B5 },
- { LedId.Mouse6, CorsairLedId.B6 },
- { LedId.Mouse7, CorsairLedId.B7 },
- { LedId.Mouse8, CorsairLedId.B8 },
- { LedId.Mouse9, CorsairLedId.B9 },
- { LedId.Mouse10, CorsairLedId.B10 },
- { LedId.Mouse11, CorsairLedId.B11 },
- { LedId.Mouse12, CorsairLedId.B12 },
- { LedId.Mouse13, CorsairLedId.B13 },
- { LedId.Mouse14, CorsairLedId.B14 },
- { LedId.Mouse15, CorsairLedId.B15 },
- { LedId.Mouse16, CorsairLedId.B16 },
- { LedId.Mouse17, CorsairLedId.B17 },
- { LedId.Mouse18, CorsairLedId.B18 },
- { LedId.Mouse19, CorsairLedId.B19 },
- { LedId.Mouse20, CorsairLedId.B20 },
- };
+ LedMapping mapping = KEYBOARD_MAPPING;
- ///
- /// Gets the mapping for keyboards.
- ///
- public static LedMapping Keyboard { get; } = new()
- {
- { LedId.Invalid, CorsairLedId.Invalid },
- { LedId.Logo, CorsairLedId.Logo },
- { LedId.Keyboard_Escape, CorsairLedId.Escape },
- { LedId.Keyboard_F1, CorsairLedId.F1 },
- { LedId.Keyboard_F2, CorsairLedId.F2 },
- { LedId.Keyboard_F3, CorsairLedId.F3 },
- { LedId.Keyboard_F4, CorsairLedId.F4 },
- { LedId.Keyboard_F5, CorsairLedId.F5 },
- { LedId.Keyboard_F6, CorsairLedId.F6 },
- { LedId.Keyboard_F7, CorsairLedId.F7 },
- { LedId.Keyboard_F8, CorsairLedId.F8 },
- { LedId.Keyboard_F9, CorsairLedId.F9 },
- { LedId.Keyboard_F10, CorsairLedId.F10 },
- { LedId.Keyboard_F11, CorsairLedId.F11 },
- { LedId.Keyboard_GraveAccentAndTilde, CorsairLedId.GraveAccentAndTilde },
- { LedId.Keyboard_1, CorsairLedId.D1 },
- { LedId.Keyboard_2, CorsairLedId.D2 },
- { LedId.Keyboard_3, CorsairLedId.D3 },
- { LedId.Keyboard_4, CorsairLedId.D4 },
- { LedId.Keyboard_5, CorsairLedId.D5 },
- { LedId.Keyboard_6, CorsairLedId.D6 },
- { LedId.Keyboard_7, CorsairLedId.D7 },
- { LedId.Keyboard_8, CorsairLedId.D8 },
- { LedId.Keyboard_9, CorsairLedId.D9 },
- { LedId.Keyboard_0, CorsairLedId.D0 },
- { LedId.Keyboard_MinusAndUnderscore, CorsairLedId.MinusAndUnderscore },
- { LedId.Keyboard_Tab, CorsairLedId.Tab },
- { LedId.Keyboard_Q, CorsairLedId.Q },
- { LedId.Keyboard_W, CorsairLedId.W },
- { LedId.Keyboard_E, CorsairLedId.E },
- { LedId.Keyboard_R, CorsairLedId.R },
- { LedId.Keyboard_T, CorsairLedId.T },
- { LedId.Keyboard_Y, CorsairLedId.Y },
- { LedId.Keyboard_U, CorsairLedId.U },
- { LedId.Keyboard_I, CorsairLedId.I },
- { LedId.Keyboard_O, CorsairLedId.O },
- { LedId.Keyboard_P, CorsairLedId.P },
- { LedId.Keyboard_BracketLeft, CorsairLedId.BracketLeft },
- { LedId.Keyboard_CapsLock, CorsairLedId.CapsLock },
- { LedId.Keyboard_A, CorsairLedId.A },
- { LedId.Keyboard_S, CorsairLedId.S },
- { LedId.Keyboard_D, CorsairLedId.D },
- { LedId.Keyboard_F, CorsairLedId.F },
- { LedId.Keyboard_G, CorsairLedId.G },
- { LedId.Keyboard_H, CorsairLedId.H },
- { LedId.Keyboard_J, CorsairLedId.J },
- { LedId.Keyboard_K, CorsairLedId.K },
- { LedId.Keyboard_L, CorsairLedId.L },
- { LedId.Keyboard_SemicolonAndColon, CorsairLedId.SemicolonAndColon },
- { LedId.Keyboard_ApostropheAndDoubleQuote, CorsairLedId.ApostropheAndDoubleQuote },
- { LedId.Keyboard_LeftShift, CorsairLedId.LeftShift },
- { LedId.Keyboard_NonUsBackslash, CorsairLedId.NonUsBackslash },
- { LedId.Keyboard_Z, CorsairLedId.Z },
- { LedId.Keyboard_X, CorsairLedId.X },
- { LedId.Keyboard_C, CorsairLedId.C },
- { LedId.Keyboard_V, CorsairLedId.V },
- { LedId.Keyboard_B, CorsairLedId.B },
- { LedId.Keyboard_N, CorsairLedId.N },
- { LedId.Keyboard_M, CorsairLedId.M },
- { LedId.Keyboard_CommaAndLessThan, CorsairLedId.CommaAndLessThan },
- { LedId.Keyboard_PeriodAndBiggerThan, CorsairLedId.PeriodAndBiggerThan },
- { LedId.Keyboard_SlashAndQuestionMark, CorsairLedId.SlashAndQuestionMark },
- { LedId.Keyboard_LeftCtrl, CorsairLedId.LeftCtrl },
- { LedId.Keyboard_LeftGui, CorsairLedId.LeftGui },
- { LedId.Keyboard_LeftAlt, CorsairLedId.LeftAlt },
- { LedId.Keyboard_Lang2, CorsairLedId.Lang2 },
- { LedId.Keyboard_Space, CorsairLedId.Space },
- { LedId.Keyboard_Lang1, CorsairLedId.Lang1 },
- { LedId.Keyboard_International2, CorsairLedId.International2 },
- { LedId.Keyboard_RightAlt, CorsairLedId.RightAlt },
- { LedId.Keyboard_RightGui, CorsairLedId.RightGui },
- { LedId.Keyboard_Application, CorsairLedId.Application },
- { LedId.Keyboard_Brightness, CorsairLedId.Brightness },
- { LedId.Keyboard_F12, CorsairLedId.F12 },
- { LedId.Keyboard_PrintScreen, CorsairLedId.PrintScreen },
- { LedId.Keyboard_ScrollLock, CorsairLedId.ScrollLock },
- { LedId.Keyboard_PauseBreak, CorsairLedId.PauseBreak },
- { LedId.Keyboard_Insert, CorsairLedId.Insert },
- { LedId.Keyboard_Home, CorsairLedId.Home },
- { LedId.Keyboard_PageUp, CorsairLedId.PageUp },
- { LedId.Keyboard_BracketRight, CorsairLedId.BracketRight },
- { LedId.Keyboard_Backslash, CorsairLedId.Backslash },
- { LedId.Keyboard_NonUsTilde, CorsairLedId.NonUsTilde },
- { LedId.Keyboard_Enter, CorsairLedId.Enter },
- { LedId.Keyboard_International1, CorsairLedId.International1 },
- { LedId.Keyboard_EqualsAndPlus, CorsairLedId.EqualsAndPlus },
- { LedId.Keyboard_International3, CorsairLedId.International3 },
- { LedId.Keyboard_Backspace, CorsairLedId.Backspace },
- { LedId.Keyboard_Delete, CorsairLedId.Delete },
- { LedId.Keyboard_End, CorsairLedId.End },
- { LedId.Keyboard_PageDown, CorsairLedId.PageDown },
- { LedId.Keyboard_RightShift, CorsairLedId.RightShift },
- { LedId.Keyboard_RightCtrl, CorsairLedId.RightCtrl },
- { LedId.Keyboard_ArrowUp, CorsairLedId.UpArrow },
- { LedId.Keyboard_ArrowLeft, CorsairLedId.LeftArrow },
- { LedId.Keyboard_ArrowDown, CorsairLedId.DownArrow },
- { LedId.Keyboard_ArrowRight, CorsairLedId.RightArrow },
- { LedId.Keyboard_WinLock, CorsairLedId.WinLock },
- { LedId.Keyboard_MediaMute, CorsairLedId.Mute },
- { LedId.Keyboard_MediaStop, CorsairLedId.Stop },
- { LedId.Keyboard_MediaPreviousTrack, CorsairLedId.ScanPreviousTrack },
- { LedId.Keyboard_MediaPlay, CorsairLedId.PlayPause },
- { LedId.Keyboard_MediaNextTrack, CorsairLedId.ScanNextTrack },
- { LedId.Keyboard_NumLock, CorsairLedId.NumLock },
- { LedId.Keyboard_NumSlash, CorsairLedId.KeypadSlash },
- { LedId.Keyboard_NumAsterisk, CorsairLedId.KeypadAsterisk },
- { LedId.Keyboard_NumMinus, CorsairLedId.KeypadMinus },
- { LedId.Keyboard_NumPlus, CorsairLedId.KeypadPlus },
- { LedId.Keyboard_NumEnter, CorsairLedId.KeypadEnter },
- { LedId.Keyboard_Num7, CorsairLedId.Keypad7 },
- { LedId.Keyboard_Num8, CorsairLedId.Keypad8 },
- { LedId.Keyboard_Num9, CorsairLedId.Keypad9 },
- { LedId.Keyboard_NumComma, CorsairLedId.KeypadComma },
- { LedId.Keyboard_Num4, CorsairLedId.Keypad4 },
- { LedId.Keyboard_Num5, CorsairLedId.Keypad5 },
- { LedId.Keyboard_Num6, CorsairLedId.Keypad6 },
- { LedId.Keyboard_Num1, CorsairLedId.Keypad1 },
- { LedId.Keyboard_Num2, CorsairLedId.Keypad2 },
- { LedId.Keyboard_Num3, CorsairLedId.Keypad3 },
- { LedId.Keyboard_Num0, CorsairLedId.Keypad0 },
- { LedId.Keyboard_NumPeriodAndDelete, CorsairLedId.KeypadPeriodAndDelete },
- { LedId.Keyboard_Programmable1, CorsairLedId.G1 },
- { LedId.Keyboard_Programmable2, CorsairLedId.G2 },
- { LedId.Keyboard_Programmable3, CorsairLedId.G3 },
- { LedId.Keyboard_Programmable4, CorsairLedId.G4 },
- { LedId.Keyboard_Programmable5, CorsairLedId.G5 },
- { LedId.Keyboard_Programmable6, CorsairLedId.G6 },
- { LedId.Keyboard_Programmable7, CorsairLedId.G7 },
- { LedId.Keyboard_Programmable8, CorsairLedId.G8 },
- { LedId.Keyboard_Programmable9, CorsairLedId.G9 },
- { LedId.Keyboard_Programmable10, CorsairLedId.G10 },
- { LedId.Keyboard_MediaVolumeUp, CorsairLedId.VolumeUp },
- { LedId.Keyboard_MediaVolumeDown, CorsairLedId.VolumeDown },
- { LedId.Keyboard_MacroRecording, CorsairLedId.MR },
- { LedId.Keyboard_Macro1, CorsairLedId.M1 },
- { LedId.Keyboard_Macro2, CorsairLedId.M2 },
- { LedId.Keyboard_Macro3, CorsairLedId.M3 },
- { LedId.Keyboard_Programmable11, CorsairLedId.G11 },
- { LedId.Keyboard_Programmable12, CorsairLedId.G12 },
- { LedId.Keyboard_Programmable13, CorsairLedId.G13 },
- { LedId.Keyboard_Programmable14, CorsairLedId.G14 },
- { LedId.Keyboard_Programmable15, CorsairLedId.G15 },
- { LedId.Keyboard_Programmable16, CorsairLedId.G16 },
- { LedId.Keyboard_Programmable17, CorsairLedId.G17 },
- { LedId.Keyboard_Programmable18, CorsairLedId.G18 },
- { LedId.Keyboard_International5, CorsairLedId.International5 },
- { LedId.Keyboard_International4, CorsairLedId.International4 },
- { LedId.Keyboard_Profile, CorsairLedId.Profile },
- { LedId.Keyboard_LedProgramming, CorsairLedId.LedProgramming },
- { LedId.Keyboard_Function, CorsairLedId.Fn },
+ foreach (CorsairLedId corsairLedId in ids.OrderBy(x => x).Where(x => x.Group != CorsairLedGroup.Keyboard))
+ switch (corsairLedId.Group)
+ {
+ case CorsairLedGroup.KeyboardOem:
+ mapping.Add(LedId.Keyboard_Custom1 + groupCounter[CorsairLedGroup.KeyboardOem]++, corsairLedId);
+ break;
- { LedId.LedStripe1, CorsairLedId.Lightbar1 },
- { LedId.LedStripe2, CorsairLedId.Lightbar2 },
- { LedId.LedStripe3, CorsairLedId.Lightbar3 },
- { LedId.LedStripe4, CorsairLedId.Lightbar4 },
- { LedId.LedStripe5, CorsairLedId.Lightbar5 },
- { LedId.LedStripe6, CorsairLedId.Lightbar6 },
- { LedId.LedStripe7, CorsairLedId.Lightbar7 },
- { LedId.LedStripe8, CorsairLedId.Lightbar8 },
- { LedId.LedStripe9, CorsairLedId.Lightbar9 },
- { LedId.LedStripe10, CorsairLedId.Lightbar10 },
- { LedId.LedStripe11, CorsairLedId.Lightbar11 },
- { LedId.LedStripe12, CorsairLedId.Lightbar12 },
- { LedId.LedStripe13, CorsairLedId.Lightbar13 },
- { LedId.LedStripe14, CorsairLedId.Lightbar14 },
- { LedId.LedStripe15, CorsairLedId.Lightbar15 },
- { LedId.LedStripe16, CorsairLedId.Lightbar16 },
- { LedId.LedStripe17, CorsairLedId.Lightbar17 },
- { LedId.LedStripe18, CorsairLedId.Lightbar18 },
- { LedId.LedStripe19, CorsairLedId.Lightbar19 },
- { LedId.LedStripe20, CorsairLedId.Lightbar20 },
- { LedId.LedStripe21, CorsairLedId.Lightbar21 },
- { LedId.LedStripe22, CorsairLedId.Lightbar22 },
- { LedId.LedStripe23, CorsairLedId.Lightbar23 },
- { LedId.LedStripe24, CorsairLedId.Lightbar24 },
- { LedId.LedStripe25, CorsairLedId.Lightbar25 },
- { LedId.LedStripe26, CorsairLedId.Lightbar26 },
- { LedId.LedStripe27, CorsairLedId.Lightbar27 },
- { LedId.LedStripe28, CorsairLedId.Lightbar28 },
- { LedId.LedStripe29, CorsairLedId.Lightbar29 },
- { LedId.LedStripe30, CorsairLedId.Lightbar30 },
- { LedId.LedStripe31, CorsairLedId.Lightbar31 },
- { LedId.LedStripe32, CorsairLedId.Lightbar32 },
- { LedId.LedStripe33, CorsairLedId.Lightbar33 },
- { LedId.LedStripe34, CorsairLedId.Lightbar34 },
- { LedId.LedStripe35, CorsairLedId.Lightbar35 },
- { LedId.LedStripe36, CorsairLedId.Lightbar36 },
- { LedId.LedStripe37, CorsairLedId.Lightbar37 },
- { LedId.LedStripe38, CorsairLedId.Lightbar38 },
- { LedId.LedStripe39, CorsairLedId.Lightbar39 },
- { LedId.LedStripe40, CorsairLedId.Lightbar40 },
- { LedId.LedStripe41, CorsairLedId.Lightbar41 },
- { LedId.LedStripe42, CorsairLedId.Lightbar42 },
- { LedId.LedStripe43, CorsairLedId.Lightbar43 },
- { LedId.LedStripe44, CorsairLedId.Lightbar44 },
- { LedId.LedStripe45, CorsairLedId.Lightbar45 },
- { LedId.LedStripe46, CorsairLedId.Lightbar46 },
- { LedId.LedStripe47, CorsairLedId.Lightbar47 },
- { LedId.LedStripe48, CorsairLedId.Lightbar48 },
- { LedId.LedStripe49, CorsairLedId.Lightbar49 },
- { LedId.LedStripe50, CorsairLedId.Lightbar50 },
- };
+ case CorsairLedGroup.KeyboardGKeys:
+ mapping.Add(LedId.Keyboard_Programmable1 + groupCounter[CorsairLedGroup.KeyboardGKeys]++, corsairLedId);
+ break;
+
+ case CorsairLedGroup.KeyboardEdge:
+ mapping.Add(LedId.LedStripe1 + groupCounter[CorsairLedGroup.KeyboardEdge]++, corsairLedId);
+ break;
+
+ default:
+ mapping.Add(LedId.Unknown1 + groupCounter[CorsairLedGroup.Keyboard]++, corsairLedId);
+ break;
+ }
+
+ return mapping;
+ }
+
+ #endregion
}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/GraphicsCard/CorsairGraphicsCardRGBDevice.cs b/RGB.NET.Devices.Corsair/GraphicsCard/CorsairGraphicsCardRGBDevice.cs
index b1238c1..51aa88a 100644
--- a/RGB.NET.Devices.Corsair/GraphicsCard/CorsairGraphicsCardRGBDevice.cs
+++ b/RGB.NET.Devices.Corsair/GraphicsCard/CorsairGraphicsCardRGBDevice.cs
@@ -1,6 +1,7 @@
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable UnusedMember.Global
+using System.Collections.Generic;
using RGB.NET.Core;
namespace RGB.NET.Devices.Corsair;
@@ -9,7 +10,7 @@ namespace RGB.NET.Devices.Corsair;
///
/// Represents a corsair graphics card.
///
-public class CorsairGraphicsCardRGBDevice : CorsairRGBDevice, IGraphicsCard
+public sealed class CorsairGraphicsCardRGBDevice : CorsairRGBDevice, IGraphicsCard
{
#region Constructors
@@ -20,8 +21,14 @@ public class CorsairGraphicsCardRGBDevice : CorsairRGBDeviceThe specific information provided by CUE for the graphics card.
/// The queue used to update this device.
internal CorsairGraphicsCardRGBDevice(CorsairGraphicsCardRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
- : base(info, LedMappings.GraphicsCard, updateQueue)
+ : base(info, updateQueue)
{ }
#endregion
+
+ #region Methods
+
+ protected override LedMapping CreateMapping(IEnumerable ids) => LedMappings.CreateGraphicsCardMapping(ids);
+
+ #endregion
}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/GraphicsCard/CorsairGraphicsCardRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair/GraphicsCard/CorsairGraphicsCardRGBDeviceInfo.cs
index d58120c..7c57ff0 100644
--- a/RGB.NET.Devices.Corsair/GraphicsCard/CorsairGraphicsCardRGBDeviceInfo.cs
+++ b/RGB.NET.Devices.Corsair/GraphicsCard/CorsairGraphicsCardRGBDeviceInfo.cs
@@ -10,18 +10,13 @@ namespace RGB.NET.Devices.Corsair;
///
/// Represents a generic information for a .
///
-public class CorsairGraphicsCardRGBDeviceInfo : CorsairRGBDeviceInfo
+public sealed class CorsairGraphicsCardRGBDeviceInfo : CorsairRGBDeviceInfo
{
#region Constructors
///
- ///
- /// Internal constructor of managed .
- ///
- /// The index of the .
- /// The native -struct
- internal CorsairGraphicsCardRGBDeviceInfo(int deviceIndex, _CorsairDeviceInfo nativeInfo)
- : base(deviceIndex, RGBDeviceType.GraphicsCard, nativeInfo)
+ internal CorsairGraphicsCardRGBDeviceInfo(_CorsairDeviceInfo nativeInfo, int ledCount, int ledOffset)
+ : base(RGBDeviceType.GraphicsCard, nativeInfo, ledCount, ledOffset)
{ }
#endregion
diff --git a/RGB.NET.Devices.Corsair/Headset/CorsairHeadsetRGBDevice.cs b/RGB.NET.Devices.Corsair/Headset/CorsairHeadsetRGBDevice.cs
index f52d548..1cbd113 100644
--- a/RGB.NET.Devices.Corsair/Headset/CorsairHeadsetRGBDevice.cs
+++ b/RGB.NET.Devices.Corsair/Headset/CorsairHeadsetRGBDevice.cs
@@ -2,6 +2,7 @@
// ReSharper disable UnusedMember.Global
using RGB.NET.Core;
+using System.Collections.Generic;
namespace RGB.NET.Devices.Corsair;
@@ -9,7 +10,7 @@ namespace RGB.NET.Devices.Corsair;
///
/// Represents a corsair headset.
///
-public class CorsairHeadsetRGBDevice : CorsairRGBDevice, IHeadset
+public sealed class CorsairHeadsetRGBDevice : CorsairRGBDevice, IHeadset
{
#region Constructors
@@ -20,8 +21,14 @@ public class CorsairHeadsetRGBDevice : CorsairRGBDeviceThe specific information provided by CUE for the headset
/// The queue used to update this device.
internal CorsairHeadsetRGBDevice(CorsairHeadsetRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
- : base(info, LedMappings.Headset, updateQueue)
+ : base(info, updateQueue)
{ }
#endregion
+
+ #region Methods
+
+ protected override LedMapping CreateMapping(IEnumerable ids) => LedMappings.CreateHeadsetMapping(ids);
+
+ #endregion
}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Headset/CorsairHeadsetRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair/Headset/CorsairHeadsetRGBDeviceInfo.cs
index fb3e696..c7de7f9 100644
--- a/RGB.NET.Devices.Corsair/Headset/CorsairHeadsetRGBDeviceInfo.cs
+++ b/RGB.NET.Devices.Corsair/Headset/CorsairHeadsetRGBDeviceInfo.cs
@@ -7,18 +7,13 @@ namespace RGB.NET.Devices.Corsair;
///
/// Represents a generic information for a .
///
-public class CorsairHeadsetRGBDeviceInfo : CorsairRGBDeviceInfo
+public sealed class CorsairHeadsetRGBDeviceInfo : CorsairRGBDeviceInfo
{
#region Constructors
///
- ///
- /// Internal constructor of managed .
- ///
- /// The index of the .
- /// The native -struct
- internal CorsairHeadsetRGBDeviceInfo(int deviceIndex, _CorsairDeviceInfo nativeInfo)
- : base(deviceIndex, RGBDeviceType.Headset, nativeInfo)
+ internal CorsairHeadsetRGBDeviceInfo(_CorsairDeviceInfo nativeInfo, int ledCount, int ledOffset)
+ : base(RGBDeviceType.Headset, nativeInfo, ledCount, ledOffset)
{ }
#endregion
diff --git a/RGB.NET.Devices.Corsair/HeadsetStand/CorsairHeadsetStandRGBDevice.cs b/RGB.NET.Devices.Corsair/HeadsetStand/CorsairHeadsetStandRGBDevice.cs
index def410d..5d79725 100644
--- a/RGB.NET.Devices.Corsair/HeadsetStand/CorsairHeadsetStandRGBDevice.cs
+++ b/RGB.NET.Devices.Corsair/HeadsetStand/CorsairHeadsetStandRGBDevice.cs
@@ -2,6 +2,7 @@
// ReSharper disable UnusedMember.Global
using RGB.NET.Core;
+using System.Collections.Generic;
namespace RGB.NET.Devices.Corsair;
@@ -9,7 +10,7 @@ namespace RGB.NET.Devices.Corsair;
///
/// Represents a corsair headset stand.
///
-public class CorsairHeadsetStandRGBDevice : CorsairRGBDevice, IHeadsetStand
+public sealed class CorsairHeadsetStandRGBDevice : CorsairRGBDevice, IHeadsetStand
{
#region Constructors
@@ -20,8 +21,14 @@ public class CorsairHeadsetStandRGBDevice : CorsairRGBDeviceThe specific information provided by CUE for the headset stand
/// The queue used to update this device.
internal CorsairHeadsetStandRGBDevice(CorsairHeadsetStandRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
- : base(info, LedMappings.HeadsetStand, updateQueue)
+ : base(info, updateQueue)
{ }
#endregion
+
+ #region Methods
+
+ protected override LedMapping CreateMapping(IEnumerable ids) => LedMappings.CreateHeadsetStandMapping(ids);
+
+ #endregion
}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/HeadsetStand/CorsairHeadsetStandRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair/HeadsetStand/CorsairHeadsetStandRGBDeviceInfo.cs
index b880a6c..48b2049 100644
--- a/RGB.NET.Devices.Corsair/HeadsetStand/CorsairHeadsetStandRGBDeviceInfo.cs
+++ b/RGB.NET.Devices.Corsair/HeadsetStand/CorsairHeadsetStandRGBDeviceInfo.cs
@@ -7,18 +7,13 @@ namespace RGB.NET.Devices.Corsair;
///
/// Represents a generic information for a .
///
-public class CorsairHeadsetStandRGBDeviceInfo : CorsairRGBDeviceInfo
+public sealed class CorsairHeadsetStandRGBDeviceInfo : CorsairRGBDeviceInfo
{
#region Constructors
///
- ///
- /// Internal constructor of managed .
- ///
- /// The index of the .
- /// The native -struct
- internal CorsairHeadsetStandRGBDeviceInfo(int deviceIndex, _CorsairDeviceInfo nativeInfo)
- : base(deviceIndex, RGBDeviceType.HeadsetStand, nativeInfo)
+ internal CorsairHeadsetStandRGBDeviceInfo(_CorsairDeviceInfo nativeInfo, int ledCount, int ledOffset)
+ : base(RGBDeviceType.HeadsetStand, nativeInfo, ledCount, ledOffset)
{ }
#endregion
diff --git a/RGB.NET.Devices.Corsair/Helper/NativeExtensions.cs b/RGB.NET.Devices.Corsair/Helper/NativeExtensions.cs
index b78851b..e60424e 100644
--- a/RGB.NET.Devices.Corsair/Helper/NativeExtensions.cs
+++ b/RGB.NET.Devices.Corsair/Helper/NativeExtensions.cs
@@ -1,5 +1,6 @@
using RGB.NET.Core;
using RGB.NET.Devices.Corsair.Native;
+using System.Runtime.InteropServices;
namespace RGB.NET.Devices.Corsair;
@@ -7,12 +8,25 @@ internal static class NativeExtensions
{
internal static Rectangle ToRectangle(this _CorsairLedPosition position)
{
- //HACK DarthAffe 08.07.2018: It seems like corsair introduced a bug here - it's always 0.
- float width = position.width < 0.5f ? 10 : (float)position.width;
- float height = position.height < 0.5f ? 10 : (float)position.height;
- float posX = (float)position.left;
- float posY = (float)position.top;
+ const float WIDTH = 10;
+ const float HEIGHT = 10;
+ float posX = (float)position.cx;
+ float posY = (float)position.cy;
- return new Rectangle(posX, posY, width, height);
+ return new Rectangle(posX, posY, WIDTH, HEIGHT);
+ }
+
+ internal static T[] ToArray(this nint ptr, int size)
+ {
+ int tSize = Marshal.SizeOf();
+ T[] array = new T[size];
+ nint loopPtr = ptr;
+ for (int i = 0; i < size; i++)
+ {
+ array[i] = Marshal.PtrToStructure(loopPtr)!;
+ loopPtr += tSize;
+ }
+
+ return array;
}
}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Keyboard/CorsairKeyboardRGBDevice.cs b/RGB.NET.Devices.Corsair/Keyboard/CorsairKeyboardRGBDevice.cs
index bdc9425..5133619 100644
--- a/RGB.NET.Devices.Corsair/Keyboard/CorsairKeyboardRGBDevice.cs
+++ b/RGB.NET.Devices.Corsair/Keyboard/CorsairKeyboardRGBDevice.cs
@@ -2,6 +2,7 @@
// ReSharper disable UnusedMember.Global
using RGB.NET.Core;
+using System.Collections.Generic;
namespace RGB.NET.Devices.Corsair;
@@ -9,7 +10,7 @@ namespace RGB.NET.Devices.Corsair;
///
/// Represents a corsair keyboard.
///
-public class CorsairKeyboardRGBDevice : CorsairRGBDevice, IKeyboard
+public sealed class CorsairKeyboardRGBDevice : CorsairRGBDevice, IKeyboard
{
#region Properties & Fields
@@ -26,8 +27,14 @@ public class CorsairKeyboardRGBDevice : CorsairRGBDeviceThe specific information provided by CUE for the keyboard.
/// The queue used to update this device.
internal CorsairKeyboardRGBDevice(CorsairKeyboardRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
- : base(info, LedMappings.Keyboard, updateQueue)
+ : base(info, updateQueue)
{ }
#endregion
+
+ #region Methods
+
+ protected override LedMapping CreateMapping(IEnumerable ids) => LedMappings.CreateKeyboardMapping(ids);
+
+ #endregion
}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Keyboard/CorsairKeyboardRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair/Keyboard/CorsairKeyboardRGBDeviceInfo.cs
index efa40a8..8f5774c 100644
--- a/RGB.NET.Devices.Corsair/Keyboard/CorsairKeyboardRGBDeviceInfo.cs
+++ b/RGB.NET.Devices.Corsair/Keyboard/CorsairKeyboardRGBDeviceInfo.cs
@@ -9,7 +9,7 @@ namespace RGB.NET.Devices.Corsair;
///
/// Represents a generic information for a .
///
-public class CorsairKeyboardRGBDeviceInfo : CorsairRGBDeviceInfo, IKeyboardDeviceInfo
+public sealed class CorsairKeyboardRGBDeviceInfo : CorsairRGBDeviceInfo, IKeyboardDeviceInfo
{
#region Properties & Fields
@@ -36,11 +36,12 @@ public class CorsairKeyboardRGBDeviceInfo : CorsairRGBDeviceInfo, IKeyboardDevic
///
/// The index of the .
/// The native -struct
- internal CorsairKeyboardRGBDeviceInfo(int deviceIndex, _CorsairDeviceInfo nativeInfo)
- : base(deviceIndex, RGBDeviceType.Keyboard, nativeInfo)
+ internal CorsairKeyboardRGBDeviceInfo(_CorsairDeviceInfo nativeInfo, int ledCount, int ledOffset)
+ : base(RGBDeviceType.Keyboard, nativeInfo, ledCount, ledOffset)
{
- this.PhysicalLayout = (CorsairPhysicalKeyboardLayout)nativeInfo.physicalLayout;
- this.LogicalLayout = (CorsairLogicalKeyboardLayout)nativeInfo.logicalLayout;
+ PhysicalLayout = (CorsairPhysicalKeyboardLayout)_CUESDK.ReadDevicePropertySimpleInt32(nativeInfo.id!, CorsairDevicePropertyId.PhysicalLayout);
+ LogicalLayout = (CorsairLogicalKeyboardLayout)_CUESDK.ReadDevicePropertySimpleInt32(nativeInfo.id!, CorsairDevicePropertyId.LogicalLayout);
+
this.Layout = PhysicalLayout switch
{
CorsairPhysicalKeyboardLayout.US => KeyboardLayoutType.ANSI,
diff --git a/RGB.NET.Devices.Corsair/LedStrip/CorsairLedStripGBDevice.cs b/RGB.NET.Devices.Corsair/LedStrip/CorsairLedStripGBDevice.cs
new file mode 100644
index 0000000..9f46411
--- /dev/null
+++ b/RGB.NET.Devices.Corsair/LedStrip/CorsairLedStripGBDevice.cs
@@ -0,0 +1,34 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using RGB.NET.Core;
+using System.Collections.Generic;
+
+namespace RGB.NET.Devices.Corsair;
+
+///
+///
+/// Represents a corsair ledStrip.
+///
+public sealed class CorsairLedStripRGBDevice : CorsairRGBDevice, ILedStripe
+{
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The specific information provided by CUE for the ledStrip.
+ /// The queue used to update this device.
+ internal CorsairLedStripRGBDevice(CorsairLedStripRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
+ : base(info, updateQueue)
+ { }
+
+ #endregion
+
+ #region Methods
+
+ protected override LedMapping CreateMapping(IEnumerable ids) => LedMappings.CreateLedStripMapping(ids);
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/LedStrip/CorsairLedStripRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair/LedStrip/CorsairLedStripRGBDeviceInfo.cs
new file mode 100644
index 0000000..a6497ac
--- /dev/null
+++ b/RGB.NET.Devices.Corsair/LedStrip/CorsairLedStripRGBDeviceInfo.cs
@@ -0,0 +1,28 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using RGB.NET.Core;
+using RGB.NET.Devices.Corsair.Native;
+
+namespace RGB.NET.Devices.Corsair;
+
+///
+///
+/// Represents a generic information for a .
+///
+public sealed class CorsairLedStripRGBDeviceInfo : CorsairRGBDeviceInfo
+{
+ #region Constructors
+
+ ///
+ internal CorsairLedStripRGBDeviceInfo(_CorsairDeviceInfo nativeInfo, int ledCount, int ledOffset)
+ : base(RGBDeviceType.LedStripe, nativeInfo, ledCount, ledOffset)
+ { }
+
+ ///
+ internal CorsairLedStripRGBDeviceInfo(_CorsairDeviceInfo nativeInfo, int ledCount, int ledOffset, string modelName)
+ : base(RGBDeviceType.LedStripe, nativeInfo, ledCount, ledOffset, modelName)
+ { }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Mainboard/CorsairMainboardRGBDevice.cs b/RGB.NET.Devices.Corsair/Mainboard/CorsairMainboardRGBDevice.cs
index fc23e18..98c02e1 100644
--- a/RGB.NET.Devices.Corsair/Mainboard/CorsairMainboardRGBDevice.cs
+++ b/RGB.NET.Devices.Corsair/Mainboard/CorsairMainboardRGBDevice.cs
@@ -2,6 +2,7 @@
// ReSharper disable UnusedMember.Global
using RGB.NET.Core;
+using System.Collections.Generic;
namespace RGB.NET.Devices.Corsair;
@@ -9,7 +10,7 @@ namespace RGB.NET.Devices.Corsair;
///
/// Represents a corsair memory.
///
-public class CorsairMainboardRGBDevice : CorsairRGBDevice, IMainboard
+public sealed class CorsairMainboardRGBDevice : CorsairRGBDevice, IMainboard
{
#region Constructors
@@ -20,8 +21,14 @@ public class CorsairMainboardRGBDevice : CorsairRGBDeviceThe specific information provided by CUE for the memory.
/// The queue used to update this device.
internal CorsairMainboardRGBDevice(CorsairMainboardRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
- : base(info, LedMappings.Mainboard, updateQueue)
+ : base(info, updateQueue)
{ }
#endregion
+
+ #region Methods
+
+ protected override LedMapping CreateMapping(IEnumerable ids) => LedMappings.CreateMainboardMapping(ids);
+
+ #endregion
}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Mainboard/CorsairMainboardRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair/Mainboard/CorsairMainboardRGBDeviceInfo.cs
index 94d836c..761f951 100644
--- a/RGB.NET.Devices.Corsair/Mainboard/CorsairMainboardRGBDeviceInfo.cs
+++ b/RGB.NET.Devices.Corsair/Mainboard/CorsairMainboardRGBDeviceInfo.cs
@@ -10,18 +10,13 @@ namespace RGB.NET.Devices.Corsair;
///
/// Represents a generic information for a .
///
-public class CorsairMainboardRGBDeviceInfo : CorsairRGBDeviceInfo
+public sealed class CorsairMainboardRGBDeviceInfo : CorsairRGBDeviceInfo
{
#region Constructors
///
- ///
- /// Internal constructor of managed .
- ///
- /// The index of the .
- /// The native -struct
- internal CorsairMainboardRGBDeviceInfo(int deviceIndex, _CorsairDeviceInfo nativeInfo)
- : base(deviceIndex, RGBDeviceType.Mainboard, nativeInfo)
+ internal CorsairMainboardRGBDeviceInfo(_CorsairDeviceInfo nativeInfo, int ledCount, int ledOffset)
+ : base(RGBDeviceType.Mainboard, nativeInfo, ledCount, ledOffset)
{ }
#endregion
diff --git a/RGB.NET.Devices.Corsair/Memory/CorsairMemoryRGBDevice.cs b/RGB.NET.Devices.Corsair/Memory/CorsairMemoryRGBDevice.cs
index f44d7ee..ec35a34 100644
--- a/RGB.NET.Devices.Corsair/Memory/CorsairMemoryRGBDevice.cs
+++ b/RGB.NET.Devices.Corsair/Memory/CorsairMemoryRGBDevice.cs
@@ -2,6 +2,7 @@
// ReSharper disable UnusedMember.Global
using RGB.NET.Core;
+using System.Collections.Generic;
namespace RGB.NET.Devices.Corsair;
@@ -9,7 +10,7 @@ namespace RGB.NET.Devices.Corsair;
///
/// Represents a corsair memory.
///
-public class CorsairMemoryRGBDevice : CorsairRGBDevice, IDRAM
+public sealed class CorsairMemoryRGBDevice : CorsairRGBDevice, IDRAM
{
#region Constructors
@@ -20,8 +21,14 @@ public class CorsairMemoryRGBDevice : CorsairRGBDeviceThe specific information provided by CUE for the memory.
/// The queue used to update this device.
internal CorsairMemoryRGBDevice(CorsairMemoryRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
- : base(info, LedMappings.Memory, updateQueue)
+ : base(info, updateQueue)
{ }
#endregion
+
+ #region Methods
+
+ protected override LedMapping CreateMapping(IEnumerable ids) => LedMappings.CreateMemoryMapping(ids);
+
+ #endregion
}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Memory/CorsairMemoryRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair/Memory/CorsairMemoryRGBDeviceInfo.cs
index afd8843..326bd80 100644
--- a/RGB.NET.Devices.Corsair/Memory/CorsairMemoryRGBDeviceInfo.cs
+++ b/RGB.NET.Devices.Corsair/Memory/CorsairMemoryRGBDeviceInfo.cs
@@ -10,18 +10,18 @@ namespace RGB.NET.Devices.Corsair;
///
/// Represents a generic information for a .
///
-public class CorsairMemoryRGBDeviceInfo : CorsairRGBDeviceInfo
+public sealed class CorsairMemoryRGBDeviceInfo : CorsairRGBDeviceInfo
{
#region Constructors
///
- ///
- /// Internal constructor of managed .
- ///
- /// The index of the .
- /// The native -struct
- internal CorsairMemoryRGBDeviceInfo(int deviceIndex, _CorsairDeviceInfo nativeInfo)
- : base(deviceIndex, RGBDeviceType.DRAM, nativeInfo)
+ internal CorsairMemoryRGBDeviceInfo(_CorsairDeviceInfo nativeInfo, int ledCount, int ledOffset)
+ : base(RGBDeviceType.DRAM, nativeInfo, ledCount, ledOffset)
+ { }
+
+ ///
+ internal CorsairMemoryRGBDeviceInfo(_CorsairDeviceInfo nativeInfo, int ledCount, int ledOffset, string modelName)
+ : base(RGBDeviceType.DRAM, nativeInfo, ledCount, ledOffset, modelName)
{ }
#endregion
diff --git a/RGB.NET.Devices.Corsair/Mouse/CorsairMouseRGBDevice.cs b/RGB.NET.Devices.Corsair/Mouse/CorsairMouseRGBDevice.cs
index 5c81249..4f66d31 100644
--- a/RGB.NET.Devices.Corsair/Mouse/CorsairMouseRGBDevice.cs
+++ b/RGB.NET.Devices.Corsair/Mouse/CorsairMouseRGBDevice.cs
@@ -2,6 +2,7 @@
// ReSharper disable UnusedMember.Global
using RGB.NET.Core;
+using System.Collections.Generic;
namespace RGB.NET.Devices.Corsair;
@@ -9,7 +10,7 @@ namespace RGB.NET.Devices.Corsair;
///
/// Represents a corsair mouse.
///
-public class CorsairMouseRGBDevice : CorsairRGBDevice, IMouse
+public sealed class CorsairMouseRGBDevice : CorsairRGBDevice, IMouse
{
#region Constructors
@@ -20,8 +21,14 @@ public class CorsairMouseRGBDevice : CorsairRGBDevice
/// The specific information provided by CUE for the mouse
/// The queue used to update this device.
internal CorsairMouseRGBDevice(CorsairMouseRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
- : base(info, LedMappings.Mouse, updateQueue)
+ : base(info, updateQueue)
{ }
#endregion
+
+ #region Methods
+
+ protected override LedMapping CreateMapping(IEnumerable ids) => LedMappings.CreateMouseMapping(ids);
+
+ #endregion
}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Mouse/CorsairMouseRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair/Mouse/CorsairMouseRGBDeviceInfo.cs
index a501466..b5ab17d 100644
--- a/RGB.NET.Devices.Corsair/Mouse/CorsairMouseRGBDeviceInfo.cs
+++ b/RGB.NET.Devices.Corsair/Mouse/CorsairMouseRGBDeviceInfo.cs
@@ -7,30 +7,14 @@ namespace RGB.NET.Devices.Corsair;
///
/// Represents a generic information for a .
///
-public class CorsairMouseRGBDeviceInfo : CorsairRGBDeviceInfo
+public sealed class CorsairMouseRGBDeviceInfo : CorsairRGBDeviceInfo
{
- #region Properties & Fields
-
- ///
- /// Gets the physical layout of the mouse.
- ///
- public CorsairPhysicalMouseLayout PhysicalLayout { get; }
-
- #endregion
-
#region Constructors
///
- ///
- /// Internal constructor of managed .
- ///
- /// The index of the .
- /// The native -struct
- internal CorsairMouseRGBDeviceInfo(int deviceIndex, _CorsairDeviceInfo nativeInfo)
- : base(deviceIndex, RGBDeviceType.Mouse, nativeInfo)
- {
- this.PhysicalLayout = (CorsairPhysicalMouseLayout)nativeInfo.physicalLayout;
- }
+ internal CorsairMouseRGBDeviceInfo(_CorsairDeviceInfo nativeInfo, int ledCount, int ledOffset)
+ : base(RGBDeviceType.Mouse, nativeInfo, ledCount, ledOffset)
+ { }
#endregion
}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Mousepad/CorsairMousepadRGBDevice.cs b/RGB.NET.Devices.Corsair/Mousepad/CorsairMousepadRGBDevice.cs
index 65c0f00..7c005ea 100644
--- a/RGB.NET.Devices.Corsair/Mousepad/CorsairMousepadRGBDevice.cs
+++ b/RGB.NET.Devices.Corsair/Mousepad/CorsairMousepadRGBDevice.cs
@@ -2,6 +2,7 @@
// ReSharper disable UnusedMember.Global
using RGB.NET.Core;
+using System.Collections.Generic;
namespace RGB.NET.Devices.Corsair;
@@ -9,7 +10,7 @@ namespace RGB.NET.Devices.Corsair;
///
/// Represents a corsair mousepad.
///
-public class CorsairMousepadRGBDevice : CorsairRGBDevice, IMousepad
+public sealed class CorsairMousepadRGBDevice : CorsairRGBDevice, IMousepad
{
#region Constructors
@@ -20,8 +21,14 @@ public class CorsairMousepadRGBDevice : CorsairRGBDeviceThe specific information provided by CUE for the mousepad
/// The queue used to update this device.
internal CorsairMousepadRGBDevice(CorsairMousepadRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
- : base(info, LedMappings.Mousepad, updateQueue)
+ : base(info, updateQueue)
{ }
#endregion
+
+ #region Methods
+
+ protected override LedMapping CreateMapping(IEnumerable ids) => LedMappings.CreateMousepadMapping(ids);
+
+ #endregion
}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Mousepad/CorsairMousepadRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair/Mousepad/CorsairMousepadRGBDeviceInfo.cs
index 8c5d62c..901f54f 100644
--- a/RGB.NET.Devices.Corsair/Mousepad/CorsairMousepadRGBDeviceInfo.cs
+++ b/RGB.NET.Devices.Corsair/Mousepad/CorsairMousepadRGBDeviceInfo.cs
@@ -7,18 +7,13 @@ namespace RGB.NET.Devices.Corsair;
///
/// Represents a generic information for a .
///
-public class CorsairMousepadRGBDeviceInfo : CorsairRGBDeviceInfo
+public sealed class CorsairMousepadRGBDeviceInfo : CorsairRGBDeviceInfo
{
#region Constructors
///
- ///
- /// Internal constructor of managed .
- ///
- /// The index if the .
- /// The native -struct
- internal CorsairMousepadRGBDeviceInfo(int deviceIndex, _CorsairDeviceInfo nativeInfo)
- : base(deviceIndex, RGBDeviceType.Mousepad, nativeInfo)
+ internal CorsairMousepadRGBDeviceInfo(_CorsairDeviceInfo nativeInfo, int ledCount, int ledOffset)
+ : base(RGBDeviceType.Mousepad, nativeInfo, ledCount, ledOffset)
{ }
#endregion
diff --git a/RGB.NET.Devices.Corsair/Native/_CUESDK.cs b/RGB.NET.Devices.Corsair/Native/_CUESDK.cs
index 9455cb3..00d9f92 100644
--- a/RGB.NET.Devices.Corsair/Native/_CUESDK.cs
+++ b/RGB.NET.Devices.Corsair/Native/_CUESDK.cs
@@ -11,12 +11,66 @@ using RGB.NET.Core;
namespace RGB.NET.Devices.Corsair.Native;
+internal delegate void CorsairSessionStateChangedHandler(nint context, _CorsairSessionStateChanged eventData);
+
// ReSharper disable once InconsistentNaming
-internal static class _CUESDK
+internal static unsafe class _CUESDK
{
+ #region Constants
+
+ ///
+ /// iCUE-SDK: small string length
+ ///
+ internal const int CORSAIR_STRING_SIZE_S = 64;
+
+ ///
+ /// iCUE-SDK: medium string length
+ ///
+ internal const int CORSAIR_STRING_SIZE_M = 128;
+
+ ///
+ /// iCUE-SDK: maximum level of layer’s priority that can be used in CorsairSetLayerPriority
+ ///
+ internal const int CORSAIR_LAYER_PRIORITY_MAX = 255;
+
+ ///
+ /// iCUE-SDK: maximum number of devices to be discovered
+ ///
+ internal const int CORSAIR_DEVICE_COUNT_MAX = 64;
+
+ ///
+ /// iCUE-SDK: maximum number of LEDs controlled by device
+ ///
+ internal const int CORSAIR_DEVICE_LEDCOUNT_MAX = 512;
+
+ #endregion
+
+ #region Properties & Fields
+
+ internal static bool IsConnected => SesionState == CorsairSessionState.Connected;
+ internal static CorsairSessionState SesionState { get; private set; }
+
+ #endregion
+
+ #region Events
+
+ internal static event EventHandler? SessionStateChanged;
+
+ #endregion
+
+ #region Methods
+
+ private static void CorsairSessionStateChangedCallback(nint context, _CorsairSessionStateChanged eventdata)
+ {
+ SesionState = eventdata.state;
+ SessionStateChanged?.Invoke(null, eventdata.state);
+ }
+
+ #endregion
+
#region Libary Management
- private static IntPtr _handle = IntPtr.Zero;
+ private static nint _handle = 0;
///
/// Reloads the SDK.
@@ -29,7 +83,7 @@ internal static class _CUESDK
private static void LoadCUESDK()
{
- if (_handle != IntPtr.Zero) return;
+ if (_handle != 0) return;
List possiblePathList = GetPossibleLibraryPaths().ToList();
@@ -37,24 +91,27 @@ internal static class _CUESDK
if (dllPath == null) throw new RGBDeviceException($"Can't find the CUE-SDK at one of the expected locations:\r\n '{string.Join("\r\n", possiblePathList.Select(Path.GetFullPath))}'");
if (!NativeLibrary.TryLoad(dllPath, out _handle))
-#if NET6_0
throw new RGBDeviceException($"Corsair LoadLibrary failed with error code {Marshal.GetLastPInvokeError()}");
-#else
- throw new RGBDeviceException($"Corsair LoadLibrary failed with error code {Marshal.GetLastWin32Error()}");
-#endif
- if (!NativeLibrary.TryGetExport(_handle, "CorsairSetLedsColorsBufferByDeviceIndex", out _corsairSetLedsColorsBufferByDeviceIndexPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairSetLedsColorsBufferByDeviceIndex'");
- if (!NativeLibrary.TryGetExport(_handle, "CorsairSetLedsColorsFlushBuffer", out _corsairSetLedsColorsFlushBufferPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairSetLedsColorsFlushBuffer'");
- if (!NativeLibrary.TryGetExport(_handle, "CorsairGetLedsColorsByDeviceIndex", out _corsairGetLedsColorsByDeviceIndexPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairGetLedsColorsByDeviceIndex'");
- if (!NativeLibrary.TryGetExport(_handle, "CorsairSetLayerPriority", out _corsairSetLayerPriorityPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairSetLayerPriority'");
- if (!NativeLibrary.TryGetExport(_handle, "CorsairGetDeviceCount", out _corsairGetDeviceCountPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairGetDeviceCount'");
- if (!NativeLibrary.TryGetExport(_handle, "CorsairGetDeviceInfo", out _corsairGetDeviceInfoPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairGetDeviceInfo'");
- if (!NativeLibrary.TryGetExport(_handle, "CorsairGetLedIdForKeyName", out _corsairGetLedIdForKeyNamePointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairGetLedIdForKeyName'");
- if (!NativeLibrary.TryGetExport(_handle, "CorsairGetLedPositionsByDeviceIndex", out _corsairGetLedPositionsByDeviceIndexPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairGetLedPositionsByDeviceIndex'");
- if (!NativeLibrary.TryGetExport(_handle, "CorsairRequestControl", out _corsairRequestControlPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairRequestControl'");
- if (!NativeLibrary.TryGetExport(_handle, "CorsairReleaseControl", out _corsairReleaseControlPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairReleaseControl'");
- if (!NativeLibrary.TryGetExport(_handle, "CorsairPerformProtocolHandshake", out _corsairPerformProtocolHandshakePointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairPerformProtocolHandshake'");
- if (!NativeLibrary.TryGetExport(_handle, "CorsairGetLastError", out _corsairGetLastErrorPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairGetLastError'");
+ _corsairConnectPtr = (delegate* unmanaged[Cdecl])LoadFunction("CorsairConnect");
+ _corsairGetSessionDetails = (delegate* unmanaged[Cdecl])LoadFunction("CorsairGetSessionDetails");
+ _corsairDisconnect = (delegate* unmanaged[Cdecl])LoadFunction("CorsairDisconnect");
+ _corsairGetDevices = (delegate* unmanaged[Cdecl]<_CorsairDeviceFilter, int, nint, out int, CorsairError>)LoadFunction("CorsairGetDevices");
+ _corsairGetDeviceInfo = (delegate* unmanaged[Cdecl])LoadFunction("CorsairGetDeviceInfo");
+ _corsairGetLedPositions = (delegate* unmanaged[Cdecl])LoadFunction("CorsairGetLedPositions");
+ _corsairSetLedColors = (delegate* unmanaged[Cdecl])LoadFunction("CorsairSetLedColors");
+ _corsairSetLayerPriority = (delegate* unmanaged[Cdecl])LoadFunction("CorsairSetLayerPriority");
+ _corsairGetLedLuidForKeyName = (delegate* unmanaged[Cdecl])LoadFunction("CorsairGetLedLuidForKeyName");
+ _corsairRequestControl = (delegate* unmanaged[Cdecl])LoadFunction("CorsairRequestControl");
+ _corsairReleaseControl = (delegate* unmanaged[Cdecl])LoadFunction("CorsairReleaseControl");
+ _getDevicePropertyInfo = (delegate* unmanaged[Cdecl])LoadFunction("CorsairGetDevicePropertyInfo");
+ _readDeviceProperty = (delegate* unmanaged[Cdecl])LoadFunction("CorsairReadDeviceProperty");
+ }
+
+ private static nint LoadFunction(string function)
+ {
+ if (!NativeLibrary.TryGetExport(_handle, function, out nint ptr)) throw new RGBDeviceException($"Failed to load Corsair function '{function}'");
+ return ptr;
}
private static IEnumerable GetPossibleLibraryPaths()
@@ -71,23 +128,24 @@ internal static class _CUESDK
internal static void UnloadCUESDK()
{
- if (_handle == IntPtr.Zero) return;
+ if (_handle == 0) return;
- _corsairSetLedsColorsBufferByDeviceIndexPointer = IntPtr.Zero;
- _corsairSetLedsColorsFlushBufferPointer = IntPtr.Zero;
- _corsairGetLedsColorsByDeviceIndexPointer = IntPtr.Zero;
- _corsairSetLayerPriorityPointer = IntPtr.Zero;
- _corsairGetDeviceCountPointer = IntPtr.Zero;
- _corsairGetDeviceInfoPointer = IntPtr.Zero;
- _corsairGetLedIdForKeyNamePointer = IntPtr.Zero;
- _corsairGetLedPositionsByDeviceIndexPointer = IntPtr.Zero;
- _corsairRequestControlPointer = IntPtr.Zero;
- _corsairReleaseControlPointer = IntPtr.Zero;
- _corsairPerformProtocolHandshakePointer = IntPtr.Zero;
- _corsairGetLastErrorPointer = IntPtr.Zero;
+ _corsairConnectPtr = null;
+ _corsairGetSessionDetails = null;
+ _corsairDisconnect = null;
+ _corsairGetDevices = null;
+ _corsairGetDeviceInfo = null;
+ _corsairGetLedPositions = null;
+ _corsairSetLedColors = null;
+ _corsairSetLayerPriority = null;
+ _corsairGetLedLuidForKeyName = null;
+ _corsairRequestControl = null;
+ _corsairReleaseControl = null;
+ _getDevicePropertyInfo = null;
+ _readDeviceProperty = null;
NativeLibrary.Free(_handle);
- _handle = IntPtr.Zero;
+ _handle = 0;
}
#endregion
@@ -96,97 +154,182 @@ internal static class _CUESDK
#region Pointers
- private static IntPtr _corsairSetLedsColorsBufferByDeviceIndexPointer;
- private static IntPtr _corsairSetLedsColorsFlushBufferPointer;
- private static IntPtr _corsairGetLedsColorsByDeviceIndexPointer;
- private static IntPtr _corsairSetLayerPriorityPointer;
- private static IntPtr _corsairGetDeviceCountPointer;
- private static IntPtr _corsairGetDeviceInfoPointer;
- private static IntPtr _corsairGetLedIdForKeyNamePointer;
- private static IntPtr _corsairGetLedPositionsByDeviceIndexPointer;
- private static IntPtr _corsairRequestControlPointer;
- private static IntPtr _corsairReleaseControlPointer;
- private static IntPtr _corsairPerformProtocolHandshakePointer;
- private static IntPtr _corsairGetLastErrorPointer;
+ private static delegate* unmanaged[Cdecl] _corsairConnectPtr;
+ private static delegate* unmanaged[Cdecl] _corsairGetSessionDetails;
+ private static delegate* unmanaged[Cdecl] _corsairDisconnect;
+ private static delegate* unmanaged[Cdecl]<_CorsairDeviceFilter, int, nint, out int, CorsairError> _corsairGetDevices;
+ private static delegate* unmanaged[Cdecl] _corsairGetDeviceInfo;
+ private static delegate* unmanaged[Cdecl] _corsairGetLedPositions;
+ private static delegate* unmanaged[Cdecl] _corsairSetLedColors;
+ private static delegate* unmanaged[Cdecl] _corsairSetLayerPriority;
+ private static delegate* unmanaged[Cdecl] _corsairGetLedLuidForKeyName;
+ private static delegate* unmanaged[Cdecl] _corsairRequestControl;
+ private static delegate* unmanaged[Cdecl] _corsairReleaseControl;
+ private static delegate* unmanaged[Cdecl] _getDevicePropertyInfo;
+ private static delegate* unmanaged[Cdecl] _readDeviceProperty;
#endregion
- ///
- /// CUE-SDK: set specified LEDs to some colors.
- /// This function set LEDs colors in the buffer which is written to the devices via CorsairSetLedsColorsFlushBuffer or CorsairSetLedsColorsFlushBufferAsync.
- /// Typical usecase is next: CorsairSetLedsColorsFlushBuffer or CorsairSetLedsColorsFlushBufferAsync is called to write LEDs colors to the device
- /// and follows after one or more calls of CorsairSetLedsColorsBufferByDeviceIndex to set the LEDs buffer.
- /// This function does not take logical layout into account.
- ///
- internal static unsafe bool CorsairSetLedsColorsBufferByDeviceIndex(int deviceIndex, int size, IntPtr ledsColors)
- => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairSetLedsColorsBufferByDeviceIndexPointer))(deviceIndex, size, ledsColors);
-
- ///
- /// CUE-SDK: writes to the devices LEDs colors buffer which is previously filled by the CorsairSetLedsColorsBufferByDeviceIndex function.
- /// This function executes synchronously, if you are concerned about delays consider using CorsairSetLedsColorsFlushBufferAsync
- ///
- internal static unsafe bool CorsairSetLedsColorsFlushBuffer() => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairSetLedsColorsFlushBufferPointer))();
-
- ///
- /// CUE-SDK: get current color for the list of requested LEDs.
- /// The color should represent the actual state of the hardware LED, which could be a combination of SDK and/or CUE input.
- /// This function works for keyboard, mouse, mousemat, headset, headset stand and DIY-devices.
- ///
- internal static unsafe bool CorsairGetLedsColorsByDeviceIndex(int deviceIndex, int size, IntPtr ledsColors)
- => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairGetLedsColorsByDeviceIndexPointer))(deviceIndex, size, ledsColors);
-
- ///
- /// CUE-SDK: set layer priority for this shared client.
- /// By default CUE has priority of 127 and all shared clients have priority of 128 if they don’t call this function.
- /// Layers with higher priority value are shown on top of layers with lower priority.
- ///
- internal static unsafe bool CorsairSetLayerPriority(int priority) => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairSetLayerPriorityPointer))(priority);
-
- ///
- /// CUE-SDK: returns number of connected Corsair devices that support lighting control.
- ///
- internal static unsafe int CorsairGetDeviceCount() => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairGetDeviceCountPointer))();
-
- ///
- /// CUE-SDK: returns information about device at provided index.
- ///
- internal static unsafe IntPtr CorsairGetDeviceInfo(int deviceIndex) => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairGetDeviceInfoPointer))(deviceIndex);
-
- ///
- /// CUE-SDK: provides list of keyboard or mousepad LEDs with their physical positions.
- ///
- internal static unsafe IntPtr CorsairGetLedPositionsByDeviceIndex(int deviceIndex) => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairGetLedPositionsByDeviceIndexPointer))(deviceIndex);
-
- ///
- /// CUE-SDK: retrieves led id for key name taking logical layout into account.
- ///
- internal static unsafe CorsairLedId CorsairGetLedIdForKeyName(char keyName) => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairGetLedIdForKeyNamePointer))(keyName);
-
- ///
- /// CUE-SDK: requestes control using specified access mode.
- /// By default client has shared control over lighting so there is no need to call CorsairRequestControl unless client requires exclusive control.
- ///
- internal static unsafe bool CorsairRequestControl(CorsairAccessMode accessMode) => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairRequestControlPointer))(accessMode);
-
- ///
- /// CUE-SDK: releases previously requested control for specified access mode.
- ///
- internal static unsafe bool CorsairReleaseControl(CorsairAccessMode accessMode) => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairReleaseControlPointer))(accessMode);
-
- ///
- /// CUE-SDK: checks file and protocol version of CUE to understand which of SDK functions can be used with this version of CUE.
- ///
- internal static unsafe _CorsairProtocolDetails CorsairPerformProtocolHandshake() => ((delegate* unmanaged[Cdecl]<_CorsairProtocolDetails>)ThrowIfZero(_corsairPerformProtocolHandshakePointer))();
-
- ///
- /// CUE-SDK: returns last error that occured while using any of Corsair* functions.
- ///
- internal static unsafe CorsairError CorsairGetLastError() => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairGetLastErrorPointer))();
-
- private static IntPtr ThrowIfZero(IntPtr ptr)
+ internal static CorsairError CorsairConnect()
{
- if (ptr == IntPtr.Zero) throw new RGBDeviceException("The Corsair-SDK is not initialized.");
- return ptr;
+ if (_corsairConnectPtr == null) throw new RGBDeviceException("The Corsair-SDK is not initialized.");
+ if (IsConnected) throw new RGBDeviceException("The Corsair-SDK is already connected.");
+ return _corsairConnectPtr(CorsairSessionStateChangedCallback, 0);
+ }
+
+ internal static CorsairError CorsairGetSessionDetails(out _CorsairSessionDetails? details)
+ {
+ if (!IsConnected) throw new RGBDeviceException("The Corsair-SDK is not connected.");
+
+ nint sessionDetailPtr = Marshal.AllocHGlobal(Marshal.SizeOf<_CorsairSessionDetails>());
+ try
+ {
+ CorsairError error = _corsairGetSessionDetails(sessionDetailPtr);
+ details = Marshal.PtrToStructure<_CorsairSessionDetails>(sessionDetailPtr);
+
+ return error;
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(sessionDetailPtr);
+ }
+ }
+
+ internal static CorsairError CorsairDisconnect()
+ {
+ if (!IsConnected) throw new RGBDeviceException("The Corsair-SDK is not connected.");
+ return _corsairDisconnect();
+ }
+
+ internal static CorsairError CorsairGetDevices(_CorsairDeviceFilter filter, out _CorsairDeviceInfo[] devices)
+ {
+ if (!IsConnected) throw new RGBDeviceException("The Corsair-SDK is not connected.");
+
+ int structSize = Marshal.SizeOf<_CorsairDeviceInfo>();
+ nint devicePtr = Marshal.AllocHGlobal(structSize * CORSAIR_DEVICE_COUNT_MAX);
+ try
+ {
+ CorsairError error = _corsairGetDevices(filter, CORSAIR_DEVICE_COUNT_MAX, devicePtr, out int size);
+ devices = devicePtr.ToArray<_CorsairDeviceInfo>(size);
+
+ return error;
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(devicePtr);
+ }
+ }
+
+ internal static CorsairError CorsairGetDeviceInfo(string deviceId, _CorsairDeviceInfo deviceInfo)
+ {
+ if (!IsConnected) throw new RGBDeviceException("The Corsair-SDK is not connected.");
+ return _corsairGetDeviceInfo(deviceId, deviceInfo);
+ }
+
+ internal static CorsairError CorsairGetLedPositions(string deviceId, out _CorsairLedPosition[] ledPositions)
+ {
+ if (!IsConnected) throw new RGBDeviceException("The Corsair-SDK is not connected.");
+
+ int structSize = Marshal.SizeOf<_CorsairLedPosition>();
+ nint ledPositionsPtr = Marshal.AllocHGlobal(structSize * CORSAIR_DEVICE_LEDCOUNT_MAX);
+ try
+ {
+ CorsairError error = _corsairGetLedPositions(deviceId, CORSAIR_DEVICE_LEDCOUNT_MAX, ledPositionsPtr, out int size);
+ ledPositions = ledPositionsPtr.ToArray<_CorsairLedPosition>(size);
+
+ return error;
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(ledPositionsPtr);
+ }
+ }
+
+ internal static CorsairError CorsairSetLedColors(string deviceId, int ledCount, nint ledColorsPtr)
+ {
+ if (!IsConnected) throw new RGBDeviceException("The Corsair-SDK is not connected.");
+ return _corsairSetLedColors(deviceId, ledCount, ledColorsPtr);
+ }
+
+ internal static CorsairError CorsairSetLayerPriority(uint priority)
+ {
+ if (!IsConnected) throw new RGBDeviceException("The Corsair-SDK is not connected.");
+ return _corsairSetLayerPriority(priority);
+ }
+
+ internal static CorsairError CorsairGetLedLuidForKeyName(string deviceId, char keyName, out uint ledId)
+ {
+ if (!IsConnected) throw new RGBDeviceException("The Corsair-SDK is not connected.");
+ return _corsairGetLedLuidForKeyName(deviceId, keyName, out ledId);
+ }
+
+ internal static CorsairError CorsairRequestControl(string deviceId, CorsairAccessLevel accessLevel)
+ {
+ if (!IsConnected) throw new RGBDeviceException("The Corsair-SDK is not connected.");
+ return _corsairRequestControl(deviceId, accessLevel);
+ }
+
+ internal static CorsairError CorsairReleaseControl(string deviceId)
+ {
+ if (!IsConnected) throw new RGBDeviceException("The Corsair-SDK is not connected.");
+ return _corsairReleaseControl(deviceId);
+ }
+
+ internal static CorsairError GetDevicePropertyInfo(string deviceId, CorsairDevicePropertyId propertyId, uint index, out CorsairDataType dataType, out CorsairPropertyFlag flags)
+ {
+ if (!IsConnected) throw new RGBDeviceException("The Corsair-SDK is not connected.");
+ return _getDevicePropertyInfo(deviceId, propertyId, index, out dataType, out flags);
+ }
+
+ internal static CorsairError ReadDeviceProperty(string deviceId, CorsairDevicePropertyId propertyId, uint index, out _CorsairProperty? property)
+ {
+ if (!IsConnected) throw new RGBDeviceException("The Corsair-SDK is not connected.");
+
+ nint propertyPtr = Marshal.AllocHGlobal(Marshal.SizeOf<_CorsairProperty>());
+ try
+ {
+ CorsairError error = _readDeviceProperty(deviceId, propertyId, index, propertyPtr);
+ property = Marshal.PtrToStructure<_CorsairProperty>(propertyPtr);
+
+ return error;
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(propertyPtr);
+ }
+ }
+
+ internal static int ReadDevicePropertySimpleInt32(string deviceId, CorsairDevicePropertyId propertyId, uint index = 0) => ReadDevicePropertySimple(deviceId, propertyId, CorsairDataType.Int32, index).int32;
+
+ internal static int[] ReadDevicePropertySimpleInt32Array(string deviceId, CorsairDevicePropertyId propertyId, uint index = 0)
+ {
+ _CorsairDataValue dataValue = ReadDevicePropertySimple(deviceId, propertyId, CorsairDataType.Int32Array, index);
+ return dataValue.int32Array.items.ToArray((int)dataValue.int32Array.count);
+ }
+
+ internal static _CorsairDataValue ReadDevicePropertySimple(string deviceId, CorsairDevicePropertyId propertyId, CorsairDataType expectedDataType, uint index = 0)
+ {
+ CorsairError errorCode = GetDevicePropertyInfo(deviceId, propertyId, index, out CorsairDataType dataType, out CorsairPropertyFlag flags);
+ if (errorCode != CorsairError.Success)
+ throw new RGBDeviceException($"Failed to read device-property-info '{propertyId}' for corsair device '{deviceId}'. (ErrorCode: {errorCode})");
+
+ if (dataType != expectedDataType)
+ throw new RGBDeviceException($"Failed to read device-property-info '{propertyId}' for corsair device '{deviceId}'. (Wrong data-type '{dataType}', expected: '{expectedDataType}')");
+
+ if (!flags.HasFlag(CorsairPropertyFlag.CanRead))
+ throw new RGBDeviceException($"Failed to read device-property-info '{propertyId}' for corsair device '{deviceId}'. (Not readable)");
+
+ errorCode = ReadDeviceProperty(deviceId, propertyId, index, out _CorsairProperty? property);
+ if (errorCode != CorsairError.Success)
+ throw new RGBDeviceException($"Failed to read device-property '{propertyId}' for corsair device '{deviceId}'. (ErrorCode: {errorCode})");
+
+ if (property == null)
+ throw new RGBDeviceException($"Failed to read device-property '{propertyId}' for corsair device '{deviceId}'. (Invalid return value)");
+
+ if (property.Value.type != expectedDataType)
+ throw new RGBDeviceException($"Failed to read device-property '{propertyId}' for corsair device '{deviceId}'. (Wrong data-type '{dataType}', expected: '{expectedDataType}')");
+
+ return property.Value.value;
}
#endregion
diff --git a/RGB.NET.Devices.Corsair/Native/_CorsairDataValue.cs b/RGB.NET.Devices.Corsair/Native/_CorsairDataValue.cs
new file mode 100644
index 0000000..bfb5e3d
--- /dev/null
+++ b/RGB.NET.Devices.Corsair/Native/_CorsairDataValue.cs
@@ -0,0 +1,140 @@
+#pragma warning disable 169 // Field 'x' is never used
+#pragma warning disable 414 // Field 'x' is assigned but its value never used
+#pragma warning disable 649 // Field 'x' is never assigned
+#pragma warning disable IDE1006 // Naming Styles
+
+using System.Runtime.InteropServices;
+
+namespace RGB.NET.Devices.Corsair.Native;
+
+// ReSharper disable once InconsistentNaming
+///
+/// iCUE-SDK: a union of all property data types
+///
+[StructLayout(LayoutKind.Explicit)]
+internal struct _CorsairDataValue
+{
+ #region Properties & Fields
+
+ ///
+ /// iCUE-SDK: actual property value if it’s type is CPDT_Boolean
+ ///
+ [FieldOffset(0)]
+ internal bool boolean;
+
+ ///
+ /// iCUE-SDK: actual property value if it’s type is CPDT_Int32
+ ///
+ [FieldOffset(0)]
+ internal int int32;
+
+ ///
+ /// iCUE-SDK: actual property value if it’s type is CPDT_Float64
+ ///
+ [FieldOffset(0)]
+ internal double float64;
+
+ ///
+ /// iCUE-SDK: actual property value if it’s type is CPDT_String
+ ///
+ [FieldOffset(0)]
+ internal nint @string;
+
+ ///
+ /// iCUE-SDK: actual property value if it’s type is CPDT_Boolean_Array
+ ///
+ [FieldOffset(0)]
+ internal CorsairDataTypeBooleanArray booleanArray;
+
+ ///
+ /// iCUE-SDK: actual property value if it’s type is CPDT_Int32_Array
+ ///
+ [FieldOffset(0)]
+ internal CorsairDataTypeInt32Array int32Array;
+
+ ///
+ /// iCUE-SDK: actual property value if it’s type is CPDT_Float64_Array
+ ///
+ [FieldOffset(0)]
+ internal CorsairDataTypeFloat64Array float64Array;
+
+ ///
+ /// iCUE-SDK: actual property value if it’s type is CPDT_String_Array
+ ///
+ [FieldOffset(0)]
+ internal CorsairDataTypeStringArray stringArray;
+
+ #endregion
+
+ #region Data Types
+
+ ///
+ /// iCUE: represents an array of boolean values
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct CorsairDataTypeBooleanArray
+ {
+ ///
+ /// iCUE: an array of boolean values
+ ///
+ internal nint items;
+
+ ///
+ /// iCUE: number of items array elements
+ ///
+ internal uint count;
+ };
+
+ ///
+ /// iCUE: represents an array of integer values
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct CorsairDataTypeInt32Array
+ {
+ ///
+ /// iCUE: an array of integer values
+ ///
+ internal nint items;
+
+ ///
+ /// iCUE: number of items array elements
+ ///
+ internal uint count;
+ };
+
+ ///
+ /// iCUE: represents an array of double values
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct CorsairDataTypeFloat64Array
+ {
+ ///
+ /// iCUE: an array of double values
+ ///
+ internal nint items;
+
+ ///
+ /// iCUE: number of items array elements
+ ///
+ internal uint count;
+ };
+
+ ///
+ /// iCUE: represents an array of pointers to null terminated strings
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct CorsairDataTypeStringArray
+ {
+ ///
+ /// iCUE: an array of pointers to null terminated strings
+ ///
+ internal nint items;
+
+ ///
+ /// iCUE: number of items array elements
+ ///
+ internal uint count;
+ };
+
+ #endregion
+}
diff --git a/RGB.NET.Devices.Corsair/Native/_CorsairDeviceFilter.cs b/RGB.NET.Devices.Corsair/Native/_CorsairDeviceFilter.cs
new file mode 100644
index 0000000..c2005c5
--- /dev/null
+++ b/RGB.NET.Devices.Corsair/Native/_CorsairDeviceFilter.cs
@@ -0,0 +1,37 @@
+#pragma warning disable 169 // Field 'x' is never used
+#pragma warning disable 414 // Field 'x' is assigned but its value never used
+#pragma warning disable 649 // Field 'x' is never assigned
+#pragma warning disable IDE1006 // Naming Styles
+
+using System.Runtime.InteropServices;
+
+namespace RGB.NET.Devices.Corsair.Native;
+
+// ReSharper disable once InconsistentNaming
+///
+/// iCUE-SDK: contains device search filter
+///
+[StructLayout(LayoutKind.Sequential)]
+internal sealed class _CorsairDeviceFilter
+{
+ #region Properties & Fields
+
+ ///
+ /// iCUE-SDK: mask that describes device types, formed as logical “or” of CorsairDeviceType enum values
+ ///
+ // ReSharper disable once NotAccessedField.Global
+ internal CorsairDeviceType deviceTypeMask;
+
+ #endregion
+
+ #region Constructors
+
+ public _CorsairDeviceFilter() { }
+
+ public _CorsairDeviceFilter(CorsairDeviceType filter)
+ {
+ this.deviceTypeMask = filter;
+ }
+
+ #endregion
+}
diff --git a/RGB.NET.Devices.Corsair/Native/_CorsairDeviceInfo.cs b/RGB.NET.Devices.Corsair/Native/_CorsairDeviceInfo.cs
index 799fc5a..b4c8813 100644
--- a/RGB.NET.Devices.Corsair/Native/_CorsairDeviceInfo.cs
+++ b/RGB.NET.Devices.Corsair/Native/_CorsairDeviceInfo.cs
@@ -3,56 +3,47 @@
#pragma warning disable 649 // Field 'x' is never assigned
#pragma warning disable IDE1006 // Naming Styles
-using System;
using System.Runtime.InteropServices;
namespace RGB.NET.Devices.Corsair.Native;
// ReSharper disable once InconsistentNaming
///
-/// CUE-SDK: contains information about device
+/// iCUE-SDK: contains information about device
///
[StructLayout(LayoutKind.Sequential)]
-internal class _CorsairDeviceInfo
+internal sealed class _CorsairDeviceInfo
{
///
- /// CUE-SDK: enum describing device type
+ /// iCUE-SDK: enum describing device type
///
internal CorsairDeviceType type;
///
- /// CUE-SDK: null - terminated device model(like “K95RGB”)
+ /// iCUE-SDK: null terminated Unicode string that contains unique device identifier serial number. Can be empty, if serial number is not available for the device
///
- internal IntPtr model;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = _CUESDK.CORSAIR_STRING_SIZE_M)]
+ internal string? id;
///
- /// CUE-SDK: enum describing physical layout of the keyboard or mouse
+ /// iCUE-SDK: null terminated Unicode string that contains device serial number. Can be empty, if serial number is not available for the device
///
- internal int physicalLayout;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = _CUESDK.CORSAIR_STRING_SIZE_M)]
+ internal string? serial;
///
- /// CUE-SDK: enum describing logical layout of the keyboard as set in CUE settings
+ /// iCUE-SDK: null terminated Unicode string that contains device model (like “K95RGB”)
///
- internal int logicalLayout;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = _CUESDK.CORSAIR_STRING_SIZE_M)]
+ internal string? model;
///
- /// CUE-SDK: mask that describes device capabilities, formed as logical “or” of CorsairDeviceCaps enum values
+ /// iCUE-SDK: number of controllable LEDs on the device
///
- internal int capsMask;
+ internal int ledCount;
///
- /// CUE-SDK: number of controllable LEDs on the device
+ /// iCUE-SDK: number of channels controlled by the device
///
- internal int ledsCount;
-
- ///
- /// CUE-SDK: structure that describes channels of the DIY-devices
- ///
- internal _CorsairChannelsInfo? channels;
-
- ///
- /// CUE-SDK: null-terminated string that contains unique device identifier that uniquely identifies device at least within session
- ///
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
- internal string? deviceId;
+ internal int channelCount;
}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Native/_CorsairLedColor.cs b/RGB.NET.Devices.Corsair/Native/_CorsairLedColor.cs
index 004b36a..60e6496 100644
--- a/RGB.NET.Devices.Corsair/Native/_CorsairLedColor.cs
+++ b/RGB.NET.Devices.Corsair/Native/_CorsairLedColor.cs
@@ -10,28 +10,52 @@ namespace RGB.NET.Devices.Corsair.Native;
// ReSharper disable once InconsistentNaming
///
-/// CUE-SDK: contains information about led and its color
+/// iCUE-SDK: contains information about led and its color
///
[StructLayout(LayoutKind.Sequential)]
-internal class _CorsairLedColor
+internal struct _CorsairLedColor
{
- ///
- /// CUE-SDK: identifier of LED to set
- ///
- internal int ledId;
+ #region Properties & Fields
///
- /// CUE-SDK: red brightness[0..255]
+ /// iCUE-SDK: identifier of LED to set
///
- internal int r;
+ internal CorsairLedId ledId;
///
- /// CUE-SDK: green brightness[0..255]
+ /// iCUE-SDK: red brightness[0..255]
///
- internal int g;
+ internal byte r;
///
- /// CUE-SDK: blue brightness[0..255]
+ /// iCUE-SDK: green brightness[0..255]
///
- internal int b;
+ internal byte g;
+
+ ///
+ /// iCUE-SDK: blue brightness[0..255]
+ ///
+ internal byte b;
+
+ ///
+ /// iCUE-SDK: alpha channel [0..255]. The opacity of the color from 0 for completely translucent to 255 for opaque
+ ///
+ internal byte a;
+
+ #endregion
+
+ #region Constructors
+
+ public _CorsairLedColor() { }
+
+ public _CorsairLedColor(CorsairLedId ledId, byte r, byte g, byte b, byte a)
+ {
+ this.ledId = ledId;
+ this.r = r;
+ this.g = g;
+ this.b = b;
+ this.a = a;
+ }
+
+ #endregion
};
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Native/_CorsairLedPosition.cs b/RGB.NET.Devices.Corsair/Native/_CorsairLedPosition.cs
index 34f4108..af2bad1 100644
--- a/RGB.NET.Devices.Corsair/Native/_CorsairLedPosition.cs
+++ b/RGB.NET.Devices.Corsair/Native/_CorsairLedPosition.cs
@@ -2,41 +2,31 @@
#pragma warning disable 414 // Field 'x' is assigned but its value never used
#pragma warning disable 649 // Field 'x' is never assigned
#pragma warning disable IDE1006 // Naming Styles
+// ReSharper disable NotAccessedField.Global
using System.Runtime.InteropServices;
namespace RGB.NET.Devices.Corsair.Native;
-// ReSharper disable once InconsistentNaming
+// ReSharper disable once InconsistentNaming
///
-/// CUE-SDK: contains led id and position of led rectangle.Most of the keys are rectangular.
-/// In case if key is not rectangular(like Enter in ISO / UK layout) it returns the smallest rectangle that fully contains the key
+/// iCUE-SDK: contains led id and position of led
///
[StructLayout(LayoutKind.Sequential)]
-internal class _CorsairLedPosition
+internal sealed class _CorsairLedPosition
{
///
- /// CUE-SDK: identifier of led
+ /// iCUE-SDK: unique identifier of led
///
- internal CorsairLedId LedId;
+ internal uint id;
///
- /// CUE-SDK: values in mm
+ /// iCUE-SDK: for keyboards, mice, mousemats, headset stands and memory modules values are
///
- internal double top;
+ internal double cx;
///
- /// CUE-SDK: values in mm
+ /// iCUE-SDK: in mm, for DIY-devices, headsets and coolers values are in logical units
///
- internal double left;
-
- ///
- /// CUE-SDK: values in mm
- ///
- internal double height;
-
- ///
- /// CUE-SDK: values in mm
- ///
- internal double width;
-}
\ No newline at end of file
+ internal double cy;
+};
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Native/_CorsairProperty.cs b/RGB.NET.Devices.Corsair/Native/_CorsairProperty.cs
new file mode 100644
index 0000000..4a275b2
--- /dev/null
+++ b/RGB.NET.Devices.Corsair/Native/_CorsairProperty.cs
@@ -0,0 +1,30 @@
+#pragma warning disable 169 // Field 'x' is never used
+#pragma warning disable 414 // Field 'x' is assigned but its value never used
+#pragma warning disable 649 // Field 'x' is never assigned
+#pragma warning disable IDE1006 // Naming Styles
+
+using System.Runtime.InteropServices;
+
+namespace RGB.NET.Devices.Corsair.Native;
+
+// ReSharper disable once InconsistentNaming
+///
+/// iCUE-SDK: contains information about device property type and value
+///
+[StructLayout(LayoutKind.Sequential)]
+internal struct _CorsairProperty
+{
+ #region Properties & Fields
+
+ ///
+ /// iCUE-SDK: type of property
+ ///
+ internal CorsairDataType type;
+
+ ///
+ /// iCUE-SDK: property value
+ ///
+ internal _CorsairDataValue value;
+
+ #endregion
+}
diff --git a/RGB.NET.Devices.Corsair/Native/_CorsairSessionDetails.cs b/RGB.NET.Devices.Corsair/Native/_CorsairSessionDetails.cs
new file mode 100644
index 0000000..2fbf755
--- /dev/null
+++ b/RGB.NET.Devices.Corsair/Native/_CorsairSessionDetails.cs
@@ -0,0 +1,32 @@
+#pragma warning disable 169 // Field 'x' is never used
+#pragma warning disable 414 // Field 'x' is assigned but its value never used
+#pragma warning disable 649 // Field 'x' is never assigned
+#pragma warning disable IDE1006 // Naming Styles
+// ReSharper disable NotAccessedField.Global
+
+using System.Runtime.InteropServices;
+
+namespace RGB.NET.Devices.Corsair.Native;
+
+// ReSharper disable once InconsistentNaming
+///
+/// iCUE-SDK: contains information about SDK and iCUE versions
+///
+[StructLayout(LayoutKind.Sequential)]
+internal sealed class _CorsairSessionDetails
+{
+ ///
+ /// iCUE-SDK: version of SDK client (like {4,0,1}). Always contains valid value even if there was no iCUE found. Must comply with the semantic versioning rules.
+ ///
+ internal _CorsairVersion clientVersion = new();
+
+ ///
+ /// iCUE-SDK: version of SDK server (like {4,0,1}) or empty struct ({0,0,0}) if the iCUE was not found. Must comply with the semantic versioning rules.
+ ///
+ internal _CorsairVersion serverVersion = new();
+
+ ///
+ /// iCUE-SDK: version of iCUE (like {3,33,100}) or empty struct ({0,0,0}) if the iCUE was not found.
+ ///
+ internal _CorsairVersion serverHostVersion = new();
+};
diff --git a/RGB.NET.Devices.Corsair/Native/_CorsairSessionStateChanged.cs b/RGB.NET.Devices.Corsair/Native/_CorsairSessionStateChanged.cs
new file mode 100644
index 0000000..07b1a38
--- /dev/null
+++ b/RGB.NET.Devices.Corsair/Native/_CorsairSessionStateChanged.cs
@@ -0,0 +1,27 @@
+#pragma warning disable 169 // Field 'x' is never used
+#pragma warning disable 414 // Field 'x' is assigned but its value never used
+#pragma warning disable 649 // Field 'x' is never assigned
+#pragma warning disable IDE1006 // Naming Styles
+// ReSharper disable NotAccessedField.Global
+
+using System.Runtime.InteropServices;
+
+namespace RGB.NET.Devices.Corsair.Native;
+
+// ReSharper disable once InconsistentNaming
+///
+/// iCUE-SDK: contains information about session state and client/server versions
+///
+[StructLayout(LayoutKind.Sequential)]
+internal sealed class _CorsairSessionStateChanged
+{
+ ///
+ /// iCUE-SDK: new session state which SDK client has been transitioned to
+ ///
+ internal CorsairSessionState state;
+
+ ///
+ /// iCUE-SDK: information about client/server versions
+ ///
+ internal _CorsairSessionDetails details = new();
+};
diff --git a/RGB.NET.Devices.Corsair/Native/_CorsairVersion.cs b/RGB.NET.Devices.Corsair/Native/_CorsairVersion.cs
new file mode 100644
index 0000000..d786b0f
--- /dev/null
+++ b/RGB.NET.Devices.Corsair/Native/_CorsairVersion.cs
@@ -0,0 +1,31 @@
+#pragma warning disable 169 // Field 'x' is never used
+#pragma warning disable 414 // Field 'x' is assigned but its value never used
+#pragma warning disable 649 // Field 'x' is never assigned
+#pragma warning disable IDE1006 // Naming Styles
+// ReSharper disable NotAccessedField.Global
+
+using System.Runtime.InteropServices;
+
+namespace RGB.NET.Devices.Corsair.Native;
+
+// ReSharper disable once InconsistentNaming
+///
+/// iCUE-SDK: contains information about version that consists of three components
+///
+[StructLayout(LayoutKind.Sequential)]
+internal sealed class _CorsairVersion
+{
+ #region Properties & Fields
+
+ internal int major;
+ internal int minor;
+ internal int patch;
+
+ #endregion
+
+ #region Methods
+
+ public override string ToString() => $"{major}.{minor}.{patch}";
+
+ #endregion
+};
diff --git a/RGB.NET.Devices.Corsair/README.md b/RGB.NET.Devices.Corsair/README.md
index dd30377..191ad60 100644
--- a/RGB.NET.Devices.Corsair/README.md
+++ b/RGB.NET.Devices.Corsair/README.md
@@ -11,14 +11,16 @@ surface.Load(CorsairDeviceProvider.Instance);
This providers requires native SDK-dlls.
You can get them directly from Corsair at [https://github.com/CorsairOfficial/cue-sdk/releases](https://github.com/CorsairOfficial/cue-sdk/releases)
+(Developed and tested with iCUE SDK v4.0.84)
+
Since the SDK-dlls are native it's important to use the correct architecture you're building your application for. (If in doubt you can always include both.)
### x64
-`redist\x64\CUESDK.x64_2019.dll` from the SDK-zip needs to be distributed as `\x64\CUESDK.x64_2019.dll` (or simply named `CUESDK.dll`)
+`redist\x64\iCUESDK.x64_2019.dll` from the SDK-zip needs to be distributed as `\x64\iCUESDK.x64_2019.dll` (or simply named `iCUESDK.dll`)
You can use other, custom paths by adding them to `CorsairDeviceProvider.PossibleX64NativePaths`.
-### x86
-`redist\i386\CUESDK_2019.dll` from the SDK-zip needs to be distributed as `\x86\CUESDK_2019.dll` (or simply named `CUESDK.dll`)
+### x86 (only SDKs before v4.0.84)
+`redist\i386\iCUESDK_2019.dll` from the SDK-zip needs to be distributed as `\x86\iCUESDK_2019.dll` (or simply named `iCUESDK.dll`)
You can use other, custom paths by adding them to `CorsairDeviceProvider.PossibleX86NativePaths`.
diff --git a/RGB.NET.Devices.Corsair/RGB.NET.Devices.Corsair.csproj b/RGB.NET.Devices.Corsair/RGB.NET.Devices.Corsair.csproj
index 302d93d..ee6cfca 100644
--- a/RGB.NET.Devices.Corsair/RGB.NET.Devices.Corsair.csproj
+++ b/RGB.NET.Devices.Corsair/RGB.NET.Devices.Corsair.csproj
@@ -1,6 +1,6 @@
- net7.0;net6.0;net5.0
+ net8.0;net7.0;net6.0
latest
enable
@@ -41,7 +41,7 @@
- $(DefineConstants);TRACE;DEBUG
+ TRACE;DEBUG
true
false
@@ -49,7 +49,7 @@
true
$(NoWarn);CS1591;CS1572;CS1573
- $(DefineConstants);RELEASE
+ RELEASE
diff --git a/RGB.NET.Devices.Corsair/RGB.NET.Devices.Corsair.csproj.DotSettings b/RGB.NET.Devices.Corsair/RGB.NET.Devices.Corsair.csproj.DotSettings
index eeca971..9eb538f 100644
--- a/RGB.NET.Devices.Corsair/RGB.NET.Devices.Corsair.csproj.DotSettings
+++ b/RGB.NET.Devices.Corsair/RGB.NET.Devices.Corsair.csproj.DotSettings
@@ -1,8 +1,13 @@
+ True
+ True
+ True
True
True
True
True
+ True
+ True
True
True
True
@@ -19,4 +24,5 @@
True
True
True
+ True
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Touchbar/CorsairTouchbarRGBDevice.cs b/RGB.NET.Devices.Corsair/Touchbar/CorsairTouchbarRGBDevice.cs
index 092e84c..d5f9248 100644
--- a/RGB.NET.Devices.Corsair/Touchbar/CorsairTouchbarRGBDevice.cs
+++ b/RGB.NET.Devices.Corsair/Touchbar/CorsairTouchbarRGBDevice.cs
@@ -2,6 +2,7 @@
// ReSharper disable UnusedMember.Global
using RGB.NET.Core;
+using System.Collections.Generic;
namespace RGB.NET.Devices.Corsair;
@@ -9,7 +10,7 @@ namespace RGB.NET.Devices.Corsair;
///
/// Represents a corsair touchbar.
///
-public class CorsairTouchbarRGBDevice : CorsairRGBDevice, IDRAM
+public sealed class CorsairTouchbarRGBDevice : CorsairRGBDevice, ILedStripe
{
#region Constructors
@@ -20,8 +21,14 @@ public class CorsairTouchbarRGBDevice : CorsairRGBDeviceThe specific information provided by CUE for the touchbar.
/// The queue used to update this device.
internal CorsairTouchbarRGBDevice(CorsairTouchbarRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
- : base(info, LedMappings.Keyboard, updateQueue) //TODO DarthAffe 17.07.2022: Find someone with such a device and check which LedIds are actually used
+ : base(info, updateQueue)
{ }
#endregion
+
+ #region Methods
+
+ protected override LedMapping CreateMapping(IEnumerable ids) => LedMappings.CreateLedStripMapping(ids);
+
+ #endregion
}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Touchbar/CorsairTouchbarRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair/Touchbar/CorsairTouchbarRGBDeviceInfo.cs
index 9ee690c..04f400d 100644
--- a/RGB.NET.Devices.Corsair/Touchbar/CorsairTouchbarRGBDeviceInfo.cs
+++ b/RGB.NET.Devices.Corsair/Touchbar/CorsairTouchbarRGBDeviceInfo.cs
@@ -10,18 +10,13 @@ namespace RGB.NET.Devices.Corsair;
///
/// Represents a generic information for a .
///
-public class CorsairTouchbarRGBDeviceInfo : CorsairRGBDeviceInfo
+public sealed class CorsairTouchbarRGBDeviceInfo : CorsairRGBDeviceInfo
{
#region Constructors
///
- ///
- /// Internal constructor of managed .
- ///
- /// The index of the .
- /// The native -struct
- internal CorsairTouchbarRGBDeviceInfo(int deviceIndex, _CorsairDeviceInfo nativeInfo)
- : base(deviceIndex, RGBDeviceType.Keypad, nativeInfo)
+ internal CorsairTouchbarRGBDeviceInfo(_CorsairDeviceInfo nativeInfo, int ledCount, int ledOffset)
+ : base(RGBDeviceType.LedStripe, nativeInfo, ledCount, ledOffset)
{ }
#endregion
diff --git a/RGB.NET.Devices.Corsair/Unknown/CorsairUnknownRGBDevice.cs b/RGB.NET.Devices.Corsair/Unknown/CorsairUnknownRGBDevice.cs
new file mode 100644
index 0000000..655bafc
--- /dev/null
+++ b/RGB.NET.Devices.Corsair/Unknown/CorsairUnknownRGBDevice.cs
@@ -0,0 +1,34 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using RGB.NET.Core;
+using System.Collections.Generic;
+
+namespace RGB.NET.Devices.Corsair;
+
+///
+///
+/// Represents a unknown corsair device.
+///
+public sealed class CorsairUnknownRGBDevice : CorsairRGBDevice, IUnknownDevice
+{
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The specific information provided by CUE for the unknown device.
+ /// The queue used to update this device.
+ internal CorsairUnknownRGBDevice(CorsairUnknownRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
+ : base(info, updateQueue)
+ { }
+
+ #endregion
+
+ #region Methods
+
+ protected override LedMapping CreateMapping(IEnumerable ids) => LedMappings.CreateUnknownMapping(ids);
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Unknown/CorsairUnknownRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair/Unknown/CorsairUnknownRGBDeviceInfo.cs
new file mode 100644
index 0000000..770f65b
--- /dev/null
+++ b/RGB.NET.Devices.Corsair/Unknown/CorsairUnknownRGBDeviceInfo.cs
@@ -0,0 +1,23 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using RGB.NET.Core;
+using RGB.NET.Devices.Corsair.Native;
+
+namespace RGB.NET.Devices.Corsair;
+
+///
+///
+/// Represents a generic information for a .
+///
+public sealed class CorsairUnknownRGBDeviceInfo : CorsairRGBDeviceInfo
+{
+ #region Constructors
+
+ ///
+ internal CorsairUnknownRGBDeviceInfo(_CorsairDeviceInfo nativeInfo, int ledCount, int ledOffset)
+ : base(RGBDeviceType.Unknown, nativeInfo, ledCount, ledOffset)
+ { }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/CorsairLegacyDeviceProvider.cs b/RGB.NET.Devices.Corsair_Legacy/CorsairLegacyDeviceProvider.cs
new file mode 100644
index 0000000..9f770e8
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/CorsairLegacyDeviceProvider.cs
@@ -0,0 +1,231 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using RGB.NET.Core;
+using RGB.NET.Devices.CorsairLegacy.Native;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+///
+/// Represents a device provider responsible for corsair (CUE) devices.
+///
+public sealed class CorsairLegacyDeviceProvider : AbstractRGBDeviceProvider
+{
+ #region Properties & Fields
+
+ // ReSharper disable once InconsistentNaming
+ private static readonly object _lock = new();
+
+ private static CorsairLegacyDeviceProvider? _instance;
+ ///
+ /// Gets the singleton instance.
+ ///
+ public static CorsairLegacyDeviceProvider Instance
+ {
+ get
+ {
+ lock (_lock)
+ return _instance ?? new CorsairLegacyDeviceProvider();
+ }
+ }
+
+ ///
+ /// Gets a modifiable list of paths used to find the native SDK-dlls for x86 applications.
+ /// The first match will be used.
+ ///
+ public static List PossibleX86NativePaths { get; } = ["x86/CUESDK.dll", "x86/CUESDK_2019.dll", "x86/CUESDK_2017.dll", "x86/CUESDK_2015.dll", "x86/CUESDK_2013.dll"];
+
+ ///
+ /// Gets a modifiable list of paths used to find the native SDK-dlls for x64 applications.
+ /// The first match will be used.
+ ///
+ public static List PossibleX64NativePaths { get; } = ["x64/CUESDK.dll", "x64/CUESDK.x64_2019.dll", "x64/CUESDK.x64_2017.dll", "x64/CUESDK_2019.dll", "x64/CUESDK_2017.dll", "x64/CUESDK_2015.dll", "x64/CUESDK_2013.dll"];
+
+ ///
+ /// Gets the protocol details for the current SDK-connection.
+ ///
+ public CorsairProtocolDetails? ProtocolDetails { get; private set; }
+
+ ///
+ /// Gets the last error documented by CUE.
+ ///
+ public static CorsairError LastError => _CUESDK.CorsairGetLastError();
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Thrown if this constructor is called even if there is already an instance of this class.
+ public CorsairLegacyDeviceProvider()
+ {
+ lock (_lock)
+ {
+ if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(CorsairLegacyDeviceProvider)}");
+ _instance = this;
+ }
+ }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ protected override void InitializeSDK()
+ {
+ _CUESDK.Reload();
+
+ ProtocolDetails = new CorsairProtocolDetails(_CUESDK.CorsairPerformProtocolHandshake());
+
+ CorsairError error = LastError;
+ if (error != CorsairError.Success)
+ Throw(new CUEException(error), true);
+
+ if (ProtocolDetails.BreakingChanges)
+ Throw(new RGBDeviceException("The SDK currently used isn't compatible with the installed version of CUE.\r\n"
+ + $"CUE-Version: {ProtocolDetails.ServerVersion} (Protocol {ProtocolDetails.ServerProtocolVersion})\r\n"
+ + $"SDK-Version: {ProtocolDetails.SdkVersion} (Protocol {ProtocolDetails.SdkProtocolVersion})"), true);
+
+ // DarthAffe 02.02.2021: 127 is iCUE
+ if (!_CUESDK.CorsairSetLayerPriority(128))
+ Throw(new CUEException(LastError));
+ }
+
+ ///
+ protected override IEnumerable LoadDevices()
+ {
+ foreach (ICorsairRGBDevice corsairDevice in LoadCorsairDevices())
+ {
+ corsairDevice.Initialize();
+ yield return corsairDevice;
+ }
+ }
+
+ private IEnumerable LoadCorsairDevices()
+ {
+ int deviceCount = _CUESDK.CorsairGetDeviceCount();
+ for (int i = 0; i < deviceCount; i++)
+ {
+ _CorsairDeviceInfo nativeDeviceInfo = (_CorsairDeviceInfo)Marshal.PtrToStructure(_CUESDK.CorsairGetDeviceInfo(i), typeof(_CorsairDeviceInfo))!;
+ if (!((CorsairDeviceCaps)nativeDeviceInfo.capsMask).HasFlag(CorsairDeviceCaps.Lighting))
+ continue; // Everything that doesn't support lighting control is useless
+
+ CorsairDeviceUpdateQueue updateQueue = new(GetUpdateTrigger(), i);
+ switch (nativeDeviceInfo.type)
+ {
+ case CorsairDeviceType.Keyboard:
+ yield return new CorsairKeyboardRGBDevice(new CorsairKeyboardRGBDeviceInfo(i, nativeDeviceInfo), updateQueue);
+ break;
+
+ case CorsairDeviceType.Mouse:
+ yield return new CorsairMouseRGBDevice(new CorsairMouseRGBDeviceInfo(i, nativeDeviceInfo), updateQueue);
+ break;
+
+ case CorsairDeviceType.Headset:
+ yield return new CorsairHeadsetRGBDevice(new CorsairHeadsetRGBDeviceInfo(i, nativeDeviceInfo), updateQueue);
+ break;
+
+ case CorsairDeviceType.Mousepad:
+ yield return new CorsairMousepadRGBDevice(new CorsairMousepadRGBDeviceInfo(i, nativeDeviceInfo), updateQueue);
+ break;
+
+ case CorsairDeviceType.HeadsetStand:
+ yield return new CorsairHeadsetStandRGBDevice(new CorsairHeadsetStandRGBDeviceInfo(i, nativeDeviceInfo), updateQueue);
+ break;
+
+ case CorsairDeviceType.MemoryModule:
+ yield return new CorsairMemoryRGBDevice(new CorsairMemoryRGBDeviceInfo(i, nativeDeviceInfo), updateQueue);
+ break;
+
+ case CorsairDeviceType.Mainboard:
+ yield return new CorsairMainboardRGBDevice(new CorsairMainboardRGBDeviceInfo(i, nativeDeviceInfo), updateQueue);
+ break;
+
+ case CorsairDeviceType.GraphicsCard:
+ yield return new CorsairGraphicsCardRGBDevice(new CorsairGraphicsCardRGBDeviceInfo(i, nativeDeviceInfo), updateQueue);
+ break;
+
+ case CorsairDeviceType.Touchbar:
+ yield return new CorsairTouchbarRGBDevice(new CorsairTouchbarRGBDeviceInfo(i, nativeDeviceInfo), updateQueue);
+ break;
+
+ case CorsairDeviceType.Cooler:
+ case CorsairDeviceType.CommanderPro:
+ case CorsairDeviceType.LightningNodePro:
+ List<_CorsairChannelInfo> channels = GetChannels(nativeDeviceInfo).ToList();
+ int channelsLedCount = channels.Sum(x => x.totalLedsCount);
+ int deviceLedCount = nativeDeviceInfo.ledsCount - channelsLedCount;
+
+ if (deviceLedCount > 0)
+ yield return new CorsairCustomRGBDevice(new CorsairCustomRGBDeviceInfo(i, nativeDeviceInfo, deviceLedCount), updateQueue);
+
+ int ledOffset = deviceLedCount;
+ foreach (_CorsairChannelInfo channelInfo in channels)
+ {
+ int channelDeviceInfoStructSize = Marshal.SizeOf(typeof(_CorsairChannelDeviceInfo));
+ nint channelDeviceInfoPtr = channelInfo.devices;
+ for (int device = 0; (device < channelInfo.devicesCount) && (ledOffset < nativeDeviceInfo.ledsCount); device++)
+ {
+ _CorsairChannelDeviceInfo channelDeviceInfo = (_CorsairChannelDeviceInfo)Marshal.PtrToStructure(channelDeviceInfoPtr, typeof(_CorsairChannelDeviceInfo))!;
+
+ yield return new CorsairCustomRGBDevice(new CorsairCustomRGBDeviceInfo(i, nativeDeviceInfo, channelDeviceInfo, ledOffset), updateQueue);
+
+ ledOffset += channelDeviceInfo.deviceLedCount;
+ channelDeviceInfoPtr += channelDeviceInfoStructSize;
+ }
+ }
+ break;
+
+ default:
+ Throw(new RGBDeviceException("Unknown Device-Type"));
+ break;
+ }
+ }
+ }
+
+ private static IEnumerable<_CorsairChannelInfo> GetChannels(_CorsairDeviceInfo deviceInfo)
+ {
+ _CorsairChannelsInfo? channelsInfo = deviceInfo.channels;
+ if (channelsInfo == null) yield break;
+
+ nint channelInfoPtr = channelsInfo.channels;
+ for (int channel = 0; channel < channelsInfo.channelsCount; channel++)
+ {
+ yield return (_CorsairChannelInfo)Marshal.PtrToStructure(channelInfoPtr, typeof(_CorsairChannelInfo))!;
+
+ int channelInfoStructSize = Marshal.SizeOf(typeof(_CorsairChannelInfo));
+ channelInfoPtr += channelInfoStructSize;
+ }
+ }
+
+ ///
+ protected override void Reset()
+ {
+ ProtocolDetails = null;
+
+ base.Reset();
+ }
+
+ ///
+ protected override void Dispose(bool disposing)
+ {
+ lock (_lock)
+ {
+ base.Dispose(disposing);
+
+ try { _CUESDK.UnloadCUESDK(); }
+ catch { /* at least we tried */ }
+
+ _instance = null;
+ }
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Custom/CorsairCustomRGBDevice.cs b/RGB.NET.Devices.Corsair_Legacy/Custom/CorsairCustomRGBDevice.cs
similarity index 71%
rename from RGB.NET.Devices.Corsair/Custom/CorsairCustomRGBDevice.cs
rename to RGB.NET.Devices.Corsair_Legacy/Custom/CorsairCustomRGBDevice.cs
index 1bc3b6e..cc2b57b 100644
--- a/RGB.NET.Devices.Corsair/Custom/CorsairCustomRGBDevice.cs
+++ b/RGB.NET.Devices.Corsair_Legacy/Custom/CorsairCustomRGBDevice.cs
@@ -1,12 +1,12 @@
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable UnusedMember.Global
-using System;
+using System.Linq;
using System.Runtime.InteropServices;
using RGB.NET.Core;
-using RGB.NET.Devices.Corsair.Native;
+using RGB.NET.Devices.CorsairLegacy.Native;
-namespace RGB.NET.Devices.Corsair;
+namespace RGB.NET.Devices.CorsairLegacy;
///
///
@@ -18,12 +18,12 @@ public class CorsairCustomRGBDevice : CorsairRGBDevice
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
/// The specific information provided by CUE for the custom-device.
/// The queue used to update this device.
internal CorsairCustomRGBDevice(CorsairCustomRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
- : base(info, new LedMapping(), updateQueue)
+ : base(info, [], updateQueue)
{ }
#endregion
@@ -39,7 +39,7 @@ public class CorsairCustomRGBDevice : CorsairRGBDevice 0)
+ FixOffsetDeviceLayout();
+ }
+
+ ///
+ /// Fixes the locations for devices split by offset by aligning them to the top left.
+ ///
+ protected virtual void FixOffsetDeviceLayout()
+ {
+ float minX = this.Min(x => x.Location.X);
+ float minY = this.Min(x => x.Location.Y);
+
+ foreach (Led led in this)
+ led.Location = led.Location.Translate(-minX, -minY);
}
private static LedId GetReferenceLed(RGBDeviceType deviceType)
diff --git a/RGB.NET.Devices.Corsair/Custom/CorsairCustomRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair_Legacy/Custom/CorsairCustomRGBDeviceInfo.cs
similarity index 94%
rename from RGB.NET.Devices.Corsair/Custom/CorsairCustomRGBDeviceInfo.cs
rename to RGB.NET.Devices.Corsair_Legacy/Custom/CorsairCustomRGBDeviceInfo.cs
index 5d0858a..783089e 100644
--- a/RGB.NET.Devices.Corsair/Custom/CorsairCustomRGBDeviceInfo.cs
+++ b/RGB.NET.Devices.Corsair_Legacy/Custom/CorsairCustomRGBDeviceInfo.cs
@@ -5,13 +5,13 @@ using System;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using RGB.NET.Core;
-using RGB.NET.Devices.Corsair.Native;
+using RGB.NET.Devices.CorsairLegacy.Native;
-namespace RGB.NET.Devices.Corsair;
+namespace RGB.NET.Devices.CorsairLegacy;
///
///
-/// Represents a generic information for a .
+/// Represents a generic information for a .
///
public class CorsairCustomRGBDeviceInfo : CorsairRGBDeviceInfo
{
@@ -41,7 +41,7 @@ public class CorsairCustomRGBDeviceInfo : CorsairRGBDeviceInfo
/// The offset used to find the LEDs of this device.
internal CorsairCustomRGBDeviceInfo(int deviceIndex, _CorsairDeviceInfo nativeInfo, _CorsairChannelDeviceInfo channelDeviceInfo, int ledOffset)
: base(deviceIndex, GetDeviceType(channelDeviceInfo.type), nativeInfo,
- GetModelName(nativeInfo.model == IntPtr.Zero ? string.Empty : Regex.Replace(Marshal.PtrToStringAnsi(nativeInfo.model) ?? string.Empty, " ?DEMO", string.Empty, RegexOptions.IgnoreCase), channelDeviceInfo))
+ GetModelName(nativeInfo.model == 0 ? string.Empty : Regex.Replace(Marshal.PtrToStringAnsi(nativeInfo.model) ?? string.Empty, " ?DEMO", string.Empty, RegexOptions.IgnoreCase), channelDeviceInfo))
{
this.LedOffset = ledOffset;
diff --git a/RGB.NET.Devices.Corsair/Enum/CorsairAccessMode.cs b/RGB.NET.Devices.Corsair_Legacy/Enum/CorsairAccessMode.cs
similarity index 88%
rename from RGB.NET.Devices.Corsair/Enum/CorsairAccessMode.cs
rename to RGB.NET.Devices.Corsair_Legacy/Enum/CorsairAccessMode.cs
index 1ecdda4..98885da 100644
--- a/RGB.NET.Devices.Corsair/Enum/CorsairAccessMode.cs
+++ b/RGB.NET.Devices.Corsair_Legacy/Enum/CorsairAccessMode.cs
@@ -3,7 +3,7 @@
#pragma warning disable 1591 // Missing XML comment for publicly visible type or member
-namespace RGB.NET.Devices.Corsair;
+namespace RGB.NET.Devices.CorsairLegacy;
///
/// Represents an SDK access mode.
diff --git a/RGB.NET.Devices.Corsair_Legacy/Enum/CorsairChannelDeviceType.cs b/RGB.NET.Devices.Corsair_Legacy/Enum/CorsairChannelDeviceType.cs
new file mode 100644
index 0000000..99c943f
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Enum/CorsairChannelDeviceType.cs
@@ -0,0 +1,25 @@
+// ReSharper disable InconsistentNaming
+// ReSharper disable UnusedMember.Global
+
+
+#pragma warning disable 1591 // Missing XML comment for publicly visible type or member
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+/// Contains a list of available corsair channel device types.
+///
+public enum CorsairChannelDeviceType
+{
+ Invalid = 0,
+ FanHD = 1,
+ FanSP = 2,
+ FanLL = 3,
+ FanML = 4,
+ Strip = 5,
+ DAP = 6,
+ Pump = 7,
+ FanQL = 8,
+ WaterBlock = 9,
+ EightLedSeriesFan = 10 // Previously called FanSPPRO
+};
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Enum/CorsairDeviceCaps.cs b/RGB.NET.Devices.Corsair_Legacy/Enum/CorsairDeviceCaps.cs
similarity index 93%
rename from RGB.NET.Devices.Corsair/Enum/CorsairDeviceCaps.cs
rename to RGB.NET.Devices.Corsair_Legacy/Enum/CorsairDeviceCaps.cs
index c92807b..2e77521 100644
--- a/RGB.NET.Devices.Corsair/Enum/CorsairDeviceCaps.cs
+++ b/RGB.NET.Devices.Corsair_Legacy/Enum/CorsairDeviceCaps.cs
@@ -3,7 +3,7 @@
using System;
-namespace RGB.NET.Devices.Corsair;
+namespace RGB.NET.Devices.CorsairLegacy;
///
/// Contains a list of corsair device capabilities.
diff --git a/RGB.NET.Devices.Corsair_Legacy/Enum/CorsairDeviceType.cs b/RGB.NET.Devices.Corsair_Legacy/Enum/CorsairDeviceType.cs
new file mode 100644
index 0000000..339a72f
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Enum/CorsairDeviceType.cs
@@ -0,0 +1,27 @@
+// ReSharper disable InconsistentNaming
+// ReSharper disable UnusedMember.Global
+
+
+#pragma warning disable 1591 // Missing XML comment for publicly visible type or member
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+/// Contains a list of available corsair device types.
+///
+public enum CorsairDeviceType
+{
+ Unknown = 0,
+ Mouse = 1,
+ Keyboard = 2,
+ Headset = 3,
+ Mousepad = 4,
+ HeadsetStand = 5,
+ CommanderPro = 6,
+ LightningNodePro = 7,
+ MemoryModule = 8,
+ Cooler = 9,
+ Mainboard = 10,
+ GraphicsCard = 11,
+ Touchbar = 12
+};
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Enum/CorsairError.cs b/RGB.NET.Devices.Corsair_Legacy/Enum/CorsairError.cs
new file mode 100644
index 0000000..dfe8703
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Enum/CorsairError.cs
@@ -0,0 +1,41 @@
+// ReSharper disable InconsistentNaming
+// ReSharper disable UnusedMember.Global
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+/// Shared list of all errors which could happen during calling of Corsair* functions.
+///
+public enum CorsairError
+{
+ ///
+ /// If previously called function completed successfully.
+ ///
+ Success,
+
+ ///
+ /// CUE is not running or was shut down or third-party control is disabled in CUE settings. (runtime error)
+ ///
+ ServerNotFound,
+
+ ///
+ /// If some other client has or took over exclusive control. (runtime error)
+ ///
+ NoControl,
+
+ ///
+ /// If developer did not perform protocol handshake. (developer error)
+ ///
+ ProtocolHandshakeMissing,
+
+ ///
+ /// If developer is calling the function that is not supported by the server (either because protocol has broken by server or client or because the function is new and server is too old.
+ /// Check CorsairProtocolDetails for details). (developer error)
+ ///
+ IncompatibleProtocol,
+
+ ///
+ /// If developer supplied invalid arguments to the function (for specifics look at function descriptions). (developer error)
+ ///
+ InvalidArguments
+};
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Enum/CorsairLedId.cs b/RGB.NET.Devices.Corsair_Legacy/Enum/CorsairLedId.cs
similarity index 99%
rename from RGB.NET.Devices.Corsair/Enum/CorsairLedId.cs
rename to RGB.NET.Devices.Corsair_Legacy/Enum/CorsairLedId.cs
index a0cfeab..00ce18b 100644
--- a/RGB.NET.Devices.Corsair/Enum/CorsairLedId.cs
+++ b/RGB.NET.Devices.Corsair_Legacy/Enum/CorsairLedId.cs
@@ -2,7 +2,7 @@
// ReSharper disable UnusedMember.Global
#pragma warning disable 1591
-namespace RGB.NET.Devices.Corsair;
+namespace RGB.NET.Devices.CorsairLegacy;
///
/// Contains a list of all LEDs available for all corsair devices.
diff --git a/RGB.NET.Devices.Corsair_Legacy/Enum/CorsairLogicalKeyboardLayout.cs b/RGB.NET.Devices.Corsair_Legacy/Enum/CorsairLogicalKeyboardLayout.cs
new file mode 100644
index 0000000..48c8c21
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Enum/CorsairLogicalKeyboardLayout.cs
@@ -0,0 +1,30 @@
+// ReSharper disable InconsistentNaming
+// ReSharper disable UnusedMember.Global
+#pragma warning disable 1591
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+/// Contains a list of available logical layouts for corsair keyboards.
+///
+public enum CorsairLogicalKeyboardLayout
+{
+ US_Int = 1,
+ NA = 2,
+ EU = 3,
+ UK = 4,
+ BE = 5,
+ BR = 6,
+ CH = 7,
+ CN = 8,
+ DE = 9,
+ ES = 10,
+ FR = 11,
+ IT = 12,
+ ND = 13,
+ RU = 14,
+ JP = 15,
+ KR = 16,
+ TW = 17,
+ MEX = 18
+};
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Enum/CorsairPhysicalKeyboardLayout.cs b/RGB.NET.Devices.Corsair_Legacy/Enum/CorsairPhysicalKeyboardLayout.cs
new file mode 100644
index 0000000..c917741
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Enum/CorsairPhysicalKeyboardLayout.cs
@@ -0,0 +1,35 @@
+// ReSharper disable UnusedMember.Global
+// ReSharper disable InconsistentNaming
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+/// Contains a list of available physical layouts for corsair keyboards.
+///
+public enum CorsairPhysicalKeyboardLayout
+{
+ ///
+ /// US-Keyboard
+ ///
+ US = 1,
+
+ ///
+ /// UK-Keyboard
+ ///
+ UK = 2,
+
+ ///
+ /// BR-Keyboard
+ ///
+ BR = 3,
+
+ ///
+ /// JP-Keyboard
+ ///
+ JP = 4,
+
+ ///
+ /// KR-Keyboard
+ ///
+ KR = 5
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Enum/CorsairPhysicalMouseLayout.cs b/RGB.NET.Devices.Corsair_Legacy/Enum/CorsairPhysicalMouseLayout.cs
similarity index 97%
rename from RGB.NET.Devices.Corsair/Enum/CorsairPhysicalMouseLayout.cs
rename to RGB.NET.Devices.Corsair_Legacy/Enum/CorsairPhysicalMouseLayout.cs
index 33c317c..9be87b4 100644
--- a/RGB.NET.Devices.Corsair/Enum/CorsairPhysicalMouseLayout.cs
+++ b/RGB.NET.Devices.Corsair_Legacy/Enum/CorsairPhysicalMouseLayout.cs
@@ -1,4 +1,4 @@
-namespace RGB.NET.Devices.Corsair;
+namespace RGB.NET.Devices.CorsairLegacy;
///
/// Contains a list of available physical layouts for mice.
diff --git a/RGB.NET.Devices.Corsair_Legacy/Exceptions/CUEException.cs b/RGB.NET.Devices.Corsair_Legacy/Exceptions/CUEException.cs
new file mode 100644
index 0000000..1618afb
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Exceptions/CUEException.cs
@@ -0,0 +1,36 @@
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable MemberCanBePrivate.Global
+
+using System;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+///
+/// Represents an exception thrown by the CUE.
+///
+public class CUEException : ApplicationException
+{
+ #region Properties & Fields
+
+ ///
+ /// Gets the provided by CUE.
+ ///
+ public CorsairError Error { get; }
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The provided by CUE, which leads to this exception.
+ public CUEException(CorsairError error)
+ {
+ this.Error = error;
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Generic/CorsairDeviceUpdateQueue.cs b/RGB.NET.Devices.Corsair_Legacy/Generic/CorsairDeviceUpdateQueue.cs
new file mode 100644
index 0000000..a766911
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Generic/CorsairDeviceUpdateQueue.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Runtime.InteropServices;
+using RGB.NET.Core;
+using RGB.NET.Devices.CorsairLegacy.Native;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+///
+/// Represents the update-queue performing updates for corsair devices.
+///
+public class CorsairDeviceUpdateQueue : UpdateQueue
+{
+ #region Properties & Fields
+
+ private int _deviceIndex;
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The update trigger used by this queue.
+ /// The index used to identify the device.
+ public CorsairDeviceUpdateQueue(IDeviceUpdateTrigger updateTrigger, int deviceIndex)
+ : base(updateTrigger)
+ {
+ this._deviceIndex = deviceIndex;
+ }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ protected override bool Update(in ReadOnlySpan<(object key, Color color)> dataSet)
+ {
+ try
+ {
+ int structSize = Marshal.SizeOf(typeof(_CorsairLedColor));
+ nint ptr = Marshal.AllocHGlobal(structSize * dataSet.Length);
+ nint addPtr = ptr;
+ try
+ {
+ foreach ((object key, Color color) in dataSet)
+ {
+ _CorsairLedColor corsairColor = new()
+ {
+ ledId = (int)key,
+ r = color.GetR(),
+ g = color.GetG(),
+ b = color.GetB()
+ };
+
+ Marshal.StructureToPtr(corsairColor, addPtr, false);
+ addPtr += structSize;
+ }
+
+ _CUESDK.CorsairSetLedsColorsBufferByDeviceIndex(_deviceIndex, dataSet.Length, ptr);
+ _CUESDK.CorsairSetLedsColorsFlushBuffer();
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(ptr);
+ }
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ CorsairLegacyDeviceProvider.Instance.Throw(ex);
+ }
+
+ return false;
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Generic/CorsairProtocolDetails.cs b/RGB.NET.Devices.Corsair_Legacy/Generic/CorsairProtocolDetails.cs
new file mode 100644
index 0000000..8bab4b4
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Generic/CorsairProtocolDetails.cs
@@ -0,0 +1,64 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+
+using System.Runtime.InteropServices;
+using RGB.NET.Devices.CorsairLegacy.Native;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+/// Managed wrapper for CorsairProtocolDetails.
+///
+public class CorsairProtocolDetails
+{
+ #region Properties & Fields
+
+ ///
+ /// String containing version of SDK(like "1.0.0.1").
+ /// Always contains valid value even if there was no CUE found.
+ ///
+ public string? SdkVersion { get; }
+
+ ///
+ /// String containing version of CUE(like "1.0.0.1") or NULL if CUE was not found.
+ ///
+ public string? ServerVersion { get; }
+
+ ///
+ /// Integer that specifies version of protocol that is implemented by current SDK.
+ /// Numbering starts from 1.
+ /// Always contains valid value even if there was no CUE found.
+ ///
+ public int SdkProtocolVersion { get; }
+
+ ///
+ /// Integer that specifies version of protocol that is implemented by CUE.
+ /// Numbering starts from 1.
+ /// If CUE was not found then this value will be 0.
+ ///
+ public int ServerProtocolVersion { get; }
+
+ ///
+ /// Boolean that specifies if there were breaking changes between version of protocol implemented by server and client.
+ ///
+ public bool BreakingChanges { get; }
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Internal constructor of managed CorsairProtocolDetails.
+ ///
+ /// The native CorsairProtocolDetails-struct
+ internal CorsairProtocolDetails(_CorsairProtocolDetails nativeDetails)
+ {
+ this.SdkVersion = nativeDetails.sdkVersion == 0 ? null : Marshal.PtrToStringAnsi(nativeDetails.sdkVersion);
+ this.ServerVersion = nativeDetails.serverVersion == 0 ? null : Marshal.PtrToStringAnsi(nativeDetails.serverVersion);
+ this.SdkProtocolVersion = nativeDetails.sdkProtocolVersion;
+ this.ServerProtocolVersion = nativeDetails.serverProtocolVersion;
+ this.BreakingChanges = nativeDetails.breakingChanges != 0;
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Generic/CorsairRGBDevice.cs b/RGB.NET.Devices.Corsair_Legacy/Generic/CorsairRGBDevice.cs
new file mode 100644
index 0000000..e86a92a
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Generic/CorsairRGBDevice.cs
@@ -0,0 +1,75 @@
+using System.Runtime.InteropServices;
+using RGB.NET.Core;
+using RGB.NET.Devices.CorsairLegacy.Native;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+///
+/// Represents a generic CUE-device. (keyboard, mouse, headset, mousepad).
+///
+public abstract class CorsairRGBDevice : AbstractRGBDevice, ICorsairRGBDevice
+ where TDeviceInfo : CorsairRGBDeviceInfo
+{
+ #region Properties & Fields
+
+ ///
+ /// Gets the mapping of to used to update the LEDs of this device.
+ ///
+ protected LedMapping Mapping { get; }
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The generic information provided by CUE for the device.
+ /// The mapping to used to update the LEDs of this device.
+ /// The queue used to update this device.
+ protected CorsairRGBDevice(TDeviceInfo info, LedMapping mapping, CorsairDeviceUpdateQueue updateQueue)
+ : base(info, updateQueue)
+ {
+ this.Mapping = mapping;
+ }
+
+ #endregion
+
+ #region Methods
+
+ void ICorsairRGBDevice.Initialize() => InitializeLayout();
+
+ ///
+ /// Initializes the LEDs of the device based on the data provided by the SDK.
+ ///
+ protected virtual void InitializeLayout()
+ {
+ _CorsairLedPositions? nativeLedPositions = (_CorsairLedPositions?)Marshal.PtrToStructure(_CUESDK.CorsairGetLedPositionsByDeviceIndex(DeviceInfo.CorsairDeviceIndex), typeof(_CorsairLedPositions));
+ if (nativeLedPositions == null) return;
+
+ int structSize = Marshal.SizeOf(typeof(_CorsairLedPosition));
+ nint ptr = nativeLedPositions.pLedPosition;
+
+ for (int i = 0; i < nativeLedPositions.numberOfLed; i++)
+ {
+ _CorsairLedPosition? ledPosition = (_CorsairLedPosition?)Marshal.PtrToStructure(ptr, typeof(_CorsairLedPosition));
+ if (ledPosition == null)
+ {
+ ptr += structSize;
+ continue;
+ }
+
+ LedId ledId = Mapping.TryGetValue(ledPosition.LedId, out LedId id) ? id : LedId.Invalid;
+ Rectangle rectangle = ledPosition.ToRectangle();
+ AddLed(ledId, rectangle.Location, rectangle.Size);
+
+ ptr += structSize;
+ }
+ }
+
+ ///
+ protected override object GetLedCustomData(LedId ledId) => Mapping.TryGetValue(ledId, out CorsairLedId corsairLedId) ? corsairLedId : CorsairLedId.Invalid;
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Generic/CorsairRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair_Legacy/Generic/CorsairRGBDeviceInfo.cs
new file mode 100644
index 0000000..8715185
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Generic/CorsairRGBDeviceInfo.cs
@@ -0,0 +1,94 @@
+using System.Runtime.InteropServices;
+using System.Text.RegularExpressions;
+using RGB.NET.Core;
+using RGB.NET.Devices.CorsairLegacy.Native;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+///
+/// Represents a generic information for a Corsair-.
+///
+public class CorsairRGBDeviceInfo : IRGBDeviceInfo
+{
+ #region Properties & Fields
+
+ ///
+ /// Gets the corsair specific device type.
+ ///
+ public CorsairDeviceType CorsairDeviceType { get; }
+
+ ///
+ /// Gets the index of the .
+ ///
+ public int CorsairDeviceIndex { get; }
+
+ ///
+ public RGBDeviceType DeviceType { get; }
+
+ ///
+ public string DeviceName { get; }
+
+ ///
+ public string Manufacturer => "Corsair";
+
+ ///
+ public string Model { get; }
+
+ ///
+ /// Returns the unique ID provided by the Corsair-SDK.
+ /// Returns string.Empty for Custom devices.
+ ///
+ public string DeviceId { get; }
+
+ ///
+ public object? LayoutMetadata { get; set; }
+
+ ///
+ /// Gets a flag that describes device capabilities. ()
+ ///
+ public CorsairDeviceCaps CapsMask { get; }
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Internal constructor of managed .
+ ///
+ /// The index of the .
+ /// The type of the .
+ /// The native -struct
+ internal CorsairRGBDeviceInfo(int deviceIndex, RGBDeviceType deviceType, _CorsairDeviceInfo nativeInfo)
+ {
+ this.CorsairDeviceIndex = deviceIndex;
+ this.DeviceType = deviceType;
+ this.CorsairDeviceType = nativeInfo.type;
+ this.Model = nativeInfo.model == 0 ? string.Empty : Regex.Replace(Marshal.PtrToStringAnsi(nativeInfo.model) ?? string.Empty, " ?DEMO", string.Empty, RegexOptions.IgnoreCase);
+ this.DeviceId = nativeInfo.deviceId ?? string.Empty;
+ this.CapsMask = (CorsairDeviceCaps)nativeInfo.capsMask;
+
+ DeviceName = DeviceHelper.CreateDeviceName(Manufacturer, Model);
+ }
+
+ ///
+ /// Internal constructor of managed .
+ ///
+ /// The index of the .
+ /// The type of the .
+ /// The native -struct
+ /// The name of the device-model (overwrites the one provided with the device info).
+ internal CorsairRGBDeviceInfo(int deviceIndex, RGBDeviceType deviceType, _CorsairDeviceInfo nativeInfo, string modelName)
+ {
+ this.CorsairDeviceIndex = deviceIndex;
+ this.DeviceType = deviceType;
+ this.CorsairDeviceType = nativeInfo.type;
+ this.Model = modelName;
+ this.DeviceId = nativeInfo.deviceId ?? string.Empty;
+ this.CapsMask = (CorsairDeviceCaps)nativeInfo.capsMask;
+
+ DeviceName = DeviceHelper.CreateDeviceName(Manufacturer, Model);
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Generic/ICorsairRGBDevice.cs b/RGB.NET.Devices.Corsair_Legacy/Generic/ICorsairRGBDevice.cs
new file mode 100644
index 0000000..dbb031b
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Generic/ICorsairRGBDevice.cs
@@ -0,0 +1,11 @@
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+/// Represents a corsair RGB-device.
+///
+public interface ICorsairRGBDevice : IRGBDevice
+{
+ internal void Initialize();
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Generic/LedMappings.cs b/RGB.NET.Devices.Corsair_Legacy/Generic/LedMappings.cs
new file mode 100644
index 0000000..d528c2e
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Generic/LedMappings.cs
@@ -0,0 +1,302 @@
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+/// Contains mappings for to .
+///
+public static class LedMappings
+{
+ static LedMappings()
+ {
+ for (int i = 0; i <= (CorsairLedId.GPU50 - CorsairLedId.GPU1); i++)
+ GraphicsCard.Add(LedId.GraphicsCard1 + i, CorsairLedId.GPU1 + i);
+
+ for (int i = 0; i <= (CorsairLedId.HeadsetStandZone9 - CorsairLedId.HeadsetStandZone1); i++)
+ HeadsetStand.Add(LedId.HeadsetStand1 + i, CorsairLedId.HeadsetStandZone1 + i);
+
+ for (int i = 0; i <= (CorsairLedId.Mainboard100 - CorsairLedId.Mainboard1); i++)
+ Mainboard.Add(LedId.Mainboard1 + i, CorsairLedId.Mainboard1 + i);
+
+ for (int i = 0; i <= (CorsairLedId.DRAM12 - CorsairLedId.DRAM1); i++)
+ Memory.Add(LedId.DRAM1 + i, CorsairLedId.DRAM1 + i);
+
+ for (int i = 0; i <= (CorsairLedId.Zone15 - CorsairLedId.Zone1); i++)
+ Mousepad.Add(LedId.Mousepad1 + i, CorsairLedId.Zone1 + i);
+
+ for (int i = 0; i <= (CorsairLedId.OemLed100 - CorsairLedId.OemLed1); i++)
+ Keyboard.Add(LedId.Custom1 + i, CorsairLedId.OemLed1 + i);
+
+ for (int i = 0; i <= (CorsairLedId.OemLed250 - CorsairLedId.OemLed101); i++)
+ Keyboard.Add(LedId.Custom101 + i, CorsairLedId.OemLed101 + i);
+ }
+
+ ///
+ /// Gets the mapping for graphics cards.
+ ///
+ public static LedMapping GraphicsCard { get; } = [];
+
+ ///
+ /// Gets the mapping for headsets.
+ ///
+ public static LedMapping HeadsetStand { get; } = [];
+
+ ///
+ /// Gets the mapping for mainboards.
+ ///
+ public static LedMapping Mainboard { get; } = [];
+
+ ///
+ /// Gets the mapping for memory.
+ ///
+ public static LedMapping Memory { get; } = [];
+
+ ///
+ /// Gets the mapping for mousepads.
+ ///
+ public static LedMapping Mousepad { get; } = [];
+
+ ///
+ /// Gets the mapping for headsets.
+ ///
+ public static LedMapping Headset { get; } = new()
+ {
+ { LedId.Headset1, CorsairLedId.LeftLogo },
+ { LedId.Headset2, CorsairLedId.RightLogo },
+ };
+
+ ///
+ /// Gets the mapping for mice.
+ ///
+ public static LedMapping Mouse { get; } = new()
+ {
+ { LedId.Mouse1, CorsairLedId.B1 },
+ { LedId.Mouse2, CorsairLedId.B2 },
+ { LedId.Mouse3, CorsairLedId.B3 },
+ { LedId.Mouse4, CorsairLedId.B4 },
+ { LedId.Mouse5, CorsairLedId.B5 },
+ { LedId.Mouse6, CorsairLedId.B6 },
+ { LedId.Mouse7, CorsairLedId.B7 },
+ { LedId.Mouse8, CorsairLedId.B8 },
+ { LedId.Mouse9, CorsairLedId.B9 },
+ { LedId.Mouse10, CorsairLedId.B10 },
+ { LedId.Mouse11, CorsairLedId.B11 },
+ { LedId.Mouse12, CorsairLedId.B12 },
+ { LedId.Mouse13, CorsairLedId.B13 },
+ { LedId.Mouse14, CorsairLedId.B14 },
+ { LedId.Mouse15, CorsairLedId.B15 },
+ { LedId.Mouse16, CorsairLedId.B16 },
+ { LedId.Mouse17, CorsairLedId.B17 },
+ { LedId.Mouse18, CorsairLedId.B18 },
+ { LedId.Mouse19, CorsairLedId.B19 },
+ { LedId.Mouse20, CorsairLedId.B20 },
+ };
+
+ ///
+ /// Gets the mapping for keyboards.
+ ///
+ public static LedMapping Keyboard { get; } = new()
+ {
+ { LedId.Invalid, CorsairLedId.Invalid },
+ { LedId.Logo, CorsairLedId.Logo },
+ { LedId.Keyboard_Escape, CorsairLedId.Escape },
+ { LedId.Keyboard_F1, CorsairLedId.F1 },
+ { LedId.Keyboard_F2, CorsairLedId.F2 },
+ { LedId.Keyboard_F3, CorsairLedId.F3 },
+ { LedId.Keyboard_F4, CorsairLedId.F4 },
+ { LedId.Keyboard_F5, CorsairLedId.F5 },
+ { LedId.Keyboard_F6, CorsairLedId.F6 },
+ { LedId.Keyboard_F7, CorsairLedId.F7 },
+ { LedId.Keyboard_F8, CorsairLedId.F8 },
+ { LedId.Keyboard_F9, CorsairLedId.F9 },
+ { LedId.Keyboard_F10, CorsairLedId.F10 },
+ { LedId.Keyboard_F11, CorsairLedId.F11 },
+ { LedId.Keyboard_GraveAccentAndTilde, CorsairLedId.GraveAccentAndTilde },
+ { LedId.Keyboard_1, CorsairLedId.D1 },
+ { LedId.Keyboard_2, CorsairLedId.D2 },
+ { LedId.Keyboard_3, CorsairLedId.D3 },
+ { LedId.Keyboard_4, CorsairLedId.D4 },
+ { LedId.Keyboard_5, CorsairLedId.D5 },
+ { LedId.Keyboard_6, CorsairLedId.D6 },
+ { LedId.Keyboard_7, CorsairLedId.D7 },
+ { LedId.Keyboard_8, CorsairLedId.D8 },
+ { LedId.Keyboard_9, CorsairLedId.D9 },
+ { LedId.Keyboard_0, CorsairLedId.D0 },
+ { LedId.Keyboard_MinusAndUnderscore, CorsairLedId.MinusAndUnderscore },
+ { LedId.Keyboard_Tab, CorsairLedId.Tab },
+ { LedId.Keyboard_Q, CorsairLedId.Q },
+ { LedId.Keyboard_W, CorsairLedId.W },
+ { LedId.Keyboard_E, CorsairLedId.E },
+ { LedId.Keyboard_R, CorsairLedId.R },
+ { LedId.Keyboard_T, CorsairLedId.T },
+ { LedId.Keyboard_Y, CorsairLedId.Y },
+ { LedId.Keyboard_U, CorsairLedId.U },
+ { LedId.Keyboard_I, CorsairLedId.I },
+ { LedId.Keyboard_O, CorsairLedId.O },
+ { LedId.Keyboard_P, CorsairLedId.P },
+ { LedId.Keyboard_BracketLeft, CorsairLedId.BracketLeft },
+ { LedId.Keyboard_CapsLock, CorsairLedId.CapsLock },
+ { LedId.Keyboard_A, CorsairLedId.A },
+ { LedId.Keyboard_S, CorsairLedId.S },
+ { LedId.Keyboard_D, CorsairLedId.D },
+ { LedId.Keyboard_F, CorsairLedId.F },
+ { LedId.Keyboard_G, CorsairLedId.G },
+ { LedId.Keyboard_H, CorsairLedId.H },
+ { LedId.Keyboard_J, CorsairLedId.J },
+ { LedId.Keyboard_K, CorsairLedId.K },
+ { LedId.Keyboard_L, CorsairLedId.L },
+ { LedId.Keyboard_SemicolonAndColon, CorsairLedId.SemicolonAndColon },
+ { LedId.Keyboard_ApostropheAndDoubleQuote, CorsairLedId.ApostropheAndDoubleQuote },
+ { LedId.Keyboard_LeftShift, CorsairLedId.LeftShift },
+ { LedId.Keyboard_NonUsBackslash, CorsairLedId.NonUsBackslash },
+ { LedId.Keyboard_Z, CorsairLedId.Z },
+ { LedId.Keyboard_X, CorsairLedId.X },
+ { LedId.Keyboard_C, CorsairLedId.C },
+ { LedId.Keyboard_V, CorsairLedId.V },
+ { LedId.Keyboard_B, CorsairLedId.B },
+ { LedId.Keyboard_N, CorsairLedId.N },
+ { LedId.Keyboard_M, CorsairLedId.M },
+ { LedId.Keyboard_CommaAndLessThan, CorsairLedId.CommaAndLessThan },
+ { LedId.Keyboard_PeriodAndBiggerThan, CorsairLedId.PeriodAndBiggerThan },
+ { LedId.Keyboard_SlashAndQuestionMark, CorsairLedId.SlashAndQuestionMark },
+ { LedId.Keyboard_LeftCtrl, CorsairLedId.LeftCtrl },
+ { LedId.Keyboard_LeftGui, CorsairLedId.LeftGui },
+ { LedId.Keyboard_LeftAlt, CorsairLedId.LeftAlt },
+ { LedId.Keyboard_Lang2, CorsairLedId.Lang2 },
+ { LedId.Keyboard_Space, CorsairLedId.Space },
+ { LedId.Keyboard_Lang1, CorsairLedId.Lang1 },
+ { LedId.Keyboard_International2, CorsairLedId.International2 },
+ { LedId.Keyboard_RightAlt, CorsairLedId.RightAlt },
+ { LedId.Keyboard_RightGui, CorsairLedId.RightGui },
+ { LedId.Keyboard_Application, CorsairLedId.Application },
+ { LedId.Keyboard_Brightness, CorsairLedId.Brightness },
+ { LedId.Keyboard_F12, CorsairLedId.F12 },
+ { LedId.Keyboard_PrintScreen, CorsairLedId.PrintScreen },
+ { LedId.Keyboard_ScrollLock, CorsairLedId.ScrollLock },
+ { LedId.Keyboard_PauseBreak, CorsairLedId.PauseBreak },
+ { LedId.Keyboard_Insert, CorsairLedId.Insert },
+ { LedId.Keyboard_Home, CorsairLedId.Home },
+ { LedId.Keyboard_PageUp, CorsairLedId.PageUp },
+ { LedId.Keyboard_BracketRight, CorsairLedId.BracketRight },
+ { LedId.Keyboard_Backslash, CorsairLedId.Backslash },
+ { LedId.Keyboard_NonUsTilde, CorsairLedId.NonUsTilde },
+ { LedId.Keyboard_Enter, CorsairLedId.Enter },
+ { LedId.Keyboard_International1, CorsairLedId.International1 },
+ { LedId.Keyboard_EqualsAndPlus, CorsairLedId.EqualsAndPlus },
+ { LedId.Keyboard_International3, CorsairLedId.International3 },
+ { LedId.Keyboard_Backspace, CorsairLedId.Backspace },
+ { LedId.Keyboard_Delete, CorsairLedId.Delete },
+ { LedId.Keyboard_End, CorsairLedId.End },
+ { LedId.Keyboard_PageDown, CorsairLedId.PageDown },
+ { LedId.Keyboard_RightShift, CorsairLedId.RightShift },
+ { LedId.Keyboard_RightCtrl, CorsairLedId.RightCtrl },
+ { LedId.Keyboard_ArrowUp, CorsairLedId.UpArrow },
+ { LedId.Keyboard_ArrowLeft, CorsairLedId.LeftArrow },
+ { LedId.Keyboard_ArrowDown, CorsairLedId.DownArrow },
+ { LedId.Keyboard_ArrowRight, CorsairLedId.RightArrow },
+ { LedId.Keyboard_WinLock, CorsairLedId.WinLock },
+ { LedId.Keyboard_MediaMute, CorsairLedId.Mute },
+ { LedId.Keyboard_MediaStop, CorsairLedId.Stop },
+ { LedId.Keyboard_MediaPreviousTrack, CorsairLedId.ScanPreviousTrack },
+ { LedId.Keyboard_MediaPlay, CorsairLedId.PlayPause },
+ { LedId.Keyboard_MediaNextTrack, CorsairLedId.ScanNextTrack },
+ { LedId.Keyboard_NumLock, CorsairLedId.NumLock },
+ { LedId.Keyboard_NumSlash, CorsairLedId.KeypadSlash },
+ { LedId.Keyboard_NumAsterisk, CorsairLedId.KeypadAsterisk },
+ { LedId.Keyboard_NumMinus, CorsairLedId.KeypadMinus },
+ { LedId.Keyboard_NumPlus, CorsairLedId.KeypadPlus },
+ { LedId.Keyboard_NumEnter, CorsairLedId.KeypadEnter },
+ { LedId.Keyboard_Num7, CorsairLedId.Keypad7 },
+ { LedId.Keyboard_Num8, CorsairLedId.Keypad8 },
+ { LedId.Keyboard_Num9, CorsairLedId.Keypad9 },
+ { LedId.Keyboard_NumComma, CorsairLedId.KeypadComma },
+ { LedId.Keyboard_Num4, CorsairLedId.Keypad4 },
+ { LedId.Keyboard_Num5, CorsairLedId.Keypad5 },
+ { LedId.Keyboard_Num6, CorsairLedId.Keypad6 },
+ { LedId.Keyboard_Num1, CorsairLedId.Keypad1 },
+ { LedId.Keyboard_Num2, CorsairLedId.Keypad2 },
+ { LedId.Keyboard_Num3, CorsairLedId.Keypad3 },
+ { LedId.Keyboard_Num0, CorsairLedId.Keypad0 },
+ { LedId.Keyboard_NumPeriodAndDelete, CorsairLedId.KeypadPeriodAndDelete },
+ { LedId.Keyboard_Programmable1, CorsairLedId.G1 },
+ { LedId.Keyboard_Programmable2, CorsairLedId.G2 },
+ { LedId.Keyboard_Programmable3, CorsairLedId.G3 },
+ { LedId.Keyboard_Programmable4, CorsairLedId.G4 },
+ { LedId.Keyboard_Programmable5, CorsairLedId.G5 },
+ { LedId.Keyboard_Programmable6, CorsairLedId.G6 },
+ { LedId.Keyboard_Programmable7, CorsairLedId.G7 },
+ { LedId.Keyboard_Programmable8, CorsairLedId.G8 },
+ { LedId.Keyboard_Programmable9, CorsairLedId.G9 },
+ { LedId.Keyboard_Programmable10, CorsairLedId.G10 },
+ { LedId.Keyboard_MediaVolumeUp, CorsairLedId.VolumeUp },
+ { LedId.Keyboard_MediaVolumeDown, CorsairLedId.VolumeDown },
+ { LedId.Keyboard_MacroRecording, CorsairLedId.MR },
+ { LedId.Keyboard_Macro1, CorsairLedId.M1 },
+ { LedId.Keyboard_Macro2, CorsairLedId.M2 },
+ { LedId.Keyboard_Macro3, CorsairLedId.M3 },
+ { LedId.Keyboard_Programmable11, CorsairLedId.G11 },
+ { LedId.Keyboard_Programmable12, CorsairLedId.G12 },
+ { LedId.Keyboard_Programmable13, CorsairLedId.G13 },
+ { LedId.Keyboard_Programmable14, CorsairLedId.G14 },
+ { LedId.Keyboard_Programmable15, CorsairLedId.G15 },
+ { LedId.Keyboard_Programmable16, CorsairLedId.G16 },
+ { LedId.Keyboard_Programmable17, CorsairLedId.G17 },
+ { LedId.Keyboard_Programmable18, CorsairLedId.G18 },
+ { LedId.Keyboard_International5, CorsairLedId.International5 },
+ { LedId.Keyboard_International4, CorsairLedId.International4 },
+ { LedId.Keyboard_Profile, CorsairLedId.Profile },
+ { LedId.Keyboard_LedProgramming, CorsairLedId.LedProgramming },
+ { LedId.Keyboard_Function, CorsairLedId.Fn },
+
+ { LedId.LedStripe1, CorsairLedId.Lightbar1 },
+ { LedId.LedStripe2, CorsairLedId.Lightbar2 },
+ { LedId.LedStripe3, CorsairLedId.Lightbar3 },
+ { LedId.LedStripe4, CorsairLedId.Lightbar4 },
+ { LedId.LedStripe5, CorsairLedId.Lightbar5 },
+ { LedId.LedStripe6, CorsairLedId.Lightbar6 },
+ { LedId.LedStripe7, CorsairLedId.Lightbar7 },
+ { LedId.LedStripe8, CorsairLedId.Lightbar8 },
+ { LedId.LedStripe9, CorsairLedId.Lightbar9 },
+ { LedId.LedStripe10, CorsairLedId.Lightbar10 },
+ { LedId.LedStripe11, CorsairLedId.Lightbar11 },
+ { LedId.LedStripe12, CorsairLedId.Lightbar12 },
+ { LedId.LedStripe13, CorsairLedId.Lightbar13 },
+ { LedId.LedStripe14, CorsairLedId.Lightbar14 },
+ { LedId.LedStripe15, CorsairLedId.Lightbar15 },
+ { LedId.LedStripe16, CorsairLedId.Lightbar16 },
+ { LedId.LedStripe17, CorsairLedId.Lightbar17 },
+ { LedId.LedStripe18, CorsairLedId.Lightbar18 },
+ { LedId.LedStripe19, CorsairLedId.Lightbar19 },
+ { LedId.LedStripe20, CorsairLedId.Lightbar20 },
+ { LedId.LedStripe21, CorsairLedId.Lightbar21 },
+ { LedId.LedStripe22, CorsairLedId.Lightbar22 },
+ { LedId.LedStripe23, CorsairLedId.Lightbar23 },
+ { LedId.LedStripe24, CorsairLedId.Lightbar24 },
+ { LedId.LedStripe25, CorsairLedId.Lightbar25 },
+ { LedId.LedStripe26, CorsairLedId.Lightbar26 },
+ { LedId.LedStripe27, CorsairLedId.Lightbar27 },
+ { LedId.LedStripe28, CorsairLedId.Lightbar28 },
+ { LedId.LedStripe29, CorsairLedId.Lightbar29 },
+ { LedId.LedStripe30, CorsairLedId.Lightbar30 },
+ { LedId.LedStripe31, CorsairLedId.Lightbar31 },
+ { LedId.LedStripe32, CorsairLedId.Lightbar32 },
+ { LedId.LedStripe33, CorsairLedId.Lightbar33 },
+ { LedId.LedStripe34, CorsairLedId.Lightbar34 },
+ { LedId.LedStripe35, CorsairLedId.Lightbar35 },
+ { LedId.LedStripe36, CorsairLedId.Lightbar36 },
+ { LedId.LedStripe37, CorsairLedId.Lightbar37 },
+ { LedId.LedStripe38, CorsairLedId.Lightbar38 },
+ { LedId.LedStripe39, CorsairLedId.Lightbar39 },
+ { LedId.LedStripe40, CorsairLedId.Lightbar40 },
+ { LedId.LedStripe41, CorsairLedId.Lightbar41 },
+ { LedId.LedStripe42, CorsairLedId.Lightbar42 },
+ { LedId.LedStripe43, CorsairLedId.Lightbar43 },
+ { LedId.LedStripe44, CorsairLedId.Lightbar44 },
+ { LedId.LedStripe45, CorsairLedId.Lightbar45 },
+ { LedId.LedStripe46, CorsairLedId.Lightbar46 },
+ { LedId.LedStripe47, CorsairLedId.Lightbar47 },
+ { LedId.LedStripe48, CorsairLedId.Lightbar48 },
+ { LedId.LedStripe49, CorsairLedId.Lightbar49 },
+ { LedId.LedStripe50, CorsairLedId.Lightbar50 },
+ };
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/GraphicsCard/CorsairGraphicsCardRGBDevice.cs b/RGB.NET.Devices.Corsair_Legacy/GraphicsCard/CorsairGraphicsCardRGBDevice.cs
new file mode 100644
index 0000000..ece723e
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/GraphicsCard/CorsairGraphicsCardRGBDevice.cs
@@ -0,0 +1,27 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+///
+/// Represents a corsair graphics card.
+///
+public class CorsairGraphicsCardRGBDevice : CorsairRGBDevice, IGraphicsCard
+{
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The specific information provided by CUE for the graphics card.
+ /// The queue used to update this device.
+ internal CorsairGraphicsCardRGBDevice(CorsairGraphicsCardRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
+ : base(info, LedMappings.GraphicsCard, updateQueue)
+ { }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/GraphicsCard/CorsairGraphicsCardRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair_Legacy/GraphicsCard/CorsairGraphicsCardRGBDeviceInfo.cs
new file mode 100644
index 0000000..d1b38b6
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/GraphicsCard/CorsairGraphicsCardRGBDeviceInfo.cs
@@ -0,0 +1,28 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using RGB.NET.Core;
+using RGB.NET.Devices.CorsairLegacy.Native;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+///
+/// Represents a generic information for a .
+///
+public class CorsairGraphicsCardRGBDeviceInfo : CorsairRGBDeviceInfo
+{
+ #region Constructors
+
+ ///
+ ///
+ /// Internal constructor of managed .
+ ///
+ /// The index of the .
+ /// The native -struct
+ internal CorsairGraphicsCardRGBDeviceInfo(int deviceIndex, _CorsairDeviceInfo nativeInfo)
+ : base(deviceIndex, RGBDeviceType.GraphicsCard, nativeInfo)
+ { }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Headset/CorsairHeadsetRGBDevice.cs b/RGB.NET.Devices.Corsair_Legacy/Headset/CorsairHeadsetRGBDevice.cs
new file mode 100644
index 0000000..1a6adfa
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Headset/CorsairHeadsetRGBDevice.cs
@@ -0,0 +1,27 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+///
+/// Represents a corsair headset.
+///
+public class CorsairHeadsetRGBDevice : CorsairRGBDevice, IHeadset
+{
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The specific information provided by CUE for the headset
+ /// The queue used to update this device.
+ internal CorsairHeadsetRGBDevice(CorsairHeadsetRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
+ : base(info, LedMappings.Headset, updateQueue)
+ { }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Headset/CorsairHeadsetRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair_Legacy/Headset/CorsairHeadsetRGBDeviceInfo.cs
new file mode 100644
index 0000000..090760b
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Headset/CorsairHeadsetRGBDeviceInfo.cs
@@ -0,0 +1,25 @@
+using RGB.NET.Core;
+using RGB.NET.Devices.CorsairLegacy.Native;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+///
+/// Represents a generic information for a .
+///
+public class CorsairHeadsetRGBDeviceInfo : CorsairRGBDeviceInfo
+{
+ #region Constructors
+
+ ///
+ ///
+ /// Internal constructor of managed .
+ ///
+ /// The index of the .
+ /// The native -struct
+ internal CorsairHeadsetRGBDeviceInfo(int deviceIndex, _CorsairDeviceInfo nativeInfo)
+ : base(deviceIndex, RGBDeviceType.Headset, nativeInfo)
+ { }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/HeadsetStand/CorsairHeadsetStandRGBDevice.cs b/RGB.NET.Devices.Corsair_Legacy/HeadsetStand/CorsairHeadsetStandRGBDevice.cs
new file mode 100644
index 0000000..d696cff
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/HeadsetStand/CorsairHeadsetStandRGBDevice.cs
@@ -0,0 +1,27 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+///
+/// Represents a corsair headset stand.
+///
+public class CorsairHeadsetStandRGBDevice : CorsairRGBDevice, IHeadsetStand
+{
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The specific information provided by CUE for the headset stand
+ /// The queue used to update this device.
+ internal CorsairHeadsetStandRGBDevice(CorsairHeadsetStandRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
+ : base(info, LedMappings.HeadsetStand, updateQueue)
+ { }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/HeadsetStand/CorsairHeadsetStandRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair_Legacy/HeadsetStand/CorsairHeadsetStandRGBDeviceInfo.cs
new file mode 100644
index 0000000..61ab548
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/HeadsetStand/CorsairHeadsetStandRGBDeviceInfo.cs
@@ -0,0 +1,25 @@
+using RGB.NET.Core;
+using RGB.NET.Devices.CorsairLegacy.Native;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+///
+/// Represents a generic information for a .
+///
+public class CorsairHeadsetStandRGBDeviceInfo : CorsairRGBDeviceInfo
+{
+ #region Constructors
+
+ ///
+ ///
+ /// Internal constructor of managed .
+ ///
+ /// The index of the .
+ /// The native -struct
+ internal CorsairHeadsetStandRGBDeviceInfo(int deviceIndex, _CorsairDeviceInfo nativeInfo)
+ : base(deviceIndex, RGBDeviceType.HeadsetStand, nativeInfo)
+ { }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Helper/DictionaryExtension.cs b/RGB.NET.Devices.Corsair_Legacy/Helper/DictionaryExtension.cs
new file mode 100644
index 0000000..f33fdea
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Helper/DictionaryExtension.cs
@@ -0,0 +1,12 @@
+using System.Collections.Generic;
+using System.Linq;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+internal static class DictionaryExtension
+{
+ public static Dictionary SwapKeyValue(this Dictionary dictionary)
+ where TKey : notnull
+ where TValue : notnull
+ => dictionary.ToDictionary(x => x.Value, x => x.Key);
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Helper/NativeExtensions.cs b/RGB.NET.Devices.Corsair_Legacy/Helper/NativeExtensions.cs
new file mode 100644
index 0000000..0da20e5
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Helper/NativeExtensions.cs
@@ -0,0 +1,18 @@
+using RGB.NET.Core;
+using RGB.NET.Devices.CorsairLegacy.Native;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+internal static class NativeExtensions
+{
+ internal static Rectangle ToRectangle(this _CorsairLedPosition position)
+ {
+ //HACK DarthAffe 08.07.2018: It seems like corsair introduced a issue here - it's always 0.
+ float width = position.width < 0.5f ? 10 : (float)position.width;
+ float height = position.height < 0.5f ? 10 : (float)position.height;
+ float posX = (float)position.left;
+ float posY = (float)position.top;
+
+ return new Rectangle(posX, posY, width, height);
+ }
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Keyboard/CorsairKeyboardRGBDevice.cs b/RGB.NET.Devices.Corsair_Legacy/Keyboard/CorsairKeyboardRGBDevice.cs
new file mode 100644
index 0000000..5505c80
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Keyboard/CorsairKeyboardRGBDevice.cs
@@ -0,0 +1,33 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+///
+/// Represents a corsair keyboard.
+///
+public class CorsairKeyboardRGBDevice : CorsairRGBDevice, IKeyboard
+{
+ #region Properties & Fields
+
+ IKeyboardDeviceInfo IKeyboard.DeviceInfo => DeviceInfo;
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The specific information provided by CUE for the keyboard.
+ /// The queue used to update this device.
+ internal CorsairKeyboardRGBDevice(CorsairKeyboardRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
+ : base(info, LedMappings.Keyboard, updateQueue)
+ { }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Keyboard/CorsairKeyboardRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair_Legacy/Keyboard/CorsairKeyboardRGBDeviceInfo.cs
new file mode 100644
index 0000000..c603b75
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Keyboard/CorsairKeyboardRGBDeviceInfo.cs
@@ -0,0 +1,56 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using RGB.NET.Core;
+using RGB.NET.Devices.CorsairLegacy.Native;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+/// Represents a generic information for a .
+///
+public class CorsairKeyboardRGBDeviceInfo : CorsairRGBDeviceInfo, IKeyboardDeviceInfo
+{
+ #region Properties & Fields
+
+ ///
+ public KeyboardLayoutType Layout { get; }
+
+ ///
+ /// Gets the physical layout of the keyboard.
+ ///
+ public CorsairPhysicalKeyboardLayout PhysicalLayout { get; }
+
+ ///
+ /// Gets the logical layout of the keyboard as set in CUE settings.
+ ///
+ public CorsairLogicalKeyboardLayout LogicalLayout { get; }
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ ///
+ /// Internal constructor of managed .
+ ///
+ /// The index of the .
+ /// The native -struct
+ internal CorsairKeyboardRGBDeviceInfo(int deviceIndex, _CorsairDeviceInfo nativeInfo)
+ : base(deviceIndex, RGBDeviceType.Keyboard, nativeInfo)
+ {
+ this.PhysicalLayout = (CorsairPhysicalKeyboardLayout)nativeInfo.physicalLayout;
+ this.LogicalLayout = (CorsairLogicalKeyboardLayout)nativeInfo.logicalLayout;
+ this.Layout = PhysicalLayout switch
+ {
+ CorsairPhysicalKeyboardLayout.US => KeyboardLayoutType.ANSI,
+ CorsairPhysicalKeyboardLayout.UK => KeyboardLayoutType.ISO,
+ CorsairPhysicalKeyboardLayout.BR => KeyboardLayoutType.ABNT,
+ CorsairPhysicalKeyboardLayout.JP => KeyboardLayoutType.JIS,
+ CorsairPhysicalKeyboardLayout.KR => KeyboardLayoutType.KS,
+ _ => KeyboardLayoutType.Unknown
+ };
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Mainboard/CorsairMainboardRGBDevice.cs b/RGB.NET.Devices.Corsair_Legacy/Mainboard/CorsairMainboardRGBDevice.cs
new file mode 100644
index 0000000..c7f238e
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Mainboard/CorsairMainboardRGBDevice.cs
@@ -0,0 +1,27 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+///
+/// Represents a corsair memory.
+///
+public class CorsairMainboardRGBDevice : CorsairRGBDevice, IMainboard
+{
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The specific information provided by CUE for the memory.
+ /// The queue used to update this device.
+ internal CorsairMainboardRGBDevice(CorsairMainboardRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
+ : base(info, LedMappings.Mainboard, updateQueue)
+ { }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Mainboard/CorsairMainboardRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair_Legacy/Mainboard/CorsairMainboardRGBDeviceInfo.cs
new file mode 100644
index 0000000..56fbb90
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Mainboard/CorsairMainboardRGBDeviceInfo.cs
@@ -0,0 +1,28 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using RGB.NET.Core;
+using RGB.NET.Devices.CorsairLegacy.Native;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+///
+/// Represents a generic information for a .
+///
+public class CorsairMainboardRGBDeviceInfo : CorsairRGBDeviceInfo
+{
+ #region Constructors
+
+ ///
+ ///
+ /// Internal constructor of managed .
+ ///
+ /// The index of the .
+ /// The native -struct
+ internal CorsairMainboardRGBDeviceInfo(int deviceIndex, _CorsairDeviceInfo nativeInfo)
+ : base(deviceIndex, RGBDeviceType.Mainboard, nativeInfo)
+ { }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Memory/CorsairMemoryRGBDevice.cs b/RGB.NET.Devices.Corsair_Legacy/Memory/CorsairMemoryRGBDevice.cs
new file mode 100644
index 0000000..053ee81
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Memory/CorsairMemoryRGBDevice.cs
@@ -0,0 +1,27 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+///
+/// Represents a corsair memory.
+///
+public class CorsairMemoryRGBDevice : CorsairRGBDevice, IDRAM
+{
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The specific information provided by CUE for the memory.
+ /// The queue used to update this device.
+ internal CorsairMemoryRGBDevice(CorsairMemoryRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
+ : base(info, LedMappings.Memory, updateQueue)
+ { }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Memory/CorsairMemoryRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair_Legacy/Memory/CorsairMemoryRGBDeviceInfo.cs
new file mode 100644
index 0000000..9934135
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Memory/CorsairMemoryRGBDeviceInfo.cs
@@ -0,0 +1,28 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using RGB.NET.Core;
+using RGB.NET.Devices.CorsairLegacy.Native;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+///
+/// Represents a generic information for a .
+///
+public class CorsairMemoryRGBDeviceInfo : CorsairRGBDeviceInfo
+{
+ #region Constructors
+
+ ///
+ ///
+ /// Internal constructor of managed .
+ ///
+ /// The index of the .
+ /// The native -struct
+ internal CorsairMemoryRGBDeviceInfo(int deviceIndex, _CorsairDeviceInfo nativeInfo)
+ : base(deviceIndex, RGBDeviceType.DRAM, nativeInfo)
+ { }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Mouse/CorsairMouseRGBDevice.cs b/RGB.NET.Devices.Corsair_Legacy/Mouse/CorsairMouseRGBDevice.cs
new file mode 100644
index 0000000..b9a84bf
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Mouse/CorsairMouseRGBDevice.cs
@@ -0,0 +1,27 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+///
+/// Represents a corsair mouse.
+///
+public class CorsairMouseRGBDevice : CorsairRGBDevice, IMouse
+{
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The specific information provided by CUE for the mouse
+ /// The queue used to update this device.
+ internal CorsairMouseRGBDevice(CorsairMouseRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
+ : base(info, LedMappings.Mouse, updateQueue)
+ { }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Mouse/CorsairMouseRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair_Legacy/Mouse/CorsairMouseRGBDeviceInfo.cs
new file mode 100644
index 0000000..89de824
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Mouse/CorsairMouseRGBDeviceInfo.cs
@@ -0,0 +1,36 @@
+using RGB.NET.Core;
+using RGB.NET.Devices.CorsairLegacy.Native;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+///
+/// Represents a generic information for a .
+///
+public class CorsairMouseRGBDeviceInfo : CorsairRGBDeviceInfo
+{
+ #region Properties & Fields
+
+ ///
+ /// Gets the physical layout of the mouse.
+ ///
+ public CorsairPhysicalMouseLayout PhysicalLayout { get; }
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ ///
+ /// Internal constructor of managed .
+ ///
+ /// The index of the .
+ /// The native -struct
+ internal CorsairMouseRGBDeviceInfo(int deviceIndex, _CorsairDeviceInfo nativeInfo)
+ : base(deviceIndex, RGBDeviceType.Mouse, nativeInfo)
+ {
+ this.PhysicalLayout = (CorsairPhysicalMouseLayout)nativeInfo.physicalLayout;
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Mousepad/CorsairMousepadRGBDevice.cs b/RGB.NET.Devices.Corsair_Legacy/Mousepad/CorsairMousepadRGBDevice.cs
new file mode 100644
index 0000000..5d78d5d
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Mousepad/CorsairMousepadRGBDevice.cs
@@ -0,0 +1,27 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+///
+/// Represents a corsair mousepad.
+///
+public class CorsairMousepadRGBDevice : CorsairRGBDevice, IMousepad
+{
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The specific information provided by CUE for the mousepad
+ /// The queue used to update this device.
+ internal CorsairMousepadRGBDevice(CorsairMousepadRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
+ : base(info, LedMappings.Mousepad, updateQueue)
+ { }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Mousepad/CorsairMousepadRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair_Legacy/Mousepad/CorsairMousepadRGBDeviceInfo.cs
new file mode 100644
index 0000000..40f42b5
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Mousepad/CorsairMousepadRGBDeviceInfo.cs
@@ -0,0 +1,25 @@
+using RGB.NET.Core;
+using RGB.NET.Devices.CorsairLegacy.Native;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+///
+/// Represents a generic information for a .
+///
+public class CorsairMousepadRGBDeviceInfo : CorsairRGBDeviceInfo
+{
+ #region Constructors
+
+ ///
+ ///
+ /// Internal constructor of managed .
+ ///
+ /// The index if the .
+ /// The native -struct
+ internal CorsairMousepadRGBDeviceInfo(int deviceIndex, _CorsairDeviceInfo nativeInfo)
+ : base(deviceIndex, RGBDeviceType.Mousepad, nativeInfo)
+ { }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Native/_CUESDK.cs b/RGB.NET.Devices.Corsair_Legacy/Native/_CUESDK.cs
new file mode 100644
index 0000000..3ace435
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Native/_CUESDK.cs
@@ -0,0 +1,193 @@
+#pragma warning disable IDE1006 // Naming Styles
+// ReSharper disable UnusedMethodReturnValue.Global
+// ReSharper disable UnusedMember.Global
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.CorsairLegacy.Native;
+
+// ReSharper disable once InconsistentNaming
+internal static class _CUESDK
+{
+ #region Libary Management
+
+ private static nint _handle = 0;
+
+ ///
+ /// Reloads the SDK.
+ ///
+ internal static void Reload()
+ {
+ UnloadCUESDK();
+ LoadCUESDK();
+ }
+
+ private static void LoadCUESDK()
+ {
+ if (_handle != 0) return;
+
+ List possiblePathList = GetPossibleLibraryPaths().ToList();
+
+ string? dllPath = possiblePathList.FirstOrDefault(File.Exists);
+ if (dllPath == null) throw new RGBDeviceException($"Can't find the CUE-SDK at one of the expected locations:\r\n '{string.Join("\r\n", possiblePathList.Select(Path.GetFullPath))}'");
+
+ if (!NativeLibrary.TryLoad(dllPath, out _handle))
+#if NET6_0
+ throw new RGBDeviceException($"Corsair LoadLibrary failed with error code {Marshal.GetLastPInvokeError()}");
+#else
+ throw new RGBDeviceException($"Corsair LoadLibrary failed with error code {Marshal.GetLastWin32Error()}");
+#endif
+
+ if (!NativeLibrary.TryGetExport(_handle, "CorsairSetLedsColorsBufferByDeviceIndex", out _corsairSetLedsColorsBufferByDeviceIndexPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairSetLedsColorsBufferByDeviceIndex'");
+ if (!NativeLibrary.TryGetExport(_handle, "CorsairSetLedsColorsFlushBuffer", out _corsairSetLedsColorsFlushBufferPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairSetLedsColorsFlushBuffer'");
+ if (!NativeLibrary.TryGetExport(_handle, "CorsairGetLedsColorsByDeviceIndex", out _corsairGetLedsColorsByDeviceIndexPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairGetLedsColorsByDeviceIndex'");
+ if (!NativeLibrary.TryGetExport(_handle, "CorsairSetLayerPriority", out _corsairSetLayerPriorityPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairSetLayerPriority'");
+ if (!NativeLibrary.TryGetExport(_handle, "CorsairGetDeviceCount", out _corsairGetDeviceCountPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairGetDeviceCount'");
+ if (!NativeLibrary.TryGetExport(_handle, "CorsairGetDeviceInfo", out _corsairGetDeviceInfoPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairGetDeviceInfo'");
+ if (!NativeLibrary.TryGetExport(_handle, "CorsairGetLedIdForKeyName", out _corsairGetLedIdForKeyNamePointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairGetLedIdForKeyName'");
+ if (!NativeLibrary.TryGetExport(_handle, "CorsairGetLedPositionsByDeviceIndex", out _corsairGetLedPositionsByDeviceIndexPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairGetLedPositionsByDeviceIndex'");
+ if (!NativeLibrary.TryGetExport(_handle, "CorsairRequestControl", out _corsairRequestControlPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairRequestControl'");
+ if (!NativeLibrary.TryGetExport(_handle, "CorsairReleaseControl", out _corsairReleaseControlPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairReleaseControl'");
+ if (!NativeLibrary.TryGetExport(_handle, "CorsairPerformProtocolHandshake", out _corsairPerformProtocolHandshakePointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairPerformProtocolHandshake'");
+ if (!NativeLibrary.TryGetExport(_handle, "CorsairGetLastError", out _corsairGetLastErrorPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairGetLastError'");
+ }
+
+ private static IEnumerable GetPossibleLibraryPaths()
+ {
+ IEnumerable possibleLibraryPaths;
+
+ if (OperatingSystem.IsWindows())
+ possibleLibraryPaths = Environment.Is64BitProcess ? CorsairLegacyDeviceProvider.PossibleX64NativePaths : CorsairLegacyDeviceProvider.PossibleX86NativePaths;
+ else
+ possibleLibraryPaths = Enumerable.Empty();
+
+ return possibleLibraryPaths.Select(Environment.ExpandEnvironmentVariables);
+ }
+
+ internal static void UnloadCUESDK()
+ {
+ if (_handle == 0) return;
+
+ _corsairSetLedsColorsBufferByDeviceIndexPointer = 0;
+ _corsairSetLedsColorsFlushBufferPointer = 0;
+ _corsairGetLedsColorsByDeviceIndexPointer = 0;
+ _corsairSetLayerPriorityPointer = 0;
+ _corsairGetDeviceCountPointer = 0;
+ _corsairGetDeviceInfoPointer = 0;
+ _corsairGetLedIdForKeyNamePointer = 0;
+ _corsairGetLedPositionsByDeviceIndexPointer = 0;
+ _corsairRequestControlPointer = 0;
+ _corsairReleaseControlPointer = 0;
+ _corsairPerformProtocolHandshakePointer = 0;
+ _corsairGetLastErrorPointer = 0;
+
+ NativeLibrary.Free(_handle);
+ _handle = 0;
+ }
+
+ #endregion
+
+ #region SDK-METHODS
+
+ #region Pointers
+
+ private static nint _corsairSetLedsColorsBufferByDeviceIndexPointer;
+ private static nint _corsairSetLedsColorsFlushBufferPointer;
+ private static nint _corsairGetLedsColorsByDeviceIndexPointer;
+ private static nint _corsairSetLayerPriorityPointer;
+ private static nint _corsairGetDeviceCountPointer;
+ private static nint _corsairGetDeviceInfoPointer;
+ private static nint _corsairGetLedIdForKeyNamePointer;
+ private static nint _corsairGetLedPositionsByDeviceIndexPointer;
+ private static nint _corsairRequestControlPointer;
+ private static nint _corsairReleaseControlPointer;
+ private static nint _corsairPerformProtocolHandshakePointer;
+ private static nint _corsairGetLastErrorPointer;
+
+ #endregion
+
+ ///
+ /// CUE-SDK: set specified LEDs to some colors.
+ /// This function set LEDs colors in the buffer which is written to the devices via CorsairSetLedsColorsFlushBuffer or CorsairSetLedsColorsFlushBufferAsync.
+ /// Typical usecase is next: CorsairSetLedsColorsFlushBuffer or CorsairSetLedsColorsFlushBufferAsync is called to write LEDs colors to the device
+ /// and follows after one or more calls of CorsairSetLedsColorsBufferByDeviceIndex to set the LEDs buffer.
+ /// This function does not take logical layout into account.
+ ///
+ internal static unsafe bool CorsairSetLedsColorsBufferByDeviceIndex(int deviceIndex, int size, nint ledsColors)
+ => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairSetLedsColorsBufferByDeviceIndexPointer))(deviceIndex, size, ledsColors);
+
+ ///
+ /// CUE-SDK: writes to the devices LEDs colors buffer which is previously filled by the CorsairSetLedsColorsBufferByDeviceIndex function.
+ /// This function executes synchronously, if you are concerned about delays consider using CorsairSetLedsColorsFlushBufferAsync
+ ///
+ internal static unsafe bool CorsairSetLedsColorsFlushBuffer() => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairSetLedsColorsFlushBufferPointer))();
+
+ ///
+ /// CUE-SDK: get current color for the list of requested LEDs.
+ /// The color should represent the actual state of the hardware LED, which could be a combination of SDK and/or CUE input.
+ /// This function works for keyboard, mouse, mousemat, headset, headset stand and DIY-devices.
+ ///
+ internal static unsafe bool CorsairGetLedsColorsByDeviceIndex(int deviceIndex, int size, nint ledsColors)
+ => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairGetLedsColorsByDeviceIndexPointer))(deviceIndex, size, ledsColors);
+
+ ///
+ /// CUE-SDK: set layer priority for this shared client.
+ /// By default CUE has priority of 127 and all shared clients have priority of 128 if they don’t call this function.
+ /// Layers with higher priority value are shown on top of layers with lower priority.
+ ///
+ internal static unsafe bool CorsairSetLayerPriority(int priority) => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairSetLayerPriorityPointer))(priority);
+
+ ///
+ /// CUE-SDK: returns number of connected Corsair devices that support lighting control.
+ ///
+ internal static unsafe int CorsairGetDeviceCount() => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairGetDeviceCountPointer))();
+
+ ///
+ /// CUE-SDK: returns information about device at provided index.
+ ///
+ internal static unsafe nint CorsairGetDeviceInfo(int deviceIndex) => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairGetDeviceInfoPointer))(deviceIndex);
+
+ ///
+ /// CUE-SDK: provides list of keyboard or mousepad LEDs with their physical positions.
+ ///
+ internal static unsafe nint CorsairGetLedPositionsByDeviceIndex(int deviceIndex) => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairGetLedPositionsByDeviceIndexPointer))(deviceIndex);
+
+ ///
+ /// CUE-SDK: retrieves led id for key name taking logical layout into account.
+ ///
+ internal static unsafe CorsairLedId CorsairGetLedIdForKeyName(char keyName) => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairGetLedIdForKeyNamePointer))(keyName);
+
+ ///
+ /// CUE-SDK: requestes control using specified access mode.
+ /// By default client has shared control over lighting so there is no need to call CorsairRequestControl unless client requires exclusive control.
+ ///
+ internal static unsafe bool CorsairRequestControl(CorsairAccessMode accessMode) => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairRequestControlPointer))(accessMode);
+
+ ///
+ /// CUE-SDK: releases previously requested control for specified access mode.
+ ///
+ internal static unsafe bool CorsairReleaseControl(CorsairAccessMode accessMode) => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairReleaseControlPointer))(accessMode);
+
+ ///
+ /// CUE-SDK: checks file and protocol version of CUE to understand which of SDK functions can be used with this version of CUE.
+ ///
+ internal static unsafe _CorsairProtocolDetails CorsairPerformProtocolHandshake() => ((delegate* unmanaged[Cdecl]<_CorsairProtocolDetails>)ThrowIfZero(_corsairPerformProtocolHandshakePointer))();
+
+ ///
+ /// CUE-SDK: returns last error that occured while using any of Corsair* functions.
+ ///
+ internal static unsafe CorsairError CorsairGetLastError() => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairGetLastErrorPointer))();
+
+ private static nint ThrowIfZero(nint ptr)
+ {
+ if (ptr == 0) throw new RGBDeviceException("The Corsair-SDK is not initialized.");
+ return ptr;
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Native/_CorsairChannelDeviceInfo.cs b/RGB.NET.Devices.Corsair_Legacy/Native/_CorsairChannelDeviceInfo.cs
similarity index 94%
rename from RGB.NET.Devices.Corsair/Native/_CorsairChannelDeviceInfo.cs
rename to RGB.NET.Devices.Corsair_Legacy/Native/_CorsairChannelDeviceInfo.cs
index 3f44c7a..466e99d 100644
--- a/RGB.NET.Devices.Corsair/Native/_CorsairChannelDeviceInfo.cs
+++ b/RGB.NET.Devices.Corsair_Legacy/Native/_CorsairChannelDeviceInfo.cs
@@ -5,7 +5,7 @@
using System.Runtime.InteropServices;
-namespace RGB.NET.Devices.Corsair.Native;
+namespace RGB.NET.Devices.CorsairLegacy.Native;
// ReSharper disable once InconsistentNaming
///
diff --git a/RGB.NET.Devices.Corsair/Native/_CorsairChannelInfo.cs b/RGB.NET.Devices.Corsair_Legacy/Native/_CorsairChannelInfo.cs
similarity index 92%
rename from RGB.NET.Devices.Corsair/Native/_CorsairChannelInfo.cs
rename to RGB.NET.Devices.Corsair_Legacy/Native/_CorsairChannelInfo.cs
index 3190b87..82c07b8 100644
--- a/RGB.NET.Devices.Corsair/Native/_CorsairChannelInfo.cs
+++ b/RGB.NET.Devices.Corsair_Legacy/Native/_CorsairChannelInfo.cs
@@ -3,10 +3,9 @@
#pragma warning disable 649 // Field 'x' is never assigned
#pragma warning disable IDE1006 // Naming Styles
-using System;
using System.Runtime.InteropServices;
-namespace RGB.NET.Devices.Corsair.Native;
+namespace RGB.NET.Devices.CorsairLegacy.Native;
// ReSharper disable once InconsistentNaming
///
@@ -29,5 +28,5 @@ internal class _CorsairChannelInfo
/// CUE-SDK: array containing information about each separate LED-device connected to the channel controlled by the DIY device.
/// Index of the LED-device in array is same as the index of the LED-device connected to the DIY-device.
///
- internal IntPtr devices;
+ internal nint devices;
}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Native/_CorsairChannelsInfo.cs b/RGB.NET.Devices.Corsair_Legacy/Native/_CorsairChannelsInfo.cs
similarity index 90%
rename from RGB.NET.Devices.Corsair/Native/_CorsairChannelsInfo.cs
rename to RGB.NET.Devices.Corsair_Legacy/Native/_CorsairChannelsInfo.cs
index e2a5a12..3dd7d04 100644
--- a/RGB.NET.Devices.Corsair/Native/_CorsairChannelsInfo.cs
+++ b/RGB.NET.Devices.Corsair_Legacy/Native/_CorsairChannelsInfo.cs
@@ -3,10 +3,9 @@
#pragma warning disable 649 // Field 'x' is never assigned
#pragma warning disable IDE1006 // Naming Styles
-using System;
using System.Runtime.InteropServices;
-namespace RGB.NET.Devices.Corsair.Native;
+namespace RGB.NET.Devices.CorsairLegacy.Native;
// ReSharper disable once InconsistentNaming
///
@@ -24,5 +23,5 @@ internal class _CorsairChannelsInfo
/// CUE-SDK: array containing information about each separate channel of the DIY-device.
/// Index of the channel in the array is same as index of the channel on the DIY-device.
///
- internal IntPtr channels;
+ internal nint channels;
}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Native/_CorsairDeviceInfo.cs b/RGB.NET.Devices.Corsair_Legacy/Native/_CorsairDeviceInfo.cs
new file mode 100644
index 0000000..f2f7eb8
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Native/_CorsairDeviceInfo.cs
@@ -0,0 +1,57 @@
+#pragma warning disable 169 // Field 'x' is never used
+#pragma warning disable 414 // Field 'x' is assigned but its value never used
+#pragma warning disable 649 // Field 'x' is never assigned
+#pragma warning disable IDE1006 // Naming Styles
+
+using System.Runtime.InteropServices;
+
+namespace RGB.NET.Devices.CorsairLegacy.Native;
+
+// ReSharper disable once InconsistentNaming
+///
+/// CUE-SDK: contains information about device
+///
+[StructLayout(LayoutKind.Sequential)]
+internal class _CorsairDeviceInfo
+{
+ ///
+ /// CUE-SDK: enum describing device type
+ ///
+ internal CorsairDeviceType type;
+
+ ///
+ /// CUE-SDK: null - terminated device model(like “K95RGB”)
+ ///
+ internal nint model;
+
+ ///
+ /// CUE-SDK: enum describing physical layout of the keyboard or mouse
+ ///
+ internal int physicalLayout;
+
+ ///
+ /// CUE-SDK: enum describing logical layout of the keyboard as set in CUE settings
+ ///
+ internal int logicalLayout;
+
+ ///
+ /// CUE-SDK: mask that describes device capabilities, formed as logical “or” of CorsairDeviceCaps enum values
+ ///
+ internal int capsMask;
+
+ ///
+ /// CUE-SDK: number of controllable LEDs on the device
+ ///
+ internal int ledsCount;
+
+ ///
+ /// CUE-SDK: structure that describes channels of the DIY-devices
+ ///
+ internal _CorsairChannelsInfo? channels;
+
+ ///
+ /// CUE-SDK: null-terminated string that contains unique device identifier that uniquely identifies device at least within session
+ ///
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
+ internal string? deviceId;
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Native/_CorsairLedColor.cs b/RGB.NET.Devices.Corsair_Legacy/Native/_CorsairLedColor.cs
new file mode 100644
index 0000000..b170918
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Native/_CorsairLedColor.cs
@@ -0,0 +1,37 @@
+#pragma warning disable 169 // Field 'x' is never used
+#pragma warning disable 414 // Field 'x' is assigned but its value never used
+#pragma warning disable 649 // Field 'x' is never assigned
+#pragma warning disable IDE1006 // Naming Styles
+// ReSharper disable NotAccessedField.Global
+
+using System.Runtime.InteropServices;
+
+namespace RGB.NET.Devices.CorsairLegacy.Native;
+
+// ReSharper disable once InconsistentNaming
+///
+/// CUE-SDK: contains information about led and its color
+///
+[StructLayout(LayoutKind.Sequential)]
+internal class _CorsairLedColor
+{
+ ///
+ /// CUE-SDK: identifier of LED to set
+ ///
+ internal int ledId;
+
+ ///
+ /// CUE-SDK: red brightness[0..255]
+ ///
+ internal int r;
+
+ ///
+ /// CUE-SDK: green brightness[0..255]
+ ///
+ internal int g;
+
+ ///
+ /// CUE-SDK: blue brightness[0..255]
+ ///
+ internal int b;
+};
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Native/_CorsairLedPosition.cs b/RGB.NET.Devices.Corsair_Legacy/Native/_CorsairLedPosition.cs
new file mode 100644
index 0000000..baa959f
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Native/_CorsairLedPosition.cs
@@ -0,0 +1,42 @@
+#pragma warning disable 169 // Field 'x' is never used
+#pragma warning disable 414 // Field 'x' is assigned but its value never used
+#pragma warning disable 649 // Field 'x' is never assigned
+#pragma warning disable IDE1006 // Naming Styles
+
+using System.Runtime.InteropServices;
+
+namespace RGB.NET.Devices.CorsairLegacy.Native;
+
+// ReSharper disable once InconsistentNaming
+///
+/// CUE-SDK: contains led id and position of led rectangle.Most of the keys are rectangular.
+/// In case if key is not rectangular(like Enter in ISO / UK layout) it returns the smallest rectangle that fully contains the key
+///
+[StructLayout(LayoutKind.Sequential)]
+internal class _CorsairLedPosition
+{
+ ///
+ /// CUE-SDK: identifier of led
+ ///
+ internal CorsairLedId LedId;
+
+ ///
+ /// CUE-SDK: values in mm
+ ///
+ internal double top;
+
+ ///
+ /// CUE-SDK: values in mm
+ ///
+ internal double left;
+
+ ///
+ /// CUE-SDK: values in mm
+ ///
+ internal double height;
+
+ ///
+ /// CUE-SDK: values in mm
+ ///
+ internal double width;
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Native/_CorsairLedPositions.cs b/RGB.NET.Devices.Corsair_Legacy/Native/_CorsairLedPositions.cs
similarity index 88%
rename from RGB.NET.Devices.Corsair/Native/_CorsairLedPositions.cs
rename to RGB.NET.Devices.Corsair_Legacy/Native/_CorsairLedPositions.cs
index c3186d3..a3f0dbd 100644
--- a/RGB.NET.Devices.Corsair/Native/_CorsairLedPositions.cs
+++ b/RGB.NET.Devices.Corsair_Legacy/Native/_CorsairLedPositions.cs
@@ -2,10 +2,9 @@
#pragma warning disable 414 // Field 'x' is assigned but its value never used
#pragma warning disable 649 // Field 'x' is never assigned
-using System;
using System.Runtime.InteropServices;
-namespace RGB.NET.Devices.Corsair.Native;
+namespace RGB.NET.Devices.CorsairLegacy.Native;
// ReSharper disable once InconsistentNaming
///
@@ -22,5 +21,5 @@ internal class _CorsairLedPositions
///
/// CUE-SDK: array of led positions
///
- internal IntPtr pLedPosition;
+ internal nint pLedPosition;
}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair/Native/_CorsairProtocolDetails.cs b/RGB.NET.Devices.Corsair_Legacy/Native/_CorsairProtocolDetails.cs
similarity index 92%
rename from RGB.NET.Devices.Corsair/Native/_CorsairProtocolDetails.cs
rename to RGB.NET.Devices.Corsair_Legacy/Native/_CorsairProtocolDetails.cs
index cd6bf6e..5b85faa 100644
--- a/RGB.NET.Devices.Corsair/Native/_CorsairProtocolDetails.cs
+++ b/RGB.NET.Devices.Corsair_Legacy/Native/_CorsairProtocolDetails.cs
@@ -2,10 +2,9 @@
#pragma warning disable 414 // Field 'x' is assigned but its value never used
#pragma warning disable 649 // Field 'x' is never assigned
-using System;
using System.Runtime.InteropServices;
-namespace RGB.NET.Devices.Corsair.Native;
+namespace RGB.NET.Devices.CorsairLegacy.Native;
// ReSharper disable once InconsistentNaming
///
@@ -17,12 +16,12 @@ internal struct _CorsairProtocolDetails
///
/// CUE-SDK: null - terminated string containing version of SDK(like “1.0.0.1”). Always contains valid value even if there was no CUE found
///
- internal IntPtr sdkVersion;
+ internal nint sdkVersion;
///
/// CUE-SDK: null - terminated string containing version of CUE(like “1.0.0.1”) or NULL if CUE was not found.
///
- internal IntPtr serverVersion;
+ internal nint serverVersion;
///
/// CUE-SDK: integer number that specifies version of protocol that is implemented by current SDK.
diff --git a/RGB.NET.Devices.Corsair_Legacy/README.md b/RGB.NET.Devices.Corsair_Legacy/README.md
new file mode 100644
index 0000000..4448ae1
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/README.md
@@ -0,0 +1,24 @@
+[RGB.NET](https://github.com/DarthAffe/RGB.NET) Device-Provider-Package for Corsair-Devices.
+
+## Usage
+This provider follows the default pattern and does not require additional setup.
+
+```csharp
+surface.Load(CorsairDeviceProvider.Instance);
+```
+
+# Required SDK
+This providers requires native SDK-dlls. (version < 4.x)
+You can get them directly from Corsair at [https://github.com/CorsairOfficial/cue-sdk/releases](https://github.com/CorsairOfficial/cue-sdk/releases)
+
+Since the SDK-dlls are native it's important to use the correct architecture you're building your application for. (If in doubt you can always include both.)
+
+### x64
+`redist\x64\CUESDK.x64_2019.dll` from the SDK-zip needs to be distributed as `\x64\CUESDK.x64_2019.dll` (or simply named `CUESDK.dll`)
+
+You can use other, custom paths by adding them to `CorsairDeviceProvider.PossibleX64NativePaths`.
+
+### x86
+`redist\i386\CUESDK_2019.dll` from the SDK-zip needs to be distributed as `\x86\CUESDK_2019.dll` (or simply named `CUESDK.dll`)
+
+You can use other, custom paths by adding them to `CorsairDeviceProvider.PossibleX86NativePaths`.
diff --git a/RGB.NET.Devices.Corsair_Legacy/RGB.NET.Devices.Corsair_Legacy.csproj b/RGB.NET.Devices.Corsair_Legacy/RGB.NET.Devices.Corsair_Legacy.csproj
new file mode 100644
index 0000000..c80995d
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/RGB.NET.Devices.Corsair_Legacy.csproj
@@ -0,0 +1,63 @@
+
+
+ net8.0;net7.0;net6.0
+ latest
+ enable
+
+ Darth Affe
+ Wyrez
+ en-US
+ en-US
+ RGB.NET.Devices.CorsairLegacy
+ RGB.NET.Devices.CorsairLegacy
+ RGB.NET.Devices.CorsairLegacy
+ RGB.NET.Devices.CorsairLegacy
+ RGB.NET.Devices.CorsairLegacy
+ Corsair-Device-Implementations of RGB.NET using the old SDK
+ Corsair-Device-Implementations of RGB.NET, a C# (.NET) library for accessing various RGB-peripherals
+ Copyright © Darth Affe 2023
+ Copyright © Darth Affe 2023
+ icon.png
+ README.md
+ https://github.com/DarthAffe/RGB.NET
+ LGPL-2.1-only
+ Github
+ https://github.com/DarthAffe/RGB.NET
+ True
+
+
+
+ 0.0.1
+ 0.0.1
+ 0.0.1
+
+ ..\bin\
+ true
+ True
+ True
+ portable
+ snupkg
+ true
+
+
+
+ TRACE;DEBUG
+ true
+ false
+
+
+
+ true
+ $(NoWarn);CS1591;CS1572;CS1573
+ RELEASE
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/RGB.NET.Devices.Corsair_Legacy.csproj.DotSettings b/RGB.NET.Devices.Corsair_Legacy/RGB.NET.Devices.Corsair_Legacy.csproj.DotSettings
new file mode 100644
index 0000000..eeca971
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/RGB.NET.Devices.Corsair_Legacy.csproj.DotSettings
@@ -0,0 +1,22 @@
+
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ False
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Touchbar/CorsairTouchbarRGBDevice.cs b/RGB.NET.Devices.Corsair_Legacy/Touchbar/CorsairTouchbarRGBDevice.cs
new file mode 100644
index 0000000..3b39611
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Touchbar/CorsairTouchbarRGBDevice.cs
@@ -0,0 +1,27 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+///
+/// Represents a corsair touchbar.
+///
+public class CorsairTouchbarRGBDevice : CorsairRGBDevice, IDRAM
+{
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The specific information provided by CUE for the touchbar.
+ /// The queue used to update this device.
+ internal CorsairTouchbarRGBDevice(CorsairTouchbarRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
+ : base(info, LedMappings.Keyboard, updateQueue) //TODO DarthAffe 17.07.2022: Find someone with such a device and check which LedIds are actually used
+ { }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Corsair_Legacy/Touchbar/CorsairTouchbarRGBDeviceInfo.cs b/RGB.NET.Devices.Corsair_Legacy/Touchbar/CorsairTouchbarRGBDeviceInfo.cs
new file mode 100644
index 0000000..575294e
--- /dev/null
+++ b/RGB.NET.Devices.Corsair_Legacy/Touchbar/CorsairTouchbarRGBDeviceInfo.cs
@@ -0,0 +1,28 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using RGB.NET.Core;
+using RGB.NET.Devices.CorsairLegacy.Native;
+
+namespace RGB.NET.Devices.CorsairLegacy;
+
+///
+///
+/// Represents a generic information for a .
+///
+public class CorsairTouchbarRGBDeviceInfo : CorsairRGBDeviceInfo
+{
+ #region Constructors
+
+ ///
+ ///
+ /// Internal constructor of managed .
+ ///
+ /// The index of the .
+ /// The native -struct
+ internal CorsairTouchbarRGBDeviceInfo(int deviceIndex, _CorsairDeviceInfo nativeInfo)
+ : base(deviceIndex, RGBDeviceType.Keypad, nativeInfo)
+ { }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/RGB.NET.Devices.DMX/DMXDeviceProvider.cs b/RGB.NET.Devices.DMX/DMXDeviceProvider.cs
index 55e8e3f..b5d725c 100644
--- a/RGB.NET.Devices.DMX/DMXDeviceProvider.cs
+++ b/RGB.NET.Devices.DMX/DMXDeviceProvider.cs
@@ -12,20 +12,30 @@ namespace RGB.NET.Devices.DMX;
///
/// Represents a device provider responsible for DMX devices.
///
-public class DMXDeviceProvider : AbstractRGBDeviceProvider
+public sealed class DMXDeviceProvider : AbstractRGBDeviceProvider
{
#region Properties & Fields
+ // ReSharper disable once InconsistentNaming
+ private static readonly object _lock = new();
+
private static DMXDeviceProvider? _instance;
///
/// Gets the singleton instance.
///
- public static DMXDeviceProvider Instance => _instance ?? new DMXDeviceProvider();
+ public static DMXDeviceProvider Instance
+ {
+ get
+ {
+ lock (_lock)
+ return _instance ?? new DMXDeviceProvider();
+ }
+ }
///
/// Gets a list of all defined device-definitions.
///
- public List DeviceDefinitions { get; } = new();
+ public List DeviceDefinitions { get; } = [];
#endregion
@@ -37,8 +47,11 @@ public class DMXDeviceProvider : AbstractRGBDeviceProvider
/// Thrown if this constructor is called even if there is already an instance of this class.
public DMXDeviceProvider()
{
- if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(DMXDeviceProvider)}");
- _instance = this;
+ lock (_lock)
+ {
+ if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(DMXDeviceProvider)}");
+ _instance = this;
+ }
}
#endregion
@@ -86,5 +99,16 @@ public class DMXDeviceProvider : AbstractRGBDeviceProvider
return updateTrigger;
}
+ ///
+ protected override void Dispose(bool disposing)
+ {
+ lock (_lock)
+ {
+ base.Dispose(disposing);
+
+ _instance = null;
+ }
+ }
+
#endregion
}
\ No newline at end of file
diff --git a/RGB.NET.Devices.DMX/E131/E131DMXDeviceDefinition.cs b/RGB.NET.Devices.DMX/E131/E131DMXDeviceDefinition.cs
index 37db5ea..b8b8336 100644
--- a/RGB.NET.Devices.DMX/E131/E131DMXDeviceDefinition.cs
+++ b/RGB.NET.Devices.DMX/E131/E131DMXDeviceDefinition.cs
@@ -12,7 +12,7 @@ namespace RGB.NET.Devices.DMX.E131;
///
/// Represents the data used to create a E1.31 DMX-device.
///
-public class E131DMXDeviceDefinition : IDMXDeviceDefinition
+public sealed class E131DMXDeviceDefinition : IDMXDeviceDefinition
{
#region Properties & Fields
@@ -55,7 +55,7 @@ public class E131DMXDeviceDefinition : IDMXDeviceDefinition
///
/// Gets or sets the led-mappings used to create the device.
///
- public Dictionary getValueFunc)>> Leds { get; } = new();
+ public Dictionary getValueFunc)>> Leds { get; } = [];
///
/// The time in ms after which the device is updated even if no changes are made in the meantime to prevent the target from timing out or similar problems.
diff --git a/RGB.NET.Devices.DMX/E131/E131Device.cs b/RGB.NET.Devices.DMX/E131/E131Device.cs
index a7d3473..5955ddb 100644
--- a/RGB.NET.Devices.DMX/E131/E131Device.cs
+++ b/RGB.NET.Devices.DMX/E131/E131Device.cs
@@ -7,7 +7,7 @@ namespace RGB.NET.Devices.DMX.E131;
///
/// Represents a E1.31-DXM-device.
///
-public class E131Device : AbstractRGBDevice, IUnknownDevice
+public sealed class E131Device : AbstractRGBDevice, IUnknownDevice
{
#region Properties & Fields
diff --git a/RGB.NET.Devices.DMX/E131/E131DeviceInfo.cs b/RGB.NET.Devices.DMX/E131/E131DeviceInfo.cs
index 330a740..db805f7 100644
--- a/RGB.NET.Devices.DMX/E131/E131DeviceInfo.cs
+++ b/RGB.NET.Devices.DMX/E131/E131DeviceInfo.cs
@@ -7,7 +7,7 @@ namespace RGB.NET.Devices.DMX.E131;
///
/// Represents device information for a />.
///
-public class E131DeviceInfo : IRGBDeviceInfo
+public sealed class E131DeviceInfo : IRGBDeviceInfo
{
#region Constants
diff --git a/RGB.NET.Devices.DMX/E131/E131UpdateQueue.cs b/RGB.NET.Devices.DMX/E131/E131UpdateQueue.cs
index b1bffdb..600a1ea 100644
--- a/RGB.NET.Devices.DMX/E131/E131UpdateQueue.cs
+++ b/RGB.NET.Devices.DMX/E131/E131UpdateQueue.cs
@@ -8,7 +8,7 @@ namespace RGB.NET.Devices.DMX.E131;
///
/// Represents the update-queue performing updates for E131-DMX devices.
///
-public class E131UpdateQueue : UpdateQueue
+public sealed class E131UpdateQueue : UpdateQueue
{
#region Properties & Fields
@@ -21,7 +21,7 @@ public class E131UpdateQueue : UpdateQueue
/// Gets the byte-representation of a E1.31 packet as described in http://tsp.esta.org/tsp/documents/docs/E1-31-2016.pdf.
/// CID, SequenceNumber, Universe and PropertyValues needs to be updated before use!
///
- internal byte[] DataPacket { get; } = { 0x00, 0x10, 0x00, 0x00, 0x41, 0x53, 0x43, 0x2D, 0x45, 0x31, 0x2E, 0x31, 0x37, 0x00, 0x00, 0x00, 0x72, 0x6E, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x58, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x72, 0x0B, 0x02, 0xA1, 0x00, 0x00, 0x00, 0x01, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ internal byte[] DataPacket { get; } = [0x00, 0x10, 0x00, 0x00, 0x41, 0x53, 0x43, 0x2D, 0x45, 0x31, 0x2E, 0x31, 0x37, 0x00, 0x00, 0x00, 0x72, 0x6E, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x58, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x72, 0x0B, 0x02, 0xA1, 0x00, 0x00, 0x00, 0x01, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
///
/// The sequence-number used to detect the order in which packages where sent.
@@ -59,18 +59,29 @@ public class E131UpdateQueue : UpdateQueue
}
///
- protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet)
+ protected override bool Update(in ReadOnlySpan<(object key, Color color)> dataSet)
{
- DataPacket.SetSequenceNumber(GetNextSequenceNumber());
-
- foreach ((object key, Color color) in dataSet)
+ try
{
- LedChannelMapping mapping = (LedChannelMapping)key;
- foreach ((int channel, Func getValue) in mapping)
- DataPacket.SetChannel(channel, getValue(color));
+ DataPacket.SetSequenceNumber(GetNextSequenceNumber());
+
+ foreach ((object key, Color color) in dataSet)
+ {
+ LedChannelMapping mapping = (LedChannelMapping)key;
+ foreach ((int channel, Func getValue) in mapping)
+ DataPacket.SetChannel(channel, getValue(color));
+ }
+
+ _socket.Send(DataPacket, DataPacket.Length);
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ DMXDeviceProvider.Instance.Throw(ex);
}
- _socket.Send(DataPacket, DataPacket.Length);
+ return false;
}
///
diff --git a/RGB.NET.Devices.DMX/Generic/IDMXDeviceDefinition.cs b/RGB.NET.Devices.DMX/Generic/IDMXDeviceDefinition.cs
index 5ec87df..0700b3f 100644
--- a/RGB.NET.Devices.DMX/Generic/IDMXDeviceDefinition.cs
+++ b/RGB.NET.Devices.DMX/Generic/IDMXDeviceDefinition.cs
@@ -3,5 +3,4 @@
///
/// Marker interface for DMX device definitions.
///
-public interface IDMXDeviceDefinition
-{ }
\ No newline at end of file
+public interface IDMXDeviceDefinition;
\ No newline at end of file
diff --git a/RGB.NET.Devices.DMX/Generic/LedChannelMapping.cs b/RGB.NET.Devices.DMX/Generic/LedChannelMapping.cs
index 2f999e3..4f9359f 100644
--- a/RGB.NET.Devices.DMX/Generic/LedChannelMapping.cs
+++ b/RGB.NET.Devices.DMX/Generic/LedChannelMapping.cs
@@ -5,20 +5,12 @@ using RGB.NET.Core;
namespace RGB.NET.Devices.DMX;
-internal class LedChannelMapping : IEnumerable<(int channel, Func getValue)>
+internal sealed class LedChannelMapping(List<(int channel, Func getValue)> mappings)
+ : IEnumerable<(int channel, Func getValue)>
{
#region Properties & Fields
- private readonly List<(int channel, Func getValue)> _mappings;
-
- #endregion
-
- #region Constructors
-
- public LedChannelMapping(List<(int channel, Func getValue)> mappings)
- {
- this._mappings = new List<(int channel, Func getValue)>(mappings);
- }
+ private readonly List<(int channel, Func getValue)> _mappings = [..mappings];
#endregion
diff --git a/RGB.NET.Devices.DMX/RGB.NET.Devices.DMX.csproj b/RGB.NET.Devices.DMX/RGB.NET.Devices.DMX.csproj
index d291aa0..df8e547 100644
--- a/RGB.NET.Devices.DMX/RGB.NET.Devices.DMX.csproj
+++ b/RGB.NET.Devices.DMX/RGB.NET.Devices.DMX.csproj
@@ -1,6 +1,6 @@
- net7.0;net6.0;net5.0
+ net8.0;net7.0;net6.0
latest
enable
@@ -40,7 +40,7 @@
- $(DefineConstants);TRACE;DEBUG
+ TRACE;DEBUG
true
false
@@ -48,7 +48,7 @@
true
$(NoWarn);CS1591;CS1572;CS1573
- $(DefineConstants);RELEASE
+ RELEASE
diff --git a/RGB.NET.Devices.Debug/DebugDeviceProvider.cs b/RGB.NET.Devices.Debug/DebugDeviceProvider.cs
index 6ec8142..636e57f 100644
--- a/RGB.NET.Devices.Debug/DebugDeviceProvider.cs
+++ b/RGB.NET.Devices.Debug/DebugDeviceProvider.cs
@@ -12,17 +12,27 @@ namespace RGB.NET.Devices.Debug;
///
/// Represents a device provider responsible for debug devices.
///
-public class DebugDeviceProvider : AbstractRGBDeviceProvider
+public sealed class DebugDeviceProvider : AbstractRGBDeviceProvider
{
#region Properties & Fields
+ // ReSharper disable once InconsistentNaming
+ private static readonly object _lock = new();
+
private static DebugDeviceProvider? _instance;
///
/// Gets the singleton instance.
///
- public static DebugDeviceProvider Instance => _instance ?? new DebugDeviceProvider();
+ public static DebugDeviceProvider Instance
+ {
+ get
+ {
+ lock (_lock)
+ return _instance ?? new DebugDeviceProvider();
+ }
+ }
- private List<(IDeviceLayout layout, Action>? updateLedsAction)> _fakeDeviceDefinitions = new();
+ private readonly List<(IDeviceLayout layout, Action>? updateLedsAction)> _fakeDeviceDefinitions = [];
#endregion
@@ -34,8 +44,11 @@ public class DebugDeviceProvider : AbstractRGBDeviceProvider
/// Thrown if this constructor is called even if there is already an instance of this class.
public DebugDeviceProvider()
{
- if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(DebugDeviceProvider)}");
- _instance = this;
+ lock (_lock)
+ {
+ if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(DebugDeviceProvider)}");
+ _instance = this;
+ }
}
#endregion
@@ -66,11 +79,16 @@ public class DebugDeviceProvider : AbstractRGBDeviceProvider
}
///
- public override void Dispose()
+ protected override void Dispose(bool disposing)
{
- base.Dispose();
+ lock (_lock)
+ {
+ base.Dispose(disposing);
- _fakeDeviceDefinitions.Clear();
+ _fakeDeviceDefinitions.Clear();
+
+ _instance = null;
+ }
}
#endregion
diff --git a/RGB.NET.Devices.Debug/DebugDeviceUpdateQueue.cs b/RGB.NET.Devices.Debug/DebugDeviceUpdateQueue.cs
index ccd0344..df86acc 100644
--- a/RGB.NET.Devices.Debug/DebugDeviceUpdateQueue.cs
+++ b/RGB.NET.Devices.Debug/DebugDeviceUpdateQueue.cs
@@ -3,19 +3,11 @@ using RGB.NET.Core;
namespace RGB.NET.Devices.Debug;
-internal class DebugDeviceUpdateQueue : UpdateQueue
+internal sealed class DebugDeviceUpdateQueue() : UpdateQueue(new DeviceUpdateTrigger())
{
- #region Constructors
-
- public DebugDeviceUpdateQueue()
- : base(new DeviceUpdateTrigger())
- { }
-
- #endregion
-
#region Methods
- protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { }
+ protected override bool Update(in ReadOnlySpan<(object key, Color color)> dataSet) => true;
#endregion
}
\ No newline at end of file
diff --git a/RGB.NET.Devices.Debug/DebugRGBDevice.cs b/RGB.NET.Devices.Debug/DebugRGBDevice.cs
index 35d1765..61296ab 100644
--- a/RGB.NET.Devices.Debug/DebugRGBDevice.cs
+++ b/RGB.NET.Devices.Debug/DebugRGBDevice.cs
@@ -9,7 +9,7 @@ namespace RGB.NET.Devices.Debug;
///
/// Represents a debug device.
///
-public class DebugRGBDevice : AbstractRGBDevice, IUnknownDevice
+public sealed class DebugRGBDevice : AbstractRGBDevice, IUnknownDevice
{
#region Properties & Fields
diff --git a/RGB.NET.Devices.Debug/DebugRGBDeviceInfo.cs b/RGB.NET.Devices.Debug/DebugRGBDeviceInfo.cs
index d724e36..43e3c64 100644
--- a/RGB.NET.Devices.Debug/DebugRGBDeviceInfo.cs
+++ b/RGB.NET.Devices.Debug/DebugRGBDeviceInfo.cs
@@ -6,7 +6,7 @@ namespace RGB.NET.Devices.Debug;
///
/// Represents device information for a />.
///
-public class DebugRGBDeviceInfo : IRGBDeviceInfo
+public sealed class DebugRGBDeviceInfo : IRGBDeviceInfo
{
#region Properties & Fields
diff --git a/RGB.NET.Devices.Debug/RGB.NET.Devices.Debug.csproj b/RGB.NET.Devices.Debug/RGB.NET.Devices.Debug.csproj
index f4edaae..1f17728 100644
--- a/RGB.NET.Devices.Debug/RGB.NET.Devices.Debug.csproj
+++ b/RGB.NET.Devices.Debug/RGB.NET.Devices.Debug.csproj
@@ -1,6 +1,6 @@
- net7.0;net6.0;net5.0
+ net8.0;net7.0;net6.0
latest
enable
@@ -40,7 +40,7 @@
- $(DefineConstants);TRACE;DEBUG
+ TRACE;DEBUG
true
false
@@ -48,7 +48,7 @@
true
$(NoWarn);CS1591;CS1572;CS1573
- $(DefineConstants);RELEASE
+ RELEASE
diff --git a/RGB.NET.Devices.Logitech/Generic/ILogitechRGBDevice.cs b/RGB.NET.Devices.Logitech/Generic/ILogitechRGBDevice.cs
index 9ff7cc9..4bcdfe3 100644
--- a/RGB.NET.Devices.Logitech/Generic/ILogitechRGBDevice.cs
+++ b/RGB.NET.Devices.Logitech/Generic/ILogitechRGBDevice.cs
@@ -5,5 +5,4 @@ namespace RGB.NET.Devices.Logitech;
///
/// Represents a logitech RGB-device.
///
-public interface ILogitechRGBDevice : IRGBDevice
-{ }
\ No newline at end of file
+public interface ILogitechRGBDevice : IRGBDevice;
\ No newline at end of file
diff --git a/RGB.NET.Devices.Logitech/HID/LightspeedHidLoader.cs b/RGB.NET.Devices.Logitech/HID/LightspeedHidLoader.cs
index a536a1e..de49881 100644
--- a/RGB.NET.Devices.Logitech/HID/LightspeedHidLoader.cs
+++ b/RGB.NET.Devices.Logitech/HID/LightspeedHidLoader.cs
@@ -14,7 +14,7 @@ namespace RGB.NET.Devices.Logitech.HID;
///
/// The type of the identifier leds are mapped to.
/// The type of the custom data added to the HID-device.
-public class LightspeedHIDLoader : IEnumerable>
+public sealed class LightspeedHIDLoader : IEnumerable>
where TLed : notnull
{
#region Constants
@@ -23,19 +23,20 @@ public class LightspeedHIDLoader : IEnumerable RECEIVER_PIDS = new()
- {
- 0xC539,
- 0xC53A,
- 0xC541,
- 0xC545
- };
+ private static readonly List RECEIVER_PIDS =
+ [
+ 0xC539,
+ 0xC53A,
+ 0xC541,
+ 0xC545,
+ 0xC547
+ ];
#endregion
#region Properties & Fields
- private readonly Dictionary> _deviceDefinitions = new();
+ private readonly Dictionary> _deviceDefinitions = [];
///
/// Gets the vendor id used for this loader.
@@ -116,7 +117,7 @@ public class LightspeedHIDLoader : IEnumerable map = new();
+ Dictionary map = [];
if (!deviceUsages.TryGetValue(1, out HidDevice? device) || !device.TryOpen(out HidStream stream))
return map;
@@ -197,4 +198,4 @@ public class LightspeedHIDLoader : IEnumerable
/// Gets the singleton instance.
///
- public static LogitechDeviceProvider Instance => _instance ?? new LogitechDeviceProvider();
+ public static LogitechDeviceProvider Instance
+ {
+ get
+ {
+ lock (_lock)
+ return _instance ?? new LogitechDeviceProvider();
+ }
+ }
///
/// Gets a modifiable list of paths used to find the native SDK-dlls for x86 applications.
/// The first match will be used.
///
- public static List PossibleX86NativePaths { get; } = new() { "x86/LogitechLedEnginesWrapper.dll" };
+ public static List PossibleX86NativePaths { get; } = ["x86/LogitechLedEnginesWrapper.dll"];
///
/// Gets a modifiable list of paths used to find the native SDK-dlls for x64 applications.
/// The first match will be used.
///
- public static List PossibleX64NativePaths { get; } = new() { "x64/LogitechLedEnginesWrapper.dll" };
+ public static List PossibleX64NativePaths { get; } = ["x64/LogitechLedEnginesWrapper.dll"];
private LogitechPerDeviceUpdateQueue? _perDeviceUpdateQueue;
private LogitechPerKeyUpdateQueue? _perKeyUpdateQueue;
@@ -73,6 +83,7 @@ public class LogitechDeviceProvider : AbstractRGBDeviceProvider
{
{ 0x407C, RGBDeviceType.Keyboard, "G915", LedMappings.PerKey, 0 },
{ 0x408E, RGBDeviceType.Keyboard, "G915 TKL", LedMappings.PerKey, 0 },
+ { 0xC232, RGBDeviceType.Keyboard, "G915 TKL", LedMappings.PerKey, 0 },
};
///
@@ -111,7 +122,7 @@ public class LogitechDeviceProvider : AbstractRGBDeviceProvider
{ 0x0A78, RGBDeviceType.Speaker, "G560", LedMappings.ZoneSpeaker, (LogitechDeviceType.Speaker, 4, 0) },
};
-
+
///
/// Gets the HID-definitions for wireless per-zone-devices.
///
@@ -151,7 +162,7 @@ public class LogitechDeviceProvider : AbstractRGBDeviceProvider
///
/// Gets the HID-definitions for wireless per-device-devices.
///
- public static LightspeedHIDLoader PerDeviceWirelessDeviceDefinitions { get; } = new();
+ public static LightspeedHIDLoader PerDeviceWirelessDeviceDefinitions { get; } = [];
#endregion
@@ -163,8 +174,12 @@ public class LogitechDeviceProvider : AbstractRGBDeviceProvider
/// Thrown if this constructor is called even if there is already an instance of this class.
public LogitechDeviceProvider()
{
- if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(LogitechDeviceProvider)}");
- _instance = this;
+ lock (_lock)
+ {
+ if (_instance != null)
+ throw new InvalidOperationException($"There can be only one instance of type {nameof(LogitechDeviceProvider)}");
+ _instance = this;
+ }
}
#endregion
@@ -253,17 +268,20 @@ public class LogitechDeviceProvider : AbstractRGBDeviceProvider
}
///
- public override void Dispose()
+ protected override void Dispose(bool disposing)
{
- base.Dispose();
+ lock (_lock)
+ {
+ base.Dispose(disposing);
- try { _LogitechGSDK.LogiLedRestoreLighting(); }
- catch { /* at least we tried */ }
+ try { _LogitechGSDK.LogiLedRestoreLighting(); }
+ catch { /* at least we tried */ }
- try { _LogitechGSDK.UnloadLogitechGSDK(); }
- catch { /* at least we tried */ }
+ try { _LogitechGSDK.UnloadLogitechGSDK(); }
+ catch { /* at least we tried */ }
- GC.SuppressFinalize(this);
+ _instance = null;
+ }
}
#endregion
diff --git a/RGB.NET.Devices.Logitech/Native/_LogitechGSDK.cs b/RGB.NET.Devices.Logitech/Native/_LogitechGSDK.cs
index 76efa36..42ebb6c 100644
--- a/RGB.NET.Devices.Logitech/Native/_LogitechGSDK.cs
+++ b/RGB.NET.Devices.Logitech/Native/_LogitechGSDK.cs
@@ -17,7 +17,7 @@ internal static class _LogitechGSDK
{
#region Libary Management
- private static IntPtr _handle = IntPtr.Zero;
+ private static nint _handle = 0;
///
/// Reloads the SDK.
@@ -30,7 +30,7 @@ internal static class _LogitechGSDK
private static void LoadLogitechGSDK()
{
- if (_handle != IntPtr.Zero) return;
+ if (_handle != 0) return;
List possiblePathList = GetPossibleLibraryPaths().ToList();
@@ -70,21 +70,21 @@ internal static class _LogitechGSDK
internal static void UnloadLogitechGSDK()
{
- if (_handle == IntPtr.Zero) return;
+ if (_handle == 0) return;
- _logiLedInitPointer = IntPtr.Zero;
- _logiLedShutdownPointer = IntPtr.Zero;
- _logiLedSetTargetDevicePointer = IntPtr.Zero;
- _logiLedGetSdkVersionPointer = IntPtr.Zero;
- _lgiLedSaveCurrentLightingPointer = IntPtr.Zero;
- _logiLedRestoreLightingPointer = IntPtr.Zero;
- _logiLedSetLightingPointer = IntPtr.Zero;
- _logiLedSetLightingForKeyWithKeyNamePointer = IntPtr.Zero;
- _logiLedSetLightingFromBitmapPointer = IntPtr.Zero;
- _logiLedSetLightingForTargetZonePointer = IntPtr.Zero;
+ _logiLedInitPointer = 0;
+ _logiLedShutdownPointer = 0;
+ _logiLedSetTargetDevicePointer = 0;
+ _logiLedGetSdkVersionPointer = 0;
+ _lgiLedSaveCurrentLightingPointer = 0;
+ _logiLedRestoreLightingPointer = 0;
+ _logiLedSetLightingPointer = 0;
+ _logiLedSetLightingForKeyWithKeyNamePointer = 0;
+ _logiLedSetLightingFromBitmapPointer = 0;
+ _logiLedSetLightingForTargetZonePointer = 0;
NativeLibrary.Free(_handle);
- _handle = IntPtr.Zero;
+ _handle = 0;
}
#endregion
@@ -93,16 +93,16 @@ internal static class _LogitechGSDK
#region Pointers
- private static IntPtr _logiLedInitPointer;
- private static IntPtr _logiLedShutdownPointer;
- private static IntPtr _logiLedSetTargetDevicePointer;
- private static IntPtr _logiLedGetSdkVersionPointer;
- private static IntPtr _lgiLedSaveCurrentLightingPointer;
- private static IntPtr _logiLedRestoreLightingPointer;
- private static IntPtr _logiLedSetLightingPointer;
- private static IntPtr _logiLedSetLightingForKeyWithKeyNamePointer;
- private static IntPtr _logiLedSetLightingFromBitmapPointer;
- private static IntPtr _logiLedSetLightingForTargetZonePointer;
+ private static nint _logiLedInitPointer;
+ private static nint _logiLedShutdownPointer;
+ private static nint _logiLedSetTargetDevicePointer;
+ private static nint _logiLedGetSdkVersionPointer;
+ private static nint _lgiLedSaveCurrentLightingPointer;
+ private static nint _logiLedRestoreLightingPointer;
+ private static nint _logiLedSetLightingPointer;
+ private static nint _logiLedSetLightingForKeyWithKeyNamePointer;
+ private static nint _logiLedSetLightingFromBitmapPointer;
+ private static nint _logiLedSetLightingForTargetZonePointer;
#endregion
@@ -146,9 +146,9 @@ internal static class _LogitechGSDK
internal static unsafe bool LogiLedSetLightingForTargetZone(LogitechDeviceType deviceType, int zone, int redPercentage, int greenPercentage, int bluePercentage)
=> ((delegate* unmanaged[Cdecl])ThrowIfZero(_logiLedSetLightingForTargetZonePointer))(deviceType, zone, redPercentage, greenPercentage, bluePercentage);
- private static IntPtr ThrowIfZero(IntPtr ptr)
+ private static nint ThrowIfZero(nint ptr)
{
- if (ptr == IntPtr.Zero) throw new RGBDeviceException("The Logitech-SDK is not initialized.");
+ if (ptr == 0) throw new RGBDeviceException("The Logitech-SDK is not initialized.");
return ptr;
}
diff --git a/RGB.NET.Devices.Logitech/PerDevice/LogitechPerDeviceRGBDevice.cs b/RGB.NET.Devices.Logitech/PerDevice/LogitechPerDeviceRGBDevice.cs
index 9fdbc79..6a31dad 100644
--- a/RGB.NET.Devices.Logitech/PerDevice/LogitechPerDeviceRGBDevice.cs
+++ b/RGB.NET.Devices.Logitech/PerDevice/LogitechPerDeviceRGBDevice.cs
@@ -1,6 +1,4 @@
-using System.Collections.Generic;
-using System.Linq;
-using RGB.NET.Core;
+using RGB.NET.Core;
namespace RGB.NET.Devices.Logitech;
@@ -8,7 +6,7 @@ namespace RGB.NET.Devices.Logitech;
///