diff --git a/RGB.NET.Core/Devices/AbstractRGBDeviceProvider.cs b/RGB.NET.Core/Devices/AbstractRGBDeviceProvider.cs index ae66ca0..d61fcbb 100644 --- a/RGB.NET.Core/Devices/AbstractRGBDeviceProvider.cs +++ b/RGB.NET.Core/Devices/AbstractRGBDeviceProvider.cs @@ -178,7 +178,7 @@ public abstract class AbstractRGBDeviceProvider : IRGBDeviceProvider /// /// The exception to throw. /// Indicates if the exception is critical for device provider to work correctly. - protected virtual void Throw(Exception ex, bool isCritical = false) + public virtual void Throw(Exception ex, bool isCritical = false) { ExceptionEventArgs args = new(ex, isCritical, ThrowsExceptions); try { OnException(args); } catch { /* we don't want to throw due to bad event handlers */ } diff --git a/RGB.NET.Core/Devices/IRGBDeviceProvider.cs b/RGB.NET.Core/Devices/IRGBDeviceProvider.cs index 48edc4d..86f41e1 100644 --- a/RGB.NET.Core/Devices/IRGBDeviceProvider.cs +++ b/RGB.NET.Core/Devices/IRGBDeviceProvider.cs @@ -20,6 +20,10 @@ public interface IRGBDeviceProvider : IDisposable /// /// Indicates if exceptions in the device provider are thrown or silently ignored. /// + /// + /// This should only be set to true for debugging/development purposes. + /// Production code should use the -Event to handle exceptions. + /// bool ThrowsExceptions { get; } /// diff --git a/RGB.NET.Devices.Asus/Generic/AsusUpdateQueue.cs b/RGB.NET.Devices.Asus/Generic/AsusUpdateQueue.cs index 6de33fa..27f4f5b 100644 --- a/RGB.NET.Devices.Asus/Generic/AsusUpdateQueue.cs +++ b/RGB.NET.Devices.Asus/Generic/AsusUpdateQueue.cs @@ -89,8 +89,9 @@ public class AsusUpdateQueue : UpdateQueue Device.Apply(); } - catch - { /* "The server threw an exception." seems to be a thing here ... */ + catch (Exception ex) + { + AsusDeviceProvider.Instance.Throw(ex, true); } } diff --git a/RGB.NET.Devices.CoolerMaster/Generic/CoolerMasterUpdateQueue.cs b/RGB.NET.Devices.CoolerMaster/Generic/CoolerMasterUpdateQueue.cs index 6631eb1..07df7cc 100644 --- a/RGB.NET.Devices.CoolerMaster/Generic/CoolerMasterUpdateQueue.cs +++ b/RGB.NET.Devices.CoolerMaster/Generic/CoolerMasterUpdateQueue.cs @@ -39,13 +39,20 @@ public class CoolerMasterUpdateQueue : UpdateQueue /// protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { - foreach ((object key, Color color) in dataSet) + try { - (int row, int column) = ((int, int))key; - _deviceMatrix.KeyColor[row, column] = new _CoolerMasterKeyColor(color.GetR(), color.GetG(), color.GetB()); - } + foreach ((object key, Color color) in dataSet) + { + (int row, int column) = ((int, int))key; + _deviceMatrix.KeyColor[row, column] = new _CoolerMasterKeyColor(color.GetR(), color.GetG(), color.GetB()); + } - _CoolerMasterSDK.SetAllLedColor(_deviceMatrix, _deviceIndex); + _CoolerMasterSDK.SetAllLedColor(_deviceMatrix, _deviceIndex); + } + catch (Exception ex) + { + CoolerMasterDeviceProvider.Instance.Throw(ex, true); + } } #endregion diff --git a/RGB.NET.Devices.Corsair/CorsairDeviceProvider.cs b/RGB.NET.Devices.Corsair/CorsairDeviceProvider.cs index 08f692a..ac363b9 100644 --- a/RGB.NET.Devices.Corsair/CorsairDeviceProvider.cs +++ b/RGB.NET.Devices.Corsair/CorsairDeviceProvider.cs @@ -50,6 +50,26 @@ public class CorsairDeviceProvider : AbstractRGBDeviceProvider /// public CorsairSessionDetails SessionDetails { get; private set; } = new(); + private CorsairSessionState _sessionState = CorsairSessionState.Invalid; + public CorsairSessionState SessionState + { + get => _sessionState; + private set + { + _sessionState = value; + + try { SessionStateChanged?.Invoke(this, SessionState); } + catch { /* catch faulty event-handlers*/ } + } + } + + #endregion + + #region Events + + // ReSharper disable once UnassignedField.Global + public EventHandler? SessionStateChanged; + #endregion #region Constructors @@ -74,7 +94,7 @@ public class CorsairDeviceProvider : AbstractRGBDeviceProvider using ManualResetEventSlim waitEvent = new(false); - void OnSessionStateChanged(object? sender, CorsairSessionState state) + void OnInitializeSessionStateChanged(object? sender, CorsairSessionState state) { if (state == CorsairSessionState.Connected) // ReSharper disable once AccessToDisposedClosure @@ -84,6 +104,7 @@ public class CorsairDeviceProvider : AbstractRGBDeviceProvider try { _CUESDK.SessionStateChanged += OnSessionStateChanged; + _CUESDK.SessionStateChanged += OnInitializeSessionStateChanged; CorsairError errorCode = _CUESDK.CorsairConnect(); if (errorCode != CorsairError.Success) @@ -100,10 +121,12 @@ public class CorsairDeviceProvider : AbstractRGBDeviceProvider } finally { - _CUESDK.SessionStateChanged -= OnSessionStateChanged; + _CUESDK.SessionStateChanged -= OnInitializeSessionStateChanged; } } + private void OnSessionStateChanged(object? sender, CorsairSessionState state) => SessionState = state; + /// protected override IEnumerable LoadDevices() { @@ -129,7 +152,7 @@ public class CorsairDeviceProvider : AbstractRGBDeviceProvider Throw(new RGBDeviceException($"Failed to take control of device '{device.id}'. (ErrorCode: {error})")); CorsairDeviceUpdateQueue updateQueue = new(GetUpdateTrigger(), device); - + int channelLedCount = 0; for (int i = 0; i < device.channelCount; i++) { diff --git a/RGB.NET.Devices.Corsair/Generic/CorsairDeviceUpdateQueue.cs b/RGB.NET.Devices.Corsair/Generic/CorsairDeviceUpdateQueue.cs index 1d42dc2..2cc6b88 100644 --- a/RGB.NET.Devices.Corsair/Generic/CorsairDeviceUpdateQueue.cs +++ b/RGB.NET.Devices.Corsair/Generic/CorsairDeviceUpdateQueue.cs @@ -40,17 +40,24 @@ public class CorsairDeviceUpdateQueue : UpdateQueue /// protected override unsafe void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { - Span<_CorsairLedColor> colors = new((void*)_colorPtr, dataSet.Length); - for (int i = 0; i < colors.Length; i++) + try { - (object id, Color color) = dataSet[i]; - (byte a, byte r, byte g, byte b) = color.GetRGBBytes(); - colors[i] = new _CorsairLedColor((CorsairLedId)id, r, g, b, a); - } + Span<_CorsairLedColor> colors = new((void*)_colorPtr, dataSet.Length); + for (int i = 0; i < colors.Length; i++) + { + (object id, Color color) = dataSet[i]; + (byte a, byte r, byte g, byte b) = color.GetRGBBytes(); + colors[i] = new _CorsairLedColor((CorsairLedId)id, r, g, b, a); + } - CorsairError error = _CUESDK.CorsairSetLedColors(_device.id!, dataSet.Length, _colorPtr); - if (error != CorsairError.Success) - throw new RGBDeviceException($"Failed to update device '{_device.id}'. (ErrorCode: {error})"); + CorsairError error = _CUESDK.CorsairSetLedColors(_device.id!, dataSet.Length, _colorPtr); + if (error != CorsairError.Success) + throw new RGBDeviceException($"Failed to update device '{_device.id}'. (ErrorCode: {error})"); + } + catch (Exception ex) + { + CorsairDeviceProvider.Instance.Throw(ex, true); + } } /// diff --git a/RGB.NET.Devices.DMX/E131/E131UpdateQueue.cs b/RGB.NET.Devices.DMX/E131/E131UpdateQueue.cs index b1bffdb..4fc62e9 100644 --- a/RGB.NET.Devices.DMX/E131/E131UpdateQueue.cs +++ b/RGB.NET.Devices.DMX/E131/E131UpdateQueue.cs @@ -61,16 +61,23 @@ public class E131UpdateQueue : UpdateQueue /// protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { - DataPacket.SetSequenceNumber(GetNextSequenceNumber()); - - foreach ((object key, Color color) in dataSet) + try { - LedChannelMapping mapping = (LedChannelMapping)key; - foreach ((int channel, Func getValue) in mapping) - DataPacket.SetChannel(channel, getValue(color)); - } + DataPacket.SetSequenceNumber(GetNextSequenceNumber()); - _socket.Send(DataPacket, DataPacket.Length); + foreach ((object key, Color color) in dataSet) + { + LedChannelMapping mapping = (LedChannelMapping)key; + foreach ((int channel, Func getValue) in mapping) + DataPacket.SetChannel(channel, getValue(color)); + } + + _socket.Send(DataPacket, DataPacket.Length); + } + catch (Exception ex) + { + DMXDeviceProvider.Instance.Throw(ex, true); + } } /// diff --git a/RGB.NET.Devices.Logitech/PerDevice/LogitechPerDeviceUpdateQueue.cs b/RGB.NET.Devices.Logitech/PerDevice/LogitechPerDeviceUpdateQueue.cs index a3e8801..eede537 100644 --- a/RGB.NET.Devices.Logitech/PerDevice/LogitechPerDeviceUpdateQueue.cs +++ b/RGB.NET.Devices.Logitech/PerDevice/LogitechPerDeviceUpdateQueue.cs @@ -27,12 +27,19 @@ public class LogitechPerDeviceUpdateQueue : UpdateQueue /// protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { - Color color = dataSet[0].color; + try + { + Color color = dataSet[0].color; - _LogitechGSDK.LogiLedSetTargetDevice(LogitechDeviceCaps.DeviceRGB); - _LogitechGSDK.LogiLedSetLighting((int)Math.Round(color.R * 100), - (int)Math.Round(color.G * 100), - (int)Math.Round(color.B * 100)); + _LogitechGSDK.LogiLedSetTargetDevice(LogitechDeviceCaps.DeviceRGB); + _LogitechGSDK.LogiLedSetLighting((int)Math.Round(color.R * 100), + (int)Math.Round(color.G * 100), + (int)Math.Round(color.B * 100)); + } + catch (Exception ex) + { + LogitechDeviceProvider.Instance.Throw(ex, true); + } } #endregion diff --git a/RGB.NET.Devices.Logitech/PerKey/LogitechPerKeyUpdateQueue.cs b/RGB.NET.Devices.Logitech/PerKey/LogitechPerKeyUpdateQueue.cs index 3b75a3b..5c4efbb 100644 --- a/RGB.NET.Devices.Logitech/PerKey/LogitechPerKeyUpdateQueue.cs +++ b/RGB.NET.Devices.Logitech/PerKey/LogitechPerKeyUpdateQueue.cs @@ -27,16 +27,23 @@ public class LogitechPerKeyUpdateQueue : UpdateQueue /// protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { - _LogitechGSDK.LogiLedSetTargetDevice(LogitechDeviceCaps.PerKeyRGB); - - foreach ((object key, Color color) in dataSet) + try { - // These will be LogitechLedId but the SDK expects an int and doesn't care about invalid values - int keyName = (int)key; - _LogitechGSDK.LogiLedSetLightingForKeyWithKeyName(keyName, - (int)MathF.Round(color.R * 100), - (int)MathF.Round(color.G * 100), - (int)MathF.Round(color.B * 100)); + _LogitechGSDK.LogiLedSetTargetDevice(LogitechDeviceCaps.PerKeyRGB); + + foreach ((object key, Color color) in dataSet) + { + // These will be LogitechLedId but the SDK expects an int and doesn't care about invalid values + int keyName = (int)key; + _LogitechGSDK.LogiLedSetLightingForKeyWithKeyName(keyName, + (int)MathF.Round(color.R * 100), + (int)MathF.Round(color.G * 100), + (int)MathF.Round(color.B * 100)); + } + } + catch (Exception ex) + { + LogitechDeviceProvider.Instance.Throw(ex, true); } } diff --git a/RGB.NET.Devices.Msi/Generic/MsiDeviceUpdateQueue.cs b/RGB.NET.Devices.Msi/Generic/MsiDeviceUpdateQueue.cs index d503148..4a9acd5 100644 --- a/RGB.NET.Devices.Msi/Generic/MsiDeviceUpdateQueue.cs +++ b/RGB.NET.Devices.Msi/Generic/MsiDeviceUpdateQueue.cs @@ -36,8 +36,15 @@ public class MsiDeviceUpdateQueue : UpdateQueue /// protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { - foreach ((object key, Color color) in dataSet) - _MsiSDK.SetLedColor(_deviceType, (int)key, color.GetR(), color.GetG(), color.GetB()); + try + { + foreach ((object key, Color color) in dataSet) + _MsiSDK.SetLedColor(_deviceType, (int)key, color.GetR(), color.GetG(), color.GetB()); + } + catch (Exception ex) + { + MsiDeviceProvider.Instance.Throw(ex, true); + } } #endregion diff --git a/RGB.NET.Devices.Novation/Generic/MidiUpdateQueue.cs b/RGB.NET.Devices.Novation/Generic/MidiUpdateQueue.cs index dc21766..9a1af35 100644 --- a/RGB.NET.Devices.Novation/Generic/MidiUpdateQueue.cs +++ b/RGB.NET.Devices.Novation/Generic/MidiUpdateQueue.cs @@ -37,8 +37,15 @@ public abstract class MidiUpdateQueue : UpdateQueue /// protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { - foreach ((object key, Color color) in dataSet) - SendMessage(CreateMessage(key, color)); + try + { + foreach ((object key, Color color) in dataSet) + SendMessage(CreateMessage(key, color)); + } + catch (Exception ex) + { + NovationDeviceProvider.Instance.Throw(ex, true); + } } /// diff --git a/RGB.NET.Devices.OpenRGB/Generic/OpenRGBUpdateQueue.cs b/RGB.NET.Devices.OpenRGB/Generic/OpenRGBUpdateQueue.cs index aab78d4..b6c91b8 100644 --- a/RGB.NET.Devices.OpenRGB/Generic/OpenRGBUpdateQueue.cs +++ b/RGB.NET.Devices.OpenRGB/Generic/OpenRGBUpdateQueue.cs @@ -51,10 +51,17 @@ public class OpenRGBUpdateQueue : UpdateQueue /// protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { - foreach ((object key, Color color) in dataSet) - _colors[(int)key] = new OpenRGBColor(color.GetR(), color.GetG(), color.GetB()); + try + { + foreach ((object key, Color color) in dataSet) + _colors[(int)key] = new OpenRGBColor(color.GetR(), color.GetG(), color.GetB()); - _openRGB.UpdateLeds(_deviceid, _colors); + _openRGB.UpdateLeds(_deviceid, _colors); + } + catch (Exception ex) + { + OpenRGBDeviceProvider.Instance.Throw(ex, true); + } } #endregion diff --git a/RGB.NET.Devices.PicoPi/PicoPi/PicoPiBulkUpdateQueue.cs b/RGB.NET.Devices.PicoPi/PicoPi/PicoPiBulkUpdateQueue.cs index fa32893..4e0a096 100644 --- a/RGB.NET.Devices.PicoPi/PicoPi/PicoPiBulkUpdateQueue.cs +++ b/RGB.NET.Devices.PicoPi/PicoPi/PicoPiBulkUpdateQueue.cs @@ -46,20 +46,27 @@ public class PicoPiBulkUpdateQueue : UpdateQueue /// protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { - Span buffer = _dataBuffer; - foreach ((object key, Color color) in dataSet) + try { - int index = key as int? ?? -1; - if (index < 0) continue; + Span buffer = _dataBuffer; + foreach ((object key, Color color) in dataSet) + { + int index = key as int? ?? -1; + if (index < 0) continue; - (byte _, byte r, byte g, byte b) = color.GetRGBBytes(); - int offset = index * 3; - buffer[offset] = r; - buffer[offset + 1] = g; - buffer[offset + 2] = b; + (byte _, byte r, byte g, byte b) = color.GetRGBBytes(); + int offset = index * 3; + buffer[offset] = r; + buffer[offset + 1] = g; + buffer[offset + 2] = b; + } + + _sdk.SendBulkUpdate(buffer, _channel); + } + catch (Exception ex) + { + PicoPiDeviceProvider.Instance.Throw(ex, true); } - - _sdk.SendBulkUpdate(buffer, _channel); } #endregion diff --git a/RGB.NET.Devices.PicoPi/PicoPi/PicoPiHIDUpdateQueue.cs b/RGB.NET.Devices.PicoPi/PicoPi/PicoPiHIDUpdateQueue.cs index 8ee06a2..381d382 100644 --- a/RGB.NET.Devices.PicoPi/PicoPi/PicoPiHIDUpdateQueue.cs +++ b/RGB.NET.Devices.PicoPi/PicoPi/PicoPiHIDUpdateQueue.cs @@ -43,20 +43,27 @@ public class PicoPiHIDUpdateQueue : UpdateQueue /// protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { - Span buffer = _dataBuffer; - foreach ((object key, Color color) in dataSet) + try { - int index = key as int? ?? -1; - if (index < 0) continue; + Span buffer = _dataBuffer; + foreach ((object key, Color color) in dataSet) + { + int index = key as int? ?? -1; + if (index < 0) continue; - (byte _, byte r, byte g, byte b) = color.GetRGBBytes(); - int offset = index * 3; - buffer[offset] = r; - buffer[offset + 1] = g; - buffer[offset + 2] = b; + (byte _, byte r, byte g, byte b) = color.GetRGBBytes(); + int offset = index * 3; + buffer[offset] = r; + buffer[offset + 1] = g; + buffer[offset + 2] = b; + } + + _sdk.SendHidUpdate(buffer, _channel); + } + catch (Exception ex) + { + PicoPiDeviceProvider.Instance.Throw(ex, true); } - - _sdk.SendHidUpdate(buffer, _channel); } #endregion diff --git a/RGB.NET.Devices.Razer/Generic/RazerUpdateQueue.cs b/RGB.NET.Devices.Razer/Generic/RazerUpdateQueue.cs index cc8fedc..33f8d32 100644 --- a/RGB.NET.Devices.Razer/Generic/RazerUpdateQueue.cs +++ b/RGB.NET.Devices.Razer/Generic/RazerUpdateQueue.cs @@ -10,7 +10,7 @@ namespace RGB.NET.Devices.Razer; public abstract class RazerUpdateQueue : UpdateQueue { #region Properties & Fields - + private Guid? _lastEffect; #endregion @@ -23,8 +23,7 @@ public abstract class RazerUpdateQueue : UpdateQueue /// The update trigger used to update this queue. protected RazerUpdateQueue(IDeviceUpdateTrigger updateTrigger) : base(updateTrigger) - { - } + { } #endregion @@ -33,16 +32,23 @@ public abstract class RazerUpdateQueue : UpdateQueue /// protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { - IntPtr effectParams = CreateEffectParams(dataSet); - Guid effectId = Guid.NewGuid(); - CreateEffect(effectParams, ref effectId); + try + { + IntPtr effectParams = CreateEffectParams(dataSet); + Guid effectId = Guid.NewGuid(); + CreateEffect(effectParams, ref effectId); - _RazerSDK.SetEffect(effectId); + _RazerSDK.SetEffect(effectId); - if (_lastEffect.HasValue) - _RazerSDK.DeleteEffect(_lastEffect.Value); + if (_lastEffect.HasValue) + _RazerSDK.DeleteEffect(_lastEffect.Value); - _lastEffect = effectId; + _lastEffect = effectId; + } + catch (Exception ex) + { + RazerDeviceProvider.Instance.Throw(ex, true); + } } /// diff --git a/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesDeviceUpdateQueue.cs b/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesDeviceUpdateQueue.cs index 67c39a4..d5b0c2a 100644 --- a/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesDeviceUpdateQueue.cs +++ b/RGB.NET.Devices.SteelSeries/Generic/SteelSeriesDeviceUpdateQueue.cs @@ -37,10 +37,17 @@ internal class SteelSeriesDeviceUpdateQueue : UpdateQueue protected override void OnUpdate(object? sender, CustomUpdateData customData) { - if (customData[CustomUpdateDataIndex.HEARTBEAT] as bool? ?? false) - SteelSeriesSDK.SendHeartbeat(); - else - base.OnUpdate(sender, customData); + try + { + if (customData[CustomUpdateDataIndex.HEARTBEAT] as bool? ?? false) + SteelSeriesSDK.SendHeartbeat(); + else + base.OnUpdate(sender, customData); + } + catch (Exception ex) + { + SteelSeriesDeviceProvider.Instance.Throw(ex, true); + } } /// diff --git a/RGB.NET.Devices.WS281X/Generic/SerialPortUpdateQueue.cs b/RGB.NET.Devices.WS281X/Generic/SerialPortUpdateQueue.cs index cdd1075..78dab04 100644 --- a/RGB.NET.Devices.WS281X/Generic/SerialPortUpdateQueue.cs +++ b/RGB.NET.Devices.WS281X/Generic/SerialPortUpdateQueue.cs @@ -58,10 +58,17 @@ public abstract class SerialConnectionUpdateQueue : UpdateQueue /// protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { - foreach (TData command in GetCommands(dataSet.ToArray())) + try { - SerialConnection.ReadTo(Prompt); - SendCommand(command); + foreach (TData command in GetCommands(dataSet.ToArray())) + { + SerialConnection.ReadTo(Prompt); + SendCommand(command); + } + } + catch (Exception ex) + { + WS281XDeviceProvider.Instance.Throw(ex, true); } } diff --git a/RGB.NET.Devices.Wooting/Generic/WootingUpdateQueue.cs b/RGB.NET.Devices.Wooting/Generic/WootingUpdateQueue.cs index a9d6f54..7e6ae67 100644 --- a/RGB.NET.Devices.Wooting/Generic/WootingUpdateQueue.cs +++ b/RGB.NET.Devices.Wooting/Generic/WootingUpdateQueue.cs @@ -13,7 +13,7 @@ public class WootingUpdateQueue : UpdateQueue #region Properties & Fields private readonly byte _deviceid; #endregion - + #region Constructors /// @@ -33,17 +33,24 @@ public class WootingUpdateQueue : UpdateQueue /// protected override void Update(in ReadOnlySpan<(object key, Color color)> dataSet) { - lock (_WootingSDK.SdkLock) + try { - _WootingSDK.SelectDevice(_deviceid); - - foreach ((object key, Color color) in dataSet) + lock (_WootingSDK.SdkLock) { - (int row, int column) = ((int, int))key; - _WootingSDK.ArraySetSingle((byte)row, (byte)column, color.GetR(), color.GetG(), color.GetB()); - } + _WootingSDK.SelectDevice(_deviceid); - _WootingSDK.ArrayUpdateKeyboard(); + foreach ((object key, Color color) in dataSet) + { + (int row, int column) = ((int, int))key; + _WootingSDK.ArraySetSingle((byte)row, (byte)column, color.GetR(), color.GetG(), color.GetB()); + } + + _WootingSDK.ArrayUpdateKeyboard(); + } + } + catch (Exception ex) + { + WootingDeviceProvider.Instance.Throw(ex, true); } }