1
0
mirror of https://github.com/DarthAffe/RGB.NET.git synced 2025-12-13 01:58:30 +00:00

Streamlined device loading/handling in device providers

This commit is contained in:
Darth Affe 2021-03-04 23:33:00 +01:00
parent f6f3e9185c
commit 2a9a43683c
81 changed files with 867 additions and 1864 deletions

View File

@ -34,7 +34,7 @@ namespace RGB.NET.Core
} }
/// <inheritdoc /> /// <inheritdoc />
public abstract TDeviceInfo DeviceInfo { get; } public TDeviceInfo DeviceInfo { get; }
/// <inheritdoc /> /// <inheritdoc />
IRGBDeviceInfo IRGBDevice.DeviceInfo => DeviceInfo; IRGBDeviceInfo IRGBDevice.DeviceInfo => DeviceInfo;
@ -52,6 +52,8 @@ namespace RGB.NET.Core
/// </summary> /// </summary>
protected Dictionary<LedId, Led> LedMapping { get; } = new(); protected Dictionary<LedId, Led> LedMapping { get; } = new();
protected IUpdateQueue UpdateQueue { get; }
#region Indexer #region Indexer
/// <inheritdoc /> /// <inheritdoc />
@ -68,6 +70,16 @@ namespace RGB.NET.Core
#endregion #endregion
#region Constructors
protected AbstractRGBDevice(TDeviceInfo deviceOnfo, IUpdateQueue updateQueue)
{
this.DeviceInfo = deviceOnfo;
this.UpdateQueue = updateQueue;
}
#endregion
#region Methods #region Methods
/// <inheritdoc /> /// <inheritdoc />
@ -112,14 +124,16 @@ namespace RGB.NET.Core
} }
} }
/// <summary>
/// Sends all the updated <see cref="Led"/> to the device.
/// </summary>
protected virtual void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate));
/// <inheritdoc /> /// <inheritdoc />
public virtual void Dispose() public virtual void Dispose()
{ {
try try { UpdateQueue.Dispose(); } catch { /* :( */ }
{ try { LedMapping.Clear(); } catch { /* this really shouldn't happen */ }
LedMapping.Clear();
}
catch { /* this really shouldn't happen */ }
} }
/// <summary> /// <summary>
@ -128,11 +142,6 @@ namespace RGB.NET.Core
protected virtual void DeviceUpdate() protected virtual void DeviceUpdate()
{ } { }
/// <summary>
/// Sends all the updated <see cref="Led"/> to the device.
/// </summary>
protected abstract void UpdateLeds(IEnumerable<Led> ledsToUpdate);
/// <summary> /// <summary>
/// Initializes the <see cref="Led"/> with the specified id. /// Initializes the <see cref="Led"/> with the specified id.
/// </summary> /// </summary>

View File

@ -0,0 +1,119 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace RGB.NET.Core
{
public abstract class AbstractRGBDeviceProvider : IRGBDeviceProvider
{
#region Properties & Fields
private readonly double _defaultUpdateRateHardLimit;
public bool IsInitialized { get; protected set; }
public bool ThrowsExceptions { get; protected set; }
public virtual IEnumerable<IRGBDevice> Devices { get; protected set; } = Enumerable.Empty<IRGBDevice>();
protected Dictionary<int, IDeviceUpdateTrigger> UpdateTriggers { get; } = new();
#endregion
#region Events
public event EventHandler<Exception>? Exception;
#endregion
#region Constructors
protected AbstractRGBDeviceProvider(double defaultUpdateRateHardLimit = 0)
{
this._defaultUpdateRateHardLimit = defaultUpdateRateHardLimit;
}
#endregion
#region Methods
public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false)
{
ThrowsExceptions = throwExceptions;
try
{
Reset();
InitializeSDK();
Devices = new ReadOnlyCollection<IRGBDevice>(GetLoadedDevices(loadFilter).ToList());
foreach (IDeviceUpdateTrigger updateTrigger in UpdateTriggers.Values)
updateTrigger.Start();
IsInitialized = true;
}
catch (Exception ex)
{
Reset();
Throw(ex);
return false;
}
return true;
}
protected virtual IEnumerable<IRGBDevice> GetLoadedDevices(RGBDeviceType loadFilter)
{
foreach (IRGBDevice device in LoadDevices())
{
if (loadFilter.HasFlag(device.DeviceInfo.DeviceType))
yield return device;
else
device.Dispose();
}
}
protected abstract void InitializeSDK();
protected abstract IEnumerable<IRGBDevice> LoadDevices();
protected virtual IDeviceUpdateTrigger GetUpdateTrigger(int id = -1, double? updateRateHardLimit = null)
{
if (!UpdateTriggers.TryGetValue(id, out IDeviceUpdateTrigger? updaeTrigger))
UpdateTriggers[id] = (updaeTrigger = new DeviceUpdateTrigger(updateRateHardLimit ?? _defaultUpdateRateHardLimit));
return updaeTrigger;
}
protected virtual void Reset()
{
foreach (IDeviceUpdateTrigger updateTrigger in UpdateTriggers.Values)
updateTrigger.Dispose();
Devices = Enumerable.Empty<IRGBDevice>();
IsInitialized = false;
}
protected virtual void Throw(Exception ex)
{
try { OnException(ex); } catch { /* we don't want to throw due to bad event handlers */ }
if (ThrowsExceptions)
throw ex;
}
protected virtual void OnException(Exception ex) => Exception?.Invoke(this, ex);
public virtual void Dispose()
{
IEnumerable<IRGBDevice> devices = Devices;
Reset();
foreach (IRGBDevice device in devices)
device.Dispose();
}
#endregion
}
}

View File

@ -19,7 +19,7 @@ namespace RGB.NET.Core
/// Gets generic information about the <see cref="IRGBDevice"/>. /// Gets generic information about the <see cref="IRGBDevice"/>.
/// </summary> /// </summary>
IRGBDeviceInfo DeviceInfo { get; } IRGBDeviceInfo DeviceInfo { get; }
IList<IColorCorrection> ColorCorrections { get; } IList<IColorCorrection> ColorCorrections { get; }
#endregion #endregion

View File

@ -22,6 +22,15 @@ namespace RGB.NET.Core
#endregion #endregion
#region Events
/// <summary>
/// Occurs when an exception is thrown in the device provider
/// </summary>
event EventHandler<Exception>? Exception;
#endregion
#region Methods #region Methods
bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false); bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false);

View File

@ -30,6 +30,9 @@ namespace RGB.NET.Core
/// <param name="updateData">Optional custom-data passed to the subscribers of the <see cref="Update"/>.event.</param> /// <param name="updateData">Optional custom-data passed to the subscribers of the <see cref="Update"/>.event.</param>
protected virtual void OnUpdate(CustomUpdateData? updateData = null) => Update?.Invoke(this, updateData ?? new CustomUpdateData()); protected virtual void OnUpdate(CustomUpdateData? updateData = null) => Update?.Invoke(this, updateData ?? new CustomUpdateData());
/// <inheritdoc />
public abstract void Start();
/// <inheritdoc /> /// <inheritdoc />
public abstract void Dispose(); public abstract void Dispose();

View File

@ -86,7 +86,7 @@ namespace RGB.NET.Core
/// <summary> /// <summary>
/// Starts the trigger. /// Starts the trigger.
/// </summary> /// </summary>
public void Start() public override void Start()
{ {
if (IsRunning) return; if (IsRunning) return;

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
namespace RGB.NET.Core
{
public interface IUpdateQueue<TIdentifier, TData> : IDisposable
where TIdentifier : notnull
{
/// <summary>
/// Sets or merges the provided data set in the current dataset and notifies the trigger that there is new data available.
/// </summary>
/// <param name="dataSet">The set of data.</param>
// ReSharper disable once MemberCanBeProtected.Global
void SetData(IEnumerable<(TIdentifier, TData)> dataSet);
/// <summary>
/// Resets the current data set.
/// </summary>
void Reset();
}
public interface IUpdateQueue : IUpdateQueue<object, Color>
{ }
}

View File

@ -10,7 +10,7 @@ namespace RGB.NET.Core
/// </summary> /// </summary>
/// <typeparam name="TIdentifier">The type of the key used to identify some data.</typeparam> /// <typeparam name="TIdentifier">The type of the key used to identify some data.</typeparam>
/// <typeparam name="TData">The type of the data.</typeparam> /// <typeparam name="TData">The type of the data.</typeparam>
public abstract class UpdateQueue<TIdentifier, TData> : IDisposable public abstract class UpdateQueue<TIdentifier, TData> : IUpdateQueue<TIdentifier, TData>
where TIdentifier : notnull where TIdentifier : notnull
{ {
#region Properties & Fields #region Properties & Fields
@ -123,7 +123,7 @@ namespace RGB.NET.Core
/// <summary> /// <summary>
/// Represents a generic <see cref="UpdateQueue{TIdentifier,TData}"/> using an object as the key and a color as the value. /// Represents a generic <see cref="UpdateQueue{TIdentifier,TData}"/> using an object as the key and a color as the value.
/// </summary> /// </summary>
public abstract class UpdateQueue : UpdateQueue<object, Color> public abstract class UpdateQueue : UpdateQueue<object, Color>, IUpdateQueue
{ {
#region Constructors #region Constructors

View File

@ -16,5 +16,7 @@ namespace RGB.NET.Core
/// Occurs when the trigger wants to cause an update. /// Occurs when the trigger wants to cause an update.
/// </summary> /// </summary>
event EventHandler<CustomUpdateData>? Update; event EventHandler<CustomUpdateData>? Update;
void Start();
} }
} }

View File

@ -44,7 +44,7 @@ namespace RGB.NET.Core
/// <summary> /// <summary>
/// Starts the trigger if needed, causing it to performing updates. /// Starts the trigger if needed, causing it to performing updates.
/// </summary> /// </summary>
private void Start() public override void Start()
{ {
if (UpdateTask == null) if (UpdateTask == null)
{ {

View File

@ -56,7 +56,7 @@ namespace RGB.NET.Core
/// <summary> /// <summary>
/// Starts the trigger if needed, causing it to performing updates. /// Starts the trigger if needed, causing it to performing updates.
/// </summary> /// </summary>
public void Start() public override void Start()
{ {
lock (_lock) lock (_lock)
{ {

View File

@ -3,8 +3,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using AuraServiceLib; using AuraServiceLib;
using RGB.NET.Core; using RGB.NET.Core;
@ -14,7 +12,7 @@ namespace RGB.NET.Devices.Asus
/// <summary> /// <summary>
/// Represents a device provider responsible for Cooler Master devices. /// Represents a device provider responsible for Cooler Master devices.
/// </summary> /// </summary>
public class AsusDeviceProvider : IRGBDeviceProvider public class AsusDeviceProvider : AbstractRGBDeviceProvider
{ {
#region Properties & Fields #region Properties & Fields
@ -24,20 +22,6 @@ namespace RGB.NET.Devices.Asus
/// </summary> /// </summary>
public static AsusDeviceProvider Instance => _instance ?? new AsusDeviceProvider(); public static AsusDeviceProvider Instance => _instance ?? new AsusDeviceProvider();
/// <inheritdoc />
/// <summary>
/// Indicates if the SDK is initialized and ready to use.
/// </summary>
public bool IsInitialized { get; private set; }
/// <inheritdoc />
public IEnumerable<IRGBDevice> Devices { get; private set; } = Enumerable.Empty<IRGBDevice>();
/// <summary>
/// The <see cref="DeviceUpdateTrigger"/> used to trigger the updates for asus devices.
/// </summary>
public DeviceUpdateTrigger UpdateTrigger { get; }
private IAuraSdk2? _sdk; private IAuraSdk2? _sdk;
#endregion #endregion
@ -52,107 +36,44 @@ namespace RGB.NET.Devices.Asus
{ {
if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(AsusDeviceProvider)}"); if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(AsusDeviceProvider)}");
_instance = this; _instance = this;
UpdateTrigger = new DeviceUpdateTrigger();
} }
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> protected override void InitializeSDK()
public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false)
{ {
IsInitialized = false; _sdk = (IAuraSdk2)new AuraSdk();
_sdk.SwitchMode();
}
try protected override IEnumerable<IRGBDevice> LoadDevices()
{
if (_sdk == null) yield break;
foreach (IAuraSyncDevice device in _sdk.Enumerate(0))
{ {
UpdateTrigger.Stop(); yield return (AsusDeviceType)device.Type switch
// ReSharper disable once SuspiciousTypeConversion.Global
_sdk = (IAuraSdk2)new AuraSdk();
_sdk.SwitchMode();
IList<IRGBDevice> devices = new List<IRGBDevice>();
foreach (IAuraSyncDevice device in _sdk.Enumerate(0))
{ {
try AsusDeviceType.MB_RGB => new AsusMainboardRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Mainboard, device, WMIHelper.GetMainboardInfo()?.model ?? device.Name), GetUpdateTrigger()),
{ AsusDeviceType.MB_ADDRESABLE => new AsusUnspecifiedRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.LedStripe, device), LedId.LedStripe1, GetUpdateTrigger()),
IAsusRGBDevice rgbDevice; AsusDeviceType.VGA_RGB => new AsusGraphicsCardRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.GraphicsCard, device), GetUpdateTrigger()),
switch ((AsusDeviceType)device.Type) AsusDeviceType.HEADSET_RGB => new AsusHeadsetRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Headset, device), GetUpdateTrigger()),
{ AsusDeviceType.DRAM_RGB => new AsusDramRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.DRAM, device), GetUpdateTrigger()),
case AsusDeviceType.MB_RGB: AsusDeviceType.KEYBOARD_RGB => new AsusKeyboardRGBDevice(new AsusKeyboardRGBDeviceInfo(device), GetUpdateTrigger()),
rgbDevice = new AsusMainboardRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Mainboard, device, WMIHelper.GetMainboardInfo()?.model ?? device.Name)); AsusDeviceType.NB_KB_RGB => new AsusKeyboardRGBDevice(new AsusKeyboardRGBDeviceInfo(device), GetUpdateTrigger()),
break; AsusDeviceType.NB_KB_4ZONE_RGB => new AsusKeyboardRGBDevice(new AsusKeyboardRGBDeviceInfo(device), GetUpdateTrigger()),
AsusDeviceType.MOUSE_RGB => new AsusMouseRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Mouse, device), GetUpdateTrigger()),
case AsusDeviceType.MB_ADDRESABLE: _ => new AsusUnspecifiedRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Unknown, device), LedId.Custom1, GetUpdateTrigger())
rgbDevice = new AsusUnspecifiedRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.LedStripe, device), LedId.LedStripe1); };
break;
case AsusDeviceType.VGA_RGB:
rgbDevice = new AsusGraphicsCardRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.GraphicsCard, device));
break;
case AsusDeviceType.HEADSET_RGB:
rgbDevice = new AsusHeadsetRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Headset, device));
break;
case AsusDeviceType.DRAM_RGB:
rgbDevice = new AsusDramRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.DRAM, device));
break;
case AsusDeviceType.KEYBOARD_RGB:
case AsusDeviceType.NB_KB_RGB:
case AsusDeviceType.NB_KB_4ZONE_RGB:
rgbDevice = new AsusKeyboardRGBDevice(new AsusKeyboardRGBDeviceInfo(device));
break;
case AsusDeviceType.MOUSE_RGB:
rgbDevice = new AsusMouseRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Mouse, device));
break;
default:
rgbDevice = new AsusUnspecifiedRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Unknown, device), LedId.Custom1);
break;
}
if (loadFilter.HasFlag(rgbDevice.DeviceInfo.DeviceType))
{
rgbDevice.Initialize(UpdateTrigger);
devices.Add(rgbDevice);
}
}
catch
{
if (throwExceptions)
throw;
}
}
UpdateTrigger.Start();
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
IsInitialized = true;
} }
catch
{
if (throwExceptions)
throw;
return false;
}
return true;
} }
/// <inheritdoc /> /// <inheritdoc />
public void Dispose() public override void Dispose()
{ {
try { UpdateTrigger.Dispose(); } base.Dispose();
catch { /* at least we tried */ }
foreach (IRGBDevice device in Devices)
try { device.Dispose(); }
catch { /* at least we tried */ }
Devices = Enumerable.Empty<IRGBDevice>();
try { _sdk?.ReleaseControl(0); } try { _sdk?.ReleaseControl(0); }
catch { /* at least we tried */ } catch { /* at least we tried */ }

View File

@ -15,16 +15,17 @@ namespace RGB.NET.Devices.Asus
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Asus.AsusDramRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Asus.AsusDramRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by Asus for the DRAM.</param> /// <param name="info">The specific information provided by Asus for the DRAM.</param>
internal AsusDramRGBDevice(AsusRGBDeviceInfo info) internal AsusDramRGBDevice(AsusRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info) : base(info, updateTrigger)
{ } {
InitializeLayout();
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
protected override void InitializeLayout()
{ {
int ledCount = DeviceInfo.Device.Lights.Count; int ledCount = DeviceInfo.Device.Lights.Count;
for (int i = 0; i < ledCount; i++) for (int i = 0; i < ledCount; i++)

View File

@ -1,75 +1,23 @@
using System.Collections.Generic; using RGB.NET.Core;
using System.Linq;
using RGB.NET.Core;
namespace RGB.NET.Devices.Asus namespace RGB.NET.Devices.Asus
{ {
/// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}" /> /// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}" />
/// <inheritdoc cref="IAsusRGBDevice" />
/// <summary> /// <summary>
/// Represents a generic Asus-device. (keyboard, mouse, headset, mousepad). /// Represents a generic Asus-device. (keyboard, mouse, headset, mousepad).
/// </summary> /// </summary>
public abstract class AsusRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, IAsusRGBDevice public abstract class AsusRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, IAsusRGBDevice
where TDeviceInfo : AsusRGBDeviceInfo where TDeviceInfo : AsusRGBDeviceInfo
{ {
#region Properties & Fields
/// <inheritdoc />
/// <summary>
/// Gets information about the <see cref="T:RGB.NET.Devices.Asus.AsusRGBDevice" />.
/// </summary>
public override TDeviceInfo DeviceInfo { get; }
/// <summary>
/// Gets or sets the update queue performing updates for this device.
/// </summary>
// ReSharper disable once MemberCanBePrivate.Global
protected AsusUpdateQueue? UpdateQueue { get; set; }
#endregion
#region Constructors #region Constructors
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="AsusRGBDevice{TDeviceInfo}"/> class. /// Initializes a new instance of the <see cref="AsusRGBDevice{TDeviceInfo}"/> class.
/// </summary> /// </summary>
/// <param name="info">The generic information provided by Asus for the device.</param> /// <param name="info">The generic information provided by Asus for the device.</param>
protected AsusRGBDevice(TDeviceInfo info) protected AsusRGBDevice(TDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
{ : base(info, new AsusUpdateQueue(updateTrigger, info.Device))
this.DeviceInfo = info; { }
}
#endregion
#region Methods
/// <summary>
/// Initializes the device.
/// </summary>
public void Initialize(IDeviceUpdateTrigger updateTrigger)
{
InitializeLayout();
UpdateQueue = new AsusUpdateQueue(updateTrigger);
UpdateQueue.Initialize(DeviceInfo.Device);
}
/// <summary>
/// Initializes the <see cref="Led"/> and <see cref="Size"/> of the device.
/// </summary>
protected abstract void InitializeLayout();
/// <inheritdoc />
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate));
/// <inheritdoc />
public override void Dispose()
{
try { UpdateQueue?.Dispose(); }
catch { /* at least we tried */ }
base.Dispose();
}
#endregion #endregion
} }

View File

@ -21,18 +21,19 @@ namespace RGB.NET.Devices.Asus
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Asus.AsusHeadsetRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Asus.AsusHeadsetRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by Asus for the headset.</param> /// <param name="info">The specific information provided by Asus for the headset.</param>
internal AsusUnspecifiedRGBDevice(AsusRGBDeviceInfo info, LedId baseLedId) internal AsusUnspecifiedRGBDevice(AsusRGBDeviceInfo info, LedId baseLedId, IDeviceUpdateTrigger updateTrigger)
: base(info) : base(info, updateTrigger)
{ {
this._baseLedId = baseLedId; this._baseLedId = baseLedId;
InitializeLayout();
} }
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
protected override void InitializeLayout()
{ {
int ledCount = DeviceInfo.Device.Lights.Count; int ledCount = DeviceInfo.Device.Lights.Count;
for (int i = 0; i < ledCount; i++) for (int i = 0; i < ledCount; i++)
@ -41,6 +42,7 @@ namespace RGB.NET.Devices.Asus
/// <inheritdoc /> /// <inheritdoc />
protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)_baseLedId; protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)_baseLedId;
#endregion #endregion
} }
} }

View File

@ -15,7 +15,7 @@ namespace RGB.NET.Devices.Asus
/// <summary> /// <summary>
/// The device to be updated. /// The device to be updated.
/// </summary> /// </summary>
protected IAuraSyncDevice? Device { get; private set; } protected IAuraSyncDevice Device { get; }
#endregion #endregion
@ -25,28 +25,19 @@ namespace RGB.NET.Devices.Asus
/// Initializes a new instance of the <see cref="AsusUpdateQueue"/> class. /// Initializes a new instance of the <see cref="AsusUpdateQueue"/> class.
/// </summary> /// </summary>
/// <param name="updateTrigger">The update trigger used by this queue.</param> /// <param name="updateTrigger">The update trigger used by this queue.</param>
public AsusUpdateQueue(IDeviceUpdateTrigger updateTrigger) public AsusUpdateQueue(IDeviceUpdateTrigger updateTrigger, IAuraSyncDevice device)
: base(updateTrigger) : base(updateTrigger)
{ } {
this.Device = device;
}
#endregion #endregion
#region Methods #region Methods
/// <summary>
/// Initializes the queue.
/// </summary>
/// <param name="device">The device to be updated.</param>
public void Initialize(IAuraSyncDevice device)
{
Device = device;
}
/// <inheritdoc /> /// <inheritdoc />
protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet)
{ {
if (Device == null) return;
try 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))

View File

@ -5,8 +5,6 @@ namespace RGB.NET.Devices.Asus
/// <summary> /// <summary>
/// Represents a asus RGB-device. /// Represents a asus RGB-device.
/// </summary> /// </summary>
internal interface IAsusRGBDevice : IRGBDevice public interface IAsusRGBDevice : IRGBDevice
{ { }
void Initialize(IDeviceUpdateTrigger updateTrigger);
}
} }

View File

@ -15,16 +15,17 @@ namespace RGB.NET.Devices.Asus
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Asus.AsusGraphicsCardRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Asus.AsusGraphicsCardRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by Asus for the graphics card.</param> /// <param name="info">The specific information provided by Asus for the graphics card.</param>
internal AsusGraphicsCardRGBDevice(AsusRGBDeviceInfo info) internal AsusGraphicsCardRGBDevice(AsusRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info) : base(info, updateTrigger)
{ } {
InitializeLayout();
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
protected override void InitializeLayout()
{ {
int ledCount = DeviceInfo.Device.Lights.Count; int ledCount = DeviceInfo.Device.Lights.Count;
for (int i = 0; i < ledCount; i++) for (int i = 0; i < ledCount; i++)

View File

@ -15,16 +15,17 @@ namespace RGB.NET.Devices.Asus
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Asus.AsusHeadsetRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Asus.AsusHeadsetRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by Asus for the headset.</param> /// <param name="info">The specific information provided by Asus for the headset.</param>
internal AsusHeadsetRGBDevice(AsusRGBDeviceInfo info) internal AsusHeadsetRGBDevice(AsusRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info) : base(info, updateTrigger)
{ } {
InitializeLayout();
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
protected override void InitializeLayout()
{ {
int ledCount = DeviceInfo.Device.Lights.Count; int ledCount = DeviceInfo.Device.Lights.Count;
for (int i = 0; i < ledCount; i++) for (int i = 0; i < ledCount; i++)

View File

@ -24,16 +24,17 @@ namespace RGB.NET.Devices.Asus
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Asus.AsusKeyboardRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Asus.AsusKeyboardRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by Asus for the keyboard.</param> /// <param name="info">The specific information provided by Asus for the keyboard.</param>
internal AsusKeyboardRGBDevice(AsusKeyboardRGBDeviceInfo info) internal AsusKeyboardRGBDevice(AsusKeyboardRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info) : base(info, updateTrigger)
{ } {
InitializeLayout();
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
protected override void InitializeLayout()
{ {
Dictionary<AsusLedId, LedId> reversedMapping = AsusKeyboardLedMapping.MAPPING.ToDictionary(x => x.Value, x => x.Key); Dictionary<AsusLedId, LedId> reversedMapping = AsusKeyboardLedMapping.MAPPING.ToDictionary(x => x.Value, x => x.Key);

View File

@ -15,16 +15,17 @@ namespace RGB.NET.Devices.Asus
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Asus.AsusMainboardRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Asus.AsusMainboardRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by Asus for the mainboard.</param> /// <param name="info">The specific information provided by Asus for the mainboard.</param>
internal AsusMainboardRGBDevice(AsusRGBDeviceInfo info) internal AsusMainboardRGBDevice(AsusRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info) : base(info, updateTrigger)
{ } {
InitializeLayout();
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
protected override void InitializeLayout()
{ {
int ledCount = DeviceInfo.Device.Lights.Count; int ledCount = DeviceInfo.Device.Lights.Count;
for (int i = 0; i < ledCount; i++) for (int i = 0; i < ledCount; i++)
@ -33,7 +34,7 @@ namespace RGB.NET.Devices.Asus
/// <inheritdoc /> /// <inheritdoc />
protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Mainboard1; protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Mainboard1;
#endregion #endregion
} }
} }

View File

@ -15,16 +15,17 @@ namespace RGB.NET.Devices.Asus
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Asus.AsusMouseRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Asus.AsusMouseRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by Asus for the mouse.</param> /// <param name="info">The specific information provided by Asus for the mouse.</param>
internal AsusMouseRGBDevice(AsusRGBDeviceInfo info) internal AsusMouseRGBDevice(AsusRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info) : base(info, updateTrigger)
{ } {
InitializeLayout();
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
protected override void InitializeLayout()
{ {
int ledCount = DeviceInfo.Device.Lights.Count; int ledCount = DeviceInfo.Device.Lights.Count;
for (int i = 0; i < ledCount; i++) for (int i = 0; i < ledCount; i++)

View File

@ -3,8 +3,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using RGB.NET.Core; using RGB.NET.Core;
using RGB.NET.Devices.CoolerMaster.Helper; using RGB.NET.Devices.CoolerMaster.Helper;
using RGB.NET.Devices.CoolerMaster.Native; using RGB.NET.Devices.CoolerMaster.Native;
@ -15,7 +13,7 @@ namespace RGB.NET.Devices.CoolerMaster
/// <summary> /// <summary>
/// Represents a device provider responsible for Cooler Master devices. /// Represents a device provider responsible for Cooler Master devices.
/// </summary> /// </summary>
public class CoolerMasterDeviceProvider : IRGBDeviceProvider public class CoolerMasterDeviceProvider : AbstractRGBDeviceProvider
{ {
#region Properties & Fields #region Properties & Fields
@ -37,20 +35,6 @@ namespace RGB.NET.Devices.CoolerMaster
/// </summary> /// </summary>
public static List<string> PossibleX64NativePaths { get; } = new() { "x64/CMSDK.dll" }; public static List<string> PossibleX64NativePaths { get; } = new() { "x64/CMSDK.dll" };
/// <inheritdoc />
/// <summary>
/// Indicates if the SDK is initialized and ready to use.
/// </summary>
public bool IsInitialized { get; private set; }
/// <inheritdoc />
public IEnumerable<IRGBDevice> Devices { get; private set; } = Enumerable.Empty<IRGBDevice>();
/// <summary>
/// The <see cref="DeviceUpdateTrigger"/> used to trigger the updates for cooler master devices.
/// </summary>
public DeviceUpdateTrigger UpdateTrigger { get; }
#endregion #endregion
#region Constructors #region Constructors
@ -63,97 +47,48 @@ namespace RGB.NET.Devices.CoolerMaster
{ {
if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(CoolerMasterDeviceProvider)}"); if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(CoolerMasterDeviceProvider)}");
_instance = this; _instance = this;
UpdateTrigger = new DeviceUpdateTrigger();
} }
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> protected override void InitializeSDK()
public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false)
{ {
IsInitialized = false; _CoolerMasterSDK.Reload();
if (_CoolerMasterSDK.GetSDKVersion() <= 0) Throw(new RGBDeviceException("Failed to initialize CoolerMaster-SDK"));
try
{
UpdateTrigger.Stop();
_CoolerMasterSDK.Reload();
if (_CoolerMasterSDK.GetSDKVersion() <= 0) return false;
IList<IRGBDevice> devices = new List<IRGBDevice>();
foreach (CoolerMasterDevicesIndexes index in Enum.GetValues(typeof(CoolerMasterDevicesIndexes)))
{
try
{
RGBDeviceType deviceType = index.GetDeviceType();
if (deviceType == RGBDeviceType.None) continue;
if (_CoolerMasterSDK.IsDevicePlugged(index))
{
if (!loadFilter.HasFlag(deviceType)) continue;
ICoolerMasterRGBDevice device;
switch (deviceType)
{
case RGBDeviceType.Keyboard:
CoolerMasterPhysicalKeyboardLayout physicalLayout = _CoolerMasterSDK.GetDeviceLayout(index);
device = new CoolerMasterKeyboardRGBDevice(new CoolerMasterKeyboardRGBDeviceInfo(index, physicalLayout));
break;
case RGBDeviceType.Mouse:
device = new CoolerMasterMouseRGBDevice(new CoolerMasterMouseRGBDeviceInfo(index));
break;
default:
if (throwExceptions)
throw new RGBDeviceException("Unknown Device-Type");
else
continue;
}
if (!_CoolerMasterSDK.EnableLedControl(true, index))
throw new RGBDeviceException("Failed to enable LED control for device " + index);
device.Initialize(UpdateTrigger);
devices.Add(device);
}
}
catch { if (throwExceptions) throw; }
}
UpdateTrigger.Start();
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
IsInitialized = true;
}
catch
{
if (throwExceptions)
throw;
return false;
}
return true;
} }
/// <inheritdoc /> protected override IEnumerable<IRGBDevice> LoadDevices()
public void Dispose()
{ {
try { UpdateTrigger.Dispose(); } foreach (CoolerMasterDevicesIndexes index in Enum.GetValues(typeof(CoolerMasterDevicesIndexes)))
catch { /* at least we tried */ } {
RGBDeviceType deviceType = index.GetDeviceType();
if (deviceType == RGBDeviceType.None) continue;
foreach (IRGBDevice device in Devices) if (_CoolerMasterSDK.IsDevicePlugged(index))
try { device.Dispose(); } {
catch { /* at least we tried */ } if (!_CoolerMasterSDK.EnableLedControl(true, index))
Devices = Enumerable.Empty<IRGBDevice>(); Throw(new RGBDeviceException("Failed to enable LED control for device " + index));
else
{
switch (deviceType)
{
case RGBDeviceType.Keyboard:
yield return new CoolerMasterKeyboardRGBDevice(new CoolerMasterKeyboardRGBDeviceInfo(index, _CoolerMasterSDK.GetDeviceLayout(index)), GetUpdateTrigger());
break;
// DarthAffe 03.03.2020: Should be done but isn't possible due to an weird winodws-hook inside the sdk which corrupts the stack when unloading the dll case RGBDeviceType.Mouse:
//try { _CoolerMasterSDK.UnloadCMSDK(); } yield return new CoolerMasterMouseRGBDevice(new CoolerMasterMouseRGBDeviceInfo(index), GetUpdateTrigger());
//catch { /* at least we tried */ } break;
default:
Throw(new RGBDeviceException("Unknown Device-Type"));
break;
}
}
}
}
} }
#endregion #endregion

View File

@ -1,76 +1,34 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using RGB.NET.Core; using RGB.NET.Core;
using RGB.NET.Devices.CoolerMaster.Native; using RGB.NET.Devices.CoolerMaster.Native;
namespace RGB.NET.Devices.CoolerMaster namespace RGB.NET.Devices.CoolerMaster
{ {
/// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}" /> /// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}" />
/// <inheritdoc cref="ICoolerMasterRGBDevice" />
/// <summary> /// <summary>
/// Represents a generic CoolerMaster-device. (keyboard, mouse, headset, mousepad). /// Represents a generic CoolerMaster-device. (keyboard, mouse, headset, mousepad).
/// </summary> /// </summary>
public abstract class CoolerMasterRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, ICoolerMasterRGBDevice public abstract class CoolerMasterRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, ICoolerMasterRGBDevice
where TDeviceInfo : CoolerMasterRGBDeviceInfo where TDeviceInfo : CoolerMasterRGBDeviceInfo
{ {
#region Properties & Fields
/// <inheritdoc />
/// <summary>
/// Gets information about the <see cref="T:RGB.NET.Devices.CoolerMaster.CoolerMasterRGBDevice" />.
/// </summary>
public override TDeviceInfo DeviceInfo { get; }
/// <summary>
/// Gets or sets the update queue performing updates for this device.
/// </summary>
// ReSharper disable once MemberCanBePrivate.Global
protected CoolerMasterUpdateQueue? UpdateQueue { get; set; }
#endregion
#region Constructors #region Constructors
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="CoolerMasterRGBDevice{TDeviceInfo}"/> class. /// Initializes a new instance of the <see cref="CoolerMasterRGBDevice{TDeviceInfo}"/> class.
/// </summary> /// </summary>
/// <param name="info">The generic information provided by CoolerMaster for the device.</param> /// <param name="info">The generic information provided by CoolerMaster for the device.</param>
protected CoolerMasterRGBDevice(TDeviceInfo info) protected CoolerMasterRGBDevice(TDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
{ : base(info, new CoolerMasterUpdateQueue(updateTrigger, info.DeviceIndex))
this.DeviceInfo = info; { }
}
#endregion #endregion
#region Methods #region Methods
/// <summary>
/// Initializes the device.
/// </summary>
public void Initialize(IDeviceUpdateTrigger updateTrigger)
{
InitializeLayout();
UpdateQueue = new CoolerMasterUpdateQueue(updateTrigger, DeviceInfo.DeviceIndex);
}
/// <summary>
/// Initializes the <see cref="Led"/> and <see cref="Size"/> of the device.
/// </summary>
protected abstract void InitializeLayout();
/// <inheritdoc />
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate));
/// <inheritdoc cref="IDisposable.Dispose" /> /// <inheritdoc cref="IDisposable.Dispose" />
/// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}.Dispose" /> /// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}.Dispose" />
public override void Dispose() public override void Dispose()
{ {
try { UpdateQueue?.Dispose(); }
catch { /* at least we tried */ }
_CoolerMasterSDK.EnableLedControl(false, DeviceInfo.DeviceIndex); _CoolerMasterSDK.EnableLedControl(false, DeviceInfo.DeviceIndex);
base.Dispose(); base.Dispose();

View File

@ -5,8 +5,6 @@ namespace RGB.NET.Devices.CoolerMaster
/// <summary> /// <summary>
/// Represents a CoolerMaster RGB-device. /// Represents a CoolerMaster RGB-device.
/// </summary> /// </summary>
internal interface ICoolerMasterRGBDevice : IRGBDevice public interface ICoolerMasterRGBDevice : IRGBDevice
{ { }
void Initialize(IDeviceUpdateTrigger updateTrigger);
}
} }

View File

@ -22,16 +22,17 @@ namespace RGB.NET.Devices.CoolerMaster
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.CoolerMaster.CoolerMasterKeyboardRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.CoolerMaster.CoolerMasterKeyboardRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by CoolerMaster for the keyboard</param> /// <param name="info">The specific information provided by CoolerMaster for the keyboard</param>
internal CoolerMasterKeyboardRGBDevice(CoolerMasterKeyboardRGBDeviceInfo info) internal CoolerMasterKeyboardRGBDevice(CoolerMasterKeyboardRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info) : base(info, updateTrigger)
{ } {
InitializeLayout();
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
protected override void InitializeLayout()
{ {
if (!CoolerMasterKeyboardLedMappings.Mapping.TryGetValue(DeviceInfo.DeviceIndex, out Dictionary<CoolerMasterPhysicalKeyboardLayout, Dictionary<LedId, (int row, int column)>>? deviceMappings)) if (!CoolerMasterKeyboardLedMappings.Mapping.TryGetValue(DeviceInfo.DeviceIndex, out Dictionary<CoolerMasterPhysicalKeyboardLayout, Dictionary<LedId, (int row, int column)>>? deviceMappings))
throw new RGBDeviceException($"Failed to find a CoolerMasterKeyboardLedMapping for device index {DeviceInfo.DeviceIndex}"); throw new RGBDeviceException($"Failed to find a CoolerMasterKeyboardLedMapping for device index {DeviceInfo.DeviceIndex}");
@ -44,7 +45,7 @@ namespace RGB.NET.Devices.CoolerMaster
/// <inheritdoc /> /// <inheritdoc />
protected override object GetLedCustomData(LedId ledId) => CoolerMasterKeyboardLedMappings.Mapping[DeviceInfo.DeviceIndex][DeviceInfo.PhysicalLayout][ledId]; protected override object GetLedCustomData(LedId ledId) => CoolerMasterKeyboardLedMappings.Mapping[DeviceInfo.DeviceIndex][DeviceInfo.PhysicalLayout][ledId];
#endregion #endregion
} }
} }

View File

@ -16,16 +16,15 @@ namespace RGB.NET.Devices.CoolerMaster
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.CoolerMaster.CoolerMasterMouseRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.CoolerMaster.CoolerMasterMouseRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by CoolerMaster for the mouse</param> /// <param name="info">The specific information provided by CoolerMaster for the mouse</param>
internal CoolerMasterMouseRGBDevice(CoolerMasterMouseRGBDeviceInfo info) internal CoolerMasterMouseRGBDevice(CoolerMasterMouseRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info) : base(info, updateTrigger)
{ } { }
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
protected override void InitializeLayout()
{ {
Dictionary<LedId, (int row, int column)> mapping = CoolerMasterMouseLedMappings.Mapping[DeviceInfo.DeviceIndex]; Dictionary<LedId, (int row, int column)> mapping = CoolerMasterMouseLedMappings.Mapping[DeviceInfo.DeviceIndex];
@ -35,7 +34,7 @@ namespace RGB.NET.Devices.CoolerMaster
/// <inheritdoc /> /// <inheritdoc />
protected override object GetLedCustomData(LedId ledId) => CoolerMasterMouseLedMappings.Mapping[DeviceInfo.DeviceIndex][ledId]; protected override object GetLedCustomData(LedId ledId) => CoolerMasterMouseLedMappings.Mapping[DeviceInfo.DeviceIndex][ledId];
#endregion #endregion
} }
} }

View File

@ -15,7 +15,7 @@ namespace RGB.NET.Devices.Corsair
/// <summary> /// <summary>
/// Represents a device provider responsible for corsair (CUE) devices. /// Represents a device provider responsible for corsair (CUE) devices.
/// </summary> /// </summary>
public class CorsairDeviceProvider : IRGBDeviceProvider public class CorsairDeviceProvider : AbstractRGBDeviceProvider
{ {
#region Properties & Fields #region Properties & Fields
@ -37,12 +37,6 @@ namespace RGB.NET.Devices.Corsair
/// </summary> /// </summary>
public static List<string> PossibleX64NativePaths { get; } = new() { "x64/CUESDK.dll", "x64/CUESDK_2015.dll", "x64/CUESDK_2013.dll" }; public static List<string> PossibleX64NativePaths { get; } = new() { "x64/CUESDK.dll", "x64/CUESDK_2015.dll", "x64/CUESDK_2013.dll" };
/// <inheritdoc />
/// <summary>
/// Indicates if the SDK is initialized and ready to use.
/// </summary>
public bool IsInitialized { get; private set; }
/// <summary> /// <summary>
/// Gets the protocol details for the current SDK-connection. /// Gets the protocol details for the current SDK-connection.
/// </summary> /// </summary>
@ -53,14 +47,6 @@ namespace RGB.NET.Devices.Corsair
/// </summary> /// </summary>
public CorsairError LastError => _CUESDK.CorsairGetLastError(); public CorsairError LastError => _CUESDK.CorsairGetLastError();
/// <inheritdoc />
public IEnumerable<IRGBDevice> Devices { get; private set; } = Enumerable.Empty<IRGBDevice>();
/// <summary>
/// The <see cref="DeviceUpdateTrigger"/> used to trigger the updates for corsair devices.
/// </summary>
public DeviceUpdateTrigger UpdateTrigger { get; }
#endregion #endregion
#region Constructors #region Constructors
@ -73,156 +59,108 @@ namespace RGB.NET.Devices.Corsair
{ {
if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(CorsairDeviceProvider)}"); if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(CorsairDeviceProvider)}");
_instance = this; _instance = this;
UpdateTrigger = new DeviceUpdateTrigger();
} }
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> protected override void InitializeSDK()
/// <exception cref="RGBDeviceException">Thrown if the SDK is already initialized or if the SDK is not compatible to CUE.</exception>
/// <exception cref="CUEException">Thrown if the CUE-SDK provides an error.</exception>
public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false)
{ {
IsInitialized = false; _CUESDK.Reload();
try ProtocolDetails = new CorsairProtocolDetails(_CUESDK.CorsairPerformProtocolHandshake());
{
UpdateTrigger.Stop();
_CUESDK.Reload(); CorsairError error = LastError;
if (error != CorsairError.Success)
Throw(new CUEException(error));
ProtocolDetails = new CorsairProtocolDetails(_CUESDK.CorsairPerformProtocolHandshake()); 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})"));
CorsairError error = LastError; // DarthAffe 02.02.2021: 127 is iCUE
if (error != CorsairError.Success) if (!_CUESDK.CorsairSetLayerPriority(128))
throw new CUEException(error); Throw(new CUEException(LastError));
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})");
// DarthAffe 02.02.2021: 127 is iCUE
if (!_CUESDK.CorsairSetLayerPriority(128))
throw new CUEException(LastError);
Dictionary<string, int> modelCounter = new();
IList<IRGBDevice> devices = new List<IRGBDevice>();
int deviceCount = _CUESDK.CorsairGetDeviceCount();
for (int i = 0; i < deviceCount; i++)
{
try
{
_CorsairDeviceInfo nativeDeviceInfo = (_CorsairDeviceInfo)Marshal.PtrToStructure(_CUESDK.CorsairGetDeviceInfo(i), typeof(_CorsairDeviceInfo))!;
CorsairRGBDeviceInfo info = new(i, RGBDeviceType.Unknown, nativeDeviceInfo, modelCounter);
if (!info.CapsMask.HasFlag(CorsairDeviceCaps.Lighting))
continue; // Everything that doesn't support lighting control is useless
CorsairDeviceUpdateQueue? deviceUpdateQueue = null;
foreach (ICorsairRGBDevice device in GetRGBDevice(info, i, nativeDeviceInfo, modelCounter))
{
if ((device == null) || !loadFilter.HasFlag(device.DeviceInfo.DeviceType)) continue;
deviceUpdateQueue ??= new CorsairDeviceUpdateQueue(UpdateTrigger, info.CorsairDeviceIndex);
device.Initialize(deviceUpdateQueue);
error = LastError;
if (error != CorsairError.Success)
throw new CUEException(error);
devices.Add(device);
}
}
catch { if (throwExceptions) throw; }
}
UpdateTrigger.Start();
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
IsInitialized = true;
}
catch
{
Reset();
if (throwExceptions) throw;
return false;
}
return true;
} }
private static IEnumerable<ICorsairRGBDevice> GetRGBDevice(CorsairRGBDeviceInfo info, int i, _CorsairDeviceInfo nativeDeviceInfo, Dictionary<string, int> modelCounter) protected override IEnumerable<IRGBDevice> LoadDevices()
{ {
switch (info.CorsairDeviceType) Dictionary<string, int> modelCounter = new();
int deviceCount = _CUESDK.CorsairGetDeviceCount();
for (int i = 0; i < deviceCount; i++)
{ {
case CorsairDeviceType.Keyboard: _CorsairDeviceInfo nativeDeviceInfo = (_CorsairDeviceInfo)Marshal.PtrToStructure(_CUESDK.CorsairGetDeviceInfo(i), typeof(_CorsairDeviceInfo))!;
yield return new CorsairKeyboardRGBDevice(new CorsairKeyboardRGBDeviceInfo(i, nativeDeviceInfo, modelCounter)); CorsairRGBDeviceInfo info = new(i, RGBDeviceType.Unknown, nativeDeviceInfo, modelCounter);
break; if (!info.CapsMask.HasFlag(CorsairDeviceCaps.Lighting))
continue; // Everything that doesn't support lighting control is useless
case CorsairDeviceType.Mouse: CorsairDeviceUpdateQueue updateQueue = new(GetUpdateTrigger(), info.CorsairDeviceIndex);
yield return new CorsairMouseRGBDevice(new CorsairMouseRGBDeviceInfo(i, nativeDeviceInfo, modelCounter)); switch (info.CorsairDeviceType)
break; {
case CorsairDeviceType.Keyboard:
yield return new CorsairKeyboardRGBDevice(new CorsairKeyboardRGBDeviceInfo(i, nativeDeviceInfo, modelCounter), updateQueue);
break;
case CorsairDeviceType.Headset: case CorsairDeviceType.Mouse:
yield return new CorsairHeadsetRGBDevice(new CorsairHeadsetRGBDeviceInfo(i, nativeDeviceInfo, modelCounter)); yield return new CorsairMouseRGBDevice(new CorsairMouseRGBDeviceInfo(i, nativeDeviceInfo, modelCounter), updateQueue);
break; break;
case CorsairDeviceType.Mousepad: case CorsairDeviceType.Headset:
yield return new CorsairMousepadRGBDevice(new CorsairMousepadRGBDeviceInfo(i, nativeDeviceInfo, modelCounter)); yield return new CorsairHeadsetRGBDevice(new CorsairHeadsetRGBDeviceInfo(i, nativeDeviceInfo, modelCounter), updateQueue);
break; break;
case CorsairDeviceType.HeadsetStand: case CorsairDeviceType.Mousepad:
yield return new CorsairHeadsetStandRGBDevice(new CorsairHeadsetStandRGBDeviceInfo(i, nativeDeviceInfo, modelCounter)); yield return new CorsairMousepadRGBDevice(new CorsairMousepadRGBDeviceInfo(i, nativeDeviceInfo, modelCounter), updateQueue);
break; break;
case CorsairDeviceType.MemoryModule: case CorsairDeviceType.HeadsetStand:
yield return new CorsairMemoryRGBDevice(new CorsairMemoryRGBDeviceInfo(i, nativeDeviceInfo, modelCounter)); yield return new CorsairHeadsetStandRGBDevice(new CorsairHeadsetStandRGBDeviceInfo(i, nativeDeviceInfo, modelCounter), updateQueue);
break; break;
case CorsairDeviceType.Cooler: case CorsairDeviceType.MemoryModule:
case CorsairDeviceType.CommanderPro: yield return new CorsairMemoryRGBDevice(new CorsairMemoryRGBDeviceInfo(i, nativeDeviceInfo, modelCounter), updateQueue);
case CorsairDeviceType.LightningNodePro: break;
_CorsairChannelsInfo? channelsInfo = nativeDeviceInfo.channels;
if (channelsInfo != null)
{
IntPtr channelInfoPtr = channelsInfo.channels;
for (int channel = 0; channel < channelsInfo.channelsCount; channel++) case CorsairDeviceType.Cooler:
case CorsairDeviceType.CommanderPro:
case CorsairDeviceType.LightningNodePro:
_CorsairChannelsInfo? channelsInfo = nativeDeviceInfo.channels;
if (channelsInfo != null)
{ {
CorsairLedId referenceLed = GetChannelReferenceId(info.CorsairDeviceType, channel); IntPtr channelInfoPtr = channelsInfo.channels;
if (referenceLed == CorsairLedId.Invalid) continue;
_CorsairChannelInfo channelInfo = (_CorsairChannelInfo)Marshal.PtrToStructure(channelInfoPtr, typeof(_CorsairChannelInfo))!; for (int channel = 0; channel < channelsInfo.channelsCount; channel++)
int channelDeviceInfoStructSize = Marshal.SizeOf(typeof(_CorsairChannelDeviceInfo));
IntPtr channelDeviceInfoPtr = channelInfo.devices;
for (int device = 0; device < channelInfo.devicesCount; device++)
{ {
_CorsairChannelDeviceInfo channelDeviceInfo = (_CorsairChannelDeviceInfo)Marshal.PtrToStructure(channelDeviceInfoPtr, typeof(_CorsairChannelDeviceInfo))!; CorsairLedId referenceLed = GetChannelReferenceId(info.CorsairDeviceType, channel);
if (referenceLed == CorsairLedId.Invalid) continue;
yield return new CorsairCustomRGBDevice(new CorsairCustomRGBDeviceInfo(info, nativeDeviceInfo, channelDeviceInfo, referenceLed, modelCounter)); _CorsairChannelInfo channelInfo = (_CorsairChannelInfo)Marshal.PtrToStructure(channelInfoPtr, typeof(_CorsairChannelInfo))!;
referenceLed += channelDeviceInfo.deviceLedCount;
channelDeviceInfoPtr = new IntPtr(channelDeviceInfoPtr.ToInt64() + channelDeviceInfoStructSize); int channelDeviceInfoStructSize = Marshal.SizeOf(typeof(_CorsairChannelDeviceInfo));
IntPtr channelDeviceInfoPtr = channelInfo.devices;
for (int device = 0; device < channelInfo.devicesCount; device++)
{
_CorsairChannelDeviceInfo channelDeviceInfo = (_CorsairChannelDeviceInfo)Marshal.PtrToStructure(channelDeviceInfoPtr, typeof(_CorsairChannelDeviceInfo))!;
yield return new CorsairCustomRGBDevice(new CorsairCustomRGBDeviceInfo(info, nativeDeviceInfo, channelDeviceInfo, referenceLed, modelCounter), updateQueue);
referenceLed += channelDeviceInfo.deviceLedCount;
channelDeviceInfoPtr = new IntPtr(channelDeviceInfoPtr.ToInt64() + channelDeviceInfoStructSize);
}
int channelInfoStructSize = Marshal.SizeOf(typeof(_CorsairChannelInfo));
channelInfoPtr = new IntPtr(channelInfoPtr.ToInt64() + channelInfoStructSize);
} }
int channelInfoStructSize = Marshal.SizeOf(typeof(_CorsairChannelInfo));
channelInfoPtr = new IntPtr(channelInfoPtr.ToInt64() + channelInfoStructSize);
} }
} break;
break; default:
Throw(new RGBDeviceException("Unknown Device-Type"));
break;
// ReSharper disable once RedundantCaseLabel }
case CorsairDeviceType.Unknown:
default:
throw new RGBDeviceException("Unknown Device-Type");
} }
} }
@ -240,23 +178,17 @@ namespace RGB.NET.Devices.Corsair
}; };
} }
private void Reset() protected override void Reset()
{ {
ProtocolDetails = null; ProtocolDetails = null;
Devices = Enumerable.Empty<IRGBDevice>();
IsInitialized = false; base.Reset();
} }
/// <inheritdoc /> /// <inheritdoc />
public void Dispose() public override void Dispose()
{ {
try { UpdateTrigger.Dispose(); } base.Dispose();
catch { /* at least we tried */ }
foreach (IRGBDevice device in Devices)
try { device.Dispose(); }
catch { /* at least we tried */ }
Devices = Enumerable.Empty<IRGBDevice>();
try { _CUESDK.UnloadCUESDK(); } try { _CUESDK.UnloadCUESDK(); }
catch { /* at least we tried */ } catch { /* at least we tried */ }

View File

@ -25,16 +25,17 @@ namespace RGB.NET.Devices.Corsair
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Corsair.CorsairCustomRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Corsair.CorsairCustomRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by CUE for the custom-device.</param> /// <param name="info">The specific information provided by CUE for the custom-device.</param>
internal CorsairCustomRGBDevice(CorsairCustomRGBDeviceInfo info) internal CorsairCustomRGBDevice(CorsairCustomRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
: base(info) : base(info, updateQueue)
{ } {
InitializeLayout();
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
protected override void InitializeLayout()
{ {
LedId referenceId = GetReferenceLed(DeviceInfo.DeviceType); LedId referenceId = GetReferenceLed(DeviceInfo.DeviceType);
@ -45,7 +46,7 @@ namespace RGB.NET.Devices.Corsair
AddLed(ledId, new Point(i * 10, 0), new Size(10, 10)); AddLed(ledId, new Point(i * 10, 0), new Size(10, 10));
} }
} }
protected override object GetLedCustomData(LedId ledId) => _idMapping.TryGetValue(ledId, out CorsairLedId id) ? id : CorsairLedId.Invalid; protected override object GetLedCustomData(LedId ledId) => _idMapping.TryGetValue(ledId, out CorsairLedId id) ? id : CorsairLedId.Invalid;
protected virtual LedId GetReferenceLed(RGBDeviceType deviceType) protected virtual LedId GetReferenceLed(RGBDeviceType deviceType)

View File

@ -1,99 +1,23 @@
using System.Collections.Generic; using RGB.NET.Core;
using System.Linq;
using RGB.NET.Core;
namespace RGB.NET.Devices.Corsair namespace RGB.NET.Devices.Corsair
{ {
/// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}" /> /// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}" />
/// <inheritdoc cref="ICorsairRGBDevice" />
/// <summary> /// <summary>
/// Represents a generic CUE-device. (keyboard, mouse, headset, mousepad). /// Represents a generic CUE-device. (keyboard, mouse, headset, mousepad).
/// </summary> /// </summary>
public abstract class CorsairRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, ICorsairRGBDevice public abstract class CorsairRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, ICorsairRGBDevice
where TDeviceInfo : CorsairRGBDeviceInfo where TDeviceInfo : CorsairRGBDeviceInfo
{ {
#region Properties & Fields
/// <inheritdoc />
/// <summary>
/// Gets information about the <see cref="T:RGB.NET.Devices.Corsair.CorsairRGBDevice" />.
/// </summary>
public override TDeviceInfo DeviceInfo { get; }
/// <summary>
/// Gets a dictionary containing all <see cref="Led"/> of the <see cref="CorsairRGBDevice{TDeviceInfo}"/>.
/// </summary>
// ReSharper disable once MemberCanBePrivate.Global
protected Dictionary<CorsairLedId, Led> InternalLedMapping { get; } = new();
/// <summary>
/// Gets or sets the update queue performing updates for this device.
/// </summary>
// ReSharper disable once MemberCanBePrivate.Global
protected CorsairDeviceUpdateQueue? DeviceUpdateQueue { get; set; }
#endregion
#region Indexer
/// <summary>
/// Gets the <see cref="Led"/> with the specified <see cref="CorsairLedId"/>.
/// </summary>
/// <param name="ledId">The <see cref="CorsairLedId"/> of the <see cref="Led"/> to get.</param>
/// <returns>The <see cref="Led"/> with the specified <see cref="CorsairLedId"/> or null if no <see cref="Led"/> is found.</returns>
// ReSharper disable once MemberCanBePrivate.Global
public Led? this[CorsairLedId ledId] => InternalLedMapping.TryGetValue(ledId, out Led? led) ? led : null;
#endregion
#region Constructors #region Constructors
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="CorsairRGBDevice{TDeviceInfo}"/> class. /// Initializes a new instance of the <see cref="CorsairRGBDevice{TDeviceInfo}"/> class.
/// </summary> /// </summary>
/// <param name="info">The generic information provided by CUE for the device.</param> /// <param name="info">The generic information provided by CUE for the device.</param>
protected CorsairRGBDevice(TDeviceInfo info) protected CorsairRGBDevice(TDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
{ : base(info, updateQueue)
this.DeviceInfo = info; { }
}
#endregion
#region Methods
/// <summary>
/// Initializes the device.
/// </summary>
public void Initialize(CorsairDeviceUpdateQueue deviceUpdateQueue)
{
DeviceUpdateQueue = deviceUpdateQueue;
InitializeLayout();
foreach (Led led in LedMapping.Values)
{
if (led.CustomData is CorsairLedId ledId && (ledId != CorsairLedId.Invalid))
InternalLedMapping.Add(ledId, led);
}
}
/// <summary>
/// Initializes the <see cref="Led"/> and <see cref="Size"/> of the device.
/// </summary>
protected abstract void InitializeLayout();
/// <inheritdoc />
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate)
=> DeviceUpdateQueue?.SetData(GetUpdateData(ledsToUpdate.Where(x => (x.Color.A > 0) && (x.CustomData is CorsairLedId ledId && (ledId != CorsairLedId.Invalid)))));
/// <inheritdoc />
public override void Dispose()
{
try { DeviceUpdateQueue?.Dispose(); }
catch { /* at least we tried */ }
base.Dispose();
}
#endregion #endregion
} }

View File

@ -5,8 +5,6 @@ namespace RGB.NET.Devices.Corsair
/// <summary> /// <summary>
/// Represents a corsair RGB-device. /// Represents a corsair RGB-device.
/// </summary> /// </summary>
internal interface ICorsairRGBDevice : IRGBDevice public interface ICorsairRGBDevice : IRGBDevice
{ { }
void Initialize(CorsairDeviceUpdateQueue deviceUpdateQueue);
}
} }

View File

@ -18,16 +18,17 @@ namespace RGB.NET.Devices.Corsair
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Corsair.CorsairHeadsetRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Corsair.CorsairHeadsetRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by CUE for the headset</param> /// <param name="info">The specific information provided by CUE for the headset</param>
internal CorsairHeadsetRGBDevice(CorsairHeadsetRGBDeviceInfo info) internal CorsairHeadsetRGBDevice(CorsairHeadsetRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
: base(info) : base(info, updateQueue)
{ } {
InitializeLayout();
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
protected override void InitializeLayout()
{ {
AddLed(LedId.Headset1, new Point(0, 0), new Size(10, 10)); AddLed(LedId.Headset1, new Point(0, 0), new Size(10, 10));
AddLed(LedId.Headset2, new Point(10, 0), new Size(10, 10)); AddLed(LedId.Headset2, new Point(10, 0), new Size(10, 10));

View File

@ -23,16 +23,17 @@ namespace RGB.NET.Devices.Corsair
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Corsair.CorsairHeadsetStandRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Corsair.CorsairHeadsetStandRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by CUE for the headset stand</param> /// <param name="info">The specific information provided by CUE for the headset stand</param>
internal CorsairHeadsetStandRGBDevice(CorsairHeadsetStandRGBDeviceInfo info) internal CorsairHeadsetStandRGBDevice(CorsairHeadsetStandRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
: base(info) : base(info, updateQueue)
{ } {
InitializeLayout();
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
protected override void InitializeLayout()
{ {
_CorsairLedPositions? nativeLedPositions = (_CorsairLedPositions?)Marshal.PtrToStructure(_CUESDK.CorsairGetLedPositionsByDeviceIndex(DeviceInfo.CorsairDeviceIndex), typeof(_CorsairLedPositions)); _CorsairLedPositions? nativeLedPositions = (_CorsairLedPositions?)Marshal.PtrToStructure(_CUESDK.CorsairGetLedPositionsByDeviceIndex(DeviceInfo.CorsairDeviceIndex), typeof(_CorsairLedPositions));
if (nativeLedPositions == null) return; if (nativeLedPositions == null) return;

View File

@ -28,16 +28,17 @@ namespace RGB.NET.Devices.Corsair
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Corsair.CorsairKeyboardRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Corsair.CorsairKeyboardRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by CUE for the keyboard</param> /// <param name="info">The specific information provided by CUE for the keyboard</param>
internal CorsairKeyboardRGBDevice(CorsairKeyboardRGBDeviceInfo info) internal CorsairKeyboardRGBDevice(CorsairKeyboardRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
: base(info) : base(info, updateQueue)
{ } {
InitializeLayout();
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
protected override void InitializeLayout()
{ {
_CorsairLedPositions? nativeLedPositions = (_CorsairLedPositions?)Marshal.PtrToStructure(_CUESDK.CorsairGetLedPositionsByDeviceIndex(DeviceInfo.CorsairDeviceIndex), typeof(_CorsairLedPositions)); _CorsairLedPositions? nativeLedPositions = (_CorsairLedPositions?)Marshal.PtrToStructure(_CUESDK.CorsairGetLedPositionsByDeviceIndex(DeviceInfo.CorsairDeviceIndex), typeof(_CorsairLedPositions));
if (nativeLedPositions == null) return; if (nativeLedPositions == null) return;

View File

@ -22,16 +22,17 @@ namespace RGB.NET.Devices.Corsair
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Corsair.CorsairMemoryRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Corsair.CorsairMemoryRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by CUE for the memory.</param> /// <param name="info">The specific information provided by CUE for the memory.</param>
internal CorsairMemoryRGBDevice(CorsairMemoryRGBDeviceInfo info) internal CorsairMemoryRGBDevice(CorsairMemoryRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
: base(info) : base(info, updateQueue)
{ } {
InitializeLayout();
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
protected override void InitializeLayout()
{ {
_CorsairLedPositions? nativeLedPositions = (_CorsairLedPositions?)Marshal.PtrToStructure(_CUESDK.CorsairGetLedPositionsByDeviceIndex(DeviceInfo.CorsairDeviceIndex), typeof(_CorsairLedPositions)); _CorsairLedPositions? nativeLedPositions = (_CorsairLedPositions?)Marshal.PtrToStructure(_CUESDK.CorsairGetLedPositionsByDeviceIndex(DeviceInfo.CorsairDeviceIndex), typeof(_CorsairLedPositions));
if (nativeLedPositions == null) return; if (nativeLedPositions == null) return;

View File

@ -19,16 +19,17 @@ namespace RGB.NET.Devices.Corsair
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Corsair.CorsairMouseRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Corsair.CorsairMouseRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by CUE for the mouse</param> /// <param name="info">The specific information provided by CUE for the mouse</param>
internal CorsairMouseRGBDevice(CorsairMouseRGBDeviceInfo info) internal CorsairMouseRGBDevice(CorsairMouseRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
: base(info) : base(info, updateQueue)
{ } {
InitializeLayout();
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
protected override void InitializeLayout()
{ {
switch (DeviceInfo.PhysicalLayout) switch (DeviceInfo.PhysicalLayout)
{ {

View File

@ -23,16 +23,17 @@ namespace RGB.NET.Devices.Corsair
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Corsair.CorsairMousepadRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Corsair.CorsairMousepadRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by CUE for the mousepad</param> /// <param name="info">The specific information provided by CUE for the mousepad</param>
internal CorsairMousepadRGBDevice(CorsairMousepadRGBDeviceInfo info) internal CorsairMousepadRGBDevice(CorsairMousepadRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
: base(info) : base(info, updateQueue)
{ } {
InitializeLayout();
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
protected override void InitializeLayout()
{ {
_CorsairLedPositions? nativeLedPositions = (_CorsairLedPositions?)Marshal.PtrToStructure(_CUESDK.CorsairGetLedPositionsByDeviceIndex(DeviceInfo.CorsairDeviceIndex), typeof(_CorsairLedPositions)); _CorsairLedPositions? nativeLedPositions = (_CorsairLedPositions?)Marshal.PtrToStructure(_CUESDK.CorsairGetLedPositionsByDeviceIndex(DeviceInfo.CorsairDeviceIndex), typeof(_CorsairLedPositions));
if (nativeLedPositions == null) return; if (nativeLedPositions == null) return;

View File

@ -3,8 +3,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using RGB.NET.Core; using RGB.NET.Core;
using RGB.NET.Devices.DMX.E131; using RGB.NET.Devices.DMX.E131;
@ -14,7 +12,7 @@ namespace RGB.NET.Devices.DMX
/// <summary> /// <summary>
/// Represents a device provider responsible for DMX devices. /// Represents a device provider responsible for DMX devices.
/// </summary> /// </summary>
public class DMXDeviceProvider : IRGBDeviceProvider public class DMXDeviceProvider : AbstractRGBDeviceProvider
{ {
#region Properties & Fields #region Properties & Fields
@ -24,22 +22,11 @@ namespace RGB.NET.Devices.DMX
/// </summary> /// </summary>
public static DMXDeviceProvider Instance => _instance ?? new DMXDeviceProvider(); public static DMXDeviceProvider Instance => _instance ?? new DMXDeviceProvider();
/// <inheritdoc />
public bool IsInitialized { get; private set; }
/// <inheritdoc />
public IEnumerable<IRGBDevice> Devices { get; private set; } = Enumerable.Empty<IRGBDevice>();
/// <summary> /// <summary>
/// Gets a list of all defined device-definitions. /// Gets a list of all defined device-definitions.
/// </summary> /// </summary>
public List<IDMXDeviceDefinition> DeviceDefinitions { get; } = new(); public List<IDMXDeviceDefinition> DeviceDefinitions { get; } = new();
/// <summary>
/// The <see cref="DeviceUpdateTrigger"/> used to trigger the updates for dmx devices.
/// </summary>
public DeviceUpdateTrigger UpdateTrigger { get; }
#endregion #endregion
#region Constructors #region Constructors
@ -52,8 +39,6 @@ namespace RGB.NET.Devices.DMX
{ {
if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(DMXDeviceProvider)}"); if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(DMXDeviceProvider)}");
_instance = this; _instance = this;
UpdateTrigger = new DeviceUpdateTrigger();
} }
#endregion #endregion
@ -66,58 +51,27 @@ namespace RGB.NET.Devices.DMX
/// <param name="deviceDefinition">The <see cref="IDMXDeviceDefinition"/> to add.</param> /// <param name="deviceDefinition">The <see cref="IDMXDeviceDefinition"/> to add.</param>
public void AddDeviceDefinition(IDMXDeviceDefinition deviceDefinition) => DeviceDefinitions.Add(deviceDefinition); public void AddDeviceDefinition(IDMXDeviceDefinition deviceDefinition) => DeviceDefinitions.Add(deviceDefinition);
/// <inheritdoc /> protected override void InitializeSDK() { }
public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false)
protected override IEnumerable<IRGBDevice> LoadDevices()
{ {
IsInitialized = false; foreach (IDMXDeviceDefinition dmxDeviceDefinition in DeviceDefinitions)
try
{ {
UpdateTrigger.Stop(); IRGBDevice? device = null;
try
IList<IRGBDevice> devices = new List<IRGBDevice>();
foreach (IDMXDeviceDefinition dmxDeviceDefinition in DeviceDefinitions)
{ {
try if (dmxDeviceDefinition is E131DMXDeviceDefinition e131DMXDeviceDefinition)
{ if (e131DMXDeviceDefinition.Leds.Count > 0)
if (dmxDeviceDefinition is E131DMXDeviceDefinition e131DMXDeviceDefinition) device = new E131Device(new E131DeviceInfo(e131DMXDeviceDefinition), e131DMXDeviceDefinition.Leds, GetUpdateTrigger(0));
{ }
if (e131DMXDeviceDefinition.Leds.Count > 0) catch (Exception ex)
{ {
E131Device device = new(new E131DeviceInfo(e131DMXDeviceDefinition), e131DMXDeviceDefinition.Leds); Throw(ex);
device.Initialize(UpdateTrigger);
devices.Add(device);
}
}
}
catch { if (throwExceptions) throw; }
} }
UpdateTrigger.Start(); if (device != null)
yield return device;
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
IsInitialized = true;
} }
catch
{
if (throwExceptions) throw;
return false;
}
return true;
}
/// <inheritdoc />
public void Dispose()
{
try { UpdateTrigger.Dispose(); }
catch { /* at least we tried */ }
foreach (IRGBDevice device in Devices)
try { device.Dispose(); }
catch { /* at least we tried */ }
Devices = Enumerable.Empty<IRGBDevice>();
} }
#endregion #endregion

View File

@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using RGB.NET.Core; using RGB.NET.Core;
namespace RGB.NET.Devices.DMX.E131 namespace RGB.NET.Devices.DMX.E131
@ -12,55 +11,39 @@ namespace RGB.NET.Devices.DMX.E131
{ {
#region Properties & Fields #region Properties & Fields
/// <inheritdoc />
public override E131DeviceInfo DeviceInfo { get; }
private readonly Dictionary<LedId, List<(int channel, Func<Color, byte> getValueFunc)>> _ledMappings; private readonly Dictionary<LedId, List<(int channel, Func<Color, byte> getValueFunc)>> _ledMappings;
private E131UpdateQueue? _updateQueue;
#endregion #endregion
#region Constructors #region Constructors
/// <inheritdoc /> /// <inheritdoc />
internal E131Device(E131DeviceInfo deviceInfo, Dictionary<LedId, List<(int channel, Func<Color, byte> getValueFunc)>> ledMappings) internal E131Device(E131DeviceInfo deviceInfo, Dictionary<LedId, List<(int channel, Func<Color, byte> getValueFunc)>> ledMappings, IDeviceUpdateTrigger updateTrigger)
: base(deviceInfo, new E131UpdateQueue(updateTrigger, deviceInfo.Hostname, deviceInfo.Port))
{ {
this.DeviceInfo = deviceInfo;
this._ledMappings = ledMappings; this._ledMappings = ledMappings;
InitializeLayout();
E131UpdateQueue updateQueue = (E131UpdateQueue)UpdateQueue;
updateQueue.DataPacket.SetCID(DeviceInfo.CID);
updateQueue.DataPacket.SetUniverse(DeviceInfo.Universe);
} }
#endregion #endregion
#region Methods #region Methods
internal void Initialize(IDeviceUpdateTrigger updateTrigger) private void InitializeLayout()
{ {
int count = 0; int count = 0;
foreach (LedId id in _ledMappings.Keys) foreach (LedId id in _ledMappings.Keys)
AddLed(id, new Point((count++) * 10, 0), new Size(10, 10)); AddLed(id, new Point((count++) * 10, 0), new Size(10, 10));
_updateQueue = new E131UpdateQueue(updateTrigger, DeviceInfo.Hostname, DeviceInfo.Port);
_updateQueue.DataPacket.SetCID(DeviceInfo.CID);
_updateQueue.DataPacket.SetUniverse(DeviceInfo.Universe);
} }
/// <inheritdoc /> /// <inheritdoc />
protected override object GetLedCustomData(LedId ledId) => new LedChannelMapping(_ledMappings[ledId]); protected override object GetLedCustomData(LedId ledId) => new LedChannelMapping(_ledMappings[ledId]);
/// <inheritdoc />
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => _updateQueue?.SetData(GetUpdateData(ledsToUpdate));
/// <inheritdoc />
public override void Dispose()
{
try { _updateQueue?.Dispose(); }
catch { /* at least we tried */ }
base.Dispose();
}
#endregion #endregion
} }
} }

View File

@ -3,8 +3,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using RGB.NET.Core; using RGB.NET.Core;
using RGB.NET.Layout; using RGB.NET.Layout;
@ -14,7 +12,7 @@ namespace RGB.NET.Devices.Debug
/// <summary> /// <summary>
/// Represents a device provider responsible for debug devices. /// Represents a device provider responsible for debug devices.
/// </summary> /// </summary>
public class DebugDeviceProvider : IRGBDeviceProvider public class DebugDeviceProvider : AbstractRGBDeviceProvider
{ {
#region Properties & Fields #region Properties & Fields
@ -24,13 +22,7 @@ namespace RGB.NET.Devices.Debug
/// </summary> /// </summary>
public static DebugDeviceProvider Instance => _instance ?? new DebugDeviceProvider(); public static DebugDeviceProvider Instance => _instance ?? new DebugDeviceProvider();
/// <inheritdoc /> private List<(IDeviceLayout layout, Action<IEnumerable<Led>>? updateLedsAction)> _fakeDeviceDefinitions = new();
public bool IsInitialized { get; private set; }
/// <inheritdoc />
public IEnumerable<IRGBDevice> Devices { get; private set; } = Enumerable.Empty<IRGBDevice>();
private List<(IDeviceLayout layout, string imageLayout, Action<IEnumerable<Led>>? updateLedsAction)> _fakeDeviceDefinitions = new();
#endregion #endregion
@ -54,48 +46,28 @@ namespace RGB.NET.Devices.Debug
/// Adds a new fake device definition. /// Adds a new fake device definition.
/// </summary> /// </summary>
/// <param name="layout">The path of the layout file to be used.</param> /// <param name="layout">The path of the layout file to be used.</param>
/// <param name="imageLayout">The image-layout to load.</param>
/// <param name="updateLedsAction">A action emulating led-updates.</param> /// <param name="updateLedsAction">A action emulating led-updates.</param>
public void AddFakeDeviceDefinition(IDeviceLayout layout, string imageLayout, Action<IEnumerable<Led>>? updateLedsAction = null) public void AddFakeDeviceDefinition(IDeviceLayout layout, Action<IEnumerable<Led>>? updateLedsAction = null)
=> _fakeDeviceDefinitions.Add((layout, imageLayout, updateLedsAction)); => _fakeDeviceDefinitions.Add((layout, updateLedsAction));
/// <summary> /// <summary>
/// Removes all previously added fake device definitions. /// Removes all previously added fake device definitions.
/// </summary> /// </summary>
public void ClearFakeDeviceDefinitions() => _fakeDeviceDefinitions.Clear(); public void ClearFakeDeviceDefinitions() => _fakeDeviceDefinitions.Clear();
/// <inheritdoc /> protected override void InitializeSDK() { }
public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.Unknown, bool throwExceptions = false)
protected override IEnumerable<IRGBDevice> LoadDevices()
{ {
IsInitialized = false; foreach ((IDeviceLayout layout, Action<IEnumerable<Led>>? updateLedsAction) in _fakeDeviceDefinitions)
try yield return new DebugRGBDevice(layout, updateLedsAction);
{
List<IRGBDevice> devices = new();
foreach ((IDeviceLayout layout, string imageLayout, Action<IEnumerable<Led>>? updateLedsAction) in _fakeDeviceDefinitions)
{
DebugRGBDevice device = new(layout, updateLedsAction);
devices.Add(device);
}
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
IsInitialized = true;
return true;
}
catch
{
if (throwExceptions) throw;
return false;
}
} }
/// <inheritdoc /> /// <inheritdoc />
public void ResetDevices() public override void Dispose()
{ }
/// <inheritdoc />
public void Dispose()
{ {
base.Dispose();
_fakeDeviceDefinitions.Clear(); _fakeDeviceDefinitions.Clear();
} }

View File

@ -0,0 +1,22 @@
using System;
using RGB.NET.Core;
namespace RGB.NET.Devices.Debug
{
internal class DebugDeviceUpdateQueue : UpdateQueue
{
#region Constructors
public DebugDeviceUpdateQueue()
: base(new DeviceUpdateTrigger())
{ }
#endregion
#region Methods
protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { }
#endregion
}
}

View File

@ -13,9 +13,6 @@ namespace RGB.NET.Devices.Debug
{ {
#region Properties & Fields #region Properties & Fields
/// <inheritdoc />
public override DebugRGBDeviceInfo DeviceInfo { get; }
public IDeviceLayout Layout { get; } public IDeviceLayout Layout { get; }
private Action<IEnumerable<Led>>? _updateLedsAction; private Action<IEnumerable<Led>>? _updateLedsAction;
@ -27,12 +24,11 @@ namespace RGB.NET.Devices.Debug
/// Internal constructor of <see cref="DebugRGBDeviceInfo"/>. /// Internal constructor of <see cref="DebugRGBDeviceInfo"/>.
/// </summary> /// </summary>
internal DebugRGBDevice(IDeviceLayout layout, Action<IEnumerable<Led>>? updateLedsAction = null) internal DebugRGBDevice(IDeviceLayout layout, Action<IEnumerable<Led>>? updateLedsAction = null)
: base(new DebugRGBDeviceInfo(layout.Type, layout.Vendor ?? "RGB.NET", layout.Model ?? "Debug", layout.CustomData), new DebugDeviceUpdateQueue())
{ {
this.Layout = layout; this.Layout = layout;
this._updateLedsAction = updateLedsAction; this._updateLedsAction = updateLedsAction;
DeviceInfo = new DebugRGBDeviceInfo(layout.Type, layout.Vendor ?? "RGB.NET", layout.Model ?? "Debug", layout.CustomData);
Layout.ApplyTo(this, true); Layout.ApplyTo(this, true);
} }

View File

@ -5,8 +5,6 @@ namespace RGB.NET.Devices.Logitech
/// <summary> /// <summary>
/// Represents a logitech RGB-device. /// Represents a logitech RGB-device.
/// </summary> /// </summary>
internal interface ILogitechRGBDevice : IRGBDevice public interface ILogitechRGBDevice : IRGBDevice
{ { }
void Initialize(UpdateQueue updateQueue);
}
} }

View File

@ -3,60 +3,21 @@
namespace RGB.NET.Devices.Logitech namespace RGB.NET.Devices.Logitech
{ {
/// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}" /> /// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}" />
/// <inheritdoc cref="ILogitechRGBDevice" />
/// <summary> /// <summary>
/// Represents a generic Logitech-device. (keyboard, mouse, headset, mousepad). /// Represents a generic Logitech-device. (keyboard, mouse, headset, mousepad).
/// </summary> /// </summary>
public abstract class LogitechRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, ILogitechRGBDevice public abstract class LogitechRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, ILogitechRGBDevice
where TDeviceInfo : LogitechRGBDeviceInfo where TDeviceInfo : LogitechRGBDeviceInfo
{ {
#region Properties & Fields
/// <inheritdoc />
/// <summary>
/// Gets information about the <see cref="T:RGB.NET.Devices.Logitech.LogitechRGBDevice" />.
/// </summary>
public override TDeviceInfo DeviceInfo { get; }
/// <summary>
/// Gets or sets the update queue performing updates for this device.
/// </summary>
// ReSharper disable once MemberCanBePrivate.Global
protected UpdateQueue? UpdateQueue { get; set; }
#endregion
#region Constructors #region Constructors
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="LogitechRGBDevice{TDeviceInfo}"/> class. /// Initializes a new instance of the <see cref="LogitechRGBDevice{TDeviceInfo}"/> class.
/// </summary> /// </summary>
/// <param name="info">The generic information provided by Logitech for the device.</param> /// <param name="info">The generic information provided by Logitech for the device.</param>
protected LogitechRGBDevice(TDeviceInfo info) protected LogitechRGBDevice(TDeviceInfo info, IUpdateQueue updateQueue)
{ : base(info, updateQueue)
this.DeviceInfo = info; { }
}
#endregion
#region Methods
/// <summary>
/// Initializes the device.
/// </summary>
public virtual void Initialize(UpdateQueue updateQueue)
{
UpdateQueue = updateQueue;
}
/// <inheritdoc />
public override void Dispose()
{
try { UpdateQueue?.Dispose(); }
catch { /* at least we tried */ }
base.Dispose();
}
#endregion #endregion
} }

View File

@ -3,8 +3,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using RGB.NET.Core; using RGB.NET.Core;
using RGB.NET.Devices.Logitech.HID; using RGB.NET.Devices.Logitech.HID;
using RGB.NET.Devices.Logitech.Native; using RGB.NET.Devices.Logitech.Native;
@ -15,7 +13,7 @@ namespace RGB.NET.Devices.Logitech
/// <summary> /// <summary>
/// Represents a device provider responsible for logitech devices. /// Represents a device provider responsible for logitech devices.
/// </summary> /// </summary>
public class LogitechDeviceProvider : IRGBDeviceProvider public class LogitechDeviceProvider : AbstractRGBDeviceProvider
{ {
#region Properties & Fields #region Properties & Fields
@ -37,21 +35,8 @@ namespace RGB.NET.Devices.Logitech
/// </summary> /// </summary>
public static List<string> PossibleX64NativePaths { get; } = new() { "x64/LogitechLedEnginesWrapper.dll" }; public static List<string> PossibleX64NativePaths { get; } = new() { "x64/LogitechLedEnginesWrapper.dll" };
/// <inheritdoc /> private LogitechPerDeviceUpdateQueue? _perDeviceUpdateQueue;
public bool IsInitialized { get; private set; } private LogitechPerKeyUpdateQueue? _perKeyUpdateQueue;
/// <inheritdoc />
public IEnumerable<IRGBDevice> Devices { get; private set; } = Enumerable.Empty<IRGBDevice>();
/// <summary>
/// The <see cref="DeviceUpdateTrigger"/> used to trigger the updates for logitech devices.
/// </summary>
public DeviceUpdateTrigger UpdateTrigger { get; }
// ReSharper disable once CollectionNeverQueried.Local - for now this is just to make sure they're never collected
private readonly Dictionary<RGBDeviceType, LogitechZoneUpdateQueue> _zoneUpdateQueues = new();
private LogitechPerDeviceUpdateQueue _perDeviceUpdateQueue;
private LogitechPerKeyUpdateQueue _perKeyUpdateQueue;
#endregion #endregion
@ -65,116 +50,54 @@ namespace RGB.NET.Devices.Logitech
{ {
if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(LogitechDeviceProvider)}"); if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(LogitechDeviceProvider)}");
_instance = this; _instance = this;
UpdateTrigger = new DeviceUpdateTrigger();
_perDeviceUpdateQueue = new LogitechPerDeviceUpdateQueue(UpdateTrigger);
_perKeyUpdateQueue = new LogitechPerKeyUpdateQueue(UpdateTrigger);
} }
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> protected override void InitializeSDK()
public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false)
{ {
try _perDeviceUpdateQueue = new LogitechPerDeviceUpdateQueue(GetUpdateTrigger());
_perKeyUpdateQueue = new LogitechPerKeyUpdateQueue(GetUpdateTrigger());
_LogitechGSDK.Reload();
if (!_LogitechGSDK.LogiLedInit()) Throw(new RGBDeviceException("Failed to initialize Logitech-SDK."));
_LogitechGSDK.LogiLedSaveCurrentLighting();
}
//TODO DarthAffe 04.03.2021: Rework device selection and configuration for HID-based providers
protected override IEnumerable<IRGBDevice> LoadDevices()
{
DeviceChecker.LoadDeviceList();
if (DeviceChecker.IsPerKeyDeviceConnected && (_perKeyUpdateQueue != null))
{ {
if (IsInitialized) (string model, RGBDeviceType deviceType, int _, int _) = DeviceChecker.PerKeyDeviceData;
_LogitechGSDK.LogiLedRestoreLighting(); yield return new LogitechPerKeyRGBDevice(new LogitechRGBDeviceInfo(deviceType, model, LogitechDeviceCaps.PerKeyRGB, 0), _perKeyUpdateQueue);
}
catch { /* At least we tried ... */ }
IsInitialized = false;
try
{
UpdateTrigger.Stop();
_LogitechGSDK.Reload();
if (!_LogitechGSDK.LogiLedInit()) return false;
_LogitechGSDK.LogiLedSaveCurrentLighting();
IList<IRGBDevice> devices = new List<IRGBDevice>();
DeviceChecker.LoadDeviceList();
try
{
if (DeviceChecker.IsPerKeyDeviceConnected)
{
(string model, RGBDeviceType deviceType, int _, int _) = DeviceChecker.PerKeyDeviceData;
if (loadFilter.HasFlag(deviceType)) //TODO DarthAffe 07.12.2017: Check if it's worth to try another device if the one returned doesn't match the filter
{
ILogitechRGBDevice device = new LogitechPerKeyRGBDevice(new LogitechRGBDeviceInfo(deviceType, model, LogitechDeviceCaps.PerKeyRGB, 0));
device.Initialize(_perKeyUpdateQueue);
devices.Add(device);
}
}
}
catch { if (throwExceptions) throw; }
try
{
if (DeviceChecker.IsPerDeviceDeviceConnected)
{
(string model, RGBDeviceType deviceType, int _, int _) = DeviceChecker.PerDeviceDeviceData;
if (loadFilter.HasFlag(deviceType)) //TODO DarthAffe 07.12.2017: Check if it's worth to try another device if the one returned doesn't match the filter
{
ILogitechRGBDevice device = new LogitechPerDeviceRGBDevice(new LogitechRGBDeviceInfo(deviceType, model, LogitechDeviceCaps.DeviceRGB, 0));
device.Initialize(_perDeviceUpdateQueue);
devices.Add(device);
}
}
}
catch { if (throwExceptions) throw; }
try
{
if (DeviceChecker.IsZoneDeviceConnected)
{
foreach ((string model, RGBDeviceType deviceType, int _, int zones) in DeviceChecker.ZoneDeviceData)
try
{
if (loadFilter.HasFlag(deviceType))
{
LogitechZoneUpdateQueue updateQueue = new(UpdateTrigger, deviceType);
ILogitechRGBDevice device = new LogitechZoneRGBDevice(new LogitechRGBDeviceInfo(deviceType, model, LogitechDeviceCaps.DeviceRGB, zones));
device.Initialize(updateQueue);
devices.Add(device);
_zoneUpdateQueues.Add(deviceType, updateQueue);
}
}
catch { if (throwExceptions) throw; }
}
}
catch { if (throwExceptions) throw; }
UpdateTrigger.Start();
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
IsInitialized = true;
}
catch
{
if (throwExceptions)
throw;
return false;
} }
return true; if (DeviceChecker.IsPerDeviceDeviceConnected && (_perDeviceUpdateQueue != null))
{
(string model, RGBDeviceType deviceType, int _, int _) = DeviceChecker.PerDeviceDeviceData;
yield return new LogitechPerDeviceRGBDevice(new LogitechRGBDeviceInfo(deviceType, model, LogitechDeviceCaps.DeviceRGB, 0), _perDeviceUpdateQueue);
}
if (DeviceChecker.IsZoneDeviceConnected)
{
foreach ((string model, RGBDeviceType deviceType, int _, int zones) in DeviceChecker.ZoneDeviceData)
{
LogitechZoneUpdateQueue updateQueue = new(GetUpdateTrigger(), deviceType);
yield return new LogitechZoneRGBDevice(new LogitechRGBDeviceInfo(deviceType, model, LogitechDeviceCaps.DeviceRGB, zones), updateQueue);
}
}
} }
/// <inheritdoc /> /// <inheritdoc />
public void Dispose() public override void Dispose()
{ {
try { UpdateTrigger.Dispose(); } base.Dispose();
catch { /* at least we tried */ }
foreach (IRGBDevice device in Devices)
try { device.Dispose(); }
catch { /* at least we tried */ }
Devices = Enumerable.Empty<IRGBDevice>();
try { _LogitechGSDK.LogiLedRestoreLighting(); } try { _LogitechGSDK.LogiLedRestoreLighting(); }
catch { /* at least we tried */ } catch { /* at least we tried */ }

View File

@ -17,26 +17,25 @@ namespace RGB.NET.Devices.Logitech
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Logitech.LogitechPerDeviceRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Logitech.LogitechPerDeviceRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by logitech for the per-device-lightable device</param> /// <param name="info">The specific information provided by logitech for the per-device-lightable device</param>
internal LogitechPerDeviceRGBDevice(LogitechRGBDeviceInfo info) internal LogitechPerDeviceRGBDevice(LogitechRGBDeviceInfo info, IUpdateQueue updateQueue)
: base(info) : base(info, updateQueue)
{ } {
InitializeLayout();
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
public override void Initialize(UpdateQueue updateQueue)
{ {
base.Initialize(updateQueue);
AddLed(LedId.Custom1, new Point(0, 0), new Size(10, 10)); AddLed(LedId.Custom1, new Point(0, 0), new Size(10, 10));
} }
/// <inheritdoc /> /// <inheritdoc />
protected override object GetLedCustomData(LedId ledId) => (ledId, LogitechLedId.DEVICE); protected override object GetLedCustomData(LedId ledId) => (ledId, LogitechLedId.DEVICE);
/// <inheritdoc /> /// <inheritdoc />
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate.Take(1))); protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate.Take(1)));
#endregion #endregion
} }

View File

@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using RGB.NET.Core; using RGB.NET.Core;
namespace RGB.NET.Devices.Logitech namespace RGB.NET.Devices.Logitech
@ -17,8 +16,8 @@ namespace RGB.NET.Devices.Logitech
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Logitech.LogitechPerKeyRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Logitech.LogitechPerKeyRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by logitech for the per-key-lightable device</param> /// <param name="info">The specific information provided by logitech for the per-key-lightable device</param>
internal LogitechPerKeyRGBDevice(LogitechRGBDeviceInfo info) internal LogitechPerKeyRGBDevice(LogitechRGBDeviceInfo info, IUpdateQueue updateQueue)
: base(info) : base(info, updateQueue)
{ } { }
#endregion #endregion
@ -29,7 +28,7 @@ namespace RGB.NET.Devices.Logitech
protected override object GetLedCustomData(LedId ledId) => (ledId, PerKeyIdMapping.DEFAULT.TryGetValue(ledId, out LogitechLedId logitechLedId) ? logitechLedId : LogitechLedId.Invalid); protected override object GetLedCustomData(LedId ledId) => (ledId, PerKeyIdMapping.DEFAULT.TryGetValue(ledId, out LogitechLedId logitechLedId) ? logitechLedId : LogitechLedId.Invalid);
/// <inheritdoc /> /// <inheritdoc />
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate)); protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate));
#endregion #endregion
} }

View File

@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using RGB.NET.Core; using RGB.NET.Core;
namespace RGB.NET.Devices.Logitech namespace RGB.NET.Devices.Logitech
@ -36,21 +35,20 @@ namespace RGB.NET.Devices.Logitech
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Logitech.LogitechZoneRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Logitech.LogitechZoneRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by logitech for the zone-lightable device</param> /// <param name="info">The specific information provided by logitech for the zone-lightable device</param>
internal LogitechZoneRGBDevice(LogitechRGBDeviceInfo info) internal LogitechZoneRGBDevice(LogitechRGBDeviceInfo info, IUpdateQueue updateQueue)
: base(info) : base(info, updateQueue)
{ {
_baseLedId = BASE_LED_MAPPING.TryGetValue(info.DeviceType, out LedId id) ? id : LedId.Custom1; _baseLedId = BASE_LED_MAPPING.TryGetValue(info.DeviceType, out LedId id) ? id : LedId.Custom1;
InitializeLayout();
} }
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
public override void Initialize(UpdateQueue updateQueue)
{ {
base.Initialize(updateQueue);
for (int i = 0; i < DeviceInfo.Zones; i++) for (int i = 0; i < DeviceInfo.Zones; i++)
AddLed(_baseLedId + i, new Point(i * 10, 0), new Size(10, 10)); AddLed(_baseLedId + i, new Point(i * 10, 0), new Size(10, 10));
} }
@ -59,7 +57,7 @@ namespace RGB.NET.Devices.Logitech
protected override object? GetLedCustomData(LedId ledId) => (int)(ledId - _baseLedId); protected override object? GetLedCustomData(LedId ledId) => (int)(ledId - _baseLedId);
/// <inheritdoc /> /// <inheritdoc />
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate)); protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate));
#endregion #endregion
} }

View File

@ -5,8 +5,6 @@ namespace RGB.NET.Devices.Msi
/// <summary> /// <summary>
/// Represents a MSI RGB-device. /// Represents a MSI RGB-device.
/// </summary> /// </summary>
internal interface IMsiRGBDevice : IRGBDevice public interface IMsiRGBDevice : IRGBDevice
{ { }
void Initialize(MsiDeviceUpdateQueue updateQueue, int ledCount);
}
} }

View File

@ -1,75 +1,23 @@
using System.Collections.Generic; using RGB.NET.Core;
using System.Linq;
using RGB.NET.Core;
namespace RGB.NET.Devices.Msi namespace RGB.NET.Devices.Msi
{ {
/// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}" /> /// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}" />
/// <inheritdoc cref="IMsiRGBDevice" />
/// <summary> /// <summary>
/// Represents a generic MSI-device. (keyboard, mouse, headset, mousepad). /// Represents a generic MSI-device. (keyboard, mouse, headset, mousepad).
/// </summary> /// </summary>
public abstract class MsiRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, IMsiRGBDevice public abstract class MsiRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, IMsiRGBDevice
where TDeviceInfo : MsiRGBDeviceInfo where TDeviceInfo : MsiRGBDeviceInfo
{ {
#region Properties & Fields
/// <inheritdoc />
/// <summary>
/// Gets information about the <see cref="T:RGB.NET.Devices.Msi.MsiRGBDevice" />.
/// </summary>
public override TDeviceInfo DeviceInfo { get; }
/// <summary>
/// Gets or sets the update queue performing updates for this device.
/// </summary>
// ReSharper disable once MemberCanBePrivate.Global
protected MsiDeviceUpdateQueue? DeviceUpdateQueue { get; set; }
#endregion
#region Constructors #region Constructors
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="MsiRGBDevice{TDeviceInfo}"/> class. /// Initializes a new instance of the <see cref="MsiRGBDevice{TDeviceInfo}"/> class.
/// </summary> /// </summary>
/// <param name="info">The generic information provided by MSI for the device.</param> /// <param name="info">The generic information provided by MSI for the device.</param>
protected MsiRGBDevice(TDeviceInfo info) protected MsiRGBDevice(TDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
{ : base(info, new MsiDeviceUpdateQueue(updateTrigger, info.MsiDeviceType))
this.DeviceInfo = info; { }
}
#endregion
#region Methods
/// <summary>
/// Initializes the device.
/// </summary>
public void Initialize(MsiDeviceUpdateQueue updateQueue, int ledCount)
{
DeviceUpdateQueue = updateQueue;
InitializeLayout(ledCount);
}
/// <summary>
/// Initializes the <see cref="Led"/> and <see cref="Size"/> of the device.
/// </summary>
protected abstract void InitializeLayout(int ledCount);
/// <inheritdoc />
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate)
=> DeviceUpdateQueue?.SetData(GetUpdateData(ledsToUpdate.Where(x => (x.Color.A > 0) && (x.CustomData is int))));
/// <inheritdoc />
public override void Dispose()
{
try { DeviceUpdateQueue?.Dispose(); }
catch { /* at least we tried */ }
base.Dispose();
}
#endregion #endregion
} }

View File

@ -16,16 +16,17 @@ namespace RGB.NET.Devices.Msi
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Msi.MsiGraphicsCardRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Msi.MsiGraphicsCardRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by MSI for graphics cards.</param> /// <param name="info">The specific information provided by MSI for graphics cards.</param>
internal MsiGraphicsCardRGBDevice(MsiRGBDeviceInfo info) internal MsiGraphicsCardRGBDevice(MsiRGBDeviceInfo info, int ledCount, IDeviceUpdateTrigger updateTrigger)
: base(info) : base(info, updateTrigger)
{ } {
InitializeLayout(ledCount);
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout(int ledCount)
protected override void InitializeLayout(int ledCount)
{ {
for (int i = 0; i < ledCount; i++) for (int i = 0; i < ledCount; i++)
{ {

View File

@ -16,16 +16,17 @@ namespace RGB.NET.Devices.Msi
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Msi.MsiMainboardRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Msi.MsiMainboardRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by MSI for the mainboard.</param> /// <param name="info">The specific information provided by MSI for the mainboard.</param>
internal MsiMainboardRGBDevice(MsiRGBDeviceInfo info) internal MsiMainboardRGBDevice(MsiRGBDeviceInfo info, int ledCount, IDeviceUpdateTrigger updateTrigger)
: base(info) : base(info, updateTrigger)
{ } {
InitializeLayout(ledCount);
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout(int ledCount)
protected override void InitializeLayout(int ledCount)
{ {
for (int i = 0; i < ledCount; i++) for (int i = 0; i < ledCount; i++)
{ {

View File

@ -16,16 +16,17 @@ namespace RGB.NET.Devices.Msi
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Msi.MsiMouseRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Msi.MsiMouseRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by MSI for the mouse.</param> /// <param name="info">The specific information provided by MSI for the mouse.</param>
internal MsiMouseRGBDevice(MsiRGBDeviceInfo info) internal MsiMouseRGBDevice(MsiRGBDeviceInfo info, int ledCount, IDeviceUpdateTrigger updateTrigger)
: base(info) : base(info, updateTrigger)
{ } {
InitializeLayout(ledCount);
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout(int ledCount)
protected override void InitializeLayout(int ledCount)
{ {
for (int i = 0; i < ledCount; i++) for (int i = 0; i < ledCount; i++)
{ {

View File

@ -3,8 +3,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using RGB.NET.Core; using RGB.NET.Core;
using RGB.NET.Devices.Msi.Exceptions; using RGB.NET.Devices.Msi.Exceptions;
using RGB.NET.Devices.Msi.Native; using RGB.NET.Devices.Msi.Native;
@ -15,7 +13,7 @@ namespace RGB.NET.Devices.Msi
/// <summary> /// <summary>
/// Represents a device provider responsible for MSI devices. /// Represents a device provider responsible for MSI devices.
/// </summary> /// </summary>
public class MsiDeviceProvider : IRGBDeviceProvider public class MsiDeviceProvider : AbstractRGBDeviceProvider
{ {
#region Properties & Fields #region Properties & Fields
@ -37,20 +35,6 @@ namespace RGB.NET.Devices.Msi
/// </summary> /// </summary>
public static List<string> PossibleX64NativePaths { get; } = new() { "x64/MysticLight_SDK.dll" }; public static List<string> PossibleX64NativePaths { get; } = new() { "x64/MysticLight_SDK.dll" };
/// <inheritdoc />
/// <summary>
/// Indicates if the SDK is initialized and ready to use.
/// </summary>
public bool IsInitialized { get; private set; }
/// <inheritdoc />
public IEnumerable<IRGBDevice> Devices { get; private set; } = Enumerable.Empty<IRGBDevice>();
/// <summary>
/// The <see cref="DeviceUpdateTrigger"/> used to trigger the updates for corsair devices.
/// </summary>
public DeviceUpdateTrigger UpdateTrigger { get; }
#endregion #endregion
#region Constructors #region Constructors
@ -63,102 +47,58 @@ namespace RGB.NET.Devices.Msi
{ {
if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(MsiDeviceProvider)}"); if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(MsiDeviceProvider)}");
_instance = this; _instance = this;
UpdateTrigger = new DeviceUpdateTrigger();
} }
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> protected override void InitializeSDK()
public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false)
{ {
IsInitialized = false; _MsiSDK.Reload();
try int errorCode;
{ if ((errorCode = _MsiSDK.Initialize()) != 0)
UpdateTrigger.Stop(); ThrowMsiError(errorCode);
_MsiSDK.Reload();
IList<IRGBDevice> devices = new List<IRGBDevice>();
int errorCode;
if ((errorCode = _MsiSDK.Initialize()) != 0)
ThrowMsiError(errorCode);
if ((errorCode = _MsiSDK.GetDeviceInfo(out string[] deviceTypes, out int[] ledCounts)) != 0)
ThrowMsiError(errorCode);
for (int i = 0; i < deviceTypes.Length; i++)
{
try
{
string deviceType = deviceTypes[i];
int ledCount = ledCounts[i];
//Hex3l: MSI_MB provide access to the motherboard "leds" where a led must be intended as a led header (JRGB, JRAINBOW etc..) (Tested on MSI X570 Unify)
if (deviceType.Equals("MSI_MB"))
{
MsiDeviceUpdateQueue updateQueue = new(UpdateTrigger, deviceType);
IMsiRGBDevice motherboard = new MsiMainboardRGBDevice(new MsiRGBDeviceInfo(RGBDeviceType.Mainboard, deviceType, "MSI", "Motherboard"));
motherboard.Initialize(updateQueue, ledCount);
devices.Add(motherboard);
}
else if (deviceType.Equals("MSI_VGA"))
{
//Hex3l: Every led under MSI_VGA should be a different graphics card. Handling all the cards together seems a good way to avoid overlapping of leds
//Hex3l: The led name is the name of the card (e.g. NVIDIA GeForce RTX 2080 Ti) we could provide it in device info.
MsiDeviceUpdateQueue updateQueue = new(UpdateTrigger, deviceType);
IMsiRGBDevice graphicscard = new MsiGraphicsCardRGBDevice(new MsiRGBDeviceInfo(RGBDeviceType.GraphicsCard, deviceType, "MSI", "GraphicsCard"));
graphicscard.Initialize(updateQueue, ledCount);
devices.Add(graphicscard);
}
else if (deviceType.Equals("MSI_MOUSE"))
{
//Hex3l: Every led under MSI_MOUSE should be a different mouse. Handling all the mouses together seems a good way to avoid overlapping of leds
//Hex3l: The led name is the name of the mouse (e.g. msi CLUTCH GM11) we could provide it in device info.
MsiDeviceUpdateQueue updateQueue = new(UpdateTrigger, deviceType);
IMsiRGBDevice mouses = new MsiMouseRGBDevice(new MsiRGBDeviceInfo(RGBDeviceType.Mouse, deviceType, "MSI", "Mouse"));
mouses.Initialize(updateQueue, ledCount);
devices.Add(mouses);
}
//TODO DarthAffe 22.02.2020: Add other devices
}
catch { if (throwExceptions) throw; }
}
UpdateTrigger.Start();
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
IsInitialized = true;
}
catch
{
if (throwExceptions)
throw;
return false;
}
return true;
} }
private void ThrowMsiError(int errorCode) => throw new MysticLightException(errorCode, _MsiSDK.GetErrorMessage(errorCode)); protected override IEnumerable<IRGBDevice> LoadDevices()
{
int errorCode;
if ((errorCode = _MsiSDK.GetDeviceInfo(out string[] deviceTypes, out int[] ledCounts)) != 0)
ThrowMsiError(errorCode);
for (int i = 0; i < deviceTypes.Length; i++)
{
string deviceType = deviceTypes[i];
int ledCount = ledCounts[i];
if (deviceType.Equals("MSI_MB"))
{
//Hex3l: MSI_MB provide access to the motherboard "leds" where a led must be intended as a led header (JRGB, JRAINBOW etc..) (Tested on MSI X570 Unify)
yield return new MsiMainboardRGBDevice(new MsiRGBDeviceInfo(RGBDeviceType.Mainboard, deviceType, "MSI", "Motherboard"), ledCount, GetUpdateTrigger());
}
else if (deviceType.Equals("MSI_VGA"))
{
//Hex3l: Every led under MSI_VGA should be a different graphics card. Handling all the cards together seems a good way to avoid overlapping of leds
//Hex3l: The led name is the name of the card (e.g. NVIDIA GeForce RTX 2080 Ti) we could provide it in device info.
yield return new MsiGraphicsCardRGBDevice(new MsiRGBDeviceInfo(RGBDeviceType.GraphicsCard, deviceType, "MSI", "GraphicsCard"), ledCount, GetUpdateTrigger());
}
else if (deviceType.Equals("MSI_MOUSE"))
{
//Hex3l: Every led under MSI_MOUSE should be a different mouse. Handling all the mouses together seems a good way to avoid overlapping of leds
//Hex3l: The led name is the name of the mouse (e.g. msi CLUTCH GM11) we could provide it in device info.
yield return new MsiMouseRGBDevice(new MsiRGBDeviceInfo(RGBDeviceType.Mouse, deviceType, "MSI", "Mouse"), ledCount, GetUpdateTrigger());
}
}
}
private void ThrowMsiError(int errorCode) => Throw(new MysticLightException(errorCode, _MsiSDK.GetErrorMessage(errorCode)));
/// <inheritdoc /> /// <inheritdoc />
public void Dispose() public override void Dispose()
{ {
try { UpdateTrigger.Dispose(); } base.Dispose();
catch { /* at least we tried */ }
foreach (IRGBDevice device in Devices)
try { device.Dispose(); }
catch { /* at least we tried */ }
Devices = Enumerable.Empty<IRGBDevice>();
try { _MsiSDK.UnloadMsiSDK(); } try { _MsiSDK.UnloadMsiSDK(); }
catch { /* at least we tried */ } catch { /* at least we tried */ }

View File

@ -5,8 +5,6 @@ namespace RGB.NET.Devices.Novation
/// <summary> /// <summary>
/// Represents a novation RGB-device. /// Represents a novation RGB-device.
/// </summary> /// </summary>
internal interface INovationRGBDevice : IRGBDevice public interface INovationRGBDevice : IRGBDevice
{ { }
void Initialize(IDeviceUpdateTrigger updateTrigger);
}
} }

View File

@ -1,76 +1,45 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using RGB.NET.Core; using RGB.NET.Core;
namespace RGB.NET.Devices.Novation namespace RGB.NET.Devices.Novation
{ {
/// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}" /> /// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}" />
/// <inheritdoc cref="INovationRGBDevice" />
/// <summary> /// <summary>
/// Represents a generic Novation-device. (launchpad). /// Represents a generic Novation-device. (launchpad).
/// </summary> /// </summary>
public abstract class NovationRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, INovationRGBDevice public abstract class NovationRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, INovationRGBDevice
where TDeviceInfo : NovationRGBDeviceInfo where TDeviceInfo : NovationRGBDeviceInfo
{ {
#region Properties & Fields
/// <inheritdoc />
/// <summary>
/// Gets information about the <see cref="T:RGB.NET.Devices.Novation.NovationRGBDevice" />.
/// </summary>
public override TDeviceInfo DeviceInfo { get; }
/// <summary>
/// The <see cref="MidiUpdateQueue"/> used to update this <see cref="NovationRGBDevice{TDeviceInfo}"/>.
/// </summary>
// ReSharper disable once MemberCanBePrivate.Global
protected MidiUpdateQueue? UpdateQueue { get; set; }
#endregion
#region Constructors #region Constructors
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="NovationRGBDevice{TDeviceInfo}"/> class. /// Initializes a new instance of the <see cref="NovationRGBDevice{TDeviceInfo}"/> class.
/// </summary> /// </summary>
/// <param name="info">The generic information provided by Novation for the device.</param> /// <param name="info">The generic information provided by Novation for the device.</param>
protected NovationRGBDevice(TDeviceInfo info) protected NovationRGBDevice(TDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
{ : base(info, GetUpdateQueue(updateTrigger, info))
this.DeviceInfo = info; { }
}
#endregion #endregion
#region Methods #region Methods
/// <summary> private static UpdateQueue GetUpdateQueue(IDeviceUpdateTrigger updateTrigger, TDeviceInfo info) =>
/// Initializes the device. info.ColorCapabilities switch
/// </summary>
public void Initialize(IDeviceUpdateTrigger updateTrigger)
{
InitializeLayout();
UpdateQueue = DeviceInfo.ColorCapabilities switch
{ {
NovationColorCapabilities.LimitedRG => new LimitedColorUpdateQueue(updateTrigger, DeviceInfo.DeviceId), NovationColorCapabilities.LimitedRG => new LimitedColorUpdateQueue(updateTrigger, info.DeviceId),
NovationColorCapabilities.RGB => new RGBColorUpdateQueue(updateTrigger, DeviceInfo.DeviceId), NovationColorCapabilities.RGB => new RGBColorUpdateQueue(updateTrigger, info.DeviceId),
_ => throw new ArgumentOutOfRangeException() _ => throw new ArgumentOutOfRangeException()
}; };
}
/// <summary>
/// Initializes the <see cref="Led"/> and <see cref="Size"/> of the device.
/// </summary>
protected abstract void InitializeLayout();
/// <inheritdoc /> /// <inheritdoc />
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate)); protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate));
/// <summary> /// <summary>
/// Resets the <see cref="NovationRGBDevice{TDeviceInfo}"/> back to default. /// Resets the <see cref="NovationRGBDevice{TDeviceInfo}"/> back to default.
/// </summary> /// </summary>
public virtual void Reset() => UpdateQueue?.Reset(); public virtual void Reset() => UpdateQueue.Reset();
/// <inheritdoc cref="IDisposable.Dispose" /> /// <inheritdoc cref="IDisposable.Dispose" />
/// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}.Dispose" /> /// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}.Dispose" />
@ -78,9 +47,6 @@ namespace RGB.NET.Devices.Novation
{ {
Reset(); Reset();
try { UpdateQueue?.Dispose(); }
catch { /* at least we tried */ }
base.Dispose(); base.Dispose();
} }

View File

@ -17,16 +17,17 @@ namespace RGB.NET.Devices.Novation
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Novation.NovationLaunchpadRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Novation.NovationLaunchpadRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by Novation for the launchpad</param> /// <param name="info">The specific information provided by Novation for the launchpad</param>
internal NovationLaunchpadRGBDevice(NovationLaunchpadRGBDeviceInfo info) internal NovationLaunchpadRGBDevice(NovationLaunchpadRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info) : base(info, updateTrigger)
{ } {
InitializeLayout();
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
protected override void InitializeLayout()
{ {
Dictionary<LedId, (byte mode, byte id, int x, int y)> mapping = GetDeviceMapping(); Dictionary<LedId, (byte mode, byte id, int x, int y)> mapping = GetDeviceMapping();

View File

@ -3,7 +3,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using RGB.NET.Core; using RGB.NET.Core;
using Sanford.Multimedia.Midi; using Sanford.Multimedia.Midi;
@ -14,7 +13,7 @@ namespace RGB.NET.Devices.Novation
/// <summary> /// <summary>
/// Represents a device provider responsible for Novation devices. /// Represents a device provider responsible for Novation devices.
/// </summary> /// </summary>
public class NovationDeviceProvider : IRGBDeviceProvider public class NovationDeviceProvider : AbstractRGBDeviceProvider
{ {
#region Properties & Fields #region Properties & Fields
@ -24,20 +23,6 @@ namespace RGB.NET.Devices.Novation
/// </summary> /// </summary>
public static NovationDeviceProvider Instance => _instance ?? new NovationDeviceProvider(); public static NovationDeviceProvider Instance => _instance ?? new NovationDeviceProvider();
/// <inheritdoc />
/// <summary>
/// Indicates if the SDK is initialized and ready to use.
/// </summary>
public bool IsInitialized { get; private set; }
/// <inheritdoc />
public IEnumerable<IRGBDevice> Devices { get; private set; } = Enumerable.Empty<IRGBDevice>();
/// <summary>
/// The <see cref="DeviceUpdateTrigger"/> used to trigger the updates for novation devices.
/// </summary>
public DeviceUpdateTrigger UpdateTrigger { get; }
#endregion #endregion
#region Constructors #region Constructors
@ -50,73 +35,32 @@ namespace RGB.NET.Devices.Novation
{ {
if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(NovationDeviceProvider)}"); if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(NovationDeviceProvider)}");
_instance = this; _instance = this;
UpdateTrigger = new DeviceUpdateTrigger();
} }
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> protected override void InitializeSDK() { }
public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false)
protected override IEnumerable<IRGBDevice> LoadDevices()
{ {
IsInitialized = false; for (int index = 0; index < OutputDeviceBase.DeviceCount; index++)
try
{ {
UpdateTrigger.Stop(); MidiOutCaps outCaps = OutputDeviceBase.GetDeviceCapabilities(index);
if (outCaps.name == null) continue;
IList<IRGBDevice> devices = new List<IRGBDevice>(); NovationDevices? deviceId = (NovationDevices?)Enum.GetValues(typeof(NovationDevices))
.Cast<Enum>()
.FirstOrDefault(x => x.GetDeviceId()?.ToUpperInvariant().Contains(outCaps.name.ToUpperInvariant()) ?? false);
if (loadFilter.HasFlag(RGBDeviceType.LedMatrix)) if (deviceId == null) continue;
for (int index = 0; index < OutputDeviceBase.DeviceCount; index++)
{
try
{
MidiOutCaps outCaps = OutputDeviceBase.GetDeviceCapabilities(index);
if (outCaps.name == null) continue;
NovationDevices? deviceId = (NovationDevices?)Enum.GetValues(typeof(NovationDevices)) NovationColorCapabilities colorCapability = deviceId.GetColorCapability();
.Cast<Enum>() if (colorCapability == NovationColorCapabilities.None) continue;
.FirstOrDefault(x => x.GetDeviceId()?.ToUpperInvariant().Contains(outCaps.name.ToUpperInvariant()) ?? false);
if (deviceId == null) continue; yield return new NovationLaunchpadRGBDevice(new NovationLaunchpadRGBDeviceInfo(outCaps.name, index, colorCapability, deviceId.GetLedIdMapping()), GetUpdateTrigger());
NovationColorCapabilities colorCapability = deviceId.GetColorCapability();
if (colorCapability == NovationColorCapabilities.None) continue;
INovationRGBDevice device = new NovationLaunchpadRGBDevice(new NovationLaunchpadRGBDeviceInfo(outCaps.name, index, colorCapability, deviceId.GetLedIdMapping()));
device.Initialize(UpdateTrigger);
devices.Add(device);
}
catch { if (throwExceptions) throw; }
}
UpdateTrigger.Start();
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
IsInitialized = true;
} }
catch
{
if (throwExceptions)
throw;
return false;
}
return true;
}
/// <inheritdoc />
public void Dispose()
{
try { UpdateTrigger.Dispose(); }
catch { /* at least we tried */ }
foreach (IRGBDevice device in Devices)
try { device.Dispose(); }
catch { /* at least we tried */ }
Devices = Enumerable.Empty<IRGBDevice>();
} }
#endregion #endregion

View File

@ -19,16 +19,17 @@ namespace RGB.NET.Devices.Razer
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Razer.RazerChromaLinkRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Razer.RazerChromaLinkRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by CUE for the chroma link.</param> /// <param name="info">The specific information provided by CUE for the chroma link.</param>
internal RazerChromaLinkRGBDevice(RazerChromaLinkRGBDeviceInfo info) internal RazerChromaLinkRGBDevice(RazerChromaLinkRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info) : base(info, new RazerChromaLinkUpdateQueue(updateTrigger, info.DeviceId))
{ } {
InitializeLayout();
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
protected override void InitializeLayout()
{ {
for (int i = 0; i < _Defines.CHROMALINK_MAX_LEDS; i++) for (int i = 0; i < _Defines.CHROMALINK_MAX_LEDS; i++)
AddLed(LedId.Custom1 + i, new Point(i * 11, 0), new Size(10, 10)); AddLed(LedId.Custom1 + i, new Point(i * 11, 0), new Size(10, 10));
@ -37,9 +38,6 @@ namespace RGB.NET.Devices.Razer
/// <inheritdoc /> /// <inheritdoc />
protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Custom1; protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Custom1;
/// <inheritdoc />
protected override RazerUpdateQueue CreateUpdateQueue(IDeviceUpdateTrigger updateTrigger) => new RazerChromaLinkUpdateQueue(updateTrigger, DeviceInfo.DeviceId);
#endregion #endregion
} }
} }

View File

@ -5,9 +5,6 @@ namespace RGB.NET.Devices.Razer
/// <summary> /// <summary>
/// Represents a razer RGB-device. /// Represents a razer RGB-device.
/// </summary> /// </summary>
internal interface IRazerRGBDevice : IRGBDevice public interface IRazerRGBDevice : IRGBDevice
{ { }
void Initialize(IDeviceUpdateTrigger updateTrigger);
void Reset();
}
} }

View File

@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using RGB.NET.Core; using RGB.NET.Core;
namespace RGB.NET.Devices.Razer namespace RGB.NET.Devices.Razer
@ -12,32 +11,15 @@ namespace RGB.NET.Devices.Razer
public abstract class RazerRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, IRazerRGBDevice public abstract class RazerRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, IRazerRGBDevice
where TDeviceInfo : RazerRGBDeviceInfo where TDeviceInfo : RazerRGBDeviceInfo
{ {
#region Properties & Fields
/// <inheritdoc />
/// <summary>
/// Gets information about the <see cref="T:RGB.NET.Devices.Razer.RazerRGBDevice" />.
/// </summary>
public override TDeviceInfo DeviceInfo { get; }
/// <summary>
/// Gets or sets the update queue performing updates for this device.
/// </summary>
// ReSharper disable once MemberCanBePrivate.Global
protected RazerUpdateQueue? UpdateQueue { get; set; }
#endregion
#region Constructors #region Constructors
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="RazerRGBDevice{TDeviceInfo}"/> class. /// Initializes a new instance of the <see cref="RazerRGBDevice{TDeviceInfo}"/> class.
/// </summary> /// </summary>
/// <param name="info">The generic information provided by razer for the device.</param> /// <param name="info">The generic information provided by razer for the device.</param>
protected RazerRGBDevice(TDeviceInfo info) protected RazerRGBDevice(TDeviceInfo info, IUpdateQueue updateQueue)
: base(info, updateQueue)
{ {
this.DeviceInfo = info;
RequiresFlush = true; RequiresFlush = true;
} }
@ -45,35 +27,8 @@ namespace RGB.NET.Devices.Razer
#region Methods #region Methods
/// <summary>
/// Initializes the device.
/// </summary>
public void Initialize(IDeviceUpdateTrigger updateTrigger)
{
InitializeLayout();
UpdateQueue = CreateUpdateQueue(updateTrigger);
}
/// <summary>
/// Creates a specific <see cref="RazerUpdateQueue"/> for this device.
/// </summary>
/// <param name="updateTrigger">The trigger used to update the queue.</param>
/// <returns>The <see cref="RazerUpdateQueue"/> for this device.</returns>
protected abstract RazerUpdateQueue CreateUpdateQueue(IDeviceUpdateTrigger updateTrigger);
/// <summary>
/// Initializes the <see cref="Led"/> and <see cref="Size"/> of the device.
/// </summary>
protected abstract void InitializeLayout();
/// <inheritdoc /> /// <inheritdoc />
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate)); protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate));
/// <summary>
/// Resets the device.
/// </summary>
public void Reset() => UpdateQueue?.Reset();
/// <inheritdoc /> /// <inheritdoc />
public override void Dispose() public override void Dispose()

View File

@ -19,16 +19,17 @@ namespace RGB.NET.Devices.Razer
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Razer.RazerHeadsetRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Razer.RazerHeadsetRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by CUE for the headset.</param> /// <param name="info">The specific information provided by CUE for the headset.</param>
internal RazerHeadsetRGBDevice(RazerHeadsetRGBDeviceInfo info) internal RazerHeadsetRGBDevice(RazerHeadsetRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info) : base(info, new RazerHeadsetUpdateQueue(updateTrigger, info.DeviceId))
{ } {
InitializeLayout();
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
protected override void InitializeLayout()
{ {
for (int i = 0; i < _Defines.HEADSET_MAX_LEDS; i++) for (int i = 0; i < _Defines.HEADSET_MAX_LEDS; i++)
AddLed(LedId.Headset1 + i, new Point(i * 11, 0), new Size(10, 10)); AddLed(LedId.Headset1 + i, new Point(i * 11, 0), new Size(10, 10));
@ -37,9 +38,6 @@ namespace RGB.NET.Devices.Razer
/// <inheritdoc /> /// <inheritdoc />
protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Headset1; protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Headset1;
/// <inheritdoc />
protected override RazerUpdateQueue CreateUpdateQueue(IDeviceUpdateTrigger updateTrigger) => new RazerHeadsetUpdateQueue(updateTrigger, DeviceInfo.DeviceId);
#endregion #endregion
} }
} }

View File

@ -25,16 +25,17 @@ namespace RGB.NET.Devices.Razer
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Razer.RazerKeyboardRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Razer.RazerKeyboardRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by CUE for the keyboard.</param> /// <param name="info">The specific information provided by CUE for the keyboard.</param>
internal RazerKeyboardRGBDevice(RazerKeyboardRGBDeviceInfo info) internal RazerKeyboardRGBDevice(RazerKeyboardRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info) : base(info, new RazerKeyboardUpdateQueue(updateTrigger, info.DeviceId))
{ } {
InitializeLayout();
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
protected override void InitializeLayout()
{ {
for (int i = 0; i < _Defines.KEYBOARD_MAX_ROW; i++) for (int i = 0; i < _Defines.KEYBOARD_MAX_ROW; i++)
for (int j = 0; j < _Defines.KEYBOARD_MAX_COLUMN; j++) for (int j = 0; j < _Defines.KEYBOARD_MAX_COLUMN; j++)
@ -44,9 +45,6 @@ namespace RGB.NET.Devices.Razer
/// <inheritdoc /> /// <inheritdoc />
protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Keyboard_Escape; protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Keyboard_Escape;
/// <inheritdoc />
protected override RazerUpdateQueue CreateUpdateQueue(IDeviceUpdateTrigger updateTrigger) => new RazerKeyboardUpdateQueue(updateTrigger, DeviceInfo.DeviceId);
#endregion #endregion
} }
} }

View File

@ -19,16 +19,17 @@ namespace RGB.NET.Devices.Razer
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Razer.RazerKeypadRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Razer.RazerKeypadRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by CUE for the keypad.</param> /// <param name="info">The specific information provided by CUE for the keypad.</param>
internal RazerKeypadRGBDevice(RazerKeypadRGBDeviceInfo info) internal RazerKeypadRGBDevice(RazerKeypadRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info) : base(info, new RazerKeypadUpdateQueue(updateTrigger, info.DeviceId))
{ } {
InitializeLayout();
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
protected override void InitializeLayout()
{ {
for (int i = 0; i < _Defines.KEYPAD_MAX_ROW; i++) for (int i = 0; i < _Defines.KEYPAD_MAX_ROW; i++)
for (int j = 0; j < _Defines.KEYPAD_MAX_COLUMN; j++) for (int j = 0; j < _Defines.KEYPAD_MAX_COLUMN; j++)
@ -38,9 +39,6 @@ namespace RGB.NET.Devices.Razer
/// <inheritdoc /> /// <inheritdoc />
protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Keypad1; protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Keypad1;
/// <inheritdoc />
protected override RazerUpdateQueue CreateUpdateQueue(IDeviceUpdateTrigger updateTrigger) => new RazerKeypadUpdateQueue(updateTrigger, DeviceInfo.DeviceId);
#endregion #endregion
} }
} }

View File

@ -19,16 +19,17 @@ namespace RGB.NET.Devices.Razer
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Razer.RazerMouseRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Razer.RazerMouseRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by CUE for the mouse.</param> /// <param name="info">The specific information provided by CUE for the mouse.</param>
internal RazerMouseRGBDevice(RazerMouseRGBDeviceInfo info) internal RazerMouseRGBDevice(RazerMouseRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info) : base(info, new RazerMouseUpdateQueue(updateTrigger, info.DeviceId))
{ } {
InitializeLayout();
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
protected override void InitializeLayout()
{ {
for (int i = 0; i < _Defines.MOUSE_MAX_ROW; i++) for (int i = 0; i < _Defines.MOUSE_MAX_ROW; i++)
for (int j = 0; j < _Defines.MOUSE_MAX_COLUMN; j++) for (int j = 0; j < _Defines.MOUSE_MAX_COLUMN; j++)
@ -38,9 +39,6 @@ namespace RGB.NET.Devices.Razer
/// <inheritdoc /> /// <inheritdoc />
protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Mouse1; protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Mouse1;
/// <inheritdoc />
protected override RazerUpdateQueue CreateUpdateQueue(IDeviceUpdateTrigger updateTrigger) => new RazerMouseUpdateQueue(updateTrigger, DeviceInfo.DeviceId);
#endregion #endregion
} }
} }

View File

@ -19,16 +19,17 @@ namespace RGB.NET.Devices.Razer
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Razer.RazerMousepadRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Razer.RazerMousepadRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by CUE for the mousepad.</param> /// <param name="info">The specific information provided by CUE for the mousepad.</param>
internal RazerMousepadRGBDevice(RazerMousepadRGBDeviceInfo info) internal RazerMousepadRGBDevice(RazerMousepadRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info) : base(info, new RazerMousepadUpdateQueue(updateTrigger, info.DeviceId))
{ } {
InitializeLayout();
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
protected override void InitializeLayout()
{ {
for (int i = 0; i < _Defines.MOUSEPAD_MAX_LEDS; i++) for (int i = 0; i < _Defines.MOUSEPAD_MAX_LEDS; i++)
AddLed(LedId.Mousepad1 + i, new Point(i * 11, 0), new Size(10, 10)); AddLed(LedId.Mousepad1 + i, new Point(i * 11, 0), new Size(10, 10));
@ -36,10 +37,6 @@ namespace RGB.NET.Devices.Razer
/// <inheritdoc /> /// <inheritdoc />
protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Mousepad1; protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Mousepad1;
/// <inheritdoc />
protected override RazerUpdateQueue CreateUpdateQueue(IDeviceUpdateTrigger updateTrigger) => new RazerMousepadUpdateQueue(updateTrigger, DeviceInfo.DeviceId);
#endregion #endregion
} }
} }

View File

@ -15,7 +15,7 @@ namespace RGB.NET.Devices.Razer
/// <summary> /// <summary>
/// Represents a device provider responsible for razer devices. /// Represents a device provider responsible for razer devices.
/// </summary> /// </summary>
public class RazerDeviceProvider : IRGBDeviceProvider public class RazerDeviceProvider : AbstractRGBDeviceProvider
{ {
#region Properties & Fields #region Properties & Fields
@ -37,25 +37,11 @@ namespace RGB.NET.Devices.Razer
/// </summary> /// </summary>
public static List<string> PossibleX64NativePaths { get; } = new() { @"%systemroot%\System32\RzChromaSDK.dll", @"%systemroot%\System32\RzChromaSDK64.dll" }; public static List<string> PossibleX64NativePaths { get; } = new() { @"%systemroot%\System32\RzChromaSDK.dll", @"%systemroot%\System32\RzChromaSDK64.dll" };
/// <inheritdoc />
/// <summary>
/// Indicates if the SDK is initialized and ready to use.
/// </summary>
public bool IsInitialized { get; private set; }
/// <inheritdoc />
public IEnumerable<IRGBDevice> Devices { get; private set; } = Enumerable.Empty<IRGBDevice>();
/// <summary> /// <summary>
/// Forces to load the devices represented by the emulator even if they aren't reported to exist. /// Forces to load the devices represented by the emulator even if they aren't reported to exist.
/// </summary> /// </summary>
public bool LoadEmulatorDevices { get; set; } = false; public bool LoadEmulatorDevices { get; set; } = false;
/// <summary>
/// The <see cref="DeviceUpdateTrigger"/> used to trigger the updates for razer devices.
/// </summary>
public DeviceUpdateTrigger UpdateTrigger { get; }
#endregion #endregion
#region Constructors #region Constructors
@ -68,127 +54,75 @@ namespace RGB.NET.Devices.Razer
{ {
if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(RazerDeviceProvider)}"); if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(RazerDeviceProvider)}");
_instance = this; _instance = this;
UpdateTrigger = new DeviceUpdateTrigger();
} }
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> protected override void InitializeSDK()
public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false)
{ {
if (IsInitialized) TryUnInit();
TryUnInit();
IsInitialized = false; _RazerSDK.Reload();
try RazerError error;
{ if (((error = _RazerSDK.Init()) != RazerError.Success)
UpdateTrigger.Stop(); && Enum.IsDefined(typeof(RazerError), error)) //HACK DarthAffe 08.02.2018: The x86-SDK seems to have a problem here ...
ThrowRazerError(error);
_RazerSDK.Reload();
RazerError error;
if (((error = _RazerSDK.Init()) != RazerError.Success)
&& Enum.IsDefined(typeof(RazerError), error)) //HACK DarthAffe 08.02.2018: The x86-SDK seems to have a problem here ...
ThrowRazerError(error);
IList<IRGBDevice> devices = new List<IRGBDevice>();
if (loadFilter.HasFlag(RGBDeviceType.Keyboard))
foreach ((Guid guid, string model) in Razer.Devices.KEYBOARDS)
try
{
if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1))
&& (!LoadEmulatorDevices || (Razer.Devices.KEYBOARDS.FirstOrDefault().guid != guid))) continue;
RazerKeyboardRGBDevice device = new(new RazerKeyboardRGBDeviceInfo(guid, model));
device.Initialize(UpdateTrigger);
devices.Add(device);
}
catch { if (throwExceptions) throw; }
if (loadFilter.HasFlag(RGBDeviceType.Mouse))
foreach ((Guid guid, string model) in Razer.Devices.MICE)
try
{
if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1))
&& (!LoadEmulatorDevices || (Razer.Devices.MICE.FirstOrDefault().guid != guid))) continue;
RazerMouseRGBDevice device = new(new RazerMouseRGBDeviceInfo(guid, model));
device.Initialize(UpdateTrigger);
devices.Add(device);
}
catch { if (throwExceptions) throw; }
if (loadFilter.HasFlag(RGBDeviceType.Headset))
foreach ((Guid guid, string model) in Razer.Devices.HEADSETS)
try
{
if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1))
&& (!LoadEmulatorDevices || (Razer.Devices.HEADSETS.FirstOrDefault().guid != guid))) continue;
RazerHeadsetRGBDevice device = new(new RazerHeadsetRGBDeviceInfo(guid, model));
device.Initialize(UpdateTrigger);
devices.Add(device);
}
catch { if (throwExceptions) throw; }
if (loadFilter.HasFlag(RGBDeviceType.Mousepad))
foreach ((Guid guid, string model) in Razer.Devices.MOUSEMATS)
try
{
if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1))
&& (!LoadEmulatorDevices || (Razer.Devices.MOUSEMATS.FirstOrDefault().guid != guid))) continue;
RazerMousepadRGBDevice device = new(new RazerMousepadRGBDeviceInfo(guid, model));
device.Initialize(UpdateTrigger);
devices.Add(device);
}
catch { if (throwExceptions) throw; }
if (loadFilter.HasFlag(RGBDeviceType.Keypad))
foreach ((Guid guid, string model) in Razer.Devices.KEYPADS)
try
{
if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1))
&& (!LoadEmulatorDevices || (Razer.Devices.KEYPADS.FirstOrDefault().guid != guid))) continue;
RazerKeypadRGBDevice device = new(new RazerKeypadRGBDeviceInfo(guid, model));
device.Initialize(UpdateTrigger);
devices.Add(device);
}
catch { if (throwExceptions) throw; }
if (loadFilter.HasFlag(RGBDeviceType.Keyboard))
foreach ((Guid guid, string model) in Razer.Devices.CHROMALINKS)
try
{
if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1))
&& (!LoadEmulatorDevices || (Razer.Devices.CHROMALINKS.FirstOrDefault().guid != guid))) continue;
RazerChromaLinkRGBDevice device = new(new RazerChromaLinkRGBDeviceInfo(guid, model));
device.Initialize(UpdateTrigger);
devices.Add(device);
}
catch { if (throwExceptions) throw; }
UpdateTrigger.Start();
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
IsInitialized = true;
}
catch
{
TryUnInit();
if (throwExceptions) throw;
return false;
}
return true;
} }
protected override IEnumerable<IRGBDevice> LoadDevices()
{
foreach ((Guid guid, string model) in Razer.Devices.KEYBOARDS)
{
if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1))
&& (!LoadEmulatorDevices || (Razer.Devices.KEYBOARDS.FirstOrDefault().guid != guid))) continue;
yield return new RazerKeyboardRGBDevice(new RazerKeyboardRGBDeviceInfo(guid, model), GetUpdateTrigger());
}
foreach ((Guid guid, string model) in Razer.Devices.MICE)
{
if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1))
&& (!LoadEmulatorDevices || (Razer.Devices.MICE.FirstOrDefault().guid != guid))) continue;
yield return new RazerMouseRGBDevice(new RazerMouseRGBDeviceInfo(guid, model), GetUpdateTrigger());
}
foreach ((Guid guid, string model) in Razer.Devices.HEADSETS)
{
if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1))
&& (!LoadEmulatorDevices || (Razer.Devices.HEADSETS.FirstOrDefault().guid != guid))) continue;
yield return new RazerHeadsetRGBDevice(new RazerHeadsetRGBDeviceInfo(guid, model), GetUpdateTrigger());
}
foreach ((Guid guid, string model) in Razer.Devices.MOUSEMATS)
{
if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1))
&& (!LoadEmulatorDevices || (Razer.Devices.MOUSEMATS.FirstOrDefault().guid != guid))) continue;
yield return new RazerMousepadRGBDevice(new RazerMousepadRGBDeviceInfo(guid, model), GetUpdateTrigger());
}
foreach ((Guid guid, string model) in Razer.Devices.KEYPADS)
{
if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1))
&& (!LoadEmulatorDevices || (Razer.Devices.KEYPADS.FirstOrDefault().guid != guid))) continue;
yield return new RazerKeypadRGBDevice(new RazerKeypadRGBDeviceInfo(guid, model), GetUpdateTrigger());
}
foreach ((Guid guid, string model) in Razer.Devices.CHROMALINKS)
{
if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1))
&& (!LoadEmulatorDevices || (Razer.Devices.CHROMALINKS.FirstOrDefault().guid != guid))) continue;
yield return new RazerChromaLinkRGBDevice(new RazerChromaLinkRGBDeviceInfo(guid, model), GetUpdateTrigger());
}
}
private void ThrowRazerError(RazerError errorCode) => throw new RazerException(errorCode); private void ThrowRazerError(RazerError errorCode) => throw new RazerException(errorCode);
private void TryUnInit() private void TryUnInit()
@ -198,15 +132,9 @@ namespace RGB.NET.Devices.Razer
} }
/// <inheritdoc /> /// <inheritdoc />
public void Dispose() public override void Dispose()
{ {
try { UpdateTrigger.Dispose(); } base.Dispose();
catch { /* at least we tried */ }
foreach (IRGBDevice device in Devices)
try { device.Dispose(); }
catch { /* at least we tried */ }
Devices = Enumerable.Empty<IRGBDevice>();
TryUnInit(); TryUnInit();

View File

@ -1,5 +1,4 @@
using System.Collections.Generic; using RGB.NET.Core;
using RGB.NET.Core;
namespace RGB.NET.Devices.SteelSeries namespace RGB.NET.Devices.SteelSeries
{ {
@ -7,7 +6,5 @@ namespace RGB.NET.Devices.SteelSeries
/// Represents a steelseries RGB-device. /// Represents a steelseries RGB-device.
/// </summary> /// </summary>
internal interface ISteelSeriesRGBDevice : IRGBDevice internal interface ISteelSeriesRGBDevice : IRGBDevice
{ { }
void Initialize(UpdateQueue updateQueue, Dictionary<LedId, SteelSeriesLedId> ledMapping);
}
} }

View File

@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using RGB.NET.Core; using RGB.NET.Core;
namespace RGB.NET.Devices.SteelSeries namespace RGB.NET.Devices.SteelSeries
@ -13,19 +12,7 @@ namespace RGB.NET.Devices.SteelSeries
{ {
#region Properties & Fields #region Properties & Fields
private Dictionary<LedId, SteelSeriesLedId> _ledMapping = new(); private readonly Dictionary<LedId, SteelSeriesLedId> _ledMapping;
/// <inheritdoc />
/// <summary>
/// Gets information about the <see cref="SteelSeriesRGBDevice" />.
/// </summary>
public override SteelSeriesRGBDeviceInfo DeviceInfo { get; }
/// <summary>
/// Gets or sets the update queue performing updates for this device.
/// </summary>
// ReSharper disable once MemberCanBePrivate.Global
protected UpdateQueue? UpdateQueue { get; set; }
#endregion #endregion
@ -35,34 +22,30 @@ namespace RGB.NET.Devices.SteelSeries
/// Initializes a new instance of the <see cref="SteelSeriesRGBDevice"/> class. /// Initializes a new instance of the <see cref="SteelSeriesRGBDevice"/> class.
/// </summary> /// </summary>
/// <param name="info">The generic information provided by SteelSeries for the device.</param> /// <param name="info">The generic information provided by SteelSeries for the device.</param>
internal SteelSeriesRGBDevice(SteelSeriesRGBDeviceInfo info) internal SteelSeriesRGBDevice(SteelSeriesRGBDeviceInfo info, string apiName, Dictionary<LedId, SteelSeriesLedId> ledMapping, IDeviceUpdateTrigger updateTrigger)
: base(info, new SteelSeriesDeviceUpdateQueue(updateTrigger, apiName))
{ {
this.DeviceInfo = info; this._ledMapping = ledMapping;
InitializeLayout();
} }
#endregion #endregion
#region Methods #region Methods
/// <summary> private void InitializeLayout()
/// Initializes the device.
/// </summary>
void ISteelSeriesRGBDevice.Initialize(UpdateQueue updateQueue, Dictionary<LedId, SteelSeriesLedId> ledMapping)
{ {
_ledMapping = ledMapping;
int counter = 0; int counter = 0;
foreach (KeyValuePair<LedId, SteelSeriesLedId> mapping in ledMapping) foreach (KeyValuePair<LedId, SteelSeriesLedId> mapping in _ledMapping)
AddLed(mapping.Key, new Point((counter++) * 10, 0), new Size(10, 10)); AddLed(mapping.Key, new Point((counter++) * 10, 0), new Size(10, 10));
UpdateQueue = updateQueue;
} }
/// <inheritdoc /> /// <inheritdoc />
protected override object GetLedCustomData(LedId ledId) => _ledMapping[ledId]; protected override object GetLedCustomData(LedId ledId) => _ledMapping[ledId];
/// <inheritdoc /> /// <inheritdoc />
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate)); protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate));
/// <inheritdoc /> /// <inheritdoc />
public override void Dispose() public override void Dispose()

View File

@ -1,7 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using RGB.NET.Core; using RGB.NET.Core;
using RGB.NET.Devices.SteelSeries.API; using RGB.NET.Devices.SteelSeries.API;
using RGB.NET.Devices.SteelSeries.HID; using RGB.NET.Devices.SteelSeries.HID;
@ -12,7 +10,7 @@ namespace RGB.NET.Devices.SteelSeries
/// <summary> /// <summary>
/// Represents a device provider responsible for SteelSeries- devices. /// Represents a device provider responsible for SteelSeries- devices.
/// </summary> /// </summary>
public class SteelSeriesDeviceProvider : IRGBDeviceProvider public class SteelSeriesDeviceProvider : AbstractRGBDeviceProvider
{ {
#region Properties & Fields #region Properties & Fields
@ -22,20 +20,6 @@ namespace RGB.NET.Devices.SteelSeries
/// </summary> /// </summary>
public static SteelSeriesDeviceProvider Instance => _instance ?? new SteelSeriesDeviceProvider(); public static SteelSeriesDeviceProvider Instance => _instance ?? new SteelSeriesDeviceProvider();
/// <inheritdoc />
/// <summary>
/// Indicates if the SDK is initialized and ready to use.
/// </summary>
public bool IsInitialized { get; private set; }
/// <inheritdoc />
public IEnumerable<IRGBDevice> Devices { get; private set; } = Enumerable.Empty<IRGBDevice>();
/// <summary>
/// The <see cref="SteelSeriesDeviceUpdateTrigger"/> used to trigger the updates for SteelSeries devices.
/// </summary>
public SteelSeriesDeviceUpdateTrigger UpdateTrigger { get; }
#endregion #endregion
#region Constructors #region Constructors
@ -48,67 +32,41 @@ namespace RGB.NET.Devices.SteelSeries
{ {
if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(SteelSeriesDeviceProvider)}"); if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(SteelSeriesDeviceProvider)}");
_instance = this; _instance = this;
UpdateTrigger = new SteelSeriesDeviceUpdateTrigger();
} }
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> protected override void InitializeSDK()
public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false)
{ {
try if (!SteelSeriesSDK.IsInitialized)
{ SteelSeriesSDK.Initialize();
IsInitialized = false;
UpdateTrigger.Stop();
if (!SteelSeriesSDK.IsInitialized)
SteelSeriesSDK.Initialize();
IList<IRGBDevice> devices = new List<IRGBDevice>();
DeviceChecker.LoadDeviceList(loadFilter);
try
{
foreach ((string model, RGBDeviceType deviceType, int _, SteelSeriesDeviceType steelSeriesDeviceType, Dictionary<LedId, SteelSeriesLedId> ledMapping) in DeviceChecker.ConnectedDevices)
{
ISteelSeriesRGBDevice device = new SteelSeriesRGBDevice(new SteelSeriesRGBDeviceInfo(deviceType, model, steelSeriesDeviceType));
string apiName = steelSeriesDeviceType.GetAPIName() ?? throw new RGBDeviceException($"Missing API-name for device {model}");
SteelSeriesDeviceUpdateQueue updateQueue = new(UpdateTrigger, apiName);
device.Initialize(updateQueue, ledMapping);
devices.Add(device);
}
}
catch { if (throwExceptions) throw; }
UpdateTrigger.Start();
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
IsInitialized = true;
}
catch
{
IsInitialized = false;
if (throwExceptions) throw;
return false;
}
return true;
} }
/// <inheritdoc />
public void Dispose()
{
try { UpdateTrigger.Dispose(); }
catch { /* at least we tried */ }
foreach (IRGBDevice device in Devices) protected override IEnumerable<IRGBDevice> GetLoadedDevices(RGBDeviceType loadFilter)
try { device.Dispose(); } {
catch { /* at least we tried */ } DeviceChecker.LoadDeviceList(loadFilter);
Devices = Enumerable.Empty<IRGBDevice>();
return base.GetLoadedDevices(loadFilter);
}
protected override IEnumerable<IRGBDevice> LoadDevices()
{
foreach ((string model, RGBDeviceType deviceType, int _, SteelSeriesDeviceType steelSeriesDeviceType, Dictionary<LedId, SteelSeriesLedId> ledMapping) in DeviceChecker.ConnectedDevices)
{
string? apiName = steelSeriesDeviceType.GetAPIName();
if (apiName == null)
Throw(new RGBDeviceException($"Missing API-name for device {model}"));
else
yield return new SteelSeriesRGBDevice(new SteelSeriesRGBDeviceInfo(deviceType, model, steelSeriesDeviceType), apiName, ledMapping, GetUpdateTrigger());
}
}
/// <inheritdoc />
public override void Dispose()
{
base.Dispose();
try { SteelSeriesSDK.Dispose(); } try { SteelSeriesSDK.Dispose(); }
catch { /* shit happens */ } catch { /* shit happens */ }

View File

@ -8,22 +8,12 @@ using RGB.NET.Core;
namespace RGB.NET.Devices.WS281X.Arduino namespace RGB.NET.Devices.WS281X.Arduino
{ {
// ReSharper disable once InconsistentNaming // ReSharper disable once InconsistentNaming
/// <inheritdoc />
/// <summary> /// <summary>
/// Represents an arduino WS2812 device. /// Represents an arduino WS2812 device.
/// </summary> /// </summary>
public class ArduinoWS2812USBDevice : AbstractRGBDevice<ArduinoWS2812USBDeviceInfo>, ILedStripe public class ArduinoWS2812USBDevice : AbstractRGBDevice<ArduinoWS2812USBDeviceInfo>, ILedStripe
{ {
#region Properties & Fields #region Properties & Fields
/// <summary>
/// Gets the update queue performing updates for this device.
/// </summary>
public ArduinoWS2812USBUpdateQueue UpdateQueue { get; }
/// <inheritdoc />
public override ArduinoWS2812USBDeviceInfo DeviceInfo { get; }
/// <summary> /// <summary>
/// Gets the channel (as defined in the arduino-sketch) this device is attached to. /// Gets the channel (as defined in the arduino-sketch) this device is attached to.
/// </summary> /// </summary>
@ -39,18 +29,19 @@ namespace RGB.NET.Devices.WS281X.Arduino
/// <param name="deviceInfo">The update trigger used by this queue.</param> /// <param name="deviceInfo">The update trigger used by this queue.</param>
/// <param name="updateQueue">The update queue performing updates for this device.</param> /// <param name="updateQueue">The update queue performing updates for this device.</param>
/// <param name="channel">The channel (as defined in the arduino-sketch) this device is attached to.</param> /// <param name="channel">The channel (as defined in the arduino-sketch) this device is attached to.</param>
public ArduinoWS2812USBDevice(ArduinoWS2812USBDeviceInfo deviceInfo, ArduinoWS2812USBUpdateQueue updateQueue, int channel) public ArduinoWS2812USBDevice(ArduinoWS2812USBDeviceInfo deviceInfo, ArduinoWS2812USBUpdateQueue updateQueue, int channel, int ledCount)
: base(deviceInfo, updateQueue)
{ {
this.DeviceInfo = deviceInfo;
this.UpdateQueue = updateQueue;
this.Channel = channel; this.Channel = channel;
InitializeLayout(ledCount);
} }
#endregion #endregion
#region Methods #region Methods
internal void Initialize(int ledCount) private void InitializeLayout(int ledCount)
{ {
for (int i = 0; i < ledCount; i++) for (int i = 0; i < ledCount; i++)
AddLed(LedId.LedStripe1 + i, new Point(i * 10, 0), new Size(10, 10)); AddLed(LedId.LedStripe1 + i, new Point(i * 10, 0), new Size(10, 10));
@ -65,15 +56,6 @@ namespace RGB.NET.Devices.WS281X.Arduino
/// <inheritdoc /> /// <inheritdoc />
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate)); protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate));
/// <inheritdoc />
public override void Dispose()
{
try { UpdateQueue.Dispose(); }
catch { /* at least we tried */ }
base.Dispose();
}
#endregion #endregion
} }
} }

View File

@ -67,15 +67,14 @@ namespace RGB.NET.Devices.WS281X.Arduino
/// <inheritdoc /> /// <inheritdoc />
public IEnumerable<IRGBDevice> CreateDevices(IDeviceUpdateTrigger updateTrigger) public IEnumerable<IRGBDevice> CreateDevices(IDeviceUpdateTrigger updateTrigger)
{ {
//TODO DarthAffe 04.03.2021: one queue per device
ArduinoWS2812USBUpdateQueue queue = new(updateTrigger, SerialConnection); ArduinoWS2812USBUpdateQueue queue = new(updateTrigger, SerialConnection);
IEnumerable<(int channel, int ledCount)> channels = queue.GetChannels(); IEnumerable<(int channel, int ledCount)> channels = queue.GetChannels();
int counter = 0; int counter = 0;
foreach ((int channel, int ledCount) in channels) foreach ((int channel, int ledCount) in channels)
{ {
string name = string.Format(Name ?? $"Arduino WS2812 USB ({Port}) [{{0}}]", ++counter); string name = string.Format(Name ?? $"Arduino WS2812 USB ({Port}) [{{0}}]", ++counter);
ArduinoWS2812USBDevice device = new(new ArduinoWS2812USBDeviceInfo(name), queue, channel); yield return new ArduinoWS2812USBDevice(new ArduinoWS2812USBDeviceInfo(name), queue, channel, ledCount);
device.Initialize(ledCount);
yield return device;
} }
} }

View File

@ -2,13 +2,12 @@
// ReSharper disable UnusedMember.Global // ReSharper disable UnusedMember.Global
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using RGB.NET.Core; using RGB.NET.Core;
namespace RGB.NET.Devices.WS281X.Bitwizard namespace RGB.NET.Devices.WS281X.Bitwizard
{ {
// ReSharper disable once InconsistentNaming // ReSharper disable once InconsistentNaming
/// <inheritdoc /> /// <inheritdoc cref="AbstractRGBDevice{T}" />
/// <summary> /// <summary>
/// Represents an bitwizard WS2812 USB device. /// Represents an bitwizard WS2812 USB device.
/// </summary> /// </summary>
@ -18,14 +17,6 @@ namespace RGB.NET.Devices.WS281X.Bitwizard
private readonly int _ledOffset; private readonly int _ledOffset;
/// <summary>
/// Gets the update queue performing updates for this device.
/// </summary>
public BitwizardWS2812USBUpdateQueue UpdateQueue { get; }
/// <inheritdoc />
public override BitwizardWS2812USBDeviceInfo DeviceInfo { get; }
#endregion #endregion
#region Constructors #region Constructors
@ -35,19 +26,18 @@ namespace RGB.NET.Devices.WS281X.Bitwizard
/// </summary> /// </summary>
/// <param name="deviceInfo">The update trigger used by this queue.</param> /// <param name="deviceInfo">The update trigger used by this queue.</param>
/// <param name="updateQueue">The update queue performing updates for this device.</param> /// <param name="updateQueue">The update queue performing updates for this device.</param>
public BitwizardWS2812USBDevice(BitwizardWS2812USBDeviceInfo deviceInfo, BitwizardWS2812USBUpdateQueue updateQueue, int ledOffset) public BitwizardWS2812USBDevice(BitwizardWS2812USBDeviceInfo deviceInfo, BitwizardWS2812USBUpdateQueue updateQueue, int ledOffset, int ledCount)
: base(deviceInfo, updateQueue)
{ {
this.DeviceInfo = deviceInfo;
this.UpdateQueue = updateQueue;
this._ledOffset = ledOffset; this._ledOffset = ledOffset;
InitializeLayout(ledCount);
} }
#endregion #endregion
#region Methods #region Methods
internal void Initialize(int ledCount) private void InitializeLayout(int ledCount)
{ {
for (int i = 0; i < ledCount; i++) for (int i = 0; i < ledCount; i++)
AddLed(LedId.LedStripe1 + i, new Point(i * 10, 0), new Size(10, 10)); AddLed(LedId.LedStripe1 + i, new Point(i * 10, 0), new Size(10, 10));
@ -59,15 +49,6 @@ namespace RGB.NET.Devices.WS281X.Bitwizard
/// <inheritdoc /> /// <inheritdoc />
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate)); protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate));
/// <inheritdoc />
public override void Dispose()
{
try { UpdateQueue.Dispose(); }
catch { /* at least we tried */ }
base.Dispose();
}
#endregion #endregion
} }
} }

View File

@ -36,15 +36,7 @@ namespace RGB.NET.Devices.WS281X.Bitwizard
/// </summary> /// </summary>
public string? Name { get; set; } public string? Name { get; set; }
/// <summary> public List<(int pin, int stripLength)> Strips { get; } = new();
/// Gets or sets the pin sed to control the leds.
/// </summary>
public int Pin { get; set; } = 0;
/// <summary>
/// Gets or sets the amount of leds of this device.
/// </summary>
public int StripLength { get; set; } = 384;
/// <summary> /// <summary>
/// Gets or sets the amount of leds controlled by one pin. /// Gets or sets the amount of leds controlled by one pin.
@ -60,9 +52,11 @@ namespace RGB.NET.Devices.WS281X.Bitwizard
/// Initializes a new instance of the <see cref="BitwizardWS281XDeviceDefinition"/> class. /// Initializes a new instance of the <see cref="BitwizardWS281XDeviceDefinition"/> class.
/// </summary> /// </summary>
/// <param name="serialConnection">The serial connection used for the device.</param> /// <param name="serialConnection">The serial connection used for the device.</param>
public BitwizardWS281XDeviceDefinition(ISerialConnection serialConnection) public BitwizardWS281XDeviceDefinition(ISerialConnection serialConnection, params (int pin, int stripLength)[] strips)
{ {
this.SerialConnection = serialConnection; this.SerialConnection = serialConnection;
Strips.AddRange(strips);
} }
/// <summary> /// <summary>
@ -70,9 +64,11 @@ namespace RGB.NET.Devices.WS281X.Bitwizard
/// </summary> /// </summary>
/// <param name="port">The name of the serial-port to connect to.</param> /// <param name="port">The name of the serial-port to connect to.</param>
/// <param name="baudRate">The baud-rate of the serial-connection.</param> /// <param name="baudRate">The baud-rate of the serial-connection.</param>
public BitwizardWS281XDeviceDefinition(string port, int baudRate = 115200) public BitwizardWS281XDeviceDefinition(string port, int baudRate = 115200, params (int pin, int stripLength)[] strips)
{ {
SerialConnection = new SerialPortConnection(port, baudRate); SerialConnection = new SerialPortConnection(port, baudRate);
Strips.AddRange(strips);
} }
#endregion #endregion
@ -82,12 +78,13 @@ namespace RGB.NET.Devices.WS281X.Bitwizard
/// <inheritdoc /> /// <inheritdoc />
public IEnumerable<IRGBDevice> CreateDevices(IDeviceUpdateTrigger updateTrigger) public IEnumerable<IRGBDevice> CreateDevices(IDeviceUpdateTrigger updateTrigger)
{ {
BitwizardWS2812USBUpdateQueue queue = new(updateTrigger, SerialConnection); foreach ((int pin, int stripLength) in Strips)
string name = Name ?? $"Bitwizard WS2812 USB ({Port})"; {
int ledOffset = Pin * MaxStripLength; BitwizardWS2812USBUpdateQueue queue = new(updateTrigger, SerialConnection);
BitwizardWS2812USBDevice device = new(new BitwizardWS2812USBDeviceInfo(name), queue, ledOffset); string name = Name ?? $"Bitwizard WS2812 USB ({Port}) Pin {pin}";
device.Initialize(StripLength); int ledOffset = pin * MaxStripLength;
yield return device; yield return new BitwizardWS2812USBDevice(new BitwizardWS2812USBDeviceInfo(name), queue, ledOffset, stripLength);
}
} }
#endregion #endregion

View File

@ -16,14 +16,6 @@ namespace RGB.NET.Devices.WS281X.NodeMCU
{ {
#region Properties & Fields #region Properties & Fields
/// <summary>
/// Gets the update queue performing updates for this device.
/// </summary>
public NodeMCUWS2812USBUpdateQueue UpdateQueue { get; }
/// <inheritdoc />
public override NodeMCUWS2812USBDeviceInfo DeviceInfo { get; }
/// <summary> /// <summary>
/// Gets the channel (as defined in the NodeMCU-sketch) this device is attached to. /// Gets the channel (as defined in the NodeMCU-sketch) this device is attached to.
/// </summary> /// </summary>
@ -39,18 +31,19 @@ namespace RGB.NET.Devices.WS281X.NodeMCU
/// <param name="deviceInfo">The update trigger used by this queue.</param> /// <param name="deviceInfo">The update trigger used by this queue.</param>
/// <param name="updateQueue">The update queue performing updates for this device.</param> /// <param name="updateQueue">The update queue performing updates for this device.</param>
/// <param name="channel">The channel (as defined in the NodeMCU-sketch) this device is attached to.</param> /// <param name="channel">The channel (as defined in the NodeMCU-sketch) this device is attached to.</param>
public NodeMCUWS2812USBDevice(NodeMCUWS2812USBDeviceInfo deviceInfo, NodeMCUWS2812USBUpdateQueue updateQueue, int channel) public NodeMCUWS2812USBDevice(NodeMCUWS2812USBDeviceInfo info, NodeMCUWS2812USBUpdateQueue updateQueue, int channel, int ledCount)
: base(info, updateQueue)
{ {
this.DeviceInfo = deviceInfo;
this.UpdateQueue = updateQueue;
this.Channel = channel; this.Channel = channel;
InitializeLayout(ledCount);
} }
#endregion #endregion
#region Methods #region Methods
internal void Initialize(int ledCount) private void InitializeLayout(int ledCount)
{ {
for (int i = 0; i < ledCount; i++) for (int i = 0; i < ledCount; i++)
AddLed(LedId.LedStripe1 + i, new Point(i * 10, 0), new Size(10, 10)); AddLed(LedId.LedStripe1 + i, new Point(i * 10, 0), new Size(10, 10));
@ -65,15 +58,6 @@ namespace RGB.NET.Devices.WS281X.NodeMCU
/// <inheritdoc /> /// <inheritdoc />
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate)); protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate));
/// <inheritdoc />
public override void Dispose()
{
try { UpdateQueue.Dispose(); }
catch { /* at least we tried */ }
base.Dispose();
}
#endregion #endregion
} }
} }

View File

@ -72,9 +72,7 @@ namespace RGB.NET.Devices.WS281X.NodeMCU
foreach ((int channel, int ledCount) in channels) foreach ((int channel, int ledCount) in channels)
{ {
string name = string.Format(Name ?? $"NodeMCU WS2812 WIFI ({Hostname}) [{{0}}]", ++counter); string name = string.Format(Name ?? $"NodeMCU WS2812 WIFI ({Hostname}) [{{0}}]", ++counter);
NodeMCUWS2812USBDevice device = new(new NodeMCUWS2812USBDeviceInfo(name), queue, channel); yield return new NodeMCUWS2812USBDevice(new NodeMCUWS2812USBDeviceInfo(name), queue, channel, ledCount);
device.Initialize(ledCount);
yield return device;
} }
} }

View File

@ -2,8 +2,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using RGB.NET.Core; using RGB.NET.Core;
namespace RGB.NET.Devices.WS281X namespace RGB.NET.Devices.WS281X
@ -13,7 +11,7 @@ namespace RGB.NET.Devices.WS281X
/// Represents a device provider responsible for WS2812B- and WS2811-Led-devices. /// Represents a device provider responsible for WS2812B- and WS2811-Led-devices.
/// </summary> /// </summary>
// ReSharper disable once InconsistentNaming // ReSharper disable once InconsistentNaming
public class WS281XDeviceProvider : IRGBDeviceProvider public class WS281XDeviceProvider : AbstractRGBDeviceProvider
{ {
#region Properties & Fields #region Properties & Fields
@ -23,12 +21,6 @@ namespace RGB.NET.Devices.WS281X
/// </summary> /// </summary>
public static WS281XDeviceProvider Instance => _instance ?? new WS281XDeviceProvider(); public static WS281XDeviceProvider Instance => _instance ?? new WS281XDeviceProvider();
/// <inheritdoc />
public bool IsInitialized { get; private set; }
/// <inheritdoc />
public IEnumerable<IRGBDevice> Devices { get; private set; } = Enumerable.Empty<IRGBDevice>();
/// <summary> /// <summary>
/// Gets a list of all defined device-definitions. /// Gets a list of all defined device-definitions.
/// </summary> /// </summary>
@ -36,11 +28,6 @@ namespace RGB.NET.Devices.WS281X
// ReSharper disable once ReturnTypeCanBeEnumerable.Global // ReSharper disable once ReturnTypeCanBeEnumerable.Global
public List<IWS281XDeviceDefinition> DeviceDefinitions { get; } = new(); public List<IWS281XDeviceDefinition> DeviceDefinitions { get; } = new();
/// <summary>
/// The <see cref="DeviceUpdateTrigger"/> used to trigger the updates for corsair devices.
/// </summary>
public DeviceUpdateTrigger UpdateTrigger { get; }
#endregion #endregion
#region Constructors #region Constructors
@ -53,8 +40,6 @@ namespace RGB.NET.Devices.WS281X
{ {
if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(WS281XDeviceProvider)}"); if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(WS281XDeviceProvider)}");
_instance = this; _instance = this;
UpdateTrigger = new DeviceUpdateTrigger();
} }
#endregion #endregion
@ -68,49 +53,23 @@ namespace RGB.NET.Devices.WS281X
// ReSharper disable once UnusedMember.Global // ReSharper disable once UnusedMember.Global
public void AddDeviceDefinition(IWS281XDeviceDefinition deviceDefinition) => DeviceDefinitions.Add(deviceDefinition); public void AddDeviceDefinition(IWS281XDeviceDefinition deviceDefinition) => DeviceDefinitions.Add(deviceDefinition);
/// <inheritdoc /> protected override void InitializeSDK() { }
public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.Unknown, bool throwExceptions = false)
protected override IEnumerable<IRGBDevice> LoadDevices()
{ {
IsInitialized = false; int i = 0;
foreach (IWS281XDeviceDefinition deviceDefinition in DeviceDefinitions)
try
{ {
UpdateTrigger.Stop(); IDeviceUpdateTrigger updateTrigger = GetUpdateTrigger(i++);
foreach (IRGBDevice device in deviceDefinition.CreateDevices(updateTrigger))
List<IRGBDevice> devices = new(); yield return device;
foreach (IWS281XDeviceDefinition deviceDefinition in DeviceDefinitions)
{
try
{
devices.AddRange(deviceDefinition.CreateDevices(UpdateTrigger));
}
catch { if (throwExceptions) throw; }
}
UpdateTrigger.Start();
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
IsInitialized = true;
} }
catch
{
if (throwExceptions)
throw;
return false;
}
return true;
} }
/// <inheritdoc />
public void Dispose()
{
try { UpdateTrigger.Dispose(); }
catch { /* at least we tried */}
foreach (IRGBDevice device in Devices) /// <inheritdoc />
try { device.Dispose(); } public override void Dispose()
catch { /* at least we tried */ } {
Devices = Enumerable.Empty<IRGBDevice>(); base.Dispose();
DeviceDefinitions.Clear(); DeviceDefinitions.Clear();
} }

View File

@ -5,8 +5,6 @@ namespace RGB.NET.Devices.Wooting.Generic
/// <summary> /// <summary>
/// Represents a Wooting RGB-device. /// Represents a Wooting RGB-device.
/// </summary> /// </summary>
internal interface IWootingRGBDevice : IRGBDevice public interface IWootingRGBDevice : IRGBDevice
{ { }
void Initialize(IDeviceUpdateTrigger updateTrigger);
}
} }

View File

@ -10,60 +10,15 @@ namespace RGB.NET.Devices.Wooting.Generic
public abstract class WootingRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, IWootingRGBDevice public abstract class WootingRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, IWootingRGBDevice
where TDeviceInfo : WootingRGBDeviceInfo where TDeviceInfo : WootingRGBDeviceInfo
{ {
#region Properties & Fields
/// <inheritdoc />
/// <summary>
/// Gets information about the <see cref="T:RGB.NET.Devices.Wooting.WootingRGBDevice" />.
/// </summary>
public override TDeviceInfo DeviceInfo { get; }
/// <summary>
/// Gets or sets the update queue performing updates for this device.
/// </summary>
// ReSharper disable once MemberCanBePrivate.Global
protected UpdateQueue? UpdateQueue { get; set; }
#endregion
#region Constructors #region Constructors
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="WootingRGBDevice{TDeviceInfo}"/> class. /// Initializes a new instance of the <see cref="WootingRGBDevice{TDeviceInfo}"/> class.
/// </summary> /// </summary>
/// <param name="info">The generic information provided by Wooting for the device.</param> /// <param name="info">The generic information provided by Wooting for the device.</param>
protected WootingRGBDevice(TDeviceInfo info) protected WootingRGBDevice(TDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
{ : base(info, new WootingUpdateQueue(updateTrigger))
this.DeviceInfo = info; { }
}
#endregion
#region Methods
/// <summary>
/// Initializes the device.
/// </summary>
public void Initialize(IDeviceUpdateTrigger updateTrigger)
{
InitializeLayout();
UpdateQueue = new WootingUpdateQueue(updateTrigger);
}
/// <summary>
/// Initializes the <see cref="Led"/> and <see cref="Size"/> of the device.
/// </summary>
protected abstract void InitializeLayout();
/// <inheritdoc />
public override void Dispose()
{
try { UpdateQueue?.Dispose(); }
catch { /* at least we tried */ }
base.Dispose();
}
#endregion #endregion
} }

View File

@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using RGB.NET.Core; using RGB.NET.Core;
using RGB.NET.Devices.Wooting.Enum; using RGB.NET.Devices.Wooting.Enum;
using RGB.NET.Devices.Wooting.Generic; using RGB.NET.Devices.Wooting.Generic;
@ -25,16 +24,17 @@ namespace RGB.NET.Devices.Wooting.Keyboard
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Wooting.Keyboard.WootingKeyboardRGBDevice" /> class. /// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Wooting.Keyboard.WootingKeyboardRGBDevice" /> class.
/// </summary> /// </summary>
/// <param name="info">The specific information provided by Wooting for the keyboard</param> /// <param name="info">The specific information provided by Wooting for the keyboard</param>
internal WootingKeyboardRGBDevice(WootingKeyboardRGBDeviceInfo info) internal WootingKeyboardRGBDevice(WootingKeyboardRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info) : base(info, updateTrigger)
{ } {
InitializeLayout();
}
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> private void InitializeLayout()
protected override void InitializeLayout()
{ {
//TODO DarthAffe 13.02.2021: Check how the mapping can work without knowing the physical layout //TODO DarthAffe 13.02.2021: Check how the mapping can work without knowing the physical layout
Dictionary<LedId, (int row, int column)> mapping = WootingKeyboardLedMappings.Mapping[DeviceInfo.DeviceIndex][WootingPhysicalKeyboardLayout.US]; Dictionary<LedId, (int row, int column)> mapping = WootingKeyboardLedMappings.Mapping[DeviceInfo.DeviceIndex][WootingPhysicalKeyboardLayout.US];
@ -47,7 +47,7 @@ namespace RGB.NET.Devices.Wooting.Keyboard
protected override object GetLedCustomData(LedId ledId) => WootingKeyboardLedMappings.Mapping[DeviceInfo.DeviceIndex][WootingPhysicalKeyboardLayout.US][ledId]; protected override object GetLedCustomData(LedId ledId) => WootingKeyboardLedMappings.Mapping[DeviceInfo.DeviceIndex][WootingPhysicalKeyboardLayout.US][ledId];
/// <inheritdoc /> /// <inheritdoc />
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate)); protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate));
#endregion #endregion
} }

View File

@ -1,7 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using RGB.NET.Core; using RGB.NET.Core;
using RGB.NET.Devices.Wooting.Enum; using RGB.NET.Devices.Wooting.Enum;
@ -15,7 +13,7 @@ namespace RGB.NET.Devices.Wooting
/// <summary> /// <summary>
/// Represents a device provider responsible for Wooting devices. /// Represents a device provider responsible for Wooting devices.
/// </summary> /// </summary>
public class WootingDeviceProvider : IRGBDeviceProvider public class WootingDeviceProvider : AbstractRGBDeviceProvider
{ {
#region Properties & Fields #region Properties & Fields
@ -37,20 +35,6 @@ namespace RGB.NET.Devices.Wooting
/// </summary> /// </summary>
public static List<string> PossibleX64NativePaths { get; } = new() { "x64/wooting-rgb-sdk64.dll" }; public static List<string> PossibleX64NativePaths { get; } = new() { "x64/wooting-rgb-sdk64.dll" };
/// <inheritdoc />
/// <summary>
/// Indicates if the SDK is initialized and ready to use.
/// </summary>
public bool IsInitialized { get; private set; }
/// <inheritdoc />
public IEnumerable<IRGBDevice> Devices { get; private set; } = Enumerable.Empty<IRGBDevice>();
/// <summary>
/// The <see cref="DeviceUpdateTrigger"/> used to trigger the updates for cooler master devices.
/// </summary>
public DeviceUpdateTrigger UpdateTrigger { get; }
#endregion #endregion
#region Constructors #region Constructors
@ -61,68 +45,42 @@ namespace RGB.NET.Devices.Wooting
/// <exception cref="InvalidOperationException">Thrown if this constructor is called even if there is already an instance of this class.</exception> /// <exception cref="InvalidOperationException">Thrown if this constructor is called even if there is already an instance of this class.</exception>
public WootingDeviceProvider() public WootingDeviceProvider()
{ {
if (_instance != null) if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(WootingDeviceProvider)}");
throw new InvalidOperationException($"There can be only one instance of type {nameof(WootingDeviceProvider)}");
_instance = this; _instance = this;
UpdateTrigger = new DeviceUpdateTrigger();
} }
#endregion #endregion
#region Methods #region Methods
/// <inheritdoc /> protected override void InitializeSDK()
/// <exception cref="RGBDeviceException">Thrown if the SDK failed to initialize</exception>
public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false)
{ {
IsInitialized = false; _WootingSDK.Reload();
}
try protected override IEnumerable<IRGBDevice> LoadDevices()
{
if (_WootingSDK.KeyboardConnected())
{ {
UpdateTrigger.Stop(); _WootingDeviceInfo nativeDeviceInfo = (_WootingDeviceInfo)Marshal.PtrToStructure(_WootingSDK.GetDeviceInfo(), typeof(_WootingDeviceInfo))!;
IWootingRGBDevice? device = nativeDeviceInfo.Model switch
_WootingSDK.Reload();
IList<IRGBDevice> devices = new List<IRGBDevice>();
if (_WootingSDK.KeyboardConnected())
{ {
_WootingDeviceInfo nativeDeviceInfo = (_WootingDeviceInfo)Marshal.PtrToStructure(_WootingSDK.GetDeviceInfo(), typeof(_WootingDeviceInfo))!; "Wooting two" => new WootingKeyboardRGBDevice(new WootingKeyboardRGBDeviceInfo(WootingDevicesIndexes.WootingTwo), GetUpdateTrigger()),
IWootingRGBDevice device = nativeDeviceInfo.Model switch "Wooting one" => new WootingKeyboardRGBDevice(new WootingKeyboardRGBDeviceInfo(WootingDevicesIndexes.WootingOne), GetUpdateTrigger()),
{ _ => null
"Wooting two" => new WootingKeyboardRGBDevice(new WootingKeyboardRGBDeviceInfo(WootingDevicesIndexes.WootingTwo)), };
"Wooting one" => new WootingKeyboardRGBDevice(new WootingKeyboardRGBDeviceInfo(WootingDevicesIndexes.WootingOne)),
_ => throw new RGBDeviceException("No supported Wooting keyboard connected")
};
device.Initialize(UpdateTrigger); if (device == null)
devices.Add(device); Throw(new RGBDeviceException("No supported Wooting keyboard connected"));
} else
yield return device;
UpdateTrigger.Start();
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
IsInitialized = true;
} }
catch
{
if (throwExceptions) throw;
return false;
}
return true;
} }
/// <inheritdoc /> /// <inheritdoc />
public void Dispose() public override void Dispose()
{ {
try { UpdateTrigger.Dispose(); } base.Dispose();
catch { /* at least we tried */ }
foreach (IRGBDevice device in Devices)
try { device.Dispose(); }
catch { /* at least we tried */ }
Devices = Enumerable.Empty<IRGBDevice>();
try { _WootingSDK.Close(); } try { _WootingSDK.Close(); }
catch { /* Unlucky.. */ } catch { /* Unlucky.. */ }