diff --git a/NuGet/RGB.NET.Devices.Debug.nuspec b/NuGet/RGB.NET.Devices.Debug.nuspec
new file mode 100644
index 0000000..2509c3d
--- /dev/null
+++ b/NuGet/RGB.NET.Devices.Debug.nuspec
@@ -0,0 +1,28 @@
+
+
+
+ RGB.NET.Devices.Debug
+ RGB.NET.Devices.Debug
+ 0.0.1
+ Darth Affe
+ Darth Affe
+ https://github.com/DarthAffe/RGB.NET
+ https://raw.githubusercontent.com/DarthAffe/RGB.NET/master/LICENSE
+ true
+ Debug-Device-Implementations of RGB.NET
+
+ Debug-Device-Implementations of RGB.NET, a C# (.NET) library
+ Copyright © Wyrez 2017
+ en-US
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/RGB.NET.Devices.Debug/DebugDeviceProvider.cs b/RGB.NET.Devices.Debug/DebugDeviceProvider.cs
new file mode 100644
index 0000000..8e802f8
--- /dev/null
+++ b/RGB.NET.Devices.Debug/DebugDeviceProvider.cs
@@ -0,0 +1,103 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using System;
+using System.Collections.Generic;
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.Debug
+{
+ ///
+ ///
+ /// Represents a device provider responsible for debug devices.
+ ///
+ public class DebugDeviceProvider : IRGBDeviceProvider
+ {
+ #region Properties & Fields
+
+ private static DebugDeviceProvider _instance;
+ ///
+ /// Gets the singleton instance.
+ ///
+ public static DebugDeviceProvider Instance => _instance ?? new DebugDeviceProvider();
+
+ ///
+ public bool IsInitialized { get; private set; }
+
+ ///
+ public IEnumerable Devices { get; private set; }
+
+ ///
+ public bool HasExclusiveAccess { get; private set; }
+
+ private List<(string layout, string imageLayout, Func> syncBackFunc, Action> updateLedsAction)> _fakeDeviceDefinitions
+ = new List<(string layout, string imageLayout, Func> syncBackFunc, Action> updateLedsAction)>();
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Thrown if this constructor is called even if there is already an instance of this class.
+ public DebugDeviceProvider()
+ {
+ if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(DebugDeviceProvider)}");
+ _instance = this;
+ }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ /// Adds a new fake device definition.
+ ///
+ /// The path of the layout file to be used.
+ /// The image-layout to load.
+ /// A function emulating device syncback.
+ /// A action emulating led-updates.
+ public void AddFakeDeviceDefinition(string layout, string imageLayout, Func> syncBackFunc = null, Action> updateLedsAction = null)
+ => _fakeDeviceDefinitions.Add((layout, imageLayout, syncBackFunc, updateLedsAction));
+
+ ///
+ /// Removes all previously added fake device definitions.
+ ///
+ public void ClearFakeDeviceDefinitions() => _fakeDeviceDefinitions.Clear();
+
+ ///
+ public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.Unknown, bool exclusiveAccessIfPossible = false, bool throwExceptions = false)
+ {
+ IsInitialized = false;
+ try
+ {
+ HasExclusiveAccess = exclusiveAccessIfPossible;
+ IsInitialized = true;
+
+ List devices = new List();
+ foreach ((string layout, string imageLayout, Func> syncBackFunc, Action> updateLedsAction) in _fakeDeviceDefinitions)
+ {
+ DebugRGBDevice device = new DebugRGBDevice(layout, syncBackFunc, updateLedsAction);
+ device.Initialize(layout, imageLayout);
+ devices.Add(device);
+ }
+
+ Devices = devices;
+
+ return true;
+ }
+ catch
+ {
+ if (throwExceptions) throw;
+ return false;
+ }
+ }
+
+ ///
+ public void ResetDevices()
+ { }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Debug/DebugRGBDevice.cs b/RGB.NET.Devices.Debug/DebugRGBDevice.cs
new file mode 100644
index 0000000..45005d3
--- /dev/null
+++ b/RGB.NET.Devices.Debug/DebugRGBDevice.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Collections.Generic;
+using RGB.NET.Core;
+using RGB.NET.Core.Layout;
+
+namespace RGB.NET.Devices.Debug
+{
+ ///
+ ///
+ /// Represents a debug device.
+ ///
+ public class DebugRGBDevice : AbstractRGBDevice
+ {
+ #region Properties & Fields
+
+ ///
+ public override DebugRGBDeviceInfo DeviceInfo { get; }
+
+ private Func> _syncBackFunc;
+ private Action> _updateLedsAction;
+
+ #endregion
+
+ #region Constructors
+ ///
+ /// Internal constructor of .
+ ///
+ internal DebugRGBDevice(string layoutPath, Func> syncBackFunc = null, Action> updateLedsAction = null)
+ {
+ this._syncBackFunc = syncBackFunc;
+ this._updateLedsAction = updateLedsAction;
+
+ DeviceLayout layout = DeviceLayout.Load(layoutPath);
+ DeviceInfo = new DebugRGBDeviceInfo(layout.Type, layout.Vendor, layout.Model, layout.Lighting, syncBackFunc != null);
+ }
+
+ #endregion
+
+ #region Methods
+
+ internal void Initialize(string layoutPath, string imageLayout) => ApplyLayoutFromFile(layoutPath, imageLayout, true);
+
+ ///
+ public override void SyncBack()
+ {
+ try
+ {
+ Dictionary syncBackValues = _syncBackFunc?.Invoke();
+ if (syncBackValues == null) return;
+
+ foreach (KeyValuePair value in syncBackValues)
+ {
+ Led led = ((IRGBDevice)this)[value.Key];
+ if (led != null)
+ led.Color = value.Value;
+ }
+ }
+ catch {/* ics that's not my fault ... */}
+ }
+
+ ///
+ protected override void UpdateLeds(IEnumerable ledsToUpdate) => _updateLedsAction?.Invoke(ledsToUpdate);
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Debug/DebugRGBDeviceInfo.cs b/RGB.NET.Devices.Debug/DebugRGBDeviceInfo.cs
new file mode 100644
index 0000000..10ad430
--- /dev/null
+++ b/RGB.NET.Devices.Debug/DebugRGBDeviceInfo.cs
@@ -0,0 +1,55 @@
+using System;
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.Debug
+{
+ ///
+ ///
+ /// Represents device information for a />.
+ ///
+ public class DebugRGBDeviceInfo : IRGBDeviceInfo
+ {
+ #region Properties & Fields
+
+ ///
+ public RGBDeviceType DeviceType { get; }
+
+ ///
+ public string Manufacturer { get; }
+
+ ///
+ public string Model { get; }
+
+ ///
+ public RGBDeviceLighting Lighting { get; }
+
+ ///
+ public bool SupportsSyncBack { get; }
+
+ ///
+ public Uri Image { get; set; }
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Internal constructor of .
+ ///
+ /// The of the device.
+ /// The manufacturer of the device.
+ /// The model of the device.
+ /// The of the device.
+ /// True if the device supports syncback; false if not.
+ internal DebugRGBDeviceInfo(RGBDeviceType deviceType, string manufacturer, string model, RGBDeviceLighting lighting, bool supportsSyncBack)
+ {
+ this.DeviceType = deviceType;
+ this.Manufacturer = manufacturer;
+ this.Model = model;
+ this.Lighting = lighting;
+ this.SupportsSyncBack = supportsSyncBack;
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Debug/Properties/AssemblyInfo.cs b/RGB.NET.Devices.Debug/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..1d9cfd3
--- /dev/null
+++ b/RGB.NET.Devices.Debug/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("RGB.NET.Devices.Debug")]
+[assembly: AssemblyDescription("Debug-Device-Implementations of RGB.NET")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Wyrez")]
+[assembly: AssemblyProduct("RGB.NET.Devices.Debug")]
+[assembly: AssemblyCopyright("Copyright © Wyrez 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("d013040e-1931-4f0d-9cca-0f4ae74a507e")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/RGB.NET.Devices.Debug/RGB.NET.Devices.Debug.csproj b/RGB.NET.Devices.Debug/RGB.NET.Devices.Debug.csproj
new file mode 100644
index 0000000..c0fc769
--- /dev/null
+++ b/RGB.NET.Devices.Debug/RGB.NET.Devices.Debug.csproj
@@ -0,0 +1,63 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {D013040E-1931-4F0D-9CCA-0F4AE74A507E}
+ Library
+ Properties
+ RGB.NET.Devices.Debug
+ RGB.NET.Devices.Debug
+ v4.5
+ 512
+
+
+ true
+ full
+ false
+ ..\bin\
+ DEBUG;TRACE
+ prompt
+ 4
+ ..\bin\RGB.NET.Devices.Debug.xml
+
+
+ pdbonly
+ true
+ ..\bin\
+ TRACE
+ prompt
+ 4
+ ..\bin\RGB.NET.Devices.Debug.xml
+
+
+
+
+
+ ..\packages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {5a4f9a75-75fe-47cd-90e5-914d5b20d232}
+ RGB.NET.Core
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/RGB.NET.Devices.Debug/packages.config b/RGB.NET.Devices.Debug/packages.config
new file mode 100644
index 0000000..a59695c
--- /dev/null
+++ b/RGB.NET.Devices.Debug/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/RGB.NET.sln b/RGB.NET.sln
index 932876d..2231348 100644
--- a/RGB.NET.sln
+++ b/RGB.NET.sln
@@ -31,6 +31,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NuGet", "NuGet", "{06416566
NuGet\RGB.NET.Devices.Asus.nuspec = NuGet\RGB.NET.Devices.Asus.nuspec
NuGet\RGB.NET.Devices.CoolerMaster.nuspec = NuGet\RGB.NET.Devices.CoolerMaster.nuspec
NuGet\RGB.NET.Devices.Corsair.nuspec = NuGet\RGB.NET.Devices.Corsair.nuspec
+ NuGet\RGB.NET.Devices.Debug.nuspec = NuGet\RGB.NET.Devices.Debug.nuspec
NuGet\RGB.NET.Devices.Logitech.nuspec = NuGet\RGB.NET.Devices.Logitech.nuspec
NuGet\RGB.NET.Devices.Msi.nuspec = NuGet\RGB.NET.Devices.Msi.nuspec
NuGet\RGB.NET.Devices.Novation.nuspec = NuGet\RGB.NET.Devices.Novation.nuspec
@@ -65,6 +66,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Metapackages", "Metapackage
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RGB.NET.Devices.Razer", "RGB.NET.Devices.Razer\RGB.NET.Devices.Razer.csproj", "{24FF4ACB-D679-4B2D-86D4-50AB6C02D816}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RGB.NET.Devices.Debug", "RGB.NET.Devices.Debug\RGB.NET.Devices.Debug.csproj", "{D013040E-1931-4F0D-9CCA-0F4AE74A507E}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -123,6 +126,10 @@ Global
{24FF4ACB-D679-4B2D-86D4-50AB6C02D816}.Debug|Any CPU.Build.0 = Debug|Any CPU
{24FF4ACB-D679-4B2D-86D4-50AB6C02D816}.Release|Any CPU.ActiveCfg = Release|Any CPU
{24FF4ACB-D679-4B2D-86D4-50AB6C02D816}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D013040E-1931-4F0D-9CCA-0F4AE74A507E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D013040E-1931-4F0D-9CCA-0F4AE74A507E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D013040E-1931-4F0D-9CCA-0F4AE74A507E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D013040E-1931-4F0D-9CCA-0F4AE74A507E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -141,6 +148,7 @@ Global
{4EFD77C7-FDB4-4C6B-970C-0EF66D24BE09} = {33D5E279-1C4E-4AB6-9D1E-6D18109A6C25}
{C191D5BE-E1B2-47E4-AB39-D954B277188C} = {06416566-481F-4571-80EE-7BB05B1E0299}
{24FF4ACB-D679-4B2D-86D4-50AB6C02D816} = {33D5E279-1C4E-4AB6-9D1E-6D18109A6C25}
+ {D013040E-1931-4F0D-9CCA-0F4AE74A507E} = {33D5E279-1C4E-4AB6-9D1E-6D18109A6C25}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {CDECA6C7-8D18-4AF3-94F7-C70A69B8571B}