1
0
mirror of https://github.com/DarthAffe/RGB.NET.git synced 2025-12-12 17:48: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 />
public abstract TDeviceInfo DeviceInfo { get; }
public TDeviceInfo DeviceInfo { get; }
/// <inheritdoc />
IRGBDeviceInfo IRGBDevice.DeviceInfo => DeviceInfo;
@ -52,6 +52,8 @@ namespace RGB.NET.Core
/// </summary>
protected Dictionary<LedId, Led> LedMapping { get; } = new();
protected IUpdateQueue UpdateQueue { get; }
#region Indexer
/// <inheritdoc />
@ -68,6 +70,16 @@ namespace RGB.NET.Core
#endregion
#region Constructors
protected AbstractRGBDevice(TDeviceInfo deviceOnfo, IUpdateQueue updateQueue)
{
this.DeviceInfo = deviceOnfo;
this.UpdateQueue = updateQueue;
}
#endregion
#region Methods
/// <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 />
public virtual void Dispose()
{
try
{
LedMapping.Clear();
}
catch { /* this really shouldn't happen */ }
try { UpdateQueue.Dispose(); } catch { /* :( */ }
try { LedMapping.Clear(); } catch { /* this really shouldn't happen */ }
}
/// <summary>
@ -128,11 +142,6 @@ namespace RGB.NET.Core
protected virtual void DeviceUpdate()
{ }
/// <summary>
/// Sends all the updated <see cref="Led"/> to the device.
/// </summary>
protected abstract void UpdateLeds(IEnumerable<Led> ledsToUpdate);
/// <summary>
/// Initializes the <see cref="Led"/> with the specified id.
/// </summary>

View File

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

View File

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

View File

@ -22,6 +22,15 @@ namespace RGB.NET.Core
#endregion
#region Events
/// <summary>
/// Occurs when an exception is thrown in the device provider
/// </summary>
event EventHandler<Exception>? Exception;
#endregion
#region Methods
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>
protected virtual void OnUpdate(CustomUpdateData? updateData = null) => Update?.Invoke(this, updateData ?? new CustomUpdateData());
/// <inheritdoc />
public abstract void Start();
/// <inheritdoc />
public abstract void Dispose();

View File

@ -86,7 +86,7 @@ namespace RGB.NET.Core
/// <summary>
/// Starts the trigger.
/// </summary>
public void Start()
public override void Start()
{
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>
/// <typeparam name="TIdentifier">The type of the key used to identify some 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
{
#region Properties & Fields
@ -123,7 +123,7 @@ namespace RGB.NET.Core
/// <summary>
/// Represents a generic <see cref="UpdateQueue{TIdentifier,TData}"/> using an object as the key and a color as the value.
/// </summary>
public abstract class UpdateQueue : UpdateQueue<object, Color>
public abstract class UpdateQueue : UpdateQueue<object, Color>, IUpdateQueue
{
#region Constructors

View File

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

View File

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

View File

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

View File

@ -3,8 +3,6 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using AuraServiceLib;
using RGB.NET.Core;
@ -14,7 +12,7 @@ namespace RGB.NET.Devices.Asus
/// <summary>
/// Represents a device provider responsible for Cooler Master devices.
/// </summary>
public class AsusDeviceProvider : IRGBDeviceProvider
public class AsusDeviceProvider : AbstractRGBDeviceProvider
{
#region Properties & Fields
@ -24,20 +22,6 @@ namespace RGB.NET.Devices.Asus
/// </summary>
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;
#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)}");
_instance = this;
UpdateTrigger = new DeviceUpdateTrigger();
}
#endregion
#region Methods
/// <inheritdoc />
public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false)
protected override void InitializeSDK()
{
IsInitialized = false;
_sdk = (IAuraSdk2)new AuraSdk();
_sdk.SwitchMode();
}
try
protected override IEnumerable<IRGBDevice> LoadDevices()
{
if (_sdk == null) yield break;
foreach (IAuraSyncDevice device in _sdk.Enumerate(0))
{
UpdateTrigger.Stop();
// ReSharper disable once SuspiciousTypeConversion.Global
_sdk = (IAuraSdk2)new AuraSdk();
_sdk.SwitchMode();
IList<IRGBDevice> devices = new List<IRGBDevice>();
foreach (IAuraSyncDevice device in _sdk.Enumerate(0))
yield return (AsusDeviceType)device.Type switch
{
try
{
IAsusRGBDevice rgbDevice;
switch ((AsusDeviceType)device.Type)
{
case AsusDeviceType.MB_RGB:
rgbDevice = new AsusMainboardRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Mainboard, device, WMIHelper.GetMainboardInfo()?.model ?? device.Name));
break;
case AsusDeviceType.MB_ADDRESABLE:
rgbDevice = new AsusUnspecifiedRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.LedStripe, device), LedId.LedStripe1);
break;
case AsusDeviceType.VGA_RGB:
rgbDevice = new AsusGraphicsCardRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.GraphicsCard, device));
break;
case AsusDeviceType.HEADSET_RGB:
rgbDevice = new AsusHeadsetRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Headset, device));
break;
case AsusDeviceType.DRAM_RGB:
rgbDevice = new AsusDramRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.DRAM, device));
break;
case AsusDeviceType.KEYBOARD_RGB:
case AsusDeviceType.NB_KB_RGB:
case AsusDeviceType.NB_KB_4ZONE_RGB:
rgbDevice = new AsusKeyboardRGBDevice(new AsusKeyboardRGBDeviceInfo(device));
break;
case AsusDeviceType.MOUSE_RGB:
rgbDevice = new AsusMouseRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Mouse, device));
break;
default:
rgbDevice = new AsusUnspecifiedRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Unknown, device), LedId.Custom1);
break;
}
if (loadFilter.HasFlag(rgbDevice.DeviceInfo.DeviceType))
{
rgbDevice.Initialize(UpdateTrigger);
devices.Add(rgbDevice);
}
}
catch
{
if (throwExceptions)
throw;
}
}
UpdateTrigger.Start();
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
IsInitialized = true;
AsusDeviceType.MB_RGB => new AsusMainboardRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Mainboard, device, WMIHelper.GetMainboardInfo()?.model ?? device.Name), GetUpdateTrigger()),
AsusDeviceType.MB_ADDRESABLE => new AsusUnspecifiedRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.LedStripe, device), LedId.LedStripe1, GetUpdateTrigger()),
AsusDeviceType.VGA_RGB => new AsusGraphicsCardRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.GraphicsCard, device), GetUpdateTrigger()),
AsusDeviceType.HEADSET_RGB => new AsusHeadsetRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Headset, device), GetUpdateTrigger()),
AsusDeviceType.DRAM_RGB => new AsusDramRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.DRAM, device), GetUpdateTrigger()),
AsusDeviceType.KEYBOARD_RGB => new AsusKeyboardRGBDevice(new AsusKeyboardRGBDeviceInfo(device), GetUpdateTrigger()),
AsusDeviceType.NB_KB_RGB => new AsusKeyboardRGBDevice(new AsusKeyboardRGBDeviceInfo(device), GetUpdateTrigger()),
AsusDeviceType.NB_KB_4ZONE_RGB => new AsusKeyboardRGBDevice(new AsusKeyboardRGBDeviceInfo(device), GetUpdateTrigger()),
AsusDeviceType.MOUSE_RGB => new AsusMouseRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Mouse, device), GetUpdateTrigger()),
_ => new AsusUnspecifiedRGBDevice(new AsusRGBDeviceInfo(RGBDeviceType.Unknown, device), LedId.Custom1, GetUpdateTrigger())
};
}
catch
{
if (throwExceptions)
throw;
return false;
}
return true;
}
/// <inheritdoc />
public void Dispose()
public override 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>();
base.Dispose();
try { _sdk?.ReleaseControl(0); }
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.
/// </summary>
/// <param name="info">The specific information provided by Asus for the DRAM.</param>
internal AsusDramRGBDevice(AsusRGBDeviceInfo info)
: base(info)
{ }
internal AsusDramRGBDevice(AsusRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info, updateTrigger)
{
InitializeLayout();
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout()
private void InitializeLayout()
{
int ledCount = DeviceInfo.Device.Lights.Count;
for (int i = 0; i < ledCount; i++)

View File

@ -1,75 +1,23 @@
using System.Collections.Generic;
using System.Linq;
using RGB.NET.Core;
using RGB.NET.Core;
namespace RGB.NET.Devices.Asus
{
/// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}" />
/// <inheritdoc cref="IAsusRGBDevice" />
/// <summary>
/// Represents a generic Asus-device. (keyboard, mouse, headset, mousepad).
/// </summary>
public abstract class AsusRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, IAsusRGBDevice
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
/// <summary>
/// Initializes a new instance of the <see cref="AsusRGBDevice{TDeviceInfo}"/> class.
/// </summary>
/// <param name="info">The generic information provided by Asus for the device.</param>
protected AsusRGBDevice(TDeviceInfo info)
{
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();
}
protected AsusRGBDevice(TDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info, new AsusUpdateQueue(updateTrigger, info.Device))
{ }
#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.
/// </summary>
/// <param name="info">The specific information provided by Asus for the headset.</param>
internal AsusUnspecifiedRGBDevice(AsusRGBDeviceInfo info, LedId baseLedId)
: base(info)
internal AsusUnspecifiedRGBDevice(AsusRGBDeviceInfo info, LedId baseLedId, IDeviceUpdateTrigger updateTrigger)
: base(info, updateTrigger)
{
this._baseLedId = baseLedId;
InitializeLayout();
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout()
private void InitializeLayout()
{
int ledCount = DeviceInfo.Device.Lights.Count;
for (int i = 0; i < ledCount; i++)
@ -41,6 +42,7 @@ namespace RGB.NET.Devices.Asus
/// <inheritdoc />
protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)_baseLedId;
#endregion
}
}

View File

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

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.
/// </summary>
/// <param name="info">The specific information provided by Asus for the graphics card.</param>
internal AsusGraphicsCardRGBDevice(AsusRGBDeviceInfo info)
: base(info)
{ }
internal AsusGraphicsCardRGBDevice(AsusRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info, updateTrigger)
{
InitializeLayout();
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout()
private void InitializeLayout()
{
int ledCount = DeviceInfo.Device.Lights.Count;
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.
/// </summary>
/// <param name="info">The specific information provided by Asus for the headset.</param>
internal AsusHeadsetRGBDevice(AsusRGBDeviceInfo info)
: base(info)
{ }
internal AsusHeadsetRGBDevice(AsusRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info, updateTrigger)
{
InitializeLayout();
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout()
private void InitializeLayout()
{
int ledCount = DeviceInfo.Device.Lights.Count;
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.
/// </summary>
/// <param name="info">The specific information provided by Asus for the keyboard.</param>
internal AsusKeyboardRGBDevice(AsusKeyboardRGBDeviceInfo info)
: base(info)
{ }
internal AsusKeyboardRGBDevice(AsusKeyboardRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info, updateTrigger)
{
InitializeLayout();
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout()
private void InitializeLayout()
{
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.
/// </summary>
/// <param name="info">The specific information provided by Asus for the mainboard.</param>
internal AsusMainboardRGBDevice(AsusRGBDeviceInfo info)
: base(info)
{ }
internal AsusMainboardRGBDevice(AsusRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info, updateTrigger)
{
InitializeLayout();
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout()
private void InitializeLayout()
{
int ledCount = DeviceInfo.Device.Lights.Count;
for (int i = 0; i < ledCount; i++)
@ -33,7 +34,7 @@ namespace RGB.NET.Devices.Asus
/// <inheritdoc />
protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Mainboard1;
#endregion
}
}

View File

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

View File

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

View File

@ -1,76 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using RGB.NET.Core;
using RGB.NET.Devices.CoolerMaster.Native;
namespace RGB.NET.Devices.CoolerMaster
{
/// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}" />
/// <inheritdoc cref="ICoolerMasterRGBDevice" />
/// <summary>
/// Represents a generic CoolerMaster-device. (keyboard, mouse, headset, mousepad).
/// </summary>
public abstract class CoolerMasterRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, ICoolerMasterRGBDevice
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
/// <summary>
/// Initializes a new instance of the <see cref="CoolerMasterRGBDevice{TDeviceInfo}"/> class.
/// </summary>
/// <param name="info">The generic information provided by CoolerMaster for the device.</param>
protected CoolerMasterRGBDevice(TDeviceInfo info)
{
this.DeviceInfo = info;
}
protected CoolerMasterRGBDevice(TDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info, new CoolerMasterUpdateQueue(updateTrigger, info.DeviceIndex))
{ }
#endregion
#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="AbstractRGBDevice{TDeviceInfo}.Dispose" />
public override void Dispose()
{
try { UpdateQueue?.Dispose(); }
catch { /* at least we tried */ }
_CoolerMasterSDK.EnableLedControl(false, DeviceInfo.DeviceIndex);
base.Dispose();

View File

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

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.
/// </summary>
/// <param name="info">The specific information provided by CoolerMaster for the keyboard</param>
internal CoolerMasterKeyboardRGBDevice(CoolerMasterKeyboardRGBDeviceInfo info)
: base(info)
{ }
internal CoolerMasterKeyboardRGBDevice(CoolerMasterKeyboardRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info, updateTrigger)
{
InitializeLayout();
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout()
private void InitializeLayout()
{
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}");
@ -44,7 +45,7 @@ namespace RGB.NET.Devices.CoolerMaster
/// <inheritdoc />
protected override object GetLedCustomData(LedId ledId) => CoolerMasterKeyboardLedMappings.Mapping[DeviceInfo.DeviceIndex][DeviceInfo.PhysicalLayout][ledId];
#endregion
}
}

View File

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

View File

@ -15,7 +15,7 @@ namespace RGB.NET.Devices.Corsair
/// <summary>
/// Represents a device provider responsible for corsair (CUE) devices.
/// </summary>
public class CorsairDeviceProvider : IRGBDeviceProvider
public class CorsairDeviceProvider : AbstractRGBDeviceProvider
{
#region Properties & Fields
@ -37,12 +37,6 @@ namespace RGB.NET.Devices.Corsair
/// </summary>
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>
/// Gets the protocol details for the current SDK-connection.
/// </summary>
@ -53,14 +47,6 @@ namespace RGB.NET.Devices.Corsair
/// </summary>
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
#region Constructors
@ -73,156 +59,108 @@ namespace RGB.NET.Devices.Corsair
{
if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(CorsairDeviceProvider)}");
_instance = this;
UpdateTrigger = new DeviceUpdateTrigger();
}
#endregion
#region Methods
/// <inheritdoc />
/// <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)
protected override void InitializeSDK()
{
IsInitialized = false;
_CUESDK.Reload();
try
{
UpdateTrigger.Stop();
ProtocolDetails = new CorsairProtocolDetails(_CUESDK.CorsairPerformProtocolHandshake());
_CUESDK.Reload();
CorsairError error = LastError;
if (error != CorsairError.Success)
Throw(new CUEException(error));
ProtocolDetails = new CorsairProtocolDetails(_CUESDK.CorsairPerformProtocolHandshake());
if (ProtocolDetails.BreakingChanges)
Throw(new RGBDeviceException("The SDK currently used isn't compatible with the installed version of CUE.\r\n"
+ $"CUE-Version: {ProtocolDetails.ServerVersion} (Protocol {ProtocolDetails.ServerProtocolVersion})\r\n"
+ $"SDK-Version: {ProtocolDetails.SdkVersion} (Protocol {ProtocolDetails.SdkProtocolVersion})"));
CorsairError error = LastError;
if (error != CorsairError.Success)
throw new CUEException(error);
if (ProtocolDetails.BreakingChanges)
throw new RGBDeviceException("The SDK currently used isn't compatible with the installed version of CUE.\r\n"
+ $"CUE-Version: {ProtocolDetails.ServerVersion} (Protocol {ProtocolDetails.ServerProtocolVersion})\r\n"
+ $"SDK-Version: {ProtocolDetails.SdkVersion} (Protocol {ProtocolDetails.SdkProtocolVersion})");
// DarthAffe 02.02.2021: 127 is iCUE
if (!_CUESDK.CorsairSetLayerPriority(128))
throw new CUEException(LastError);
Dictionary<string, int> modelCounter = new();
IList<IRGBDevice> devices = new List<IRGBDevice>();
int deviceCount = _CUESDK.CorsairGetDeviceCount();
for (int i = 0; i < deviceCount; i++)
{
try
{
_CorsairDeviceInfo nativeDeviceInfo = (_CorsairDeviceInfo)Marshal.PtrToStructure(_CUESDK.CorsairGetDeviceInfo(i), typeof(_CorsairDeviceInfo))!;
CorsairRGBDeviceInfo info = new(i, RGBDeviceType.Unknown, nativeDeviceInfo, modelCounter);
if (!info.CapsMask.HasFlag(CorsairDeviceCaps.Lighting))
continue; // Everything that doesn't support lighting control is useless
CorsairDeviceUpdateQueue? deviceUpdateQueue = null;
foreach (ICorsairRGBDevice device in GetRGBDevice(info, i, nativeDeviceInfo, modelCounter))
{
if ((device == null) || !loadFilter.HasFlag(device.DeviceInfo.DeviceType)) continue;
deviceUpdateQueue ??= new CorsairDeviceUpdateQueue(UpdateTrigger, info.CorsairDeviceIndex);
device.Initialize(deviceUpdateQueue);
error = LastError;
if (error != CorsairError.Success)
throw new CUEException(error);
devices.Add(device);
}
}
catch { if (throwExceptions) throw; }
}
UpdateTrigger.Start();
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
IsInitialized = true;
}
catch
{
Reset();
if (throwExceptions) throw;
return false;
}
return true;
// DarthAffe 02.02.2021: 127 is iCUE
if (!_CUESDK.CorsairSetLayerPriority(128))
Throw(new CUEException(LastError));
}
private static IEnumerable<ICorsairRGBDevice> GetRGBDevice(CorsairRGBDeviceInfo info, int i, _CorsairDeviceInfo nativeDeviceInfo, Dictionary<string, int> modelCounter)
protected override IEnumerable<IRGBDevice> LoadDevices()
{
switch (info.CorsairDeviceType)
Dictionary<string, int> modelCounter = new();
int deviceCount = _CUESDK.CorsairGetDeviceCount();
for (int i = 0; i < deviceCount; i++)
{
case CorsairDeviceType.Keyboard:
yield return new CorsairKeyboardRGBDevice(new CorsairKeyboardRGBDeviceInfo(i, nativeDeviceInfo, modelCounter));
break;
_CorsairDeviceInfo nativeDeviceInfo = (_CorsairDeviceInfo)Marshal.PtrToStructure(_CUESDK.CorsairGetDeviceInfo(i), typeof(_CorsairDeviceInfo))!;
CorsairRGBDeviceInfo info = new(i, RGBDeviceType.Unknown, nativeDeviceInfo, modelCounter);
if (!info.CapsMask.HasFlag(CorsairDeviceCaps.Lighting))
continue; // Everything that doesn't support lighting control is useless
case CorsairDeviceType.Mouse:
yield return new CorsairMouseRGBDevice(new CorsairMouseRGBDeviceInfo(i, nativeDeviceInfo, modelCounter));
break;
CorsairDeviceUpdateQueue updateQueue = new(GetUpdateTrigger(), info.CorsairDeviceIndex);
switch (info.CorsairDeviceType)
{
case CorsairDeviceType.Keyboard:
yield return new CorsairKeyboardRGBDevice(new CorsairKeyboardRGBDeviceInfo(i, nativeDeviceInfo, modelCounter), updateQueue);
break;
case CorsairDeviceType.Headset:
yield return new CorsairHeadsetRGBDevice(new CorsairHeadsetRGBDeviceInfo(i, nativeDeviceInfo, modelCounter));
break;
case CorsairDeviceType.Mouse:
yield return new CorsairMouseRGBDevice(new CorsairMouseRGBDeviceInfo(i, nativeDeviceInfo, modelCounter), updateQueue);
break;
case CorsairDeviceType.Mousepad:
yield return new CorsairMousepadRGBDevice(new CorsairMousepadRGBDeviceInfo(i, nativeDeviceInfo, modelCounter));
break;
case CorsairDeviceType.Headset:
yield return new CorsairHeadsetRGBDevice(new CorsairHeadsetRGBDeviceInfo(i, nativeDeviceInfo, modelCounter), updateQueue);
break;
case CorsairDeviceType.HeadsetStand:
yield return new CorsairHeadsetStandRGBDevice(new CorsairHeadsetStandRGBDeviceInfo(i, nativeDeviceInfo, modelCounter));
break;
case CorsairDeviceType.Mousepad:
yield return new CorsairMousepadRGBDevice(new CorsairMousepadRGBDeviceInfo(i, nativeDeviceInfo, modelCounter), updateQueue);
break;
case CorsairDeviceType.MemoryModule:
yield return new CorsairMemoryRGBDevice(new CorsairMemoryRGBDeviceInfo(i, nativeDeviceInfo, modelCounter));
break;
case CorsairDeviceType.HeadsetStand:
yield return new CorsairHeadsetStandRGBDevice(new CorsairHeadsetStandRGBDeviceInfo(i, nativeDeviceInfo, modelCounter), updateQueue);
break;
case CorsairDeviceType.Cooler:
case CorsairDeviceType.CommanderPro:
case CorsairDeviceType.LightningNodePro:
_CorsairChannelsInfo? channelsInfo = nativeDeviceInfo.channels;
if (channelsInfo != null)
{
IntPtr channelInfoPtr = channelsInfo.channels;
case CorsairDeviceType.MemoryModule:
yield return new CorsairMemoryRGBDevice(new CorsairMemoryRGBDeviceInfo(i, nativeDeviceInfo, modelCounter), updateQueue);
break;
for (int channel = 0; channel < channelsInfo.channelsCount; channel++)
case CorsairDeviceType.Cooler:
case CorsairDeviceType.CommanderPro:
case CorsairDeviceType.LightningNodePro:
_CorsairChannelsInfo? channelsInfo = nativeDeviceInfo.channels;
if (channelsInfo != null)
{
CorsairLedId referenceLed = GetChannelReferenceId(info.CorsairDeviceType, channel);
if (referenceLed == CorsairLedId.Invalid) continue;
IntPtr channelInfoPtr = channelsInfo.channels;
_CorsairChannelInfo channelInfo = (_CorsairChannelInfo)Marshal.PtrToStructure(channelInfoPtr, typeof(_CorsairChannelInfo))!;
int channelDeviceInfoStructSize = Marshal.SizeOf(typeof(_CorsairChannelDeviceInfo));
IntPtr channelDeviceInfoPtr = channelInfo.devices;
for (int device = 0; device < channelInfo.devicesCount; device++)
for (int channel = 0; channel < channelsInfo.channelsCount; channel++)
{
_CorsairChannelDeviceInfo channelDeviceInfo = (_CorsairChannelDeviceInfo)Marshal.PtrToStructure(channelDeviceInfoPtr, typeof(_CorsairChannelDeviceInfo))!;
CorsairLedId referenceLed = GetChannelReferenceId(info.CorsairDeviceType, channel);
if (referenceLed == CorsairLedId.Invalid) continue;
yield return new CorsairCustomRGBDevice(new CorsairCustomRGBDeviceInfo(info, nativeDeviceInfo, channelDeviceInfo, referenceLed, modelCounter));
referenceLed += channelDeviceInfo.deviceLedCount;
_CorsairChannelInfo channelInfo = (_CorsairChannelInfo)Marshal.PtrToStructure(channelInfoPtr, typeof(_CorsairChannelInfo))!;
channelDeviceInfoPtr = new IntPtr(channelDeviceInfoPtr.ToInt64() + channelDeviceInfoStructSize);
int channelDeviceInfoStructSize = Marshal.SizeOf(typeof(_CorsairChannelDeviceInfo));
IntPtr channelDeviceInfoPtr = channelInfo.devices;
for (int device = 0; device < channelInfo.devicesCount; device++)
{
_CorsairChannelDeviceInfo channelDeviceInfo = (_CorsairChannelDeviceInfo)Marshal.PtrToStructure(channelDeviceInfoPtr, typeof(_CorsairChannelDeviceInfo))!;
yield return new CorsairCustomRGBDevice(new CorsairCustomRGBDeviceInfo(info, nativeDeviceInfo, channelDeviceInfo, referenceLed, modelCounter), updateQueue);
referenceLed += channelDeviceInfo.deviceLedCount;
channelDeviceInfoPtr = new IntPtr(channelDeviceInfoPtr.ToInt64() + channelDeviceInfoStructSize);
}
int channelInfoStructSize = Marshal.SizeOf(typeof(_CorsairChannelInfo));
channelInfoPtr = new IntPtr(channelInfoPtr.ToInt64() + channelInfoStructSize);
}
int channelInfoStructSize = Marshal.SizeOf(typeof(_CorsairChannelInfo));
channelInfoPtr = new IntPtr(channelInfoPtr.ToInt64() + channelInfoStructSize);
}
}
break;
break;
// ReSharper disable once RedundantCaseLabel
case CorsairDeviceType.Unknown:
default:
throw new RGBDeviceException("Unknown Device-Type");
default:
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;
Devices = Enumerable.Empty<IRGBDevice>();
IsInitialized = false;
base.Reset();
}
/// <inheritdoc />
public void Dispose()
public override 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>();
base.Dispose();
try { _CUESDK.UnloadCUESDK(); }
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.
/// </summary>
/// <param name="info">The specific information provided by CUE for the custom-device.</param>
internal CorsairCustomRGBDevice(CorsairCustomRGBDeviceInfo info)
: base(info)
{ }
internal CorsairCustomRGBDevice(CorsairCustomRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
: base(info, updateQueue)
{
InitializeLayout();
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout()
private void InitializeLayout()
{
LedId referenceId = GetReferenceLed(DeviceInfo.DeviceType);
@ -45,7 +46,7 @@ namespace RGB.NET.Devices.Corsair
AddLed(ledId, new Point(i * 10, 0), new Size(10, 10));
}
}
protected override object GetLedCustomData(LedId ledId) => _idMapping.TryGetValue(ledId, out CorsairLedId id) ? id : CorsairLedId.Invalid;
protected virtual LedId GetReferenceLed(RGBDeviceType deviceType)

View File

@ -1,99 +1,23 @@
using System.Collections.Generic;
using System.Linq;
using RGB.NET.Core;
using RGB.NET.Core;
namespace RGB.NET.Devices.Corsair
{
/// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}" />
/// <inheritdoc cref="ICorsairRGBDevice" />
/// <summary>
/// Represents a generic CUE-device. (keyboard, mouse, headset, mousepad).
/// </summary>
public abstract class CorsairRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, ICorsairRGBDevice
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
/// <summary>
/// Initializes a new instance of the <see cref="CorsairRGBDevice{TDeviceInfo}"/> class.
/// </summary>
/// <param name="info">The generic information provided by CUE for the device.</param>
protected CorsairRGBDevice(TDeviceInfo info)
{
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();
}
protected CorsairRGBDevice(TDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
: base(info, updateQueue)
{ }
#endregion
}

View File

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

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.
/// </summary>
/// <param name="info">The specific information provided by CUE for the headset</param>
internal CorsairHeadsetRGBDevice(CorsairHeadsetRGBDeviceInfo info)
: base(info)
{ }
internal CorsairHeadsetRGBDevice(CorsairHeadsetRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
: base(info, updateQueue)
{
InitializeLayout();
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout()
private void InitializeLayout()
{
AddLed(LedId.Headset1, new Point(0, 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.
/// </summary>
/// <param name="info">The specific information provided by CUE for the headset stand</param>
internal CorsairHeadsetStandRGBDevice(CorsairHeadsetStandRGBDeviceInfo info)
: base(info)
{ }
internal CorsairHeadsetStandRGBDevice(CorsairHeadsetStandRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
: base(info, updateQueue)
{
InitializeLayout();
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout()
private void InitializeLayout()
{
_CorsairLedPositions? nativeLedPositions = (_CorsairLedPositions?)Marshal.PtrToStructure(_CUESDK.CorsairGetLedPositionsByDeviceIndex(DeviceInfo.CorsairDeviceIndex), typeof(_CorsairLedPositions));
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.
/// </summary>
/// <param name="info">The specific information provided by CUE for the keyboard</param>
internal CorsairKeyboardRGBDevice(CorsairKeyboardRGBDeviceInfo info)
: base(info)
{ }
internal CorsairKeyboardRGBDevice(CorsairKeyboardRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
: base(info, updateQueue)
{
InitializeLayout();
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout()
private void InitializeLayout()
{
_CorsairLedPositions? nativeLedPositions = (_CorsairLedPositions?)Marshal.PtrToStructure(_CUESDK.CorsairGetLedPositionsByDeviceIndex(DeviceInfo.CorsairDeviceIndex), typeof(_CorsairLedPositions));
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.
/// </summary>
/// <param name="info">The specific information provided by CUE for the memory.</param>
internal CorsairMemoryRGBDevice(CorsairMemoryRGBDeviceInfo info)
: base(info)
{ }
internal CorsairMemoryRGBDevice(CorsairMemoryRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
: base(info, updateQueue)
{
InitializeLayout();
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout()
private void InitializeLayout()
{
_CorsairLedPositions? nativeLedPositions = (_CorsairLedPositions?)Marshal.PtrToStructure(_CUESDK.CorsairGetLedPositionsByDeviceIndex(DeviceInfo.CorsairDeviceIndex), typeof(_CorsairLedPositions));
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.
/// </summary>
/// <param name="info">The specific information provided by CUE for the mouse</param>
internal CorsairMouseRGBDevice(CorsairMouseRGBDeviceInfo info)
: base(info)
{ }
internal CorsairMouseRGBDevice(CorsairMouseRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
: base(info, updateQueue)
{
InitializeLayout();
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout()
private void InitializeLayout()
{
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.
/// </summary>
/// <param name="info">The specific information provided by CUE for the mousepad</param>
internal CorsairMousepadRGBDevice(CorsairMousepadRGBDeviceInfo info)
: base(info)
{ }
internal CorsairMousepadRGBDevice(CorsairMousepadRGBDeviceInfo info, CorsairDeviceUpdateQueue updateQueue)
: base(info, updateQueue)
{
InitializeLayout();
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout()
private void InitializeLayout()
{
_CorsairLedPositions? nativeLedPositions = (_CorsairLedPositions?)Marshal.PtrToStructure(_CUESDK.CorsairGetLedPositionsByDeviceIndex(DeviceInfo.CorsairDeviceIndex), typeof(_CorsairLedPositions));
if (nativeLedPositions == null) return;

View File

@ -3,8 +3,6 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using RGB.NET.Core;
using RGB.NET.Devices.DMX.E131;
@ -14,7 +12,7 @@ namespace RGB.NET.Devices.DMX
/// <summary>
/// Represents a device provider responsible for DMX devices.
/// </summary>
public class DMXDeviceProvider : IRGBDeviceProvider
public class DMXDeviceProvider : AbstractRGBDeviceProvider
{
#region Properties & Fields
@ -24,22 +22,11 @@ namespace RGB.NET.Devices.DMX
/// </summary>
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>
/// Gets a list of all defined device-definitions.
/// </summary>
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
#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)}");
_instance = this;
UpdateTrigger = new DeviceUpdateTrigger();
}
#endregion
@ -66,58 +51,27 @@ namespace RGB.NET.Devices.DMX
/// <param name="deviceDefinition">The <see cref="IDMXDeviceDefinition"/> to add.</param>
public void AddDeviceDefinition(IDMXDeviceDefinition deviceDefinition) => DeviceDefinitions.Add(deviceDefinition);
/// <inheritdoc />
public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false)
protected override void InitializeSDK() { }
protected override IEnumerable<IRGBDevice> LoadDevices()
{
IsInitialized = false;
try
foreach (IDMXDeviceDefinition dmxDeviceDefinition in DeviceDefinitions)
{
UpdateTrigger.Stop();
IList<IRGBDevice> devices = new List<IRGBDevice>();
foreach (IDMXDeviceDefinition dmxDeviceDefinition in DeviceDefinitions)
IRGBDevice? device = null;
try
{
try
{
if (dmxDeviceDefinition is E131DMXDeviceDefinition e131DMXDeviceDefinition)
{
if (e131DMXDeviceDefinition.Leds.Count > 0)
{
E131Device device = new(new E131DeviceInfo(e131DMXDeviceDefinition), e131DMXDeviceDefinition.Leds);
device.Initialize(UpdateTrigger);
devices.Add(device);
}
}
}
catch { if (throwExceptions) throw; }
if (dmxDeviceDefinition is E131DMXDeviceDefinition e131DMXDeviceDefinition)
if (e131DMXDeviceDefinition.Leds.Count > 0)
device = new E131Device(new E131DeviceInfo(e131DMXDeviceDefinition), e131DMXDeviceDefinition.Leds, GetUpdateTrigger(0));
}
catch (Exception ex)
{
Throw(ex);
}
UpdateTrigger.Start();
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
IsInitialized = true;
if (device != null)
yield return device;
}
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

View File

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using RGB.NET.Core;
namespace RGB.NET.Devices.DMX.E131
@ -12,55 +11,39 @@ namespace RGB.NET.Devices.DMX.E131
{
#region Properties & Fields
/// <inheritdoc />
public override E131DeviceInfo DeviceInfo { get; }
private readonly Dictionary<LedId, List<(int channel, Func<Color, byte> getValueFunc)>> _ledMappings;
private E131UpdateQueue? _updateQueue;
#endregion
#region Constructors
/// <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;
InitializeLayout();
E131UpdateQueue updateQueue = (E131UpdateQueue)UpdateQueue;
updateQueue.DataPacket.SetCID(DeviceInfo.CID);
updateQueue.DataPacket.SetUniverse(DeviceInfo.Universe);
}
#endregion
#region Methods
internal void Initialize(IDeviceUpdateTrigger updateTrigger)
private void InitializeLayout()
{
int count = 0;
foreach (LedId id in _ledMappings.Keys)
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 />
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
}
}

View File

@ -3,8 +3,6 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using RGB.NET.Core;
using RGB.NET.Layout;
@ -14,7 +12,7 @@ namespace RGB.NET.Devices.Debug
/// <summary>
/// Represents a device provider responsible for debug devices.
/// </summary>
public class DebugDeviceProvider : IRGBDeviceProvider
public class DebugDeviceProvider : AbstractRGBDeviceProvider
{
#region Properties & Fields
@ -24,13 +22,7 @@ namespace RGB.NET.Devices.Debug
/// </summary>
public static DebugDeviceProvider Instance => _instance ?? new DebugDeviceProvider();
/// <inheritdoc />
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();
private List<(IDeviceLayout layout, Action<IEnumerable<Led>>? updateLedsAction)> _fakeDeviceDefinitions = new();
#endregion
@ -54,48 +46,28 @@ namespace RGB.NET.Devices.Debug
/// Adds a new fake device definition.
/// </summary>
/// <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>
public void AddFakeDeviceDefinition(IDeviceLayout layout, string imageLayout, Action<IEnumerable<Led>>? updateLedsAction = null)
=> _fakeDeviceDefinitions.Add((layout, imageLayout, updateLedsAction));
public void AddFakeDeviceDefinition(IDeviceLayout layout, Action<IEnumerable<Led>>? updateLedsAction = null)
=> _fakeDeviceDefinitions.Add((layout, updateLedsAction));
/// <summary>
/// Removes all previously added fake device definitions.
/// </summary>
public void ClearFakeDeviceDefinitions() => _fakeDeviceDefinitions.Clear();
/// <inheritdoc />
public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.Unknown, bool throwExceptions = false)
protected override void InitializeSDK() { }
protected override IEnumerable<IRGBDevice> LoadDevices()
{
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);
IsInitialized = true;
return true;
}
catch
{
if (throwExceptions) throw;
return false;
}
foreach ((IDeviceLayout layout, Action<IEnumerable<Led>>? updateLedsAction) in _fakeDeviceDefinitions)
yield return new DebugRGBDevice(layout, updateLedsAction);
}
/// <inheritdoc />
public void ResetDevices()
{ }
/// <inheritdoc />
public void Dispose()
public override void Dispose()
{
base.Dispose();
_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
/// <inheritdoc />
public override DebugRGBDeviceInfo DeviceInfo { get; }
public IDeviceLayout Layout { get; }
private Action<IEnumerable<Led>>? _updateLedsAction;
@ -27,12 +24,11 @@ namespace RGB.NET.Devices.Debug
/// Internal constructor of <see cref="DebugRGBDeviceInfo"/>.
/// </summary>
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._updateLedsAction = updateLedsAction;
DeviceInfo = new DebugRGBDeviceInfo(layout.Type, layout.Vendor ?? "RGB.NET", layout.Model ?? "Debug", layout.CustomData);
Layout.ApplyTo(this, true);
}

View File

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

View File

@ -3,60 +3,21 @@
namespace RGB.NET.Devices.Logitech
{
/// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}" />
/// <inheritdoc cref="ILogitechRGBDevice" />
/// <summary>
/// Represents a generic Logitech-device. (keyboard, mouse, headset, mousepad).
/// </summary>
public abstract class LogitechRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, ILogitechRGBDevice
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
/// <summary>
/// Initializes a new instance of the <see cref="LogitechRGBDevice{TDeviceInfo}"/> class.
/// </summary>
/// <param name="info">The generic information provided by Logitech for the device.</param>
protected LogitechRGBDevice(TDeviceInfo info)
{
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();
}
protected LogitechRGBDevice(TDeviceInfo info, IUpdateQueue updateQueue)
: base(info, updateQueue)
{ }
#endregion
}

View File

@ -3,8 +3,6 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using RGB.NET.Core;
using RGB.NET.Devices.Logitech.HID;
using RGB.NET.Devices.Logitech.Native;
@ -15,7 +13,7 @@ namespace RGB.NET.Devices.Logitech
/// <summary>
/// Represents a device provider responsible for logitech devices.
/// </summary>
public class LogitechDeviceProvider : IRGBDeviceProvider
public class LogitechDeviceProvider : AbstractRGBDeviceProvider
{
#region Properties & Fields
@ -37,21 +35,8 @@ namespace RGB.NET.Devices.Logitech
/// </summary>
public static List<string> PossibleX64NativePaths { get; } = new() { "x64/LogitechLedEnginesWrapper.dll" };
/// <inheritdoc />
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 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;
private LogitechPerDeviceUpdateQueue? _perDeviceUpdateQueue;
private LogitechPerKeyUpdateQueue? _perKeyUpdateQueue;
#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)}");
_instance = this;
UpdateTrigger = new DeviceUpdateTrigger();
_perDeviceUpdateQueue = new LogitechPerDeviceUpdateQueue(UpdateTrigger);
_perKeyUpdateQueue = new LogitechPerKeyUpdateQueue(UpdateTrigger);
}
#endregion
#region Methods
/// <inheritdoc />
public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false)
protected override void InitializeSDK()
{
try
_perDeviceUpdateQueue = new LogitechPerDeviceUpdateQueue(GetUpdateTrigger());
_perKeyUpdateQueue = new LogitechPerKeyUpdateQueue(GetUpdateTrigger());
_LogitechGSDK.Reload();
if (!_LogitechGSDK.LogiLedInit()) Throw(new RGBDeviceException("Failed to initialize Logitech-SDK."));
_LogitechGSDK.LogiLedSaveCurrentLighting();
}
//TODO DarthAffe 04.03.2021: Rework device selection and configuration for HID-based providers
protected override IEnumerable<IRGBDevice> LoadDevices()
{
DeviceChecker.LoadDeviceList();
if (DeviceChecker.IsPerKeyDeviceConnected && (_perKeyUpdateQueue != null))
{
if (IsInitialized)
_LogitechGSDK.LogiLedRestoreLighting();
}
catch { /* At least we tried ... */ }
IsInitialized = false;
try
{
UpdateTrigger.Stop();
_LogitechGSDK.Reload();
if (!_LogitechGSDK.LogiLedInit()) return false;
_LogitechGSDK.LogiLedSaveCurrentLighting();
IList<IRGBDevice> devices = new List<IRGBDevice>();
DeviceChecker.LoadDeviceList();
try
{
if (DeviceChecker.IsPerKeyDeviceConnected)
{
(string model, RGBDeviceType deviceType, int _, int _) = DeviceChecker.PerKeyDeviceData;
if (loadFilter.HasFlag(deviceType)) //TODO DarthAffe 07.12.2017: Check if it's worth to try another device if the one returned doesn't match the filter
{
ILogitechRGBDevice device = new LogitechPerKeyRGBDevice(new LogitechRGBDeviceInfo(deviceType, model, LogitechDeviceCaps.PerKeyRGB, 0));
device.Initialize(_perKeyUpdateQueue);
devices.Add(device);
}
}
}
catch { if (throwExceptions) throw; }
try
{
if (DeviceChecker.IsPerDeviceDeviceConnected)
{
(string model, RGBDeviceType deviceType, int _, int _) = DeviceChecker.PerDeviceDeviceData;
if (loadFilter.HasFlag(deviceType)) //TODO DarthAffe 07.12.2017: Check if it's worth to try another device if the one returned doesn't match the filter
{
ILogitechRGBDevice device = new LogitechPerDeviceRGBDevice(new LogitechRGBDeviceInfo(deviceType, model, LogitechDeviceCaps.DeviceRGB, 0));
device.Initialize(_perDeviceUpdateQueue);
devices.Add(device);
}
}
}
catch { if (throwExceptions) throw; }
try
{
if (DeviceChecker.IsZoneDeviceConnected)
{
foreach ((string model, RGBDeviceType deviceType, int _, int zones) in DeviceChecker.ZoneDeviceData)
try
{
if (loadFilter.HasFlag(deviceType))
{
LogitechZoneUpdateQueue updateQueue = new(UpdateTrigger, deviceType);
ILogitechRGBDevice device = new LogitechZoneRGBDevice(new LogitechRGBDeviceInfo(deviceType, model, LogitechDeviceCaps.DeviceRGB, zones));
device.Initialize(updateQueue);
devices.Add(device);
_zoneUpdateQueues.Add(deviceType, updateQueue);
}
}
catch { if (throwExceptions) throw; }
}
}
catch { if (throwExceptions) throw; }
UpdateTrigger.Start();
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
IsInitialized = true;
}
catch
{
if (throwExceptions)
throw;
return false;
(string model, RGBDeviceType deviceType, int _, int _) = DeviceChecker.PerKeyDeviceData;
yield return new LogitechPerKeyRGBDevice(new LogitechRGBDeviceInfo(deviceType, model, LogitechDeviceCaps.PerKeyRGB, 0), _perKeyUpdateQueue);
}
return true;
if (DeviceChecker.IsPerDeviceDeviceConnected && (_perDeviceUpdateQueue != null))
{
(string model, RGBDeviceType deviceType, int _, int _) = DeviceChecker.PerDeviceDeviceData;
yield return new LogitechPerDeviceRGBDevice(new LogitechRGBDeviceInfo(deviceType, model, LogitechDeviceCaps.DeviceRGB, 0), _perDeviceUpdateQueue);
}
if (DeviceChecker.IsZoneDeviceConnected)
{
foreach ((string model, RGBDeviceType deviceType, int _, int zones) in DeviceChecker.ZoneDeviceData)
{
LogitechZoneUpdateQueue updateQueue = new(GetUpdateTrigger(), deviceType);
yield return new LogitechZoneRGBDevice(new LogitechRGBDeviceInfo(deviceType, model, LogitechDeviceCaps.DeviceRGB, zones), updateQueue);
}
}
}
/// <inheritdoc />
public void Dispose()
public override 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>();
base.Dispose();
try { _LogitechGSDK.LogiLedRestoreLighting(); }
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.
/// </summary>
/// <param name="info">The specific information provided by logitech for the per-device-lightable device</param>
internal LogitechPerDeviceRGBDevice(LogitechRGBDeviceInfo info)
: base(info)
{ }
internal LogitechPerDeviceRGBDevice(LogitechRGBDeviceInfo info, IUpdateQueue updateQueue)
: base(info, updateQueue)
{
InitializeLayout();
}
#endregion
#region Methods
/// <inheritdoc />
public override void Initialize(UpdateQueue updateQueue)
private void InitializeLayout()
{
base.Initialize(updateQueue);
AddLed(LedId.Custom1, new Point(0, 0), new Size(10, 10));
}
/// <inheritdoc />
protected override object GetLedCustomData(LedId ledId) => (ledId, LogitechLedId.DEVICE);
/// <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
}

View File

@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using RGB.NET.Core;
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.
/// </summary>
/// <param name="info">The specific information provided by logitech for the per-key-lightable device</param>
internal LogitechPerKeyRGBDevice(LogitechRGBDeviceInfo info)
: base(info)
internal LogitechPerKeyRGBDevice(LogitechRGBDeviceInfo info, IUpdateQueue updateQueue)
: base(info, updateQueue)
{ }
#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);
/// <inheritdoc />
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate));
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate));
#endregion
}

View File

@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using RGB.NET.Core;
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.
/// </summary>
/// <param name="info">The specific information provided by logitech for the zone-lightable device</param>
internal LogitechZoneRGBDevice(LogitechRGBDeviceInfo info)
: base(info)
internal LogitechZoneRGBDevice(LogitechRGBDeviceInfo info, IUpdateQueue updateQueue)
: base(info, updateQueue)
{
_baseLedId = BASE_LED_MAPPING.TryGetValue(info.DeviceType, out LedId id) ? id : LedId.Custom1;
InitializeLayout();
}
#endregion
#region Methods
/// <inheritdoc />
public override void Initialize(UpdateQueue updateQueue)
private void InitializeLayout()
{
base.Initialize(updateQueue);
for (int i = 0; i < DeviceInfo.Zones; i++)
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);
/// <inheritdoc />
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate));
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate));
#endregion
}

View File

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

View File

@ -1,75 +1,23 @@
using System.Collections.Generic;
using System.Linq;
using RGB.NET.Core;
using RGB.NET.Core;
namespace RGB.NET.Devices.Msi
{
/// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}" />
/// <inheritdoc cref="IMsiRGBDevice" />
/// <summary>
/// Represents a generic MSI-device. (keyboard, mouse, headset, mousepad).
/// </summary>
public abstract class MsiRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, IMsiRGBDevice
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
/// <summary>
/// Initializes a new instance of the <see cref="MsiRGBDevice{TDeviceInfo}"/> class.
/// </summary>
/// <param name="info">The generic information provided by MSI for the device.</param>
protected MsiRGBDevice(TDeviceInfo info)
{
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();
}
protected MsiRGBDevice(TDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info, new MsiDeviceUpdateQueue(updateTrigger, info.MsiDeviceType))
{ }
#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.
/// </summary>
/// <param name="info">The specific information provided by MSI for graphics cards.</param>
internal MsiGraphicsCardRGBDevice(MsiRGBDeviceInfo info)
: base(info)
{ }
internal MsiGraphicsCardRGBDevice(MsiRGBDeviceInfo info, int ledCount, IDeviceUpdateTrigger updateTrigger)
: base(info, updateTrigger)
{
InitializeLayout(ledCount);
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout(int ledCount)
private void InitializeLayout(int ledCount)
{
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.
/// </summary>
/// <param name="info">The specific information provided by MSI for the mainboard.</param>
internal MsiMainboardRGBDevice(MsiRGBDeviceInfo info)
: base(info)
{ }
internal MsiMainboardRGBDevice(MsiRGBDeviceInfo info, int ledCount, IDeviceUpdateTrigger updateTrigger)
: base(info, updateTrigger)
{
InitializeLayout(ledCount);
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout(int ledCount)
private void InitializeLayout(int ledCount)
{
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.
/// </summary>
/// <param name="info">The specific information provided by MSI for the mouse.</param>
internal MsiMouseRGBDevice(MsiRGBDeviceInfo info)
: base(info)
{ }
internal MsiMouseRGBDevice(MsiRGBDeviceInfo info, int ledCount, IDeviceUpdateTrigger updateTrigger)
: base(info, updateTrigger)
{
InitializeLayout(ledCount);
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout(int ledCount)
private void InitializeLayout(int ledCount)
{
for (int i = 0; i < ledCount; i++)
{

View File

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

View File

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

View File

@ -1,76 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using RGB.NET.Core;
namespace RGB.NET.Devices.Novation
{
/// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}" />
/// <inheritdoc cref="INovationRGBDevice" />
/// <summary>
/// Represents a generic Novation-device. (launchpad).
/// </summary>
public abstract class NovationRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, INovationRGBDevice
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
/// <summary>
/// Initializes a new instance of the <see cref="NovationRGBDevice{TDeviceInfo}"/> class.
/// </summary>
/// <param name="info">The generic information provided by Novation for the device.</param>
protected NovationRGBDevice(TDeviceInfo info)
{
this.DeviceInfo = info;
}
protected NovationRGBDevice(TDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info, GetUpdateQueue(updateTrigger, info))
{ }
#endregion
#region Methods
/// <summary>
/// Initializes the device.
/// </summary>
public void Initialize(IDeviceUpdateTrigger updateTrigger)
{
InitializeLayout();
UpdateQueue = DeviceInfo.ColorCapabilities switch
private static UpdateQueue GetUpdateQueue(IDeviceUpdateTrigger updateTrigger, TDeviceInfo info) =>
info.ColorCapabilities switch
{
NovationColorCapabilities.LimitedRG => new LimitedColorUpdateQueue(updateTrigger, DeviceInfo.DeviceId),
NovationColorCapabilities.RGB => new RGBColorUpdateQueue(updateTrigger, DeviceInfo.DeviceId),
NovationColorCapabilities.LimitedRG => new LimitedColorUpdateQueue(updateTrigger, info.DeviceId),
NovationColorCapabilities.RGB => new RGBColorUpdateQueue(updateTrigger, info.DeviceId),
_ => throw new ArgumentOutOfRangeException()
};
}
/// <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));
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate));
/// <summary>
/// Resets the <see cref="NovationRGBDevice{TDeviceInfo}"/> back to default.
/// </summary>
public virtual void Reset() => UpdateQueue?.Reset();
public virtual void Reset() => UpdateQueue.Reset();
/// <inheritdoc cref="IDisposable.Dispose" />
/// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}.Dispose" />
@ -78,9 +47,6 @@ namespace RGB.NET.Devices.Novation
{
Reset();
try { UpdateQueue?.Dispose(); }
catch { /* at least we tried */ }
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.
/// </summary>
/// <param name="info">The specific information provided by Novation for the launchpad</param>
internal NovationLaunchpadRGBDevice(NovationLaunchpadRGBDeviceInfo info)
: base(info)
{ }
internal NovationLaunchpadRGBDevice(NovationLaunchpadRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info, updateTrigger)
{
InitializeLayout();
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout()
private void InitializeLayout()
{
Dictionary<LedId, (byte mode, byte id, int x, int y)> mapping = GetDeviceMapping();

View File

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

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

View File

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

View File

@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using RGB.NET.Core;
namespace RGB.NET.Devices.Razer
@ -12,32 +11,15 @@ namespace RGB.NET.Devices.Razer
public abstract class RazerRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, IRazerRGBDevice
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
/// <summary>
/// Initializes a new instance of the <see cref="RazerRGBDevice{TDeviceInfo}"/> class.
/// </summary>
/// <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;
}
@ -45,35 +27,8 @@ namespace RGB.NET.Devices.Razer
#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 />
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate));
/// <summary>
/// Resets the device.
/// </summary>
public void Reset() => UpdateQueue?.Reset();
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate));
/// <inheritdoc />
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.
/// </summary>
/// <param name="info">The specific information provided by CUE for the headset.</param>
internal RazerHeadsetRGBDevice(RazerHeadsetRGBDeviceInfo info)
: base(info)
{ }
internal RazerHeadsetRGBDevice(RazerHeadsetRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info, new RazerHeadsetUpdateQueue(updateTrigger, info.DeviceId))
{
InitializeLayout();
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout()
private void InitializeLayout()
{
for (int i = 0; i < _Defines.HEADSET_MAX_LEDS; i++)
AddLed(LedId.Headset1 + i, new Point(i * 11, 0), new Size(10, 10));
@ -37,9 +38,6 @@ namespace RGB.NET.Devices.Razer
/// <inheritdoc />
protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Headset1;
/// <inheritdoc />
protected override RazerUpdateQueue CreateUpdateQueue(IDeviceUpdateTrigger updateTrigger) => new RazerHeadsetUpdateQueue(updateTrigger, DeviceInfo.DeviceId);
#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.
/// </summary>
/// <param name="info">The specific information provided by CUE for the keyboard.</param>
internal RazerKeyboardRGBDevice(RazerKeyboardRGBDeviceInfo info)
: base(info)
{ }
internal RazerKeyboardRGBDevice(RazerKeyboardRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info, new RazerKeyboardUpdateQueue(updateTrigger, info.DeviceId))
{
InitializeLayout();
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout()
private void InitializeLayout()
{
for (int i = 0; i < _Defines.KEYBOARD_MAX_ROW; i++)
for (int j = 0; j < _Defines.KEYBOARD_MAX_COLUMN; j++)
@ -44,9 +45,6 @@ namespace RGB.NET.Devices.Razer
/// <inheritdoc />
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
}
}

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.
/// </summary>
/// <param name="info">The specific information provided by CUE for the keypad.</param>
internal RazerKeypadRGBDevice(RazerKeypadRGBDeviceInfo info)
: base(info)
{ }
internal RazerKeypadRGBDevice(RazerKeypadRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info, new RazerKeypadUpdateQueue(updateTrigger, info.DeviceId))
{
InitializeLayout();
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout()
private void InitializeLayout()
{
for (int i = 0; i < _Defines.KEYPAD_MAX_ROW; i++)
for (int j = 0; j < _Defines.KEYPAD_MAX_COLUMN; j++)
@ -38,9 +39,6 @@ namespace RGB.NET.Devices.Razer
/// <inheritdoc />
protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Keypad1;
/// <inheritdoc />
protected override RazerUpdateQueue CreateUpdateQueue(IDeviceUpdateTrigger updateTrigger) => new RazerKeypadUpdateQueue(updateTrigger, DeviceInfo.DeviceId);
#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.
/// </summary>
/// <param name="info">The specific information provided by CUE for the mouse.</param>
internal RazerMouseRGBDevice(RazerMouseRGBDeviceInfo info)
: base(info)
{ }
internal RazerMouseRGBDevice(RazerMouseRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info, new RazerMouseUpdateQueue(updateTrigger, info.DeviceId))
{
InitializeLayout();
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout()
private void InitializeLayout()
{
for (int i = 0; i < _Defines.MOUSE_MAX_ROW; i++)
for (int j = 0; j < _Defines.MOUSE_MAX_COLUMN; j++)
@ -38,9 +39,6 @@ namespace RGB.NET.Devices.Razer
/// <inheritdoc />
protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Mouse1;
/// <inheritdoc />
protected override RazerUpdateQueue CreateUpdateQueue(IDeviceUpdateTrigger updateTrigger) => new RazerMouseUpdateQueue(updateTrigger, DeviceInfo.DeviceId);
#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.
/// </summary>
/// <param name="info">The specific information provided by CUE for the mousepad.</param>
internal RazerMousepadRGBDevice(RazerMousepadRGBDeviceInfo info)
: base(info)
{ }
internal RazerMousepadRGBDevice(RazerMousepadRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info, new RazerMousepadUpdateQueue(updateTrigger, info.DeviceId))
{
InitializeLayout();
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout()
private void InitializeLayout()
{
for (int i = 0; i < _Defines.MOUSEPAD_MAX_LEDS; i++)
AddLed(LedId.Mousepad1 + i, new Point(i * 11, 0), new Size(10, 10));
@ -36,10 +37,6 @@ namespace RGB.NET.Devices.Razer
/// <inheritdoc />
protected override object? GetLedCustomData(LedId ledId) => (int)ledId - (int)LedId.Mousepad1;
/// <inheritdoc />
protected override RazerUpdateQueue CreateUpdateQueue(IDeviceUpdateTrigger updateTrigger) => new RazerMousepadUpdateQueue(updateTrigger, DeviceInfo.DeviceId);
#endregion
}
}

View File

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

View File

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

View File

@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using RGB.NET.Core;
namespace RGB.NET.Devices.SteelSeries
@ -13,19 +12,7 @@ namespace RGB.NET.Devices.SteelSeries
{
#region Properties & Fields
private Dictionary<LedId, SteelSeriesLedId> _ledMapping = new();
/// <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; }
private readonly Dictionary<LedId, SteelSeriesLedId> _ledMapping;
#endregion
@ -35,34 +22,30 @@ namespace RGB.NET.Devices.SteelSeries
/// Initializes a new instance of the <see cref="SteelSeriesRGBDevice"/> class.
/// </summary>
/// <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
#region Methods
/// <summary>
/// Initializes the device.
/// </summary>
void ISteelSeriesRGBDevice.Initialize(UpdateQueue updateQueue, Dictionary<LedId, SteelSeriesLedId> ledMapping)
private void InitializeLayout()
{
_ledMapping = ledMapping;
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));
UpdateQueue = updateQueue;
}
/// <inheritdoc />
protected override object GetLedCustomData(LedId ledId) => _ledMapping[ledId];
/// <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()

View File

@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using RGB.NET.Core;
using RGB.NET.Devices.SteelSeries.API;
using RGB.NET.Devices.SteelSeries.HID;
@ -12,7 +10,7 @@ namespace RGB.NET.Devices.SteelSeries
/// <summary>
/// Represents a device provider responsible for SteelSeries- devices.
/// </summary>
public class SteelSeriesDeviceProvider : IRGBDeviceProvider
public class SteelSeriesDeviceProvider : AbstractRGBDeviceProvider
{
#region Properties & Fields
@ -22,20 +20,6 @@ namespace RGB.NET.Devices.SteelSeries
/// </summary>
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
#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)}");
_instance = this;
UpdateTrigger = new SteelSeriesDeviceUpdateTrigger();
}
#endregion
#region Methods
/// <inheritdoc />
public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false)
protected override void InitializeSDK()
{
try
{
IsInitialized = false;
UpdateTrigger.Stop();
if (!SteelSeriesSDK.IsInitialized)
SteelSeriesSDK.Initialize();
IList<IRGBDevice> devices = new List<IRGBDevice>();
DeviceChecker.LoadDeviceList(loadFilter);
try
{
foreach ((string model, RGBDeviceType deviceType, int _, SteelSeriesDeviceType steelSeriesDeviceType, Dictionary<LedId, SteelSeriesLedId> ledMapping) in DeviceChecker.ConnectedDevices)
{
ISteelSeriesRGBDevice device = new SteelSeriesRGBDevice(new SteelSeriesRGBDeviceInfo(deviceType, model, steelSeriesDeviceType));
string apiName = steelSeriesDeviceType.GetAPIName() ?? throw new RGBDeviceException($"Missing API-name for device {model}");
SteelSeriesDeviceUpdateQueue updateQueue = new(UpdateTrigger, apiName);
device.Initialize(updateQueue, ledMapping);
devices.Add(device);
}
}
catch { if (throwExceptions) throw; }
UpdateTrigger.Start();
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
IsInitialized = true;
}
catch
{
IsInitialized = false;
if (throwExceptions) throw;
return false;
}
return true;
if (!SteelSeriesSDK.IsInitialized)
SteelSeriesSDK.Initialize();
}
/// <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>();
protected override IEnumerable<IRGBDevice> GetLoadedDevices(RGBDeviceType loadFilter)
{
DeviceChecker.LoadDeviceList(loadFilter);
return base.GetLoadedDevices(loadFilter);
}
protected override IEnumerable<IRGBDevice> LoadDevices()
{
foreach ((string model, RGBDeviceType deviceType, int _, SteelSeriesDeviceType steelSeriesDeviceType, Dictionary<LedId, SteelSeriesLedId> ledMapping) in DeviceChecker.ConnectedDevices)
{
string? apiName = steelSeriesDeviceType.GetAPIName();
if (apiName == null)
Throw(new RGBDeviceException($"Missing API-name for device {model}"));
else
yield return new SteelSeriesRGBDevice(new SteelSeriesRGBDeviceInfo(deviceType, model, steelSeriesDeviceType), apiName, ledMapping, GetUpdateTrigger());
}
}
/// <inheritdoc />
public override void Dispose()
{
base.Dispose();
try { SteelSeriesSDK.Dispose(); }
catch { /* shit happens */ }

View File

@ -8,22 +8,12 @@ using RGB.NET.Core;
namespace RGB.NET.Devices.WS281X.Arduino
{
// ReSharper disable once InconsistentNaming
/// <inheritdoc />
/// <summary>
/// Represents an arduino WS2812 device.
/// </summary>
public class ArduinoWS2812USBDevice : AbstractRGBDevice<ArduinoWS2812USBDeviceInfo>, ILedStripe
{
#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>
/// Gets the channel (as defined in the arduino-sketch) this device is attached to.
/// </summary>
@ -39,18 +29,19 @@ namespace RGB.NET.Devices.WS281X.Arduino
/// <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="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;
InitializeLayout(ledCount);
}
#endregion
#region Methods
internal void Initialize(int ledCount)
private void InitializeLayout(int ledCount)
{
for (int i = 0; i < ledCount; i++)
AddLed(LedId.LedStripe1 + i, new Point(i * 10, 0), new Size(10, 10));
@ -65,15 +56,6 @@ namespace RGB.NET.Devices.WS281X.Arduino
/// <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
}
}

View File

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

View File

@ -2,13 +2,12 @@
// ReSharper disable UnusedMember.Global
using System.Collections.Generic;
using System.Linq;
using RGB.NET.Core;
namespace RGB.NET.Devices.WS281X.Bitwizard
{
// ReSharper disable once InconsistentNaming
/// <inheritdoc />
/// <inheritdoc cref="AbstractRGBDevice{T}" />
/// <summary>
/// Represents an bitwizard WS2812 USB device.
/// </summary>
@ -18,14 +17,6 @@ namespace RGB.NET.Devices.WS281X.Bitwizard
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
#region Constructors
@ -35,19 +26,18 @@ namespace RGB.NET.Devices.WS281X.Bitwizard
/// </summary>
/// <param name="deviceInfo">The update trigger used by this queue.</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;
InitializeLayout(ledCount);
}
#endregion
#region Methods
internal void Initialize(int ledCount)
private void InitializeLayout(int ledCount)
{
for (int i = 0; i < ledCount; i++)
AddLed(LedId.LedStripe1 + i, new Point(i * 10, 0), new Size(10, 10));
@ -59,15 +49,6 @@ namespace RGB.NET.Devices.WS281X.Bitwizard
/// <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
}
}

View File

@ -36,15 +36,7 @@ namespace RGB.NET.Devices.WS281X.Bitwizard
/// </summary>
public string? Name { get; set; }
/// <summary>
/// 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;
public List<(int pin, int stripLength)> Strips { get; } = new();
/// <summary>
/// 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.
/// </summary>
/// <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;
Strips.AddRange(strips);
}
/// <summary>
@ -70,9 +64,11 @@ namespace RGB.NET.Devices.WS281X.Bitwizard
/// </summary>
/// <param name="port">The name of the serial-port to connect to.</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);
Strips.AddRange(strips);
}
#endregion
@ -82,12 +78,13 @@ namespace RGB.NET.Devices.WS281X.Bitwizard
/// <inheritdoc />
public IEnumerable<IRGBDevice> CreateDevices(IDeviceUpdateTrigger updateTrigger)
{
BitwizardWS2812USBUpdateQueue queue = new(updateTrigger, SerialConnection);
string name = Name ?? $"Bitwizard WS2812 USB ({Port})";
int ledOffset = Pin * MaxStripLength;
BitwizardWS2812USBDevice device = new(new BitwizardWS2812USBDeviceInfo(name), queue, ledOffset);
device.Initialize(StripLength);
yield return device;
foreach ((int pin, int stripLength) in Strips)
{
BitwizardWS2812USBUpdateQueue queue = new(updateTrigger, SerialConnection);
string name = Name ?? $"Bitwizard WS2812 USB ({Port}) Pin {pin}";
int ledOffset = pin * MaxStripLength;
yield return new BitwizardWS2812USBDevice(new BitwizardWS2812USBDeviceInfo(name), queue, ledOffset, stripLength);
}
}
#endregion

View File

@ -16,14 +16,6 @@ namespace RGB.NET.Devices.WS281X.NodeMCU
{
#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>
/// Gets the channel (as defined in the NodeMCU-sketch) this device is attached to.
/// </summary>
@ -39,18 +31,19 @@ namespace RGB.NET.Devices.WS281X.NodeMCU
/// <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="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;
InitializeLayout(ledCount);
}
#endregion
#region Methods
internal void Initialize(int ledCount)
private void InitializeLayout(int ledCount)
{
for (int i = 0; i < ledCount; i++)
AddLed(LedId.LedStripe1 + i, new Point(i * 10, 0), new Size(10, 10));
@ -65,15 +58,6 @@ namespace RGB.NET.Devices.WS281X.NodeMCU
/// <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
}
}

View File

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

View File

@ -2,8 +2,6 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using RGB.NET.Core;
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.
/// </summary>
// ReSharper disable once InconsistentNaming
public class WS281XDeviceProvider : IRGBDeviceProvider
public class WS281XDeviceProvider : AbstractRGBDeviceProvider
{
#region Properties & Fields
@ -23,12 +21,6 @@ namespace RGB.NET.Devices.WS281X
/// </summary>
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>
/// Gets a list of all defined device-definitions.
/// </summary>
@ -36,11 +28,6 @@ namespace RGB.NET.Devices.WS281X
// ReSharper disable once ReturnTypeCanBeEnumerable.Global
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
#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)}");
_instance = this;
UpdateTrigger = new DeviceUpdateTrigger();
}
#endregion
@ -68,49 +53,23 @@ namespace RGB.NET.Devices.WS281X
// ReSharper disable once UnusedMember.Global
public void AddDeviceDefinition(IWS281XDeviceDefinition deviceDefinition) => DeviceDefinitions.Add(deviceDefinition);
/// <inheritdoc />
public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.Unknown, bool throwExceptions = false)
protected override void InitializeSDK() { }
protected override IEnumerable<IRGBDevice> LoadDevices()
{
IsInitialized = false;
try
int i = 0;
foreach (IWS281XDeviceDefinition deviceDefinition in DeviceDefinitions)
{
UpdateTrigger.Stop();
List<IRGBDevice> devices = new();
foreach (IWS281XDeviceDefinition deviceDefinition in DeviceDefinitions)
{
try
{
devices.AddRange(deviceDefinition.CreateDevices(UpdateTrigger));
}
catch { if (throwExceptions) throw; }
}
UpdateTrigger.Start();
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
IsInitialized = true;
IDeviceUpdateTrigger updateTrigger = GetUpdateTrigger(i++);
foreach (IRGBDevice device in deviceDefinition.CreateDevices(updateTrigger))
yield return device;
}
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>();
/// <inheritdoc />
public override void Dispose()
{
base.Dispose();
DeviceDefinitions.Clear();
}

View File

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

View File

@ -10,60 +10,15 @@ namespace RGB.NET.Devices.Wooting.Generic
public abstract class WootingRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, IWootingRGBDevice
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
/// <summary>
/// Initializes a new instance of the <see cref="WootingRGBDevice{TDeviceInfo}"/> class.
/// </summary>
/// <param name="info">The generic information provided by Wooting for the device.</param>
protected WootingRGBDevice(TDeviceInfo info)
{
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();
}
protected WootingRGBDevice(TDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info, new WootingUpdateQueue(updateTrigger))
{ }
#endregion
}

View File

@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using RGB.NET.Core;
using RGB.NET.Devices.Wooting.Enum;
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.
/// </summary>
/// <param name="info">The specific information provided by Wooting for the keyboard</param>
internal WootingKeyboardRGBDevice(WootingKeyboardRGBDeviceInfo info)
: base(info)
{ }
internal WootingKeyboardRGBDevice(WootingKeyboardRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger)
: base(info, updateTrigger)
{
InitializeLayout();
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout()
private void InitializeLayout()
{
//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];
@ -47,7 +47,7 @@ namespace RGB.NET.Devices.Wooting.Keyboard
protected override object GetLedCustomData(LedId ledId) => WootingKeyboardLedMappings.Mapping[DeviceInfo.DeviceIndex][WootingPhysicalKeyboardLayout.US][ledId];
/// <inheritdoc />
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue?.SetData(GetUpdateData(ledsToUpdate));
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate));
#endregion
}

View File

@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.InteropServices;
using RGB.NET.Core;
using RGB.NET.Devices.Wooting.Enum;
@ -15,7 +13,7 @@ namespace RGB.NET.Devices.Wooting
/// <summary>
/// Represents a device provider responsible for Wooting devices.
/// </summary>
public class WootingDeviceProvider : IRGBDeviceProvider
public class WootingDeviceProvider : AbstractRGBDeviceProvider
{
#region Properties & Fields
@ -37,20 +35,6 @@ namespace RGB.NET.Devices.Wooting
/// </summary>
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
#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>
public WootingDeviceProvider()
{
if (_instance != null)
throw new InvalidOperationException($"There can be only one instance of type {nameof(WootingDeviceProvider)}");
if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(WootingDeviceProvider)}");
_instance = this;
UpdateTrigger = new DeviceUpdateTrigger();
}
#endregion
#region Methods
/// <inheritdoc />
/// <exception cref="RGBDeviceException">Thrown if the SDK failed to initialize</exception>
public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false)
protected override void InitializeSDK()
{
IsInitialized = false;
_WootingSDK.Reload();
}
try
protected override IEnumerable<IRGBDevice> LoadDevices()
{
if (_WootingSDK.KeyboardConnected())
{
UpdateTrigger.Stop();
_WootingSDK.Reload();
IList<IRGBDevice> devices = new List<IRGBDevice>();
if (_WootingSDK.KeyboardConnected())
_WootingDeviceInfo nativeDeviceInfo = (_WootingDeviceInfo)Marshal.PtrToStructure(_WootingSDK.GetDeviceInfo(), typeof(_WootingDeviceInfo))!;
IWootingRGBDevice? device = nativeDeviceInfo.Model switch
{
_WootingDeviceInfo nativeDeviceInfo = (_WootingDeviceInfo)Marshal.PtrToStructure(_WootingSDK.GetDeviceInfo(), typeof(_WootingDeviceInfo))!;
IWootingRGBDevice device = nativeDeviceInfo.Model switch
{
"Wooting two" => new WootingKeyboardRGBDevice(new WootingKeyboardRGBDeviceInfo(WootingDevicesIndexes.WootingTwo)),
"Wooting one" => new WootingKeyboardRGBDevice(new WootingKeyboardRGBDeviceInfo(WootingDevicesIndexes.WootingOne)),
_ => throw new RGBDeviceException("No supported Wooting keyboard connected")
};
"Wooting two" => new WootingKeyboardRGBDevice(new WootingKeyboardRGBDeviceInfo(WootingDevicesIndexes.WootingTwo), GetUpdateTrigger()),
"Wooting one" => new WootingKeyboardRGBDevice(new WootingKeyboardRGBDeviceInfo(WootingDevicesIndexes.WootingOne), GetUpdateTrigger()),
_ => null
};
device.Initialize(UpdateTrigger);
devices.Add(device);
}
UpdateTrigger.Start();
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
IsInitialized = true;
if (device == null)
Throw(new RGBDeviceException("No supported Wooting keyboard connected"));
else
yield return device;
}
catch
{
if (throwExceptions) throw;
return false;
}
return true;
}
/// <inheritdoc />
public void Dispose()
public override 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>();
base.Dispose();
try { _WootingSDK.Close(); }
catch { /* Unlucky.. */ }