diff --git a/NuGet/Metapackages/RGB.NET.Devices.nuspec b/NuGet/Metapackages/RGB.NET.Devices.nuspec
index 2d578be..35e6773 100644
--- a/NuGet/Metapackages/RGB.NET.Devices.nuspec
+++ b/NuGet/Metapackages/RGB.NET.Devices.nuspec
@@ -21,6 +21,7 @@
+
\ No newline at end of file
diff --git a/NuGet/RGB.NET.Devices.Razer.nuspec b/NuGet/RGB.NET.Devices.Razer.nuspec
new file mode 100644
index 0000000..eb3e065
--- /dev/null
+++ b/NuGet/RGB.NET.Devices.Razer.nuspec
@@ -0,0 +1,32 @@
+
+
+
+ RGB.NET.Devices.Razer
+ RGB.NET.Devices.Razer
+ 0.0.1
+ Darth Affe
+ Darth Affe
+ https://github.com/DarthAffe/RGB.NET
+ https://raw.githubusercontent.com/DarthAffe/RGB.NET/master/LICENSE
+ true
+ Razer-Device-Implementations of RGB.NET
+
+ Razer-Device-Implementations of RGB.NET, a C# (.NET) library for accessing various RGB-peripherals
+ Copyright © Wyrez 2017
+ en-US
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/RGB.NET.Devices.Razer/ChromaLink/RazerChromaLinkRGBDevice.cs b/RGB.NET.Devices.Razer/ChromaLink/RazerChromaLinkRGBDevice.cs
new file mode 100644
index 0000000..36c6741
--- /dev/null
+++ b/RGB.NET.Devices.Razer/ChromaLink/RazerChromaLinkRGBDevice.cs
@@ -0,0 +1,63 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using RGB.NET.Core;
+using RGB.NET.Devices.Razer.Native;
+
+namespace RGB.NET.Devices.Razer
+{
+ ///
+ ///
+ /// Represents a razer chroma link.
+ ///
+ public class RazerChromaLinkRGBDevice : RazerRGBDevice
+ {
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The specific information provided by CUE for the chroma link.
+ internal RazerChromaLinkRGBDevice(RazerChromaLinkRGBDeviceInfo info)
+ : base(info)
+ { }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ protected override void InitializeLayout()
+ {
+ string model = DeviceInfo.Model.Replace(" ", string.Empty).ToUpper();
+ ApplyLayoutFromFile(PathHelper.GetAbsolutePath(
+ $@"Layouts\Razer\ChromaLink\{model}.xml"), null, PathHelper.GetAbsolutePath(@"Images\Razer\ChromaLink"));
+
+ if (LedMapping.Count == 0)
+ for (int i = 0; i < _Defines.CHROMALINK_MAX_LEDS; i++)
+ InitializeLed(new RazerLedId(this, i), new Rectangle(i * 11, 0, 10, 10));
+ }
+
+ ///
+ protected override IntPtr CreateEffectParams(IEnumerable leds)
+ {
+ _Color[] colors = new _Color[_Defines.CHROMALINK_MAX_LEDS];
+
+ foreach (Led led in leds)
+ colors[((RazerLedId)led.Id).Index] = new _Color(led.Color.R, led.Color.G, led.Color.B);
+
+ _ChromaLinkCustomEffect effectParams = new _ChromaLinkCustomEffect { Color = colors };
+
+ IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(effectParams));
+ Marshal.StructureToPtr(effectParams, ptr, false);
+
+ return ptr;
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Razer/ChromaLink/RazerChromaLinkRGBDeviceInfo.cs b/RGB.NET.Devices.Razer/ChromaLink/RazerChromaLinkRGBDeviceInfo.cs
new file mode 100644
index 0000000..34746d5
--- /dev/null
+++ b/RGB.NET.Devices.Razer/ChromaLink/RazerChromaLinkRGBDeviceInfo.cs
@@ -0,0 +1,32 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using System;
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.Razer
+{
+ ///
+ ///
+ /// Represents a generic information for a .
+ ///
+ public class RazerChromaLinkRGBDeviceInfo : RazerRGBDeviceInfo
+ {
+ #region Constructors
+
+ ///
+ ///
+ /// Internal constructor of managed .
+ ///
+ /// The Id of the .
+ /// The model of the .
+ internal RazerChromaLinkRGBDeviceInfo(Guid deviceId, string model)
+ : base(deviceId, RGBDeviceType.LedStripe, model)
+ {
+ string modelName = Model.Replace(" ", string.Empty).ToUpper();
+ Image = new Uri(PathHelper.GetAbsolutePath($@"Images\Razer\ChromaLinks\{modelName}.png"), UriKind.Absolute);
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Enum/DeviceType.cs b/RGB.NET.Devices.Razer/Enum/DeviceType.cs
new file mode 100644
index 0000000..d262656
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Enum/DeviceType.cs
@@ -0,0 +1,13 @@
+namespace RGB.NET.Devices.Razer
+{
+ internal enum DeviceType
+ {
+ Keyboard = 1,
+ Mouse = 2,
+ Headset = 3,
+ Mousepad = 4,
+ Keypad = 5,
+ System = 6,
+ Invalid
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Enum/RazerError.cs b/RGB.NET.Devices.Razer/Enum/RazerError.cs
new file mode 100644
index 0000000..06321a7
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Enum/RazerError.cs
@@ -0,0 +1,93 @@
+namespace RGB.NET.Devices.Razer
+{
+ ///
+ /// Razer-SDK: Error codes for Chroma SDK. If the error is not defined here, refer to WinError.h from the Windows SDK.
+ ///
+ public enum RazerError : long
+ {
+ ///
+ /// Razer-SDK: Invalid.
+ ///
+ Invalid = -1,
+
+ ///
+ /// Razer-SDK: Success.
+ ///
+ Success = 0,
+
+ ///
+ /// Razer-SDK: Access denied.
+ ///
+ AccessDenied = 5,
+
+ ///
+ /// Razer-SDK: Invalid handle.
+ ///
+ InvalidHandle = 6,
+
+ ///
+ /// Razer-SDK: Not supported.
+ ///
+ NotSupported = 50,
+
+ ///
+ /// Razer-SDK: Invalid parameter.
+ ///
+ InvalidParameter = 87,
+
+ ///
+ /// Razer-SDK: The service has not been started.
+ ///
+ ServiceNotActive = 1062,
+
+ ///
+ /// Razer-SDK: Cannot start more than one instance of the specified program.
+ ///
+ SingleInstanceApp = 1152,
+
+ ///
+ /// Razer-SDK: Device not connected.
+ ///
+ DeviceNotConnected = 1167,
+
+ ///
+ /// Razer-SDK: Element not found.
+ ///
+ NotFound = 1168,
+
+ ///
+ /// Razer-SDK: Request aborted.
+ ///
+ RequestAborted = 1235,
+
+ ///
+ /// Razer-SDK: An attempt was made to perform an initialization operation when initialization has already been completed.
+ ///
+ AlreadyInitialized = 1247,
+
+ ///
+ /// Razer-SDK: Resource not available or disabled.
+ ///
+ ResourceDisabled = 4309,
+
+ ///
+ /// Razer-SDK: Device not available or supported.
+ ///
+ DeviceNotAvailable = 4319,
+
+ ///
+ /// Razer-SDK: The group or resource is not in the correct state to perform the requested operation.
+ ///
+ NotValidState = 5023,
+
+ ///
+ /// Razer-SDK: No more items.
+ ///
+ NoMoreItems = 259,
+
+ ///
+ /// Razer-SDK: General failure.
+ ///
+ Failed = 2147500037
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Enum/RazerLogicalKeyboardLayout.cs b/RGB.NET.Devices.Razer/Enum/RazerLogicalKeyboardLayout.cs
new file mode 100644
index 0000000..1ec9382
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Enum/RazerLogicalKeyboardLayout.cs
@@ -0,0 +1,15 @@
+// ReSharper disable InconsistentNaming
+// ReSharper disable UnusedMember.Global
+
+#pragma warning disable 1591 // Missing XML comment for publicly visible type or member
+
+namespace RGB.NET.Devices.Razer
+{
+ ///
+ /// Contains list of available logical layouts for razer keyboards.
+ ///
+ public enum RazerLogicalKeyboardLayout
+ {
+ TODO
+ };
+}
diff --git a/RGB.NET.Devices.Razer/Enum/RazerPhysicalKeyboardLayout.cs b/RGB.NET.Devices.Razer/Enum/RazerPhysicalKeyboardLayout.cs
new file mode 100644
index 0000000..090a2db
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Enum/RazerPhysicalKeyboardLayout.cs
@@ -0,0 +1,15 @@
+// ReSharper disable UnusedMember.Global
+// ReSharper disable InconsistentNaming
+
+#pragma warning disable 1591 // Missing XML comment for publicly visible type or member
+
+namespace RGB.NET.Devices.Razer
+{
+ ///
+ /// Contains list of available physical layouts for razer keyboards.
+ ///
+ public enum RazerPhysicalKeyboardLayout
+ {
+ TODO
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Exceptions/RazerException.cs b/RGB.NET.Devices.Razer/Exceptions/RazerException.cs
new file mode 100644
index 0000000..edd6bac
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Exceptions/RazerException.cs
@@ -0,0 +1,37 @@
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable MemberCanBePrivate.Global
+
+using System;
+
+namespace RGB.NET.Devices.Razer
+{
+ ///
+ ///
+ /// Represents an exception thrown by the Razer-SDK.
+ ///
+ public class RazerException : ApplicationException
+ {
+ #region Properties & Fields
+
+ ///
+ /// Gets the error code provided by the SDK.
+ ///
+ public RazerError ErrorCode { get; }
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The error code provided by the SDK.
+ public RazerException(RazerError errorCode)
+ {
+ this.ErrorCode = errorCode;
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Generic/Devices.cs b/RGB.NET.Devices.Razer/Generic/Devices.cs
new file mode 100644
index 0000000..a167aa9
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Generic/Devices.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+
+namespace RGB.NET.Devices.Razer
+{
+ internal class Devices
+ {
+ public static readonly List<(Guid guid, string model)> KEYBOARDS = new List<(Guid guid, string model)>
+ {
+ (new Guid("2EA1BB63-CA28-428D-9F06-196B88330BBB"), "Blackwidow Chroma"),
+ (new Guid("ED1C1B82-BFBE-418F-B49D-D03F05B149DF"), "Razer Blackwidow Chroma Tournament Edition"),
+ (new Guid("18C5AD9B-4326-4828-92C4-2669A66D2283"), "Razer Deathstalker "),
+ (new Guid("872AB2A9-7959-4478-9FED-15F6186E72E4"), "Overwatch Keyboard"),
+ (new Guid("5AF60076-ADE9-43D4-B574-52599293B554"), "Razer Blackwidow X Chroma"),
+ (new Guid("2D84DD51-3290-4AAC-9A89-D8AFDE38B57C"), "Razer Blackwidow X TE Chroma"),
+ (new Guid("803378C1-CC48-4970-8539-D828CC1D420A"), "Razer Omata Chroma"),
+ (new Guid("C83BDFE8-E7FC-40E0-99DB-872E23F19891"), "Razer Blade Stealth"),
+ (new Guid("F2BEDFAF-A0FE-4651-9D41-B6CE603A3DDD"), "Razer Blade"),
+ (new Guid("A73AC338-F0E5-4BF7-91AE-DD1F7E1737A5"), "Razer Blade Pro"),
+ (new Guid("608E743F-B402-44BD-A7A6-7AA9F574ECF4"), "Razer Blackwidow Chroma v2")
+ };
+
+ public static readonly List<(Guid guid, string model)> MICE = new List<(Guid guid, string model)>
+ {
+ (new Guid("7EC00450-E0EE-4289-89D5-0D879C19061A"), "Razer Mamba Chroma Tournament Edition"),
+ (new Guid("AEC50D91-B1F1-452F-8E16-7B73F376FDF3"), "Razer Deathadder Chroma "),
+ (new Guid("FF8A5929-4512-4257-8D59-C647BF9935D0"), "Razer Diamondback"),
+ (new Guid("D527CBDC-EB0A-483A-9E89-66D50463EC6C"), "Razer Mamba"),
+ (new Guid("D714C50B-7158-4368-B99C-601ACB985E98"), "Razer Naga Epic"),
+ (new Guid("F1876328-6CA4-46AE-BE04-BE812B414433"), "Razer Naga"),
+ (new Guid("52C15681-4ECE-4DD9-8A52-A1418459EB34"), "Razer Orochi Chroma"),
+ (new Guid("195D70F5-F285-4CFF-99F2-B8C0E9658DB4"), "Razer Naga Hex Chroma"),
+ (new Guid("77834867-3237-4A9F-AD77-4A46C4183003"), "Razer DeathAdder Elite Chroma")
+ };
+
+ public static readonly List<(Guid guid, string model)> HEADSETS = new List<(Guid guid, string model)>
+ {
+ (new Guid("DF3164D7-5408-4A0E-8A7F-A7412F26BEBF"), "Razer ManO'War"),
+ (new Guid("CD1E09A5-D5E6-4A6C-A93B-E6D9BF1D2092"), "Razer Kraken 7.1 Chroma"),
+ (new Guid("7FB8A36E-9E74-4BB3-8C86-CAC7F7891EBD"), "Razer Kraken 7.1 Chroma Refresh")
+ };
+
+ public static readonly List<(Guid guid, string model)> MOUSEMATS = new List<(Guid guid, string model)>
+ {
+ (new Guid("80F95A94-73D2-48CA-AE9A-0986789A9AF2"), "Razer Firefly")
+ };
+
+ public static readonly List<(Guid guid, string model)> KEYPADS = new List<(Guid guid, string model)>
+ {
+ (new Guid("9D24B0AB-0162-466C-9640-7A924AA4D9FD"), "Razer Orbweaver"),
+ (new Guid("00F0545C-E180-4AD1-8E8A-419061CE505E"), "Razer Tartarus")
+ };
+
+ public static readonly List<(Guid guid, string model)> CHROMALINKS = new List<(Guid guid, string model)>
+ {
+ (new Guid("0201203B-62F3-4C50-83DD-598BABD208E0"), "Core Chroma"),
+ (new Guid("35F6F18D-1AE5-436C-A575-AB44A127903A"), "Lenovo Y900"),
+ (new Guid("47DB1FA7-6B9B-4EE6-B6F4-4071A3B2053B"), "Lenovo Y27")
+ };
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Generic/IRazerRGBDevice.cs b/RGB.NET.Devices.Razer/Generic/IRazerRGBDevice.cs
new file mode 100644
index 0000000..879537f
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Generic/IRazerRGBDevice.cs
@@ -0,0 +1,13 @@
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.Razer
+{
+ ///
+ /// Represents a razer RGB-device.
+ ///
+ internal interface IRazerRGBDevice : IRGBDevice
+ {
+ void Initialize();
+ void Reset();
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Generic/RazerLedId.cs b/RGB.NET.Devices.Razer/Generic/RazerLedId.cs
new file mode 100644
index 0000000..d8fc56d
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Generic/RazerLedId.cs
@@ -0,0 +1,94 @@
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.Razer
+{
+ ///
+ ///
+ /// Represents a Id of a on a .
+ ///
+ public class RazerLedId : ILedId
+ {
+ #region Properties & Fields
+
+ internal int Index { get; }
+
+ ///
+ public IRGBDevice Device { get; }
+
+ ///
+ public bool IsValid => true;
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The the belongs to.
+ /// The index representing the led-location in the grid.
+ public RazerLedId(IRGBDevice device, int index)
+ {
+ this.Device = device;
+ this.Index = index;
+ }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ /// Converts the Id of this to a human-readable string.
+ ///
+ /// A string that contains the Id of this . For example "Enter".
+ public override string ToString() => Index.ToString();
+
+ ///
+ /// Tests whether the specified object is a and is equivalent to this .
+ ///
+ /// The object to test.
+ /// true if is a equivalent to this ; otherwise, false.
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (!(obj is RazerLedId other)) return false;
+
+ return (Index == other.Index) && Equals(Device, other.Device);
+ }
+
+ ///
+ /// Returns a hash code for this .
+ ///
+ /// An integer value that specifies the hash code for this .
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ return (Index * 397) ^ (Device != null ? Device.GetHashCode() : 0);
+ }
+ }
+
+ #endregion
+
+ #region Operators
+
+ ///
+ /// Returns a value that indicates whether two specified are equal.
+ ///
+ /// The first to compare.
+ /// The second to compare.
+ /// true if and are equal; otherwise, false.
+ public static bool operator ==(RazerLedId ledId1, RazerLedId ledId2) => ReferenceEquals(ledId1, null) ? ReferenceEquals(ledId2, null) : ledId1.Equals(ledId2);
+
+ ///
+ /// Returns a value that indicates whether two specified are equal.
+ ///
+ /// The first to compare.
+ /// The second to compare.
+ /// true if and are not equal; otherwise, false.
+ public static bool operator !=(RazerLedId ledId1, RazerLedId ledId2) => !(ledId1 == ledId2);
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Generic/RazerRGBDevice.cs b/RGB.NET.Devices.Razer/Generic/RazerRGBDevice.cs
new file mode 100644
index 0000000..66cd55c
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Generic/RazerRGBDevice.cs
@@ -0,0 +1,143 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using RGB.NET.Core;
+using RGB.NET.Core.Layout;
+using RGB.NET.Devices.Razer.Native;
+
+namespace RGB.NET.Devices.Razer
+{
+ ///
+ ///
+ ///
+ /// Represents a generic razer-device. (keyboard, mouse, headset, mousepad).
+ ///
+ public abstract class RazerRGBDevice : AbstractRGBDevice, IRazerRGBDevice
+ where TDeviceInfo : RazerRGBDeviceInfo
+ {
+ #region Properties & Fields
+
+ private Guid? _lastEffect;
+
+ ///
+ ///
+ /// Gets information about the .
+ ///
+ public override TDeviceInfo DeviceInfo { get; }
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The generic information provided by razer for the device.
+ protected RazerRGBDevice(TDeviceInfo info)
+ {
+ this.DeviceInfo = info;
+ }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ /// Initializes the device.
+ ///
+ public void Initialize()
+ {
+ InitializeLayout();
+
+ if (Size == Size.Invalid)
+ {
+ Rectangle ledRectangle = new Rectangle(this.Select(x => x.LedRectangle));
+ Size = ledRectangle.Size + new Size(ledRectangle.Location.X, ledRectangle.Location.Y);
+ }
+ }
+
+ ///
+ /// Initializes the and of the device.
+ ///
+ protected abstract void InitializeLayout();
+
+ ///
+ /// Applies the given layout.
+ ///
+ /// The file containing the layout.
+ /// The name of the layout used to get the images of the leds.
+ /// The path images for this device are collected in.
+ protected void ApplyLayoutFromFile(string layoutPath, string imageLayout, string imageBasePath)
+ {
+ DeviceLayout layout = DeviceLayout.Load(layoutPath);
+ if (layout != null)
+ {
+ LedImageLayout ledImageLayout = layout.LedImageLayouts.FirstOrDefault(x => string.Equals(x.Layout, imageLayout, StringComparison.OrdinalIgnoreCase));
+
+ Size = new Size(layout.Width, layout.Height);
+
+ if (layout.Leds != null)
+ foreach (LedLayout layoutLed in layout.Leds)
+ {
+ if (Enum.TryParse(layoutLed.Id, true, out int ledIndex))
+ {
+ if (LedMapping.TryGetValue(new RazerLedId(this, ledIndex), out Led led))
+ {
+ led.LedRectangle.Location = new Point(layoutLed.X, layoutLed.Y);
+ led.LedRectangle.Size = new Size(layoutLed.Width, layoutLed.Height);
+
+ led.Shape = layoutLed.Shape;
+ led.ShapeData = layoutLed.ShapeData;
+
+ LedImage image = ledImageLayout?.LedImages.FirstOrDefault(x => x.Id == layoutLed.Id);
+ led.Image = (!string.IsNullOrEmpty(image?.Image))
+ ? new Uri(Path.Combine(imageBasePath, image.Image), UriKind.Absolute)
+ : new Uri(Path.Combine(imageBasePath, "Missing.png"), UriKind.Absolute);
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ protected override void UpdateLeds(IEnumerable ledsToUpdate)
+ {
+ List leds = ledsToUpdate.Where(x => x.Color.A > 0).ToList();
+
+ if (leds.Count <= 0) return;
+
+ IntPtr effectParams = CreateEffectParams(leds);
+ Guid effectId = Guid.NewGuid();
+ _RazerSDK.CreateEffect(DeviceInfo.DeviceId, _Defines.EFFECT_ID, effectParams, ref effectId);
+
+ _RazerSDK.SetEffect(effectId);
+
+ if (_lastEffect.HasValue)
+ _RazerSDK.DeleteEffect(_lastEffect.Value);
+
+ _lastEffect = effectId;
+ }
+
+ ///
+ /// Creates the device-specific effect parameters for the led-update.
+ ///
+ /// The leds to be updated.
+ /// An pointing to the effect parameter struct.
+ protected abstract IntPtr CreateEffectParams(IEnumerable leds);
+
+ ///
+ /// Resets the device.
+ ///
+ public void Reset()
+ {
+ if (_lastEffect.HasValue)
+ {
+ _RazerSDK.DeleteEffect(_lastEffect.Value);
+ _lastEffect = null;
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Generic/RazerRGBDeviceInfo.cs b/RGB.NET.Devices.Razer/Generic/RazerRGBDeviceInfo.cs
new file mode 100644
index 0000000..84b307e
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Generic/RazerRGBDeviceInfo.cs
@@ -0,0 +1,56 @@
+using System;
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.Razer
+{
+ ///
+ ///
+ /// Represents a generic information for a Razer-.
+ ///
+ public class RazerRGBDeviceInfo : IRGBDeviceInfo
+ {
+ #region Properties & Fields
+
+ ///
+ /// Gets the Id of the .
+ ///
+ public Guid DeviceId { get; }
+
+ ///
+ public RGBDeviceType DeviceType { get; }
+
+ ///
+ public string Manufacturer => "Razer";
+
+ ///
+ public string Model { get; }
+
+ ///
+ public Uri Image { get; protected set; }
+
+ ///
+ public bool SupportsSyncBack => false;
+
+ ///
+ public RGBDeviceLighting Lighting => RGBDeviceLighting.Key;
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Internal constructor of managed .
+ ///
+ /// The Id of the .
+ /// The type of the .
+ /// The model of the .
+ internal RazerRGBDeviceInfo(Guid deviceId, RGBDeviceType deviceType, string model)
+ {
+ this.DeviceId = deviceId;
+ this.DeviceType = deviceType;
+ this.Model = model;
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Headset/RazerHeadsetRGBDevice.cs b/RGB.NET.Devices.Razer/Headset/RazerHeadsetRGBDevice.cs
new file mode 100644
index 0000000..a62cb07
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Headset/RazerHeadsetRGBDevice.cs
@@ -0,0 +1,63 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using RGB.NET.Core;
+using RGB.NET.Devices.Razer.Native;
+
+namespace RGB.NET.Devices.Razer
+{
+ ///
+ ///
+ /// Represents a razer headset.
+ ///
+ public class RazerHeadsetRGBDevice : RazerRGBDevice
+ {
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The specific information provided by CUE for the headset.
+ internal RazerHeadsetRGBDevice(RazerHeadsetRGBDeviceInfo info)
+ : base(info)
+ { }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ protected override void InitializeLayout()
+ {
+ string model = DeviceInfo.Model.Replace(" ", string.Empty).ToUpper();
+ ApplyLayoutFromFile(PathHelper.GetAbsolutePath(
+ $@"Layouts\Razer\Headset\{model}.xml"), null, PathHelper.GetAbsolutePath(@"Images\Razer\Headset"));
+
+ if (LedMapping.Count == 0)
+ for (int i = 0; i < _Defines.HEADSET_MAX_LEDS; i++)
+ InitializeLed(new RazerLedId(this, i), new Rectangle(i * 11, 0, 10, 10));
+ }
+
+ ///
+ protected override IntPtr CreateEffectParams(IEnumerable leds)
+ {
+ _Color[] colors = new _Color[_Defines.HEADSET_MAX_LEDS];
+
+ foreach (Led led in leds)
+ colors[((RazerLedId)led.Id).Index] = new _Color(led.Color.R, led.Color.G, led.Color.B);
+
+ _HeadsetCustomEffect effectParams = new _HeadsetCustomEffect { Color = colors };
+
+ IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(effectParams));
+ Marshal.StructureToPtr(effectParams, ptr, false);
+
+ return ptr;
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Headset/RazerHeadsetRGBDeviceInfo.cs b/RGB.NET.Devices.Razer/Headset/RazerHeadsetRGBDeviceInfo.cs
new file mode 100644
index 0000000..34604cb
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Headset/RazerHeadsetRGBDeviceInfo.cs
@@ -0,0 +1,32 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using System;
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.Razer
+{
+ ///
+ ///
+ /// Represents a generic information for a .
+ ///
+ public class RazerHeadsetRGBDeviceInfo : RazerRGBDeviceInfo
+ {
+ #region Constructors
+
+ ///
+ ///
+ /// Internal constructor of managed .
+ ///
+ /// The Id of the .
+ /// The model of the .
+ internal RazerHeadsetRGBDeviceInfo(Guid deviceId, string model)
+ : base(deviceId, RGBDeviceType.Headset, model)
+ {
+ string modelName = Model.Replace(" ", string.Empty).ToUpper();
+ Image = new Uri(PathHelper.GetAbsolutePath($@"Images\Razer\Headsets\{modelName}.png"), UriKind.Absolute);
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Keyboard/RazerKeyboardRGBDevice.cs b/RGB.NET.Devices.Razer/Keyboard/RazerKeyboardRGBDevice.cs
new file mode 100644
index 0000000..51a7fae
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Keyboard/RazerKeyboardRGBDevice.cs
@@ -0,0 +1,67 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using RGB.NET.Core;
+using RGB.NET.Devices.Razer.Native;
+
+namespace RGB.NET.Devices.Razer
+{
+ ///
+ ///
+ /// Represents a razer keyboard.
+ ///
+ public class RazerKeyboardRGBDevice : RazerRGBDevice
+ {
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The specific information provided by CUE for the keyboard.
+ internal RazerKeyboardRGBDevice(RazerKeyboardRGBDeviceInfo info)
+ : base(info)
+ { }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ protected override void InitializeLayout()
+ {
+ //string model = DeviceInfo.Model.Replace(" ", string.Empty).ToUpper();
+ //ApplyLayoutFromFile(PathHelper.GetAbsolutePath(
+ // $@"Layouts\Razer\Keyboards\{model}\{DeviceInfo.PhysicalLayout.ToString().ToUpper()}.xml"),
+ // DeviceInfo.LogicalLayout.ToString(), PathHelper.GetAbsolutePath(@"Images\Razer\Keyboards"));
+
+ if (LedMapping.Count == 0)
+ {
+ for (int i = 0; i < _Defines.KEYBOARD_MAX_ROW; i++)
+ for (int j = 0; j < _Defines.KEYBOARD_MAX_COLUMN; j++)
+ InitializeLed(new RazerLedId(this, (i * _Defines.KEYBOARD_MAX_COLUMN) + j), new Rectangle(j * 20, i * 20, 19, 19));
+ }
+ }
+
+ ///
+ protected override IntPtr CreateEffectParams(IEnumerable leds)
+ {
+ _Color[] colors = new _Color[_Defines.KEYBOARD_MAX_LEDS];
+
+ foreach (Led led in leds)
+ colors[((RazerLedId)led.Id).Index] = new _Color(led.Color.R, led.Color.G, led.Color.B);
+
+ _KeyboardCustomEffect effectParams = new _KeyboardCustomEffect { Color = colors };
+
+ IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(effectParams));
+ Marshal.StructureToPtr(effectParams, ptr, false);
+
+ return ptr;
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Keyboard/RazerKeyboardRGBDeviceInfo.cs b/RGB.NET.Devices.Razer/Keyboard/RazerKeyboardRGBDeviceInfo.cs
new file mode 100644
index 0000000..d9173fc
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Keyboard/RazerKeyboardRGBDeviceInfo.cs
@@ -0,0 +1,66 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using System;
+using System.Globalization;
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.Razer
+{
+ ///
+ ///
+ /// Represents a generic information for a .
+ ///
+ public class RazerKeyboardRGBDeviceInfo : RazerRGBDeviceInfo
+ {
+ #region Properties & Fields
+
+ ///
+ /// Gets the physical layout of the keyboard.
+ ///
+ public RazerPhysicalKeyboardLayout PhysicalLayout { get; private set; }
+
+ ///
+ /// Gets the logical layout of the keyboard as set in CUE settings.
+ ///
+ public RazerLogicalKeyboardLayout LogicalLayout { get; private set; }
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ ///
+ /// Internal constructor of managed .
+ ///
+ /// The Id of the .
+ /// The model of the .
+ /// The of the layout this keyboard is using.
+ internal RazerKeyboardRGBDeviceInfo(Guid deviceId, string model, CultureInfo culture)
+ : base(deviceId, RGBDeviceType.Keyboard, model)
+ {
+ SetLayouts(culture.KeyboardLayoutId);
+
+ Image = new Uri(PathHelper.GetAbsolutePath($@"Images\Razer\Keyboards\{Model.Replace(" ", string.Empty).ToUpper()}.png"),
+ UriKind.Absolute);
+ }
+
+ #endregion
+
+ #region Methods
+
+ private void SetLayouts(int keyboardLayoutId)
+ {
+ switch (keyboardLayoutId)
+ {
+ //TODO DarthAffe 07.10.2017: Implement
+ default:
+ PhysicalLayout = RazerPhysicalKeyboardLayout.TODO;
+ LogicalLayout = RazerLogicalKeyboardLayout.TODO;
+ break;
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Keypad/RazerKeypadRGBDevice.cs b/RGB.NET.Devices.Razer/Keypad/RazerKeypadRGBDevice.cs
new file mode 100644
index 0000000..2c528ee
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Keypad/RazerKeypadRGBDevice.cs
@@ -0,0 +1,66 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using RGB.NET.Core;
+using RGB.NET.Devices.Razer.Native;
+
+namespace RGB.NET.Devices.Razer
+{
+ ///
+ ///
+ /// Represents a razer keypad.
+ ///
+ public class RazerKeypadRGBDevice : RazerRGBDevice
+ {
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The specific information provided by CUE for the keypad.
+ internal RazerKeypadRGBDevice(RazerKeypadRGBDeviceInfo info)
+ : base(info)
+ { }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ protected override void InitializeLayout()
+ {
+ string model = DeviceInfo.Model.Replace(" ", string.Empty).ToUpper();
+ ApplyLayoutFromFile(PathHelper.GetAbsolutePath(
+ $@"Layouts\Razer\Keypad\{model}.xml"), null, PathHelper.GetAbsolutePath(@"Images\Razer\Keypad"));
+
+ if (LedMapping.Count == 0)
+ {
+ for (int i = 0; i < _Defines.KEYPAD_MAX_ROW; i++)
+ for (int j = 0; j < _Defines.KEYPAD_MAX_COLUMN; j++)
+ InitializeLed(new RazerLedId(this, (i * _Defines.KEYPAD_MAX_COLUMN) + j), new Rectangle(j * 20, i * 20, 19, 19));
+ }
+ }
+
+ ///
+ protected override IntPtr CreateEffectParams(IEnumerable leds)
+ {
+ _Color[] colors = new _Color[_Defines.KEYPAD_MAX_LEDS];
+
+ foreach (Led led in leds)
+ colors[((RazerLedId)led.Id).Index] = new _Color(led.Color.R, led.Color.G, led.Color.B);
+
+ _KeypadCustomEffect effectParams = new _KeypadCustomEffect { Color = colors };
+
+ IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(effectParams));
+ Marshal.StructureToPtr(effectParams, ptr, false);
+
+ return ptr;
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Keypad/RazerKeypadRGBDeviceInfo.cs b/RGB.NET.Devices.Razer/Keypad/RazerKeypadRGBDeviceInfo.cs
new file mode 100644
index 0000000..a41ccc5
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Keypad/RazerKeypadRGBDeviceInfo.cs
@@ -0,0 +1,32 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using System;
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.Razer
+{
+ ///
+ ///
+ /// Represents a generic information for a .
+ ///
+ public class RazerKeypadRGBDeviceInfo : RazerRGBDeviceInfo
+ {
+ #region Constructors
+
+ ///
+ ///
+ /// Internal constructor of managed .
+ ///
+ /// The Id of the .
+ /// The model of the .
+ internal RazerKeypadRGBDeviceInfo(Guid deviceId, string model)
+ : base(deviceId, RGBDeviceType.Keypad, model)
+ {
+ string modelName = Model.Replace(" ", string.Empty).ToUpper();
+ Image = new Uri(PathHelper.GetAbsolutePath($@"Images\Razer\Keypads\{modelName}.png"), UriKind.Absolute);
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Layouts/DeviceLayout.xsd b/RGB.NET.Devices.Razer/Layouts/DeviceLayout.xsd
new file mode 100644
index 0000000..92690b3
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Layouts/DeviceLayout.xsd
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/RGB.NET.Devices.Razer/Mouse/RazerMouseRGBDevice.cs b/RGB.NET.Devices.Razer/Mouse/RazerMouseRGBDevice.cs
new file mode 100644
index 0000000..944d00c
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Mouse/RazerMouseRGBDevice.cs
@@ -0,0 +1,66 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using RGB.NET.Core;
+using RGB.NET.Devices.Razer.Native;
+
+namespace RGB.NET.Devices.Razer
+{
+ ///
+ ///
+ /// Represents a razer mouse.
+ ///
+ public class RazerMouseRGBDevice : RazerRGBDevice
+ {
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The specific information provided by CUE for the mouse.
+ internal RazerMouseRGBDevice(RazerMouseRGBDeviceInfo info)
+ : base(info)
+ { }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ protected override void InitializeLayout()
+ {
+ string model = DeviceInfo.Model.Replace(" ", string.Empty).ToUpper();
+ ApplyLayoutFromFile(PathHelper.GetAbsolutePath(
+ $@"Layouts\Razer\Mice\{model}.xml"), null, PathHelper.GetAbsolutePath(@"Images\Razer\Mice"));
+
+ if (LedMapping.Count == 0)
+ {
+ for (int i = 0; i < _Defines.MOUSE_MAX_ROW; i++)
+ for (int j = 0; j < _Defines.MOUSE_MAX_COLUMN; j++)
+ InitializeLed(new RazerLedId(this, (i * _Defines.MOUSE_MAX_COLUMN) + j), new Rectangle(j * 11, i * 11, 10, 10));
+ }
+ }
+
+ ///
+ protected override IntPtr CreateEffectParams(IEnumerable leds)
+ {
+ _Color[] colors = new _Color[_Defines.MOUSE_MAX_LEDS];
+
+ foreach (Led led in leds)
+ colors[((RazerLedId)led.Id).Index] = new _Color(led.Color.R, led.Color.G, led.Color.B);
+
+ _MouseCustomEffect effectParams = new _MouseCustomEffect { Color = colors };
+
+ IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(effectParams));
+ Marshal.StructureToPtr(effectParams, ptr, false);
+
+ return ptr;
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Mouse/RazerMouseRGBDeviceInfo.cs b/RGB.NET.Devices.Razer/Mouse/RazerMouseRGBDeviceInfo.cs
new file mode 100644
index 0000000..72782d6
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Mouse/RazerMouseRGBDeviceInfo.cs
@@ -0,0 +1,32 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using System;
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.Razer
+{
+ ///
+ ///
+ /// Represents a generic information for a .
+ ///
+ public class RazerMouseRGBDeviceInfo : RazerRGBDeviceInfo
+ {
+ #region Constructors
+
+ ///
+ ///
+ /// Internal constructor of managed .
+ ///
+ /// The Id of the .
+ /// The model of the .
+ internal RazerMouseRGBDeviceInfo(Guid deviceId, string model)
+ : base(deviceId, RGBDeviceType.Mouse, model)
+ {
+ string modelName = Model.Replace(" ", string.Empty).ToUpper();
+ Image = new Uri(PathHelper.GetAbsolutePath($@"Images\Razer\Mice\{modelName}.png"), UriKind.Absolute);
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Mousepad/RazerMousepadRGBDevice.cs b/RGB.NET.Devices.Razer/Mousepad/RazerMousepadRGBDevice.cs
new file mode 100644
index 0000000..e42b97d
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Mousepad/RazerMousepadRGBDevice.cs
@@ -0,0 +1,63 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using RGB.NET.Core;
+using RGB.NET.Devices.Razer.Native;
+
+namespace RGB.NET.Devices.Razer
+{
+ ///
+ ///
+ /// Represents a razer mousepad.
+ ///
+ public class RazerMousepadRGBDevice : RazerRGBDevice
+ {
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The specific information provided by CUE for the mousepad.
+ internal RazerMousepadRGBDevice(RazerMousepadRGBDeviceInfo info)
+ : base(info)
+ { }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ protected override void InitializeLayout()
+ {
+ string model = DeviceInfo.Model.Replace(" ", string.Empty).ToUpper();
+ ApplyLayoutFromFile(PathHelper.GetAbsolutePath(
+ $@"Layouts\Razer\Mousepad\{model}.xml"), null, PathHelper.GetAbsolutePath(@"Images\Razer\Mousepad"));
+
+ if (LedMapping.Count == 0)
+ for (int i = 0; i < _Defines.MOUSEPAD_MAX_LEDS; i++)
+ InitializeLed(new RazerLedId(this, i), new Rectangle(i * 11, 0, 10, 10));
+ }
+
+ ///
+ protected override IntPtr CreateEffectParams(IEnumerable leds)
+ {
+ _Color[] colors = new _Color[_Defines.MOUSEPAD_MAX_LEDS];
+
+ foreach (Led led in leds)
+ colors[((RazerLedId)led.Id).Index] = new _Color(led.Color.R, led.Color.G, led.Color.B);
+
+ _MousepadCustomEffect effectParams = new _MousepadCustomEffect { Color = colors };
+
+ IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(effectParams));
+ Marshal.StructureToPtr(effectParams, ptr, false);
+
+ return ptr;
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Mousepad/RazerMousepadRGBDeviceInfo.cs b/RGB.NET.Devices.Razer/Mousepad/RazerMousepadRGBDeviceInfo.cs
new file mode 100644
index 0000000..b21d49a
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Mousepad/RazerMousepadRGBDeviceInfo.cs
@@ -0,0 +1,32 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using System;
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.Razer
+{
+ ///
+ ///
+ /// Represents a generic information for a .
+ ///
+ public class RazerMousepadRGBDeviceInfo : RazerRGBDeviceInfo
+ {
+ #region Constructors
+
+ ///
+ ///
+ /// Internal constructor of managed .
+ ///
+ /// The Id of the .
+ /// The model of the .
+ internal RazerMousepadRGBDeviceInfo(Guid deviceId, string model)
+ : base(deviceId, RGBDeviceType.Mousepad, model)
+ {
+ string modelName = Model.Replace(" ", string.Empty).ToUpper();
+ Image = new Uri(PathHelper.GetAbsolutePath($@"Images\Razer\Mousepads\{modelName}.png"), UriKind.Absolute);
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Native/_ChromaLinkCustomEffect.cs b/RGB.NET.Devices.Razer/Native/_ChromaLinkCustomEffect.cs
new file mode 100644
index 0000000..267dbe0
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Native/_ChromaLinkCustomEffect.cs
@@ -0,0 +1,11 @@
+using System.Runtime.InteropServices;
+
+namespace RGB.NET.Devices.Razer.Native
+{
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct _ChromaLinkCustomEffect
+ {
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = _Defines.CHROMALINK_MAX_LEDS)]
+ public _Color[] Color;
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Native/_Color.cs b/RGB.NET.Devices.Razer/Native/_Color.cs
new file mode 100644
index 0000000..c3c5794
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Native/_Color.cs
@@ -0,0 +1,30 @@
+#pragma warning disable 169 // Field 'x' is never used
+#pragma warning disable 414 // Field 'x' is assigned but its value never used
+#pragma warning disable 649 // Field 'x' is never assigned
+// ReSharper disable MemberCanBePrivate.Global
+
+using System.Runtime.InteropServices;
+
+namespace RGB.NET.Devices.Razer.Native
+{
+ // ReSharper disable once InconsistentNaming
+ [StructLayout(LayoutKind.Sequential, Size = sizeof(uint))]
+ internal struct _Color
+ {
+ #region Properties & Fields
+
+ public uint Color;
+
+ #endregion
+
+ #region Constructors
+
+ public _Color(byte red, byte green, byte blue)
+ : this()
+ {
+ Color = red + ((uint)green << 8) + ((uint)blue << 16);
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Native/_Defines.cs b/RGB.NET.Devices.Razer/Native/_Defines.cs
new file mode 100644
index 0000000..2c0c724
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Native/_Defines.cs
@@ -0,0 +1,25 @@
+namespace RGB.NET.Devices.Razer.Native
+{
+ internal static class _Defines
+ {
+ internal const int EFFECT_ID = 7;
+
+ internal const int KEYBOARD_MAX_ROW = 6;
+ internal const int KEYBOARD_MAX_COLUMN = 22;
+ internal const int KEYBOARD_MAX_LEDS = KEYBOARD_MAX_ROW * KEYBOARD_MAX_COLUMN;
+
+ internal const int MOUSE_MAX_ROW = 9;
+ internal const int MOUSE_MAX_COLUMN = 7;
+ internal const int MOUSE_MAX_LEDS = KEYBOARD_MAX_ROW * KEYBOARD_MAX_COLUMN;
+
+ internal const int HEADSET_MAX_LEDS = 5;
+
+ internal const int MOUSEPAD_MAX_LEDS = 15;
+
+ internal const int KEYPAD_MAX_ROW = 4;
+ internal const int KEYPAD_MAX_COLUMN = 5;
+ internal const int KEYPAD_MAX_LEDS = KEYPAD_MAX_ROW * KEYPAD_MAX_COLUMN;
+
+ internal const int CHROMALINK_MAX_LEDS = 5;
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Native/_DeviceInfo.cs b/RGB.NET.Devices.Razer/Native/_DeviceInfo.cs
new file mode 100644
index 0000000..0b465c3
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Native/_DeviceInfo.cs
@@ -0,0 +1,27 @@
+#pragma warning disable 169 // Field 'x' is never used
+#pragma warning disable 414 // Field 'x' is assigned but its value never used
+#pragma warning disable 649 // Field 'x' is never assigned
+// ReSharper disable MemberCanBePrivate.Global
+
+using System.Runtime.InteropServices;
+
+namespace RGB.NET.Devices.Razer.Native
+{
+ // ReSharper disable once InconsistentNaming
+ ///
+ /// Razer-SDK: Device info.
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct _DeviceInfo
+ {
+ ///
+ /// Razer-SDK: Device types.
+ ///
+ internal DeviceType Type;
+
+ ///
+ /// Razer-SDK: Number of devices connected.
+ ///
+ internal int Connected;
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Native/_HeadsetCustomEffect.cs b/RGB.NET.Devices.Razer/Native/_HeadsetCustomEffect.cs
new file mode 100644
index 0000000..d3bcdb3
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Native/_HeadsetCustomEffect.cs
@@ -0,0 +1,11 @@
+using System.Runtime.InteropServices;
+
+namespace RGB.NET.Devices.Razer.Native
+{
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct _HeadsetCustomEffect
+ {
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = _Defines.HEADSET_MAX_LEDS)]
+ public _Color[] Color;
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Native/_KeyboardCustomEffect.cs b/RGB.NET.Devices.Razer/Native/_KeyboardCustomEffect.cs
new file mode 100644
index 0000000..5e9294f
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Native/_KeyboardCustomEffect.cs
@@ -0,0 +1,11 @@
+using System.Runtime.InteropServices;
+
+namespace RGB.NET.Devices.Razer.Native
+{
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct _KeyboardCustomEffect
+ {
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = _Defines.KEYBOARD_MAX_LEDS)]
+ public _Color[] Color;
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Native/_KeypadCustomEffect.cs b/RGB.NET.Devices.Razer/Native/_KeypadCustomEffect.cs
new file mode 100644
index 0000000..a08a175
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Native/_KeypadCustomEffect.cs
@@ -0,0 +1,11 @@
+using System.Runtime.InteropServices;
+
+namespace RGB.NET.Devices.Razer.Native
+{
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct _KeypadCustomEffect
+ {
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = _Defines.KEYPAD_MAX_LEDS)]
+ public _Color[] Color;
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Native/_MouseCustomEffect.cs b/RGB.NET.Devices.Razer/Native/_MouseCustomEffect.cs
new file mode 100644
index 0000000..a5e1599
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Native/_MouseCustomEffect.cs
@@ -0,0 +1,11 @@
+using System.Runtime.InteropServices;
+
+namespace RGB.NET.Devices.Razer.Native
+{
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct _MouseCustomEffect
+ {
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = _Defines.MOUSE_MAX_LEDS)]
+ public _Color[] Color;
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Native/_MousepadCustomEffect.cs b/RGB.NET.Devices.Razer/Native/_MousepadCustomEffect.cs
new file mode 100644
index 0000000..01368bf
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Native/_MousepadCustomEffect.cs
@@ -0,0 +1,11 @@
+using System.Runtime.InteropServices;
+
+namespace RGB.NET.Devices.Razer.Native
+{
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct _MousepadCustomEffect
+ {
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = _Defines.MOUSEPAD_MAX_LEDS)]
+ public _Color[] Color;
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Native/_RazerSDK.cs b/RGB.NET.Devices.Razer/Native/_RazerSDK.cs
new file mode 100644
index 0000000..af6310b
--- /dev/null
+++ b/RGB.NET.Devices.Razer/Native/_RazerSDK.cs
@@ -0,0 +1,146 @@
+// ReSharper disable UnusedMethodReturnValue.Global
+// ReSharper disable UnusedMember.Global
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using RGB.NET.Core.Exceptions;
+
+namespace RGB.NET.Devices.Razer.Native
+{
+ // ReSharper disable once InconsistentNaming
+ internal static class _RazerSDK
+ {
+ #region Libary Management
+
+ private static IntPtr _dllHandle = IntPtr.Zero;
+
+ ///
+ /// Gets the loaded architecture (x64/x86).
+ ///
+ internal static string LoadedArchitecture { get; private set; }
+
+ ///
+ /// Reloads the SDK.
+ ///
+ internal static void Reload()
+ {
+ UnloadRazerSDK();
+ LoadRazerSDK();
+ }
+
+ private static void LoadRazerSDK()
+ {
+ if (_dllHandle != IntPtr.Zero) return;
+
+ // HACK: Load library at runtime to support both, x86 and x64 with one managed dll
+ List possiblePathList = Environment.Is64BitProcess ? RazerDeviceProvider.PossibleX64NativePaths : RazerDeviceProvider.PossibleX86NativePaths;
+ string dllPath = possiblePathList.FirstOrDefault(File.Exists);
+ if (dllPath == null) throw new RGBDeviceException($"Can't find the Razer-SDK at one of the expected locations:\r\n '{string.Join("\r\n", possiblePathList.Select(Path.GetFullPath))}'");
+
+ _dllHandle = LoadLibrary(dllPath);
+
+ _initPointer = (InitPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "Init"), typeof(InitPointer));
+ _unInitPointer = (UnInitPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "UnInit"), typeof(UnInitPointer));
+ _queryDevicePointer = (QueryDevicePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "QueryDevice"), typeof(QueryDevicePointer));
+ _createEffectPointer = (CreateEffectPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CreateEffect"), typeof(CreateEffectPointer));
+ _setEffectPointer = (SetEffectPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "SetEffect"), typeof(SetEffectPointer));
+ _deleteEffectPointer = (DeleteEffectPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "DeleteEffect"), typeof(DeleteEffectPointer));
+ }
+
+ private static void UnloadRazerSDK()
+ {
+ if (_dllHandle == IntPtr.Zero) return;
+
+ // ReSharper disable once EmptyEmbeddedStatement - DarthAffe 09.11.2017: We might need to reduce the internal reference counter more than once to set the library free
+ while (FreeLibrary(_dllHandle)) ;
+ _dllHandle = IntPtr.Zero;
+ }
+
+ [DllImport("kernel32.dll")]
+ private static extern IntPtr LoadLibrary(string dllToLoad);
+
+ [DllImport("kernel32.dll")]
+ private static extern bool FreeLibrary(IntPtr dllHandle);
+
+ [DllImport("kernel32.dll")]
+ private static extern IntPtr GetProcAddress(IntPtr dllHandle, string name);
+
+ #endregion
+
+ #region SDK-METHODS
+
+ #region Pointers
+
+ private static InitPointer _initPointer;
+ private static UnInitPointer _unInitPointer;
+ private static QueryDevicePointer _queryDevicePointer;
+ private static CreateEffectPointer _createEffectPointer;
+ private static SetEffectPointer _setEffectPointer;
+ private static DeleteEffectPointer _deleteEffectPointer;
+
+ #endregion
+
+ #region Delegates
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate RazerError InitPointer();
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate RazerError UnInitPointer();
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate RazerError QueryDevicePointer(Guid deviceId, IntPtr deviceInfo);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate RazerError CreateEffectPointer(Guid deviceId, int effectType, IntPtr param, ref Guid effectId);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate RazerError SetEffectPointer(Guid effectId);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate RazerError DeleteEffectPointer(Guid effectId);
+
+ #endregion
+
+ // ReSharper disable EventExceptionNotDocumented
+
+ ///
+ /// Razer-SDK: Initialize Chroma SDK.
+ ///
+ internal static RazerError Init() => _initPointer();
+
+ ///
+ /// Razer-SDK: UnInitialize Chroma SDK.
+ ///
+ internal static RazerError UnInit() => _unInitPointer();
+
+ ///
+ /// Razer-SDK: Query for device information.
+ ///
+ internal static RazerError QueryDevice(Guid deviceId, out _DeviceInfo deviceInfo)
+ {
+ int structSize = Marshal.SizeOf(typeof(_DeviceInfo));
+ IntPtr deviceInfoPtr = Marshal.AllocHGlobal(structSize);
+
+ RazerError error = _queryDevicePointer(deviceId, deviceInfoPtr);
+
+ deviceInfo = (_DeviceInfo)Marshal.PtrToStructure(deviceInfoPtr, typeof(_DeviceInfo));
+ Marshal.FreeHGlobal(deviceInfoPtr);
+
+ return error;
+ }
+
+ internal static RazerError CreateEffect(Guid deviceId, int effectType, IntPtr param, ref Guid effectId) => _createEffectPointer(deviceId, effectType, param, ref effectId);
+
+ internal static RazerError SetEffect(Guid effectId) => _setEffectPointer(effectId);
+
+ internal static RazerError DeleteEffect(Guid effectId) => _deleteEffectPointer(effectId);
+
+ // ReSharper restore EventExceptionNotDocumented
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Razer/Properties/AssemblyInfo.cs b/RGB.NET.Devices.Razer/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..220a7ac
--- /dev/null
+++ b/RGB.NET.Devices.Razer/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.Razer")]
+[assembly: AssemblyDescription("Razer-Device-Implementations of RGB.NET")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Wyrez")]
+[assembly: AssemblyProduct("RGB.NET.Devices.Razer")]
+[assembly: AssemblyCopyright("Copyright © Wyrez 2017")]
+[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("24ff4acb-d679-4b2d-86d4-50ab6c02d816")]
+
+// 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.Razer/RGB.NET.Devices.Razer.csproj b/RGB.NET.Devices.Razer/RGB.NET.Devices.Razer.csproj
new file mode 100644
index 0000000..11919f7
--- /dev/null
+++ b/RGB.NET.Devices.Razer/RGB.NET.Devices.Razer.csproj
@@ -0,0 +1,105 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {24FF4ACB-D679-4B2D-86D4-50AB6C02D816}
+ Library
+ Properties
+ RGB.NET.Devices.Razer
+ RGB.NET.Devices.Razer
+ v4.5
+ 512
+
+
+ true
+ full
+ false
+ ..\bin\
+ DEBUG;TRACE
+ prompt
+ 4
+ ..\bin\RGB.NET.Devices.Razer.xml
+
+
+ pdbonly
+ true
+ ..\bin\
+ TRACE
+ prompt
+ 4
+ ..\bin\RGB.NET.Devices.Razer.xml
+
+
+
+
+
+ ..\packages\System.ValueTuple.4.3.1\lib\netstandard1.0\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {5a4f9a75-75fe-47cd-90e5-914d5b20d232}
+ RGB.NET.Core
+
+
+
+
+
+
+
+
+ Designer
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/RGB.NET.Devices.Razer/RGB.NET.Devices.Razer.csproj.DotSettings b/RGB.NET.Devices.Razer/RGB.NET.Devices.Razer.csproj.DotSettings
new file mode 100644
index 0000000..1e5aa14
--- /dev/null
+++ b/RGB.NET.Devices.Razer/RGB.NET.Devices.Razer.csproj.DotSettings
@@ -0,0 +1,11 @@
+
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
+ True
\ No newline at end of file
diff --git a/RGB.NET.Devices.Razer/RazerDeviceProvider.cs b/RGB.NET.Devices.Razer/RazerDeviceProvider.cs
new file mode 100644
index 0000000..1114dd0
--- /dev/null
+++ b/RGB.NET.Devices.Razer/RazerDeviceProvider.cs
@@ -0,0 +1,218 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Globalization;
+using System.Linq;
+using RGB.NET.Core;
+using RGB.NET.Devices.Razer.Native;
+
+namespace RGB.NET.Devices.Razer
+{
+ ///
+ ///
+ /// Represents a device provider responsible for razer devices.
+ ///
+ public class RazerDeviceProvider : IRGBDeviceProvider
+ {
+ #region Properties & Fields
+
+ private static RazerDeviceProvider _instance;
+ ///
+ /// Gets the singleton instance.
+ ///
+ public static RazerDeviceProvider Instance => _instance ?? new RazerDeviceProvider();
+
+ ///
+ /// Gets a modifiable list of paths used to find the native SDK-dlls for x86 applications.
+ /// The first match will be used.
+ ///
+ public static List PossibleX86NativePaths { get; } = new List { "x86/RzChromaSDK.dll" };
+
+ ///
+ /// Gets a modifiable list of paths used to find the native SDK-dlls for x64 applications.
+ /// The first match will be used.
+ ///
+ public static List PossibleX64NativePaths { get; } = new List { "x64/RzChromaSDK.dll", "x64/RzChromaSDK64.dll" };
+
+ ///
+ ///
+ /// Indicates if the SDK is initialized and ready to use.
+ ///
+ public bool IsInitialized { get; private set; }
+
+ ///
+ /// Gets the loaded architecture (x64/x86).
+ ///
+ public string LoadedArchitecture => _RazerSDK.LoadedArchitecture;
+
+ ///
+ ///
+ /// Gets whether the application has exclusive access to the SDK or not.
+ ///
+ public bool HasExclusiveAccess => false;
+
+ ///
+ public IEnumerable Devices { get; private set; }
+
+ ///
+ /// Gets or sets a function to get the culture for a specific device.
+ ///
+ public Func GetCulture { get; set; } = CultureHelper.GetCurrentCulture;
+
+ ///
+ /// Forces to load the devices represented by the emulator even if they aren't reported to exist.
+ ///
+ public bool LoadEmulatorDevices { get; set; } = false;
+
+ #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 RazerDeviceProvider()
+ {
+ if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(RazerDeviceProvider)}");
+ _instance = this;
+ }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool exclusiveAccessIfPossible = false, bool throwExceptions = false)
+ {
+ if (IsInitialized)
+ TryUnInit();
+
+ IsInitialized = false;
+
+ try
+ {
+ _RazerSDK.Reload();
+
+ RazerError error;
+ if ((error = _RazerSDK.Init()) != RazerError.Success)
+ ThrowRazerError(error);
+
+ IList devices = new List();
+
+ 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 RazerKeyboardRGBDevice(new RazerKeyboardRGBDeviceInfo(guid, model, GetCulture()));
+ device.Initialize();
+ 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 RazerMouseRGBDevice(new RazerMouseRGBDeviceInfo(guid, model));
+ device.Initialize();
+ 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 RazerHeadsetRGBDevice(new RazerHeadsetRGBDeviceInfo(guid, model));
+ device.Initialize();
+ 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 RazerMousepadRGBDevice(new RazerMousepadRGBDeviceInfo(guid, model));
+ device.Initialize();
+ 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 RazerKeypadRGBDevice(new RazerKeypadRGBDeviceInfo(guid, model));
+ device.Initialize();
+ 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 RazerChromaLinkRGBDevice(new RazerChromaLinkRGBDeviceInfo(guid, model));
+ device.Initialize();
+ devices.Add(device);
+ }
+ catch { if (throwExceptions) throw; }
+
+ Devices = new ReadOnlyCollection(devices);
+ IsInitialized = true;
+ }
+ catch
+ {
+ TryUnInit();
+ if (throwExceptions) throw;
+ return false;
+ }
+
+ return true;
+ }
+
+ ///
+ public void ResetDevices()
+ {
+ foreach (IRGBDevice device in Devices)
+ ((IRazerRGBDevice)device).Reset();
+ }
+
+ private void ThrowRazerError(RazerError errorCode) => throw new RazerException(errorCode);
+
+ private void TryUnInit()
+ {
+ try
+ {
+ _RazerSDK.UnInit();
+ }
+ catch { /* We tried our best */ }
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Razer/libs/x64/RzChromaSDK.dll b/RGB.NET.Devices.Razer/libs/x64/RzChromaSDK.dll
new file mode 100644
index 0000000..0ec6585
Binary files /dev/null and b/RGB.NET.Devices.Razer/libs/x64/RzChromaSDK.dll differ
diff --git a/RGB.NET.Devices.Razer/libs/x86/RzChromaSDK.dll b/RGB.NET.Devices.Razer/libs/x86/RzChromaSDK.dll
new file mode 100644
index 0000000..fa948a2
Binary files /dev/null and b/RGB.NET.Devices.Razer/libs/x86/RzChromaSDK.dll differ
diff --git a/RGB.NET.Devices.Razer/packages.config b/RGB.NET.Devices.Razer/packages.config
new file mode 100644
index 0000000..d352211
--- /dev/null
+++ b/RGB.NET.Devices.Razer/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/RGB.NET.Devices.Razer/targets/RGB.NET.Devices.Razer.targets b/RGB.NET.Devices.Razer/targets/RGB.NET.Devices.Razer.targets
new file mode 100644
index 0000000..6338df1
--- /dev/null
+++ b/RGB.NET.Devices.Razer/targets/RGB.NET.Devices.Razer.targets
@@ -0,0 +1,150 @@
+
+
+
+
+
+
+
+
+
+
+ False
+
+
+ False
+
+
+
+
+
+
+
+ %(RecursiveDir)%(FileName)%(Extension)
+ Always
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ bin\%(RecursiveDir)%(Filename)%(Extension)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(PostBuildEventDependsOn);
+ CopyRazerSDKFiles;
+
+
+ $(BuildDependsOn);
+ CopyRazerSDKFiles;
+
+
+ $(CleanDependsOn);
+ CleanRazerSDKFiles;
+
+
+
+
+
+
+
+ CollectRazerSDKFiles;
+ $(PipelineCollectFilesPhaseDependsOn);
+
+
+
diff --git a/RGB.NET.sln b/RGB.NET.sln
index 5944be8..1869c69 100644
--- a/RGB.NET.sln
+++ b/RGB.NET.sln
@@ -34,12 +34,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NuGet", "NuGet", "{06416566
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
- NuGet\RGB.NET.Devices.nuspec = NuGet\RGB.NET.Devices.nuspec
+ NuGet\RGB.NET.Devices.Razer.nuspec = NuGet\RGB.NET.Devices.Razer.nuspec
NuGet\RGB.NET.Groups.nuspec = NuGet\RGB.NET.Groups.nuspec
NuGet\RGB.NET.Input.Corsair.nuspec = NuGet\RGB.NET.Input.Corsair.nuspec
NuGet\RGB.NET.Input.nuspec = NuGet\RGB.NET.Input.nuspec
- NuGet\RGB.NET.nuspec = NuGet\RGB.NET.nuspec
- NuGet\RGB.NET.Presets.nuspec = NuGet\RGB.NET.Presets.nuspec
NuGet\RGB.NET.WPF.nuspec = NuGet\RGB.NET.WPF.nuspec
EndProjectSection
EndProject
@@ -70,6 +68,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Metapackages", "Metapackage
NuGet\Metapackages\RGB.NET.Presets.nuspec = NuGet\Metapackages\RGB.NET.Presets.nuspec
EndProjectSection
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
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -128,6 +128,10 @@ Global
{4EFD77C7-FDB4-4C6B-970C-0EF66D24BE09}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4EFD77C7-FDB4-4C6B-970C-0EF66D24BE09}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4EFD77C7-FDB4-4C6B-970C-0EF66D24BE09}.Release|Any CPU.Build.0 = Release|Any CPU
+ {24FF4ACB-D679-4B2D-86D4-50AB6C02D816}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -146,6 +150,7 @@ Global
{4F2F3FBD-A1E4-4968-A2AD-0514959E5E59} = {33D5E279-1C4E-4AB6-9D1E-6D18109A6C25}
{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}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {CDECA6C7-8D18-4AF3-94F7-C70A69B8571B}