diff --git a/NuGet/RGB.NET.Devices.Msi.nuspec b/NuGet/RGB.NET.Devices.Msi.nuspec
new file mode 100644
index 0000000..290a154
--- /dev/null
+++ b/NuGet/RGB.NET.Devices.Msi.nuspec
@@ -0,0 +1,32 @@
+
+
+
+ RGB.NET.Devices.Msi
+ RGB.NET.Devices.Msi
+ 1.0.0.0
+ Darth Affe
+ Darth Affe
+ https://github.com/DarthAffe/RGB.NET
+ https://raw.githubusercontent.com/DarthAffe/RGB.NET/master/LICENSE
+ true
+ Msi-Device-Implementations of RGB.NET
+
+ Msi-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.Msi/Enum/MsiLedIds.cs b/RGB.NET.Devices.Msi/Enum/MsiLedIds.cs
new file mode 100644
index 0000000..f290849
--- /dev/null
+++ b/RGB.NET.Devices.Msi/Enum/MsiLedIds.cs
@@ -0,0 +1,16 @@
+// ReSharper disable InconsistentNaming
+
+#pragma warning disable 1591 // Missing XML comment for publicly visible type or member
+
+namespace RGB.NET.Devices.Msi
+{
+ ///
+ /// Contains list of all LEDs available for all Msi devices.
+ ///
+ public enum MsiLedIds
+ {
+ Invalid = -1,
+
+ //TODO DarthAffe 11.11.2017: Create useful Ids for all devices
+ }
+}
diff --git a/RGB.NET.Devices.Msi/Exceptions/MysticLightException.cs b/RGB.NET.Devices.Msi/Exceptions/MysticLightException.cs
new file mode 100644
index 0000000..d36665b
--- /dev/null
+++ b/RGB.NET.Devices.Msi/Exceptions/MysticLightException.cs
@@ -0,0 +1,44 @@
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable MemberCanBePrivate.Global
+
+using System;
+
+namespace RGB.NET.Devices.Msi.Exceptions
+{
+ ///
+ ///
+ /// Represents an exception thrown by the MysticLight-SDK.
+ ///
+ public class MysticLightException : ApplicationException
+ {
+ #region Properties & Fields
+
+ ///
+ /// Gets the raw error code provided by the SDK.
+ ///
+ public int ErrorCode { get; }
+
+ ///
+ /// Gets the text-description the resolves too.
+ ///
+ public string Description { get; }
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The raw error code provided by the SDK.
+ /// The text-description of the error.
+ public MysticLightException(int errorCode, string description)
+ {
+ this.ErrorCode = errorCode;
+ this.Description = description;
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Msi/Generic/MsiLedId.cs b/RGB.NET.Devices.Msi/Generic/MsiLedId.cs
new file mode 100644
index 0000000..a69bf86
--- /dev/null
+++ b/RGB.NET.Devices.Msi/Generic/MsiLedId.cs
@@ -0,0 +1,111 @@
+using System.Diagnostics;
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.Msi
+{
+ ///
+ ///
+ /// Represents a Id of a on a .
+ ///
+ [DebuggerDisplay("{" + nameof(LedId) + "}")]
+ public class MsiLedId : ILedId
+ {
+ #region Properties & Fields
+
+ internal readonly MsiLedIds LedId;
+
+ internal readonly int Index;
+
+ ///
+ public IRGBDevice Device { get; }
+
+ ///
+ public bool IsValid => LedId != MsiLedIds.Invalid;
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The the belongs to.
+ /// The of the represented .
+ public MsiLedId(IRGBDevice device, MsiLedIds ledId)
+ {
+ this.Device = device;
+ this.LedId = ledId;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The the belongs to.
+ /// The of the represented .
+ /// The index in the mapping array of the device.
+ public MsiLedId(IRGBDevice device, MsiLedIds ledId, int index)
+ {
+ this.Device = device;
+ this.LedId = ledId;
+ 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() => LedId.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)
+ {
+ MsiLedId compareLedId = obj as MsiLedId;
+ if (ReferenceEquals(compareLedId, null))
+ return false;
+
+ if (ReferenceEquals(this, compareLedId))
+ return true;
+
+ if (GetType() != compareLedId.GetType())
+ return false;
+
+ return compareLedId.LedId == LedId;
+ }
+
+ ///
+ /// Returns a hash code for this .
+ ///
+ /// An integer value that specifies the hash code for this .
+ public override int GetHashCode() => LedId.GetHashCode();
+
+ #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 ==(MsiLedId ledId1, MsiLedId 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 !=(MsiLedId ledId1, MsiLedId ledId2) => !(ledId1 == ledId2);
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Msi/Generic/MsiRGBDevice.cs b/RGB.NET.Devices.Msi/Generic/MsiRGBDevice.cs
new file mode 100644
index 0000000..ad8a25f
--- /dev/null
+++ b/RGB.NET.Devices.Msi/Generic/MsiRGBDevice.cs
@@ -0,0 +1,117 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using RGB.NET.Core;
+using RGB.NET.Core.Layout;
+using RGB.NET.Devices.Msi.Native;
+
+namespace RGB.NET.Devices.Msi
+{
+ ///
+ ///
+ /// Represents a generic Msi-device. (keyboard, mouse, headset, mousepad).
+ ///
+ public abstract class MsiRGBDevice : AbstractRGBDevice
+ {
+ #region Properties & Fields
+
+ ///
+ ///
+ /// Gets information about the .
+ ///
+ public override IRGBDeviceInfo DeviceInfo { get; }
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The generic information provided by Msi for the device.
+ protected MsiRGBDevice(IRGBDeviceInfo info)
+ {
+ this.DeviceInfo = info;
+ }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ /// Initializes the device.
+ ///
+ internal void Initialize()
+ {
+ InitializeLayout();
+
+ if (InternalSize == null)
+ {
+ Rectangle ledRectangle = new Rectangle(this.Select(x => x.LedRectangle));
+ InternalSize = 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));
+
+ InternalSize = new Size(layout.Width, layout.Height);
+
+ if (layout.Leds != null)
+ foreach (LedLayout layoutLed in layout.Leds)
+ {
+ if (Enum.TryParse(layoutLed.Id, true, out MsiLedIds ledId))
+ {
+ if (LedMapping.TryGetValue(new MsiLedId(this, ledId), out Led led))
+ {
+ led.LedRectangle.Location.X = layoutLed.X;
+ led.LedRectangle.Location.Y = layoutLed.Y;
+ led.LedRectangle.Size.Width = layoutLed.Width;
+ led.LedRectangle.Size.Height = 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)
+ {
+ string deviceType = ((MsiRGBDeviceInfo)DeviceInfo).MsiDeviceType;
+ foreach (Led led in leds)
+ _MsiSDK.SetLedColor(deviceType, ((MsiLedId)led.Id).Index, led.Color.R, led.Color.G, led.Color.B);
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Msi/Generic/MsiRGBDeviceInfo.cs b/RGB.NET.Devices.Msi/Generic/MsiRGBDeviceInfo.cs
new file mode 100644
index 0000000..7ce90fc
--- /dev/null
+++ b/RGB.NET.Devices.Msi/Generic/MsiRGBDeviceInfo.cs
@@ -0,0 +1,52 @@
+using System;
+using RGB.NET.Core;
+
+namespace RGB.NET.Devices.Msi
+{
+ ///
+ ///
+ /// Represents a generic information for a Corsair-.
+ ///
+ public class MsiRGBDeviceInfo : IRGBDeviceInfo
+ {
+ #region Properties & Fields
+
+ ///
+ public RGBDeviceType DeviceType { get; }
+
+ public string MsiDeviceType { get; }
+
+ ///
+ public string Manufacturer { get; }
+
+ ///
+ public string Model { get; }
+
+ ///
+ public Uri Image { get; protected set; }
+
+ ///
+ public RGBDeviceLighting Lighting => RGBDeviceLighting.Key;
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Internal constructor of managed .
+ ///
+ /// The type of the .
+ /// The internal type of the .
+ /// The manufacturer-name of the .
+ /// The model-name of the .
+ internal MsiRGBDeviceInfo(RGBDeviceType deviceType, string msiDeviceType, string manufacturer = "Msi", string model = "Generic Msi-Device")
+ {
+ this.DeviceType = deviceType;
+ this.MsiDeviceType = msiDeviceType;
+ this.Manufacturer = manufacturer;
+ this.Model = model;
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Msi/Layouts/DeviceLayout.xsd b/RGB.NET.Devices.Msi/Layouts/DeviceLayout.xsd
new file mode 100644
index 0000000..92690b3
--- /dev/null
+++ b/RGB.NET.Devices.Msi/Layouts/DeviceLayout.xsd
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/RGB.NET.Devices.Msi/MsiDeviceProvider.cs b/RGB.NET.Devices.Msi/MsiDeviceProvider.cs
new file mode 100644
index 0000000..1d69325
--- /dev/null
+++ b/RGB.NET.Devices.Msi/MsiDeviceProvider.cs
@@ -0,0 +1,131 @@
+// ReSharper disable MemberCanBePrivate.Global
+// ReSharper disable UnusedMember.Global
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Globalization;
+using RGB.NET.Core;
+using RGB.NET.Devices.Msi.Exceptions;
+using RGB.NET.Devices.Msi.Native;
+
+namespace RGB.NET.Devices.Msi
+{
+ ///
+ ///
+ /// Represents a device provider responsible for Cooler Master devices.
+ ///
+ public class MsiDeviceProvider : IRGBDeviceProvider
+ {
+ #region Properties & Fields
+
+ private static MsiDeviceProvider _instance;
+ ///
+ /// Gets the singleton instance.
+ ///
+ public static MsiDeviceProvider Instance => _instance ?? new MsiDeviceProvider();
+
+ ///
+ /// 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/MysticLight_SDK.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/MysticLight_SDK.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 => _MsiSDK.LoadedArchitecture;
+
+ ///
+ ///
+ /// Gets whether the application has exclusive access to the SDK or not.
+ ///
+ public bool HasExclusiveAccess { get; private set; }
+
+ ///
+ 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;
+
+ #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 MsiDeviceProvider()
+ {
+ if (_instance != null) throw new InvalidOperationException($"There can be only one instanc of type {nameof(MsiDeviceProvider)}");
+ _instance = this;
+ }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ public bool Initialize(bool exclusiveAccessIfPossible = false, bool throwExceptions = false)
+ {
+ IsInitialized = false;
+
+ try
+ {
+ _MsiSDK.Reload();
+
+ IList devices = new List();
+
+ int errorCode;
+ if ((errorCode = _MsiSDK.Initialize()) != 0)
+ ThrowMsiError(errorCode);
+
+ if ((errorCode = _MsiSDK.GetDeviceInfo(out string[] deviceTypes, out int[] ledCounts)) != 0)
+ ThrowMsiError(errorCode);
+
+ for (int i = 0; i < deviceTypes.Length; i++)
+ {
+ //TODO DarthAffe 11.11.2017: What is this deviceType? Find someone to try that out
+ }
+
+ Devices = new ReadOnlyCollection(devices);
+ }
+ catch
+ {
+ if (throwExceptions)
+ throw;
+ else
+ return false;
+ }
+
+ IsInitialized = true;
+
+ return true;
+ }
+
+ private void ThrowMsiError(int errorCode) => throw new MysticLightException(errorCode, _MsiSDK.GetErrorMessage(errorCode));
+
+ ///
+ public void ResetDevices()
+ {
+ //TODO DarthAffe 11.11.2017: Implement
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Msi/Native/_MsiSDK.cs b/RGB.NET.Devices.Msi/Native/_MsiSDK.cs
new file mode 100644
index 0000000..8504094
--- /dev/null
+++ b/RGB.NET.Devices.Msi/Native/_MsiSDK.cs
@@ -0,0 +1,175 @@
+// 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.Msi.Native
+{
+ // ReSharper disable once InconsistentNaming
+ internal static class _MsiSDK
+ {
+ #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()
+ {
+ UnloadMsiSDK();
+ LoadMsiSDK();
+ }
+
+ private static void LoadMsiSDK()
+ {
+ if (_dllHandle != IntPtr.Zero) return;
+
+ // HACK: Load library at runtime to support both, x86 and x64 with one managed dll
+ List possiblePathList = Environment.Is64BitProcess ? MsiDeviceProvider.PossibleX64NativePaths : MsiDeviceProvider.PossibleX86NativePaths;
+ string dllPath = possiblePathList.FirstOrDefault(File.Exists);
+ if (dllPath == null) throw new RGBDeviceException($"Can't find the Msi-SDK at one of the expected locations:\r\n '{string.Join("\r\n", possiblePathList.Select(Path.GetFullPath))}'");
+
+ SetDllDirectory(Path.GetDirectoryName(Path.GetFullPath(dllPath)));
+
+ _dllHandle = LoadLibrary(dllPath);
+
+ _initializePointer = (InitializePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_Initialize"), typeof(InitializePointer));
+ _getDeviceInfoPointer = (GetDeviceInfoPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_GetDeviceInfo"), typeof(GetDeviceInfoPointer));
+ _getLedInfoPointer = (GetLedInfoPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_GetLedInfo"), typeof(GetLedInfoPointer));
+ _getLedColorPointer = (GetLedColorPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_GetLedColor"), typeof(GetLedColorPointer));
+ _getLedStylePointer = (GetLedStylePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_GetLedStyle"), typeof(GetLedStylePointer));
+ _getLedMaxBrightPointer = (GetLedMaxBrightPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_GetLedMaxBright"), typeof(GetLedMaxBrightPointer));
+ _getLedBrightPointer = (GetLedBrightPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_GetLedBright"), typeof(GetLedBrightPointer));
+ _getLedMaxSpeedPointer = (GetLedMaxSpeedPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_GetLedMaxSpeed"), typeof(GetLedMaxSpeedPointer));
+ _getLedSpeedPointer = (GetLedSpeedPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_GetLedSpeed"), typeof(GetLedSpeedPointer));
+ _setLedColorPointer = (SetLedColorPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_SetLedColor"), typeof(SetLedColorPointer));
+ _setLedStylePointer = (SetLedStylePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_SetLedStyle"), typeof(SetLedStylePointer));
+ _setLedBrightPointer = (SetLedBrightPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_SetLedBright"), typeof(SetLedBrightPointer));
+ _setLedSpeedPointer = (SetLedSpeedPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_SetLedSpeed"), typeof(SetLedSpeedPointer));
+ _getErrorMessagePointer = (GetErrorMessagePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_GetErrorMessage"), typeof(GetErrorMessagePointer));
+ }
+
+ private static void UnloadMsiSDK()
+ {
+ if (_dllHandle == IntPtr.Zero) return;
+
+ // ReSharper disable once EmptyEmbeddedStatement - DarthAffe 07.10.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 bool SetDllDirectory(string lpPathName);
+
+ [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 InitializePointer _initializePointer;
+ private static GetDeviceInfoPointer _getDeviceInfoPointer;
+ private static GetLedInfoPointer _getLedInfoPointer;
+ private static GetLedColorPointer _getLedColorPointer;
+ private static GetLedStylePointer _getLedStylePointer;
+ private static GetLedMaxBrightPointer _getLedMaxBrightPointer;
+ private static GetLedBrightPointer _getLedBrightPointer;
+ private static GetLedMaxSpeedPointer _getLedMaxSpeedPointer;
+ private static GetLedSpeedPointer _getLedSpeedPointer;
+ private static SetLedColorPointer _setLedColorPointer;
+ private static SetLedStylePointer _setLedStylePointer;
+ private static SetLedBrightPointer _setLedBrightPointer;
+ private static SetLedSpeedPointer _setLedSpeedPointer;
+ private static GetErrorMessagePointer _getErrorMessagePointer;
+
+ #endregion
+
+ #region Delegates
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate int InitializePointer();
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate int GetDeviceInfoPointer(out string[] pDevType, out int[] pLedCount);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate int GetLedInfoPointer(string type, int index, out string pName, out string[] pLedStyles);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate int GetLedColorPointer(string type, int index, out int r, out int g, out int b);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate int GetLedStylePointer(string type, int index, out int style);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate int GetLedMaxBrightPointer(string type, int index, out int maxLevel);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate int GetLedBrightPointer(string type, int index, out int currentLevel);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate int GetLedMaxSpeedPointer(string type, int index, out int maxSpeed);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate int GetLedSpeedPointer(string type, int index, out int currentSpeed);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate int SetLedColorPointer(string type, int index, int r, int g, int b);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate int SetLedStylePointer(string type, int index, string style);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate int SetLedBrightPointer(string type, int index, int level);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate int SetLedSpeedPointer(string type, int index, int speed);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ private delegate int GetErrorMessagePointer(int errorCode, out string pDesc);
+
+ #endregion
+
+ internal static int Initialize() => _initializePointer();
+ internal static int GetDeviceInfo(out string[] pDevType, out int[] pLedCount) => _getDeviceInfoPointer(out pDevType, out pLedCount);
+ internal static int GetLedInfo(string type, int index, out string pName, out string[] pLedStyles) => _getLedInfoPointer(type, index, out pName, out pLedStyles);
+ internal static int GetLedColor(string type, int index, out int r, out int g, out int b) => _getLedColorPointer(type, index, out r, out g, out b);
+ internal static int GetLedStyle(string type, int index, out int style) => _getLedStylePointer(type, index, out style);
+ internal static int GetLedMaxBright(string type, int index, out int maxLevel) => _getLedMaxBrightPointer(type, index, out maxLevel);
+ internal static int GetLedBright(string type, int index, out int currentLevel) => _getLedBrightPointer(type, index, out currentLevel);
+ internal static int GetLedMaxSpeed(string type, int index, out int maxSpeed) => _getLedMaxSpeedPointer(type, index, out maxSpeed);
+ internal static int GetLedSpeed(string type, int index, out int currentSpeed) => _getLedSpeedPointer(type, index, out currentSpeed);
+ internal static int SetLedColor(string type, int index, int r, int g, int b) => _setLedColorPointer(type, index, r, g, b);
+ internal static int SetLedStyle(string type, int index, string style) => _setLedStylePointer(type, index, style);
+ internal static int SetLedBright(string type, int index, int level) => _setLedBrightPointer(type, index, level);
+ internal static int SetLedSpeed(string type, int index, int speed) => _setLedSpeedPointer(type, index, speed);
+
+ internal static string GetErrorMessage(int errorCode)
+ {
+ _getErrorMessagePointer(errorCode, out string description);
+ return description;
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Msi/Properties/AssemblyInfo.cs b/RGB.NET.Devices.Msi/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..addbaa2
--- /dev/null
+++ b/RGB.NET.Devices.Msi/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.Msi")]
+[assembly: AssemblyDescription("Msi-Device-Implementations of RGB.NET")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Wyrez")]
+[assembly: AssemblyProduct("RGB.NET.Devices.Msi")]
+[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("dda8c4c2-8abf-4fa0-9af9-c47ad0bfe47d")]
+
+// 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.Msi/RGB.NET.Devices.Msi.csproj b/RGB.NET.Devices.Msi/RGB.NET.Devices.Msi.csproj
new file mode 100644
index 0000000..1cca868
--- /dev/null
+++ b/RGB.NET.Devices.Msi/RGB.NET.Devices.Msi.csproj
@@ -0,0 +1,79 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {4EFD77C7-FDB4-4C6B-970C-0EF66D24BE09}
+ Library
+ Properties
+ RGB.NET.Devices.Msi
+ RGB.NET.Devices.Msi
+ v4.5
+ 512
+
+
+ true
+ full
+ false
+ ..\bin\
+ DEBUG;TRACE
+ prompt
+ 4
+ ..\bin\RGB.NET.Devices.Msi.xml
+
+
+ pdbonly
+ true
+ ..\bin\
+ TRACE
+ prompt
+ 4
+ ..\bin\RGB.NET.Devices.Msi.xml
+
+
+
+
+
+ ..\packages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Designer
+
+
+
+
+
+
+ {5a4f9a75-75fe-47cd-90e5-914d5b20d232}
+ RGB.NET.Core
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/RGB.NET.Devices.Msi/RGB.NET.Devices.Msi.csproj.DotSettings b/RGB.NET.Devices.Msi/RGB.NET.Devices.Msi.csproj.DotSettings
new file mode 100644
index 0000000..bcc9d7d
--- /dev/null
+++ b/RGB.NET.Devices.Msi/RGB.NET.Devices.Msi.csproj.DotSettings
@@ -0,0 +1,3 @@
+
+ True
+ True
\ No newline at end of file
diff --git a/RGB.NET.Devices.Msi/libs/x64/MysticLight_SDK.dll b/RGB.NET.Devices.Msi/libs/x64/MysticLight_SDK.dll
new file mode 100644
index 0000000..30bbc28
Binary files /dev/null and b/RGB.NET.Devices.Msi/libs/x64/MysticLight_SDK.dll differ
diff --git a/RGB.NET.Devices.Msi/libs/x86/MysticLight_SDK.dll b/RGB.NET.Devices.Msi/libs/x86/MysticLight_SDK.dll
new file mode 100644
index 0000000..30bbc28
Binary files /dev/null and b/RGB.NET.Devices.Msi/libs/x86/MysticLight_SDK.dll differ
diff --git a/RGB.NET.Devices.Msi/packages.config b/RGB.NET.Devices.Msi/packages.config
new file mode 100644
index 0000000..a59695c
--- /dev/null
+++ b/RGB.NET.Devices.Msi/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/RGB.NET.Devices.Msi/targets/RGB.NET.Devices.Msi.targets b/RGB.NET.Devices.Msi/targets/RGB.NET.Devices.Msi.targets
new file mode 100644
index 0000000..c3044e7
--- /dev/null
+++ b/RGB.NET.Devices.Msi/targets/RGB.NET.Devices.Msi.targets
@@ -0,0 +1,150 @@
+
+
+
+
+
+
+
+
+
+
+ False
+
+
+ False
+
+
+
+
+
+
+
+ %(RecursiveDir)%(FileName)%(Extension)
+ Always
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ bin\%(RecursiveDir)%(Filename)%(Extension)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(PostBuildEventDependsOn);
+ CopyMsiSDKFiles;
+
+
+ $(BuildDependsOn);
+ CopyMsiSDKFiles;
+
+
+ $(CleanDependsOn);
+ CleanMsiSDKFiles;
+
+
+
+
+
+
+
+ CollectMsiSDKFiles;
+ $(PipelineCollectFilesPhaseDependsOn);
+
+
+
diff --git a/RGB.NET.sln b/RGB.NET.sln
index 006cd61..1b1880a 100644
--- a/RGB.NET.sln
+++ b/RGB.NET.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
-VisualStudioVersion = 15.0.26730.16
+VisualStudioVersion = 15.0.27004.2008
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RGB.NET.Core", "RGB.NET.Core\RGB.NET.Core.csproj", "{5A4F9A75-75FE-47CD-90E5-914D5B20D232}"
EndProject
@@ -32,6 +32,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NuGet", "NuGet", "{06416566
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.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.Groups.nuspec = NuGet\RGB.NET.Groups.nuspec
NuGet\RGB.NET.Input.Corsair.nuspec = NuGet\RGB.NET.Input.Corsair.nuspec
@@ -57,6 +58,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RGB.NET.Decorators", "RGB.N
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RGB.NET.Devices.Aura", "RGB.NET.Devices.Aura\RGB.NET.Devices.Aura.csproj", "{4F2F3FBD-A1E4-4968-A2AD-0514959E5E59}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RGB.NET.Devices.Msi", "RGB.NET.Devices.Msi\RGB.NET.Devices.Msi.csproj", "{4EFD77C7-FDB4-4C6B-970C-0EF66D24BE09}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -111,6 +114,10 @@ Global
{4F2F3FBD-A1E4-4968-A2AD-0514959E5E59}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4F2F3FBD-A1E4-4968-A2AD-0514959E5E59}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4F2F3FBD-A1E4-4968-A2AD-0514959E5E59}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4EFD77C7-FDB4-4C6B-970C-0EF66D24BE09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -127,6 +134,7 @@ Global
{DB2911F6-404C-4BC8-B35F-232A7450755F} = {33D5E279-1C4E-4AB6-9D1E-6D18109A6C25}
{7012C431-244A-453F-B7FD-59E030CDBC44} = {FFBCAF88-6646-43EC-9F24-2D719D3779C8}
{4F2F3FBD-A1E4-4968-A2AD-0514959E5E59} = {33D5E279-1C4E-4AB6-9D1E-6D18109A6C25}
+ {4EFD77C7-FDB4-4C6B-970C-0EF66D24BE09} = {33D5E279-1C4E-4AB6-9D1E-6D18109A6C25}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {CDECA6C7-8D18-4AF3-94F7-C70A69B8571B}