diff --git a/RGB.NET.Core/Devices/AbstractRGBDevice.cs b/RGB.NET.Core/Devices/AbstractRGBDevice.cs
index 7046139..cf47142 100644
--- a/RGB.NET.Core/Devices/AbstractRGBDevice.cs
+++ b/RGB.NET.Core/Devices/AbstractRGBDevice.cs
@@ -34,7 +34,7 @@ namespace RGB.NET.Core
}
///
- public abstract TDeviceInfo DeviceInfo { get; }
+ public TDeviceInfo DeviceInfo { get; }
///
IRGBDeviceInfo IRGBDevice.DeviceInfo => DeviceInfo;
@@ -52,6 +52,8 @@ namespace RGB.NET.Core
///
protected Dictionary LedMapping { get; } = new();
+ protected IUpdateQueue UpdateQueue { get; }
+
#region Indexer
///
@@ -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
///
@@ -112,14 +124,16 @@ namespace RGB.NET.Core
}
}
+ ///
+ /// Sends all the updated to the device.
+ ///
+ protected virtual void UpdateLeds(IEnumerable ledsToUpdate) => UpdateQueue.SetData(GetUpdateData(ledsToUpdate));
+
///
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 */ }
}
///
@@ -128,11 +142,6 @@ namespace RGB.NET.Core
protected virtual void DeviceUpdate()
{ }
- ///
- /// Sends all the updated to the device.
- ///
- protected abstract void UpdateLeds(IEnumerable ledsToUpdate);
-
///
/// Initializes the with the specified id.
///
diff --git a/RGB.NET.Core/Devices/AbstractRGBDeviceProvider.cs b/RGB.NET.Core/Devices/AbstractRGBDeviceProvider.cs
new file mode 100644
index 0000000..7f0c4ef
--- /dev/null
+++ b/RGB.NET.Core/Devices/AbstractRGBDeviceProvider.cs
@@ -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 Devices { get; protected set; } = Enumerable.Empty();
+
+ protected Dictionary UpdateTriggers { get; } = new();
+
+ #endregion
+
+ #region Events
+
+ public event EventHandler? 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(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 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 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();
+ 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 devices = Devices;
+ Reset();
+ foreach (IRGBDevice device in devices)
+ device.Dispose();
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Core/Devices/IRGBDevice.cs b/RGB.NET.Core/Devices/IRGBDevice.cs
index 0ad1dc7..983d54d 100644
--- a/RGB.NET.Core/Devices/IRGBDevice.cs
+++ b/RGB.NET.Core/Devices/IRGBDevice.cs
@@ -19,7 +19,7 @@ namespace RGB.NET.Core
/// Gets generic information about the .
///
IRGBDeviceInfo DeviceInfo { get; }
-
+
IList ColorCorrections { get; }
#endregion
diff --git a/RGB.NET.Core/Devices/IRGBDeviceProvider.cs b/RGB.NET.Core/Devices/IRGBDeviceProvider.cs
index 6060feb..afa4ab0 100644
--- a/RGB.NET.Core/Devices/IRGBDeviceProvider.cs
+++ b/RGB.NET.Core/Devices/IRGBDeviceProvider.cs
@@ -22,6 +22,15 @@ namespace RGB.NET.Core
#endregion
+ #region Events
+
+ ///
+ /// Occurs when an exception is thrown in the device provider
+ ///
+ event EventHandler? Exception;
+
+ #endregion
+
#region Methods
bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool throwExceptions = false);
diff --git a/RGB.NET.Core/Update/AbstractUpdateTrigger.cs b/RGB.NET.Core/Update/AbstractUpdateTrigger.cs
index 722c30e..3d754fd 100644
--- a/RGB.NET.Core/Update/AbstractUpdateTrigger.cs
+++ b/RGB.NET.Core/Update/AbstractUpdateTrigger.cs
@@ -30,6 +30,9 @@ namespace RGB.NET.Core
/// Optional custom-data passed to the subscribers of the .event.
protected virtual void OnUpdate(CustomUpdateData? updateData = null) => Update?.Invoke(this, updateData ?? new CustomUpdateData());
+ ///
+ public abstract void Start();
+
///
public abstract void Dispose();
diff --git a/RGB.NET.Core/Update/Devices/DeviceUpdateTrigger.cs b/RGB.NET.Core/Update/Devices/DeviceUpdateTrigger.cs
index 43caf4c..61e85a3 100644
--- a/RGB.NET.Core/Update/Devices/DeviceUpdateTrigger.cs
+++ b/RGB.NET.Core/Update/Devices/DeviceUpdateTrigger.cs
@@ -86,7 +86,7 @@ namespace RGB.NET.Core
///
/// Starts the trigger.
///
- public void Start()
+ public override void Start()
{
if (IsRunning) return;
diff --git a/RGB.NET.Core/Update/Devices/IUpdateQueue.cs b/RGB.NET.Core/Update/Devices/IUpdateQueue.cs
new file mode 100644
index 0000000..0fbcd7a
--- /dev/null
+++ b/RGB.NET.Core/Update/Devices/IUpdateQueue.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+
+namespace RGB.NET.Core
+{
+ public interface IUpdateQueue : IDisposable
+ where TIdentifier : notnull
+ {
+ ///
+ /// Sets or merges the provided data set in the current dataset and notifies the trigger that there is new data available.
+ ///
+ /// The set of data.
+ // ReSharper disable once MemberCanBeProtected.Global
+ void SetData(IEnumerable<(TIdentifier, TData)> dataSet);
+
+ ///
+ /// Resets the current data set.
+ ///
+ void Reset();
+ }
+
+ public interface IUpdateQueue : IUpdateQueue