diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj
index 3158bbcb6..ae8690d13 100644
--- a/Artemis/Artemis/Artemis.csproj
+++ b/Artemis/Artemis/Artemis.csproj
@@ -317,6 +317,8 @@
+
+
@@ -716,6 +718,9 @@
+
+ PreserveNewest
+
Always
diff --git a/Artemis/Artemis/DeviceProviders/CoolerMaster/MasterkeysProL.cs b/Artemis/Artemis/DeviceProviders/CoolerMaster/MasterkeysProL.cs
new file mode 100644
index 000000000..a5cd4bb66
--- /dev/null
+++ b/Artemis/Artemis/DeviceProviders/CoolerMaster/MasterkeysProL.cs
@@ -0,0 +1,97 @@
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Runtime.InteropServices;
+using System.Windows;
+using System.Windows.Forms;
+using Artemis.DeviceProviders.CoolerMaster.Utilities;
+using Artemis.Properties;
+using Artemis.Utilities;
+
+namespace Artemis.DeviceProviders.CoolerMaster
+{
+ public class MasterkeysProL : KeyboardProvider
+ {
+ public MasterkeysProL()
+ {
+ Name = "CM Masterkeys Pro L";
+ Slug = "cm-masterkeys-pro-l";
+
+ CantEnableText = "Couldn't connect to your CM Masterkeys Pro L.\n" +
+ "Please check your cables and try updating your CM software.\n\n" +
+ "If needed, you can select a different keyboard in Artemis under settings.";
+
+ Height = 6;
+ Width = 22;
+ // TODO
+ PreviewSettings = new PreviewSettings(665, 175, new Thickness(0, -15, 0, 0), Resources.blackwidow);
+ }
+
+ public override void Disable()
+ {
+ CmSdk.EnableLedControl(false);
+ }
+
+ public override bool CanEnable()
+ {
+ return true;
+ }
+
+ public override void Enable()
+ {
+ CmSdk.SetControlDevice(DEVICE_INDEX.DEV_MKeys_L);
+ CmSdk.EnableLedControl(true);
+ }
+
+ public override void DrawBitmap(Bitmap bitmap)
+ {
+ using (var b = ImageUtilities.ResizeImage(bitmap, Width, Height))
+ {
+ var matrix = new COLOR_MATRIX {KeyColor = new KEY_COLOR[Height, Width]};
+ for (var x = 0; x < Width; x++)
+ {
+ for (var y = 0; y < Height; y++)
+ {
+ var color = b.GetPixel(x, y);
+ matrix.KeyColor[y, x] = new KEY_COLOR(color.R, color.G, color.B);
+ }
+ }
+ CmSdk.SetAllLedColor(matrix);
+ }
+ }
+
+ public override KeyMatch? GetKeyPosition(Keys keyCode)
+ {
+ return null;
+ }
+
+ private static byte[,,] BitmapToBytes(Bitmap bitmap)
+ {
+ BitmapData bitmapData =
+ bitmap.LockBits(new Rectangle(new System.Drawing.Point(), bitmap.Size), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
+ byte[] bitmapBytes;
+ var stride = bitmapData.Stride;
+ try
+ {
+ int byteCount = bitmapData.Stride * bitmap.Height;
+ bitmapBytes = new byte[byteCount];
+ Marshal.Copy(bitmapData.Scan0, bitmapBytes, 0, byteCount);
+ }
+ finally
+ {
+ bitmap.UnlockBits(bitmapData);
+ }
+ byte[,,] result = new byte[3, bitmap.Width, bitmap.Height];
+ for (int k = 0; k < 3; k++)
+ {
+ for (int i = 0; i < bitmap.Width; i++)
+ {
+ for (int j = 0; j < bitmap.Height; j++)
+ {
+ result[k, i, j] = bitmapBytes[j * stride + i * 3 + k];
+ }
+ }
+ }
+ return result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/DeviceProviders/CoolerMaster/Utilities/CMSDK.cs b/Artemis/Artemis/DeviceProviders/CoolerMaster/Utilities/CMSDK.cs
new file mode 100644
index 000000000..a8621a27f
--- /dev/null
+++ b/Artemis/Artemis/DeviceProviders/CoolerMaster/Utilities/CMSDK.cs
@@ -0,0 +1,60 @@
+using System.Runtime.InteropServices;
+
+namespace Artemis.DeviceProviders.CoolerMaster.Utilities
+{
+
+ public struct KEY_COLOR
+ {
+ public byte r;
+ public byte g;
+ public byte b;
+
+ public KEY_COLOR(byte colR, byte colG, byte colB)
+ {
+ r = colR;
+ g = colG;
+ b = colB;
+ }
+ }
+
+ // set up/save the whole LED color structure
+
+ public struct COLOR_MATRIX
+ {
+ [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 132)]
+ public KEY_COLOR[,] KeyColor;
+ }
+
+ //Enumeration of device list
+ public enum DEVICE_INDEX
+ {
+ DEV_MKeys_L = 0,
+ DEV_MKeys_S = 1,
+ DEV_MKeys_L_White = 2,
+ DEV_MKeys_M_White = 3,
+ DEV_MMouse_L = 4
+ }
+
+ //Enumeration of device layout
+ public enum LAYOUT_KEYBOARD
+ {
+ LAYOUT_UNINIT = 0,
+ LAYOUT_US = 1,
+ LAYOUT_EU = 2
+ }
+
+ public static class CmSdk
+ {
+ [DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void SetControlDevice(DEVICE_INDEX devIndex);
+
+ [DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
+ public static extern bool EnableLedControl(bool bEnable);
+
+ [DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
+ public static extern bool SetLedColor(int iRow, int iColumn, byte r, byte g, byte b);
+
+ [DllImport("lib\\SDKDLL ", CallingConvention = CallingConvention.Cdecl)]
+ public static extern bool SetAllLedColor(COLOR_MATRIX colorMatrix);
+ }
+}
\ No newline at end of file
diff --git a/Artemis/Artemis/InjectionModules/DeviceModules.cs b/Artemis/Artemis/InjectionModules/DeviceModules.cs
index 86ecdcc59..d250abf40 100644
--- a/Artemis/Artemis/InjectionModules/DeviceModules.cs
+++ b/Artemis/Artemis/InjectionModules/DeviceModules.cs
@@ -1,4 +1,5 @@
using Artemis.DeviceProviders;
+using Artemis.DeviceProviders.CoolerMaster;
using Artemis.DeviceProviders.Corsair;
using Artemis.DeviceProviders.Logitech;
using Artemis.DeviceProviders.Razer;
@@ -15,6 +16,7 @@ namespace Artemis.InjectionModules
Bind().To().InSingletonScope();
Bind().To().InSingletonScope();
Bind().To().InSingletonScope();
+ Bind().To().InSingletonScope();
// Mice
Bind().To().InSingletonScope();
diff --git a/Artemis/Artemis/lib/SDKDLL.dll b/Artemis/Artemis/lib/SDKDLL.dll
new file mode 100644
index 000000000..279981433
Binary files /dev/null and b/Artemis/Artemis/lib/SDKDLL.dll differ