1
0
mirror of https://github.com/DarthAffe/RGB.NET.git synced 2025-12-13 10:08:31 +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

@ -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;
try
{
UpdateTrigger.Stop();
// ReSharper disable once SuspiciousTypeConversion.Global
_sdk = (IAuraSdk2)new AuraSdk(); _sdk = (IAuraSdk2)new AuraSdk();
_sdk.SwitchMode(); _sdk.SwitchMode();
}
protected override IEnumerable<IRGBDevice> LoadDevices()
{
if (_sdk == null) yield break;
IList<IRGBDevice> devices = new List<IRGBDevice>();
foreach (IAuraSyncDevice device in _sdk.Enumerate(0)) foreach (IAuraSyncDevice device in _sdk.Enumerate(0))
{ {
try yield return (AsusDeviceType)device.Type switch
{ {
IAsusRGBDevice rgbDevice; AsusDeviceType.MB_RGB => new AsusMainboardRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Mainboard, device, WMIHelper.GetMainboardInfo()?.model ?? device.Name), GetUpdateTrigger()),
switch ((AsusDeviceType)device.Type) AsusDeviceType.MB_ADDRESABLE => new AsusUnspecifiedRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.LedStripe, device), LedId.LedStripe1, GetUpdateTrigger()),
{ AsusDeviceType.VGA_RGB => new AsusGraphicsCardRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.GraphicsCard, device), GetUpdateTrigger()),
case AsusDeviceType.MB_RGB: AsusDeviceType.HEADSET_RGB => new AsusHeadsetRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Headset, device), GetUpdateTrigger()),
rgbDevice = new AsusMainboardRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Mainboard, device, WMIHelper.GetMainboardInfo()?.model ?? device.Name)); AsusDeviceType.DRAM_RGB => new AsusDramRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.DRAM, device), GetUpdateTrigger()),
break; AsusDeviceType.KEYBOARD_RGB => new AsusKeyboardRGBDevice(new AsusKeyboardRGBDeviceInfo(device), GetUpdateTrigger()),
AsusDeviceType.NB_KB_RGB => new AsusKeyboardRGBDevice(new AsusKeyboardRGBDeviceInfo(device), GetUpdateTrigger()),
case AsusDeviceType.MB_ADDRESABLE: AsusDeviceType.NB_KB_4ZONE_RGB => new AsusKeyboardRGBDevice(new AsusKeyboardRGBDeviceInfo(device), GetUpdateTrigger()),
rgbDevice = new AsusUnspecifiedRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.LedStripe, device), LedId.LedStripe1); AsusDeviceType.MOUSE_RGB => new AsusMouseRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Mouse, device), GetUpdateTrigger()),
break; _ => new AsusUnspecifiedRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Unknown, device), LedId.Custom1, GetUpdateTrigger())
};
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++)

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;
try
{
UpdateTrigger.Stop();
_CoolerMasterSDK.Reload(); _CoolerMasterSDK.Reload();
if (_CoolerMasterSDK.GetSDKVersion() <= 0) return false; if (_CoolerMasterSDK.GetSDKVersion() <= 0) Throw(new RGBDeviceException("Failed to initialize CoolerMaster-SDK"));
}
IList<IRGBDevice> devices = new List<IRGBDevice>(); protected override IEnumerable<IRGBDevice> LoadDevices()
foreach (CoolerMasterDevicesIndexes index in Enum.GetValues(typeof(CoolerMasterDevicesIndexes)))
{ {
try foreach (CoolerMasterDevicesIndexes index in Enum.GetValues(typeof(CoolerMasterDevicesIndexes)))
{ {
RGBDeviceType deviceType = index.GetDeviceType(); RGBDeviceType deviceType = index.GetDeviceType();
if (deviceType == RGBDeviceType.None) continue; if (deviceType == RGBDeviceType.None) continue;
if (_CoolerMasterSDK.IsDevicePlugged(index)) if (_CoolerMasterSDK.IsDevicePlugged(index))
{ {
if (!loadFilter.HasFlag(deviceType)) continue; if (!_CoolerMasterSDK.EnableLedControl(true, index))
Throw(new RGBDeviceException("Failed to enable LED control for device " + index));
ICoolerMasterRGBDevice device; else
{
switch (deviceType) switch (deviceType)
{ {
case RGBDeviceType.Keyboard: case RGBDeviceType.Keyboard:
CoolerMasterPhysicalKeyboardLayout physicalLayout = _CoolerMasterSDK.GetDeviceLayout(index); yield return new CoolerMasterKeyboardRGBDevice(new CoolerMasterKeyboardRGBDeviceInfo(index, _CoolerMasterSDK.GetDeviceLayout(index)), GetUpdateTrigger());
device = new CoolerMasterKeyboardRGBDevice(new CoolerMasterKeyboardRGBDeviceInfo(index, physicalLayout));
break; break;
case RGBDeviceType.Mouse: case RGBDeviceType.Mouse:
device = new CoolerMasterMouseRGBDevice(new CoolerMasterMouseRGBDeviceInfo(index)); yield return new CoolerMasterMouseRGBDevice(new CoolerMasterMouseRGBDeviceInfo(index), GetUpdateTrigger());
break; break;
default: default:
if (throwExceptions) Throw(new RGBDeviceException("Unknown Device-Type"));
throw new RGBDeviceException("Unknown Device-Type"); break;
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 />
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>();
// 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
//try { _CoolerMasterSDK.UnloadCMSDK(); }
//catch { /* at least we tried */ }
} }
#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}");

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];

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,114 +59,68 @@ 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;
try
{
UpdateTrigger.Stop();
_CUESDK.Reload(); _CUESDK.Reload();
ProtocolDetails = new CorsairProtocolDetails(_CUESDK.CorsairPerformProtocolHandshake()); ProtocolDetails = new CorsairProtocolDetails(_CUESDK.CorsairPerformProtocolHandshake());
CorsairError error = LastError; CorsairError error = LastError;
if (error != CorsairError.Success) if (error != CorsairError.Success)
throw new CUEException(error); Throw(new CUEException(error));
if (ProtocolDetails.BreakingChanges) if (ProtocolDetails.BreakingChanges)
throw new RGBDeviceException("The SDK currently used isn't compatible with the installed version of CUE.\r\n" 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" + $"CUE-Version: {ProtocolDetails.ServerVersion} (Protocol {ProtocolDetails.ServerProtocolVersion})\r\n"
+ $"SDK-Version: {ProtocolDetails.SdkVersion} (Protocol {ProtocolDetails.SdkProtocolVersion})"); + $"SDK-Version: {ProtocolDetails.SdkVersion} (Protocol {ProtocolDetails.SdkProtocolVersion})"));
// DarthAffe 02.02.2021: 127 is iCUE // DarthAffe 02.02.2021: 127 is iCUE
if (!_CUESDK.CorsairSetLayerPriority(128)) if (!_CUESDK.CorsairSetLayerPriority(128))
throw new CUEException(LastError); Throw(new CUEException(LastError));
}
protected override IEnumerable<IRGBDevice> LoadDevices()
{
Dictionary<string, int> modelCounter = new(); Dictionary<string, int> modelCounter = new();
IList<IRGBDevice> devices = new List<IRGBDevice>();
int deviceCount = _CUESDK.CorsairGetDeviceCount(); int deviceCount = _CUESDK.CorsairGetDeviceCount();
for (int i = 0; i < deviceCount; i++) for (int i = 0; i < deviceCount; i++)
{
try
{ {
_CorsairDeviceInfo nativeDeviceInfo = (_CorsairDeviceInfo)Marshal.PtrToStructure(_CUESDK.CorsairGetDeviceInfo(i), typeof(_CorsairDeviceInfo))!; _CorsairDeviceInfo nativeDeviceInfo = (_CorsairDeviceInfo)Marshal.PtrToStructure(_CUESDK.CorsairGetDeviceInfo(i), typeof(_CorsairDeviceInfo))!;
CorsairRGBDeviceInfo info = new(i, RGBDeviceType.Unknown, nativeDeviceInfo, modelCounter); CorsairRGBDeviceInfo info = new(i, RGBDeviceType.Unknown, nativeDeviceInfo, modelCounter);
if (!info.CapsMask.HasFlag(CorsairDeviceCaps.Lighting)) if (!info.CapsMask.HasFlag(CorsairDeviceCaps.Lighting))
continue; // Everything that doesn't support lighting control is useless continue; // Everything that doesn't support lighting control is useless
CorsairDeviceUpdateQueue? deviceUpdateQueue = null; CorsairDeviceUpdateQueue updateQueue = new(GetUpdateTrigger(), info.CorsairDeviceIndex);
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)
{
switch (info.CorsairDeviceType) switch (info.CorsairDeviceType)
{ {
case CorsairDeviceType.Keyboard: case CorsairDeviceType.Keyboard:
yield return new CorsairKeyboardRGBDevice(new CorsairKeyboardRGBDeviceInfo(i, nativeDeviceInfo, modelCounter)); yield return new CorsairKeyboardRGBDevice(new CorsairKeyboardRGBDeviceInfo(i, nativeDeviceInfo, modelCounter), updateQueue);
break; break;
case CorsairDeviceType.Mouse: case CorsairDeviceType.Mouse:
yield return new CorsairMouseRGBDevice(new CorsairMouseRGBDeviceInfo(i, nativeDeviceInfo, modelCounter)); yield return new CorsairMouseRGBDevice(new CorsairMouseRGBDeviceInfo(i, nativeDeviceInfo, modelCounter), updateQueue);
break; break;
case CorsairDeviceType.Headset: case CorsairDeviceType.Headset:
yield return new CorsairHeadsetRGBDevice(new CorsairHeadsetRGBDeviceInfo(i, nativeDeviceInfo, modelCounter)); yield return new CorsairHeadsetRGBDevice(new CorsairHeadsetRGBDeviceInfo(i, nativeDeviceInfo, modelCounter), updateQueue);
break; break;
case CorsairDeviceType.Mousepad: case CorsairDeviceType.Mousepad:
yield return new CorsairMousepadRGBDevice(new CorsairMousepadRGBDeviceInfo(i, nativeDeviceInfo, modelCounter)); yield return new CorsairMousepadRGBDevice(new CorsairMousepadRGBDeviceInfo(i, nativeDeviceInfo, modelCounter), updateQueue);
break; break;
case CorsairDeviceType.HeadsetStand: case CorsairDeviceType.HeadsetStand:
yield return new CorsairHeadsetStandRGBDevice(new CorsairHeadsetStandRGBDeviceInfo(i, nativeDeviceInfo, modelCounter)); yield return new CorsairHeadsetStandRGBDevice(new CorsairHeadsetStandRGBDeviceInfo(i, nativeDeviceInfo, modelCounter), updateQueue);
break; break;
case CorsairDeviceType.MemoryModule: case CorsairDeviceType.MemoryModule:
yield return new CorsairMemoryRGBDevice(new CorsairMemoryRGBDeviceInfo(i, nativeDeviceInfo, modelCounter)); yield return new CorsairMemoryRGBDevice(new CorsairMemoryRGBDeviceInfo(i, nativeDeviceInfo, modelCounter), updateQueue);
break; break;
case CorsairDeviceType.Cooler: case CorsairDeviceType.Cooler:
@ -205,7 +145,7 @@ namespace RGB.NET.Devices.Corsair
{ {
_CorsairChannelDeviceInfo channelDeviceInfo = (_CorsairChannelDeviceInfo)Marshal.PtrToStructure(channelDeviceInfoPtr, typeof(_CorsairChannelDeviceInfo))!; _CorsairChannelDeviceInfo channelDeviceInfo = (_CorsairChannelDeviceInfo)Marshal.PtrToStructure(channelDeviceInfoPtr, typeof(_CorsairChannelDeviceInfo))!;
yield return new CorsairCustomRGBDevice(new CorsairCustomRGBDeviceInfo(info, nativeDeviceInfo, channelDeviceInfo, referenceLed, modelCounter)); yield return new CorsairCustomRGBDevice(new CorsairCustomRGBDeviceInfo(info, nativeDeviceInfo, channelDeviceInfo, referenceLed, modelCounter), updateQueue);
referenceLed += channelDeviceInfo.deviceLedCount; referenceLed += channelDeviceInfo.deviceLedCount;
channelDeviceInfoPtr = new IntPtr(channelDeviceInfoPtr.ToInt64() + channelDeviceInfoStructSize); channelDeviceInfoPtr = new IntPtr(channelDeviceInfoPtr.ToInt64() + channelDeviceInfoStructSize);
@ -215,14 +155,12 @@ namespace RGB.NET.Devices.Corsair
channelInfoPtr = new IntPtr(channelInfoPtr.ToInt64() + channelInfoStructSize); channelInfoPtr = new IntPtr(channelInfoPtr.ToInt64() + channelInfoStructSize);
} }
} }
break; break;
// ReSharper disable once RedundantCaseLabel
case CorsairDeviceType.Unknown:
default: default:
throw new RGBDeviceException("Unknown Device-Type"); Throw(new RGBDeviceException("Unknown Device-Type"));
break;
}
} }
} }
@ -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);

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;
try
{
UpdateTrigger.Stop();
IList<IRGBDevice> devices = new List<IRGBDevice>();
foreach (IDMXDeviceDefinition dmxDeviceDefinition in DeviceDefinitions) foreach (IDMXDeviceDefinition dmxDeviceDefinition in DeviceDefinitions)
{ {
IRGBDevice? device = null;
try try
{ {
if (dmxDeviceDefinition is E131DMXDeviceDefinition e131DMXDeviceDefinition) if (dmxDeviceDefinition is E131DMXDeviceDefinition e131DMXDeviceDefinition)
{
if (e131DMXDeviceDefinition.Leds.Count > 0) if (e131DMXDeviceDefinition.Leds.Count > 0)
device = new E131Device(new E131DeviceInfo(e131DMXDeviceDefinition), e131DMXDeviceDefinition.Leds, GetUpdateTrigger(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)
{
IsInitialized = false;
try
{
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); protected override IEnumerable<IRGBDevice> LoadDevices()
IsInitialized = true;
return true;
}
catch
{ {
if (throwExceptions) throw; foreach ((IDeviceLayout layout, Action<IEnumerable<Led>>? updateLedsAction) in _fakeDeviceDefinitions)
return false; yield return new DebugRGBDevice(layout, updateLedsAction);
}
} }
/// <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());
if (IsInitialized)
_LogitechGSDK.LogiLedRestoreLighting();
}
catch { /* At least we tried ... */ }
IsInitialized = false;
try
{
UpdateTrigger.Stop();
_LogitechGSDK.Reload(); _LogitechGSDK.Reload();
if (!_LogitechGSDK.LogiLedInit()) return false; if (!_LogitechGSDK.LogiLedInit()) Throw(new RGBDeviceException("Failed to initialize Logitech-SDK."));
_LogitechGSDK.LogiLedSaveCurrentLighting(); _LogitechGSDK.LogiLedSaveCurrentLighting();
}
IList<IRGBDevice> devices = new List<IRGBDevice>(); //TODO DarthAffe 04.03.2021: Rework device selection and configuration for HID-based providers
protected override IEnumerable<IRGBDevice> LoadDevices()
{
DeviceChecker.LoadDeviceList(); DeviceChecker.LoadDeviceList();
try if (DeviceChecker.IsPerKeyDeviceConnected && (_perKeyUpdateQueue != null))
{
if (DeviceChecker.IsPerKeyDeviceConnected)
{ {
(string model, RGBDeviceType deviceType, int _, int _) = DeviceChecker.PerKeyDeviceData; (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 yield return new LogitechPerKeyRGBDevice(new LogitechRGBDeviceInfo(deviceType, model, LogitechDeviceCaps.PerKeyRGB, 0), _perKeyUpdateQueue);
{
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 && (_perDeviceUpdateQueue != null))
{
if (DeviceChecker.IsPerDeviceDeviceConnected)
{ {
(string model, RGBDeviceType deviceType, int _, int _) = DeviceChecker.PerDeviceDeviceData; (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 yield return new LogitechPerDeviceRGBDevice(new LogitechRGBDeviceInfo(deviceType, model, LogitechDeviceCaps.DeviceRGB, 0), _perDeviceUpdateQueue);
{
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) if (DeviceChecker.IsZoneDeviceConnected)
{ {
foreach ((string model, RGBDeviceType deviceType, int _, int zones) in DeviceChecker.ZoneDeviceData) foreach ((string model, RGBDeviceType deviceType, int _, int zones) in DeviceChecker.ZoneDeviceData)
try
{ {
if (loadFilter.HasFlag(deviceType)) LogitechZoneUpdateQueue updateQueue = new(GetUpdateTrigger(), deviceType);
{ yield return new LogitechZoneRGBDevice(new LogitechRGBDeviceInfo(deviceType, model, LogitechDeviceCaps.DeviceRGB, zones), updateQueue);
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;
} }
/// <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;
try
{
UpdateTrigger.Stop();
_MsiSDK.Reload(); _MsiSDK.Reload();
IList<IRGBDevice> devices = new List<IRGBDevice>();
int errorCode; int errorCode;
if ((errorCode = _MsiSDK.Initialize()) != 0) if ((errorCode = _MsiSDK.Initialize()) != 0)
ThrowMsiError(errorCode); ThrowMsiError(errorCode);
}
protected override IEnumerable<IRGBDevice> LoadDevices()
{
int errorCode;
if ((errorCode = _MsiSDK.GetDeviceInfo(out string[] deviceTypes, out int[] ledCounts)) != 0) if ((errorCode = _MsiSDK.GetDeviceInfo(out string[] deviceTypes, out int[] ledCounts)) != 0)
ThrowMsiError(errorCode); ThrowMsiError(errorCode);
for (int i = 0; i < deviceTypes.Length; i++) for (int i = 0; i < deviceTypes.Length; i++)
{
try
{ {
string deviceType = deviceTypes[i]; string deviceType = deviceTypes[i];
int ledCount = ledCounts[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")) if (deviceType.Equals("MSI_MB"))
{ {
MsiDeviceUpdateQueue updateQueue = new(UpdateTrigger, deviceType); //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)
IMsiRGBDevice motherboard = new MsiMainboardRGBDevice(new MsiRGBDeviceInfo(RGBDeviceType.Mainboard, deviceType, "MSI", "Motherboard")); yield return new MsiMainboardRGBDevice(new MsiRGBDeviceInfo(RGBDeviceType.Mainboard, deviceType, "MSI", "Motherboard"), ledCount, GetUpdateTrigger());
motherboard.Initialize(updateQueue, ledCount);
devices.Add(motherboard);
} }
else if (deviceType.Equals("MSI_VGA")) 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: 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. //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());
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")) 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: 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. //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());
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 private void ThrowMsiError(int errorCode) => Throw(new MysticLightException(errorCode, _MsiSDK.GetErrorMessage(errorCode)));
}
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));
/// <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(); NovationColorCapabilities.LimitedRG => new LimitedColorUpdateQueue(updateTrigger, info.DeviceId),
NovationColorCapabilities.RGB => new RGBColorUpdateQueue(updateTrigger, info.DeviceId),
UpdateQueue = DeviceInfo.ColorCapabilities switch
{
NovationColorCapabilities.LimitedRG => new LimitedColorUpdateQueue(updateTrigger, DeviceInfo.DeviceId),
NovationColorCapabilities.RGB => new RGBColorUpdateQueue(updateTrigger, DeviceInfo.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,29 +35,17 @@ 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;
try
{
UpdateTrigger.Stop();
IList<IRGBDevice> devices = new List<IRGBDevice>();
if (loadFilter.HasFlag(RGBDeviceType.LedMatrix))
for (int index = 0; index < OutputDeviceBase.DeviceCount; index++) for (int index = 0; index < OutputDeviceBase.DeviceCount; index++)
{
try
{ {
MidiOutCaps outCaps = OutputDeviceBase.GetDeviceCapabilities(index); MidiOutCaps outCaps = OutputDeviceBase.GetDeviceCapabilities(index);
if (outCaps.name == null) continue; if (outCaps.name == null) continue;
@ -86,37 +59,8 @@ namespace RGB.NET.Devices.Novation
NovationColorCapabilities colorCapability = deviceId.GetColorCapability(); NovationColorCapabilities colorCapability = deviceId.GetColorCapability();
if (colorCapability == NovationColorCapabilities.None) continue; if (colorCapability == NovationColorCapabilities.None) continue;
INovationRGBDevice device = new NovationLaunchpadRGBDevice(new NovationLaunchpadRGBDeviceInfo(outCaps.name, index, colorCapability, deviceId.GetLedIdMapping())); yield return new NovationLaunchpadRGBDevice(new NovationLaunchpadRGBDeviceInfo(outCaps.name, index, colorCapability, deviceId.GetLedIdMapping()), GetUpdateTrigger());
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,125 +54,73 @@ 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;
try
{
UpdateTrigger.Stop();
_RazerSDK.Reload(); _RazerSDK.Reload();
RazerError error; RazerError error;
if (((error = _RazerSDK.Init()) != RazerError.Success) 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 ... && Enum.IsDefined(typeof(RazerError), error)) //HACK DarthAffe 08.02.2018: The x86-SDK seems to have a problem here ...
ThrowRazerError(error); ThrowRazerError(error);
}
IList<IRGBDevice> devices = new List<IRGBDevice>(); protected override IEnumerable<IRGBDevice> LoadDevices()
{
if (loadFilter.HasFlag(RGBDeviceType.Keyboard))
foreach ((Guid guid, string model) in Razer.Devices.KEYBOARDS) foreach ((Guid guid, string model) in Razer.Devices.KEYBOARDS)
try
{ {
if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1)) if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1))
&& (!LoadEmulatorDevices || (Razer.Devices.KEYBOARDS.FirstOrDefault().guid != guid))) continue; && (!LoadEmulatorDevices || (Razer.Devices.KEYBOARDS.FirstOrDefault().guid != guid))) continue;
RazerKeyboardRGBDevice device = new(new RazerKeyboardRGBDeviceInfo(guid, model)); yield return new RazerKeyboardRGBDevice(new RazerKeyboardRGBDeviceInfo(guid, model), GetUpdateTrigger());
device.Initialize(UpdateTrigger);
devices.Add(device);
} }
catch { if (throwExceptions) throw; }
if (loadFilter.HasFlag(RGBDeviceType.Mouse))
foreach ((Guid guid, string model) in Razer.Devices.MICE) foreach ((Guid guid, string model) in Razer.Devices.MICE)
try
{ {
if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1)) if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1))
&& (!LoadEmulatorDevices || (Razer.Devices.MICE.FirstOrDefault().guid != guid))) continue; && (!LoadEmulatorDevices || (Razer.Devices.MICE.FirstOrDefault().guid != guid))) continue;
RazerMouseRGBDevice device = new(new RazerMouseRGBDeviceInfo(guid, model)); yield return new RazerMouseRGBDevice(new RazerMouseRGBDeviceInfo(guid, model), GetUpdateTrigger());
device.Initialize(UpdateTrigger);
devices.Add(device);
} }
catch { if (throwExceptions) throw; }
if (loadFilter.HasFlag(RGBDeviceType.Headset))
foreach ((Guid guid, string model) in Razer.Devices.HEADSETS) foreach ((Guid guid, string model) in Razer.Devices.HEADSETS)
try
{ {
if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1)) if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1))
&& (!LoadEmulatorDevices || (Razer.Devices.HEADSETS.FirstOrDefault().guid != guid))) continue; && (!LoadEmulatorDevices || (Razer.Devices.HEADSETS.FirstOrDefault().guid != guid))) continue;
RazerHeadsetRGBDevice device = new(new RazerHeadsetRGBDeviceInfo(guid, model)); yield return new RazerHeadsetRGBDevice(new RazerHeadsetRGBDeviceInfo(guid, model), GetUpdateTrigger());
device.Initialize(UpdateTrigger);
devices.Add(device);
} }
catch { if (throwExceptions) throw; }
if (loadFilter.HasFlag(RGBDeviceType.Mousepad))
foreach ((Guid guid, string model) in Razer.Devices.MOUSEMATS) foreach ((Guid guid, string model) in Razer.Devices.MOUSEMATS)
try
{ {
if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1)) if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1))
&& (!LoadEmulatorDevices || (Razer.Devices.MOUSEMATS.FirstOrDefault().guid != guid))) continue; && (!LoadEmulatorDevices || (Razer.Devices.MOUSEMATS.FirstOrDefault().guid != guid))) continue;
RazerMousepadRGBDevice device = new(new RazerMousepadRGBDeviceInfo(guid, model)); yield return new RazerMousepadRGBDevice(new RazerMousepadRGBDeviceInfo(guid, model), GetUpdateTrigger());
device.Initialize(UpdateTrigger);
devices.Add(device);
} }
catch { if (throwExceptions) throw; }
if (loadFilter.HasFlag(RGBDeviceType.Keypad))
foreach ((Guid guid, string model) in Razer.Devices.KEYPADS) foreach ((Guid guid, string model) in Razer.Devices.KEYPADS)
try
{ {
if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1)) if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1))
&& (!LoadEmulatorDevices || (Razer.Devices.KEYPADS.FirstOrDefault().guid != guid))) continue; && (!LoadEmulatorDevices || (Razer.Devices.KEYPADS.FirstOrDefault().guid != guid))) continue;
RazerKeypadRGBDevice device = new(new RazerKeypadRGBDeviceInfo(guid, model)); yield return new RazerKeypadRGBDevice(new RazerKeypadRGBDeviceInfo(guid, model), GetUpdateTrigger());
device.Initialize(UpdateTrigger);
devices.Add(device);
} }
catch { if (throwExceptions) throw; }
if (loadFilter.HasFlag(RGBDeviceType.Keyboard))
foreach ((Guid guid, string model) in Razer.Devices.CHROMALINKS) foreach ((Guid guid, string model) in Razer.Devices.CHROMALINKS)
try
{ {
if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1)) if (((_RazerSDK.QueryDevice(guid, out _DeviceInfo deviceInfo) != RazerError.Success) || (deviceInfo.Connected < 1))
&& (!LoadEmulatorDevices || (Razer.Devices.CHROMALINKS.FirstOrDefault().guid != guid))) continue; && (!LoadEmulatorDevices || (Razer.Devices.CHROMALINKS.FirstOrDefault().guid != guid))) continue;
RazerChromaLinkRGBDevice device = new(new RazerChromaLinkRGBDeviceInfo(guid, model)); yield return new RazerChromaLinkRGBDevice(new RazerChromaLinkRGBDeviceInfo(guid, model), GetUpdateTrigger());
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;
} }
private void ThrowRazerError(RazerError errorCode) => throw new RazerException(errorCode); private void ThrowRazerError(RazerError errorCode) => throw new RazerException(errorCode);
@ -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
{
IsInitialized = false;
UpdateTrigger.Stop();
if (!SteelSeriesSDK.IsInitialized) if (!SteelSeriesSDK.IsInitialized)
SteelSeriesSDK.Initialize(); SteelSeriesSDK.Initialize();
}
IList<IRGBDevice> devices = new List<IRGBDevice>(); protected override IEnumerable<IRGBDevice> GetLoadedDevices(RGBDeviceType loadFilter)
{
DeviceChecker.LoadDeviceList(loadFilter); DeviceChecker.LoadDeviceList(loadFilter);
try return base.GetLoadedDevices(loadFilter);
}
protected override IEnumerable<IRGBDevice> LoadDevices()
{ {
foreach ((string model, RGBDeviceType deviceType, int _, SteelSeriesDeviceType steelSeriesDeviceType, Dictionary<LedId, SteelSeriesLedId> ledMapping) in DeviceChecker.ConnectedDevices) 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();
string apiName = steelSeriesDeviceType.GetAPIName() ?? throw new RGBDeviceException($"Missing API-name for device {model}"); if (apiName == null)
SteelSeriesDeviceUpdateQueue updateQueue = new(UpdateTrigger, apiName); Throw(new RGBDeviceException($"Missing API-name for device {model}"));
device.Initialize(updateQueue, ledMapping); else
devices.Add(device); yield return new SteelSeriesRGBDevice(new SteelSeriesRGBDeviceInfo(deviceType, model, steelSeriesDeviceType), apiName, ledMapping, GetUpdateTrigger());
} }
} }
catch { if (throwExceptions) throw; }
UpdateTrigger.Start();
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
IsInitialized = true;
}
catch
{
IsInitialized = false;
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 { 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
@ -81,13 +77,14 @@ namespace RGB.NET.Devices.WS281X.Bitwizard
/// <inheritdoc /> /// <inheritdoc />
public IEnumerable<IRGBDevice> CreateDevices(IDeviceUpdateTrigger updateTrigger) public IEnumerable<IRGBDevice> CreateDevices(IDeviceUpdateTrigger updateTrigger)
{
foreach ((int pin, int stripLength) in Strips)
{ {
BitwizardWS2812USBUpdateQueue queue = new(updateTrigger, SerialConnection); BitwizardWS2812USBUpdateQueue queue = new(updateTrigger, SerialConnection);
string name = Name ?? $"Bitwizard WS2812 USB ({Port})"; string name = Name ?? $"Bitwizard WS2812 USB ({Port}) Pin {pin}";
int ledOffset = Pin * MaxStripLength; int ledOffset = pin * MaxStripLength;
BitwizardWS2812USBDevice device = new(new BitwizardWS2812USBDeviceInfo(name), queue, ledOffset); yield return new BitwizardWS2812USBDevice(new BitwizardWS2812USBDeviceInfo(name), queue, ledOffset, stripLength);
device.Initialize(StripLength); }
yield return device;
} }
#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)
{
IsInitialized = false;
try protected override IEnumerable<IRGBDevice> LoadDevices()
{ {
UpdateTrigger.Stop(); int i = 0;
List<IRGBDevice> devices = new();
foreach (IWS281XDeviceDefinition deviceDefinition in DeviceDefinitions) foreach (IWS281XDeviceDefinition deviceDefinition in DeviceDefinitions)
{ {
try IDeviceUpdateTrigger updateTrigger = GetUpdateTrigger(i++);
{ foreach (IRGBDevice device in deviceDefinition.CreateDevices(updateTrigger))
devices.AddRange(deviceDefinition.CreateDevices(UpdateTrigger)); yield return device;
} }
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>();
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;
try
{
UpdateTrigger.Stop();
_WootingSDK.Reload(); _WootingSDK.Reload();
}
IList<IRGBDevice> devices = new List<IRGBDevice>(); protected override IEnumerable<IRGBDevice> LoadDevices()
{
if (_WootingSDK.KeyboardConnected()) if (_WootingSDK.KeyboardConnected())
{ {
_WootingDeviceInfo nativeDeviceInfo = (_WootingDeviceInfo)Marshal.PtrToStructure(_WootingSDK.GetDeviceInfo(), typeof(_WootingDeviceInfo))!; _WootingDeviceInfo nativeDeviceInfo = (_WootingDeviceInfo)Marshal.PtrToStructure(_WootingSDK.GetDeviceInfo(), typeof(_WootingDeviceInfo))!;
IWootingRGBDevice device = nativeDeviceInfo.Model switch IWootingRGBDevice? device = nativeDeviceInfo.Model switch
{ {
"Wooting two" => new WootingKeyboardRGBDevice(new WootingKeyboardRGBDeviceInfo(WootingDevicesIndexes.WootingTwo)), "Wooting two" => new WootingKeyboardRGBDevice(new WootingKeyboardRGBDeviceInfo(WootingDevicesIndexes.WootingTwo), GetUpdateTrigger()),
"Wooting one" => new WootingKeyboardRGBDevice(new WootingKeyboardRGBDeviceInfo(WootingDevicesIndexes.WootingOne)), "Wooting one" => new WootingKeyboardRGBDevice(new WootingKeyboardRGBDeviceInfo(WootingDevicesIndexes.WootingOne), GetUpdateTrigger()),
_ => throw new RGBDeviceException("No supported Wooting keyboard connected") _ => null
}; };
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.. */ }