1
0
mirror of https://github.com/DarthAffe/RGB.NET.git synced 2025-12-12 17:48:31 +00:00

Added basic CoolerMaster support

This commit is contained in:
Darth Affe 2017-04-02 11:41:32 +02:00
parent 8446b9a47b
commit 8cc4688932
23 changed files with 1220 additions and 2 deletions

View File

@ -0,0 +1,34 @@
using System;
using RGB.NET.Core;
namespace RGB.NET.Devices.CoolerMaster.Attributes
{
/// <summary>
/// Specifies the <see cref="RGBDeviceType"/> of a field.
/// </summary>
[AttributeUsage(AttributeTargets.Field)]
public class DeviceTypeAttribute : Attribute
{
#region Properties & Fields
/// <summary>
/// Gets the <see cref="RGBDeviceType"/>.
/// </summary>
public RGBDeviceType DeviceType { get; }
#endregion
#region Constructors
/// <summary>
/// Internal constructor of the <see cref="DeviceTypeAttribute"/> class.
/// </summary>
/// <param name="deviceType">The <see cref="RGBDeviceType"/>.</param>
public DeviceTypeAttribute(RGBDeviceType deviceType)
{
this.DeviceType = deviceType;
}
#endregion
}
}

View File

@ -0,0 +1,143 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using RGB.NET.Core;
using RGB.NET.Core.Exceptions;
using RGB.NET.Devices.CoolerMaster.Helper;
using RGB.NET.Devices.CoolerMaster.Native;
namespace RGB.NET.Devices.CoolerMaster
{
/// <summary>
/// Represents a device provider responsible for Cooler Master devices.
/// </summary>
public class CoolerMasterDeviceProvider : IRGBDeviceProvider
{
#region Properties & Fields
/// <summary>
/// Gets the singleton <see cref="CoolerMasterDeviceProvider"/> instance.
/// </summary>
public static CoolerMasterDeviceProvider Instance { get; } = new CoolerMasterDeviceProvider();
/// <summary>
/// Indicates if the SDK is initialized and ready to use.
/// </summary>
public bool IsInitialized { get; private set; }
/// <summary>
/// Gets the loaded architecture (x64/x86).
/// </summary>
public string LoadedArchitecture => _CoolerMasterSDK.LoadedArchitecture;
/// <summary>
/// Gets whether the application has exclusive access to the SDK or not.
/// </summary>
public bool HasExclusiveAccess { get; private set; }
/// <inheritdoc />
public IEnumerable<IRGBDevice> Devices { get; private set; }
/// <summary>
/// Gets or sets a function to get the culture for a specific device.
/// </summary>
public Func<CultureInfo> GetCulture { get; set; } = () => CultureHelper.GetCurrentCulture();
#endregion
#region Constructors
private CoolerMasterDeviceProvider()
{ }
#endregion
#region Methods
/// <inheritdoc />
public bool Initialize(bool exclusiveAccessIfPossible = false, bool throwExceptions = false)
{
IsInitialized = false;
try
{
_CoolerMasterSDK.Reload();
if (_CoolerMasterSDK.GetSDKVersion() <= 0) return false;
IList<IRGBDevice> devices = new List<IRGBDevice>();
foreach (CoolerMasterDevicesIndexes index in Enum.GetValues(typeof(CoolerMasterDevicesIndexes)))
{
_CoolerMasterSDK.SetControlDevice(index);
if (_CoolerMasterSDK.IsDevicePlugged())
{
try
{
CoolerMasterRGBDevice device = null;
switch (index.GetDeviceType())
{
case RGBDeviceType.Keyboard:
CoolerMasterPhysicalKeyboardLayout physicalLayout = _CoolerMasterSDK.GetDeviceLayout();
device = new CoolerMasterKeyboardRGBDevice(new CoolerMasterKeyboardRGBDeviceInfo(index, physicalLayout, GetCulture()));
break;
default:
if (throwExceptions)
throw new RGBDeviceException("Unknown Device-Type");
else
continue;
}
_CoolerMasterSDK.EnableLedControl(true);
device.Initialize();
devices.Add(device);
}
catch
{
if (throwExceptions)
throw;
else
continue;
}
}
}
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
}
catch
{
if (throwExceptions)
throw;
else
return false;
}
IsInitialized = true;
return true;
}
/// <inheritdoc />
public void ResetDevices()
{
if (IsInitialized)
try
{
foreach (IRGBDevice device in Devices)
{
CoolerMasterRGBDeviceInfo deviceInfo = (CoolerMasterRGBDeviceInfo)device.DeviceInfo;
_CoolerMasterSDK.SetControlDevice(deviceInfo.DeviceIndex);
_CoolerMasterSDK.EnableLedControl(false);
_CoolerMasterSDK.EnableLedControl(true);
}
}
catch
{
// shit happens ...
}
}
#endregion
}
}

View File

@ -0,0 +1,49 @@
// ReSharper disable InconsistentNaming
// ReSharper disable UnusedMember.Global
using System.ComponentModel;
using RGB.NET.Core;
using RGB.NET.Devices.CoolerMaster.Attributes;
#pragma warning disable 1591 // Missing XML comment for publicly visible type or member
namespace RGB.NET.Devices.CoolerMaster
{
/// <summary>
/// Contains a list of available device-indexes.
/// </summary>
public enum CoolerMasterDevicesIndexes
{
[Description("MasterKeys Pro L")]
[DeviceType(RGBDeviceType.Keyboard)]
MasterKeys_L = 0,
[Description("MasterKeys ProS")]
[DeviceType(RGBDeviceType.Keyboard)]
MasterKeys_S = 1,
[Description("MasterKeys Pro L White")]
[DeviceType(RGBDeviceType.Keyboard)]
MasterKeys_L_White = 2,
[Description("MasterKeys Pro M White")]
[DeviceType(RGBDeviceType.Keyboard)]
MasterKeys_M_White = 3,
[Description("MasterMouse Pro L")]
[DeviceType(RGBDeviceType.Mouse)]
MasterMouse_L = 4,
[Description("MasterMouse S")]
[DeviceType(RGBDeviceType.Mouse)]
MasterMouse_S = 5,
[Description("MasterKeys Pro M")]
[DeviceType(RGBDeviceType.Keyboard)]
MasterKeys_M = 6,
[Description("MasterKeys Pro S White")]
[DeviceType(RGBDeviceType.Keyboard)]
MasterKeys_S_White = 7
}
}

View File

@ -0,0 +1,35 @@
// ReSharper disable InconsistentNaming
// ReSharper disable UnusedMember.Global
#pragma warning disable 1591 // Missing XML comment for publicly visible type or member
namespace RGB.NET.Devices.CoolerMaster
{
/// <summary>
/// Contains a list of available effects.
/// </summary>
public enum CoolerMasterEffects
{
FullOn = 0,
Breath = 1,
BreathCycle = 2,
Single = 3,
Wave = 4,
Ripple = 5,
Cross = 6,
Rain = 7,
Star = 8,
Snake = 9,
Rec = 10,
Spectrum = 11,
RapidFire = 12,
Indicator = 13, //mouse Effect
Multi1 = 0xE0,
Multi2 = 0xE1,
Multi3 = 0xE2,
Multi4 = 0xE3,
Off = 0xFE
}
}

View File

@ -0,0 +1,25 @@
// ReSharper disable InconsistentNaming
#pragma warning disable 1591 // Missing XML comment for publicly visible type or member
namespace RGB.NET.Devices.CoolerMaster
{
/// <summary>
/// Contains list of all LEDs available for all CoolerMaster devices.
/// </summary>
public enum CoolerMasterLedIds
{
Invalid = 0,
A,
S,
D,
F,
Side1,
Side2,
Side3,
Back1,
Wheel
}
}

View File

@ -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.CoolerMaster
{
/// <summary>
/// Contains list of available logical layouts for logitech keyboards.
/// </summary>
public enum CoolerMasterLogicalKeyboardLayout
{
DE
};
}

View File

@ -0,0 +1,17 @@
// ReSharper disable InconsistentNaming
// ReSharper disable UnusedMember.Global
#pragma warning disable 1591 // Missing XML comment for publicly visible type or member
namespace RGB.NET.Devices.CoolerMaster
{
/// <summary>
/// Contains list of available physical layouts for cooler master keyboards.
/// </summary>
public enum CoolerMasterPhysicalKeyboardLayout
{
UNINIT = 0,
US = 1,
EU = 2
}
}

View File

@ -0,0 +1,125 @@
using System.Diagnostics;
using RGB.NET.Core;
namespace RGB.NET.Devices.CoolerMaster
{
/// <summary>
/// Represents a Id of a <see cref="Led"/> on a <see cref="CoolerMasterRGBDevice"/>.
/// </summary>
[DebuggerDisplay("{" + nameof(LedId) + "}")]
public class CoolerMasterLedId : ILedId
{
#region Properties & Fields
internal readonly CoolerMasterLedIds LedId;
internal readonly int Row;
internal readonly int Column;
/// <inheritdoc />
public IRGBDevice Device { get; }
/// <inheritdoc />
public bool IsValid => LedId != CoolerMasterLedIds.Invalid;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="CoolerMasterLedId"/> class.
/// </summary>
/// <param name="device">The <see cref="IRGBDevice"/> the <see cref="ILedId"/> belongs to.</param>
/// <param name="ledId">The <see cref="CoolerMasterLedId"/> of the represented <see cref="Led"/>.</param>
public CoolerMasterLedId(IRGBDevice device, CoolerMasterLedIds ledId)
{
this.Device = device;
this.LedId = ledId;
}
/// <summary>
/// Initializes a new instance of the <see cref="CoolerMasterLedId"/> class.
/// </summary>
/// <param name="device">The <see cref="IRGBDevice"/> the <see cref="ILedId"/> belongs to.</param>
/// <param name="ledId">The <see cref="CoolerMasterLedId"/> of the represented <see cref="Led"/>.</param>
/// <param name="row">The row in the mapping table of the device.</param>
/// <param name="column">The column in the mapping table of the device.</param>
public CoolerMasterLedId(IRGBDevice device, CoolerMasterLedIds ledId, int row, int column)
{
this.Device = device;
this.LedId = ledId;
this.Row = row;
this.Column = column;
}
#endregion
#region Methods
/// <summary>
/// Converts the Id of this <see cref="CoolerMasterLedId"/> to a human-readable string.
/// </summary>
/// <returns>A string that contains the Id of this <see cref="CoolerMasterLedId"/>. For example "Enter".</returns>
public override string ToString()
{
return LedId.ToString();
}
/// <summary>
/// Tests whether the specified object is a <see cref="CoolerMasterLedId" /> and is equivalent to this <see cref="CoolerMasterLedId" />.
/// </summary>
/// <param name="obj">The object to test.</param>
/// <returns><c>true</c> if <paramref name="obj" /> is a <see cref="CoolerMasterLedId" /> equivalent to this <see cref="CoolerMasterLedId" />; otherwise, <c>false</c>.</returns>
public override bool Equals(object obj)
{
CoolerMasterLedId compareLedId = obj as CoolerMasterLedId;
if (ReferenceEquals(compareLedId, null))
return false;
if (ReferenceEquals(this, compareLedId))
return true;
if (GetType() != compareLedId.GetType())
return false;
return compareLedId.LedId == LedId;
}
/// <summary>
/// Returns a hash code for this <see cref="CoolerMasterLedId" />.
/// </summary>
/// <returns>An integer value that specifies the hash code for this <see cref="CoolerMasterLedId" />.</returns>
public override int GetHashCode()
{
return LedId.GetHashCode();
}
#endregion
#region Operators
/// <summary>
/// Returns a value that indicates whether two specified <see cref="CoolerMasterLedId" /> are equal.
/// </summary>
/// <param name="ledId1">The first <see cref="CoolerMasterLedId" /> to compare.</param>
/// <param name="ledId2">The second <see cref="CoolerMasterLedId" /> to compare.</param>
/// <returns><c>true</c> if <paramref name="ledId1" /> and <paramref name="ledId2" /> are equal; otherwise, <c>false</c>.</returns>
public static bool operator ==(CoolerMasterLedId ledId1, CoolerMasterLedId ledId2)
{
return ReferenceEquals(ledId1, null) ? ReferenceEquals(ledId2, null) : ledId1.Equals(ledId2);
}
/// <summary>
/// Returns a value that indicates whether two specified <see cref="CoolerMasterLedId" /> are equal.
/// </summary>
/// <param name="ledId1">The first <see cref="CoolerMasterLedId" /> to compare.</param>
/// <param name="ledId2">The second <see cref="CoolerMasterLedId" /> to compare.</param>
/// <returns><c>true</c> if <paramref name="ledId1" /> and <paramref name="ledId2" /> are not equal; otherwise, <c>false</c>.</returns>
public static bool operator !=(CoolerMasterLedId ledId1, CoolerMasterLedId ledId2)
{
return !(ledId1 == ledId2);
}
#endregion
}
}

View File

@ -0,0 +1,131 @@
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.CoolerMaster.Native;
namespace RGB.NET.Devices.CoolerMaster
{
/// <summary>
/// Represents a generic CoolerMaster-device. (keyboard, mouse, headset, mousmat).
/// </summary>
public abstract class CoolerMasterRGBDevice : AbstractRGBDevice
{
#region Properties & Fields
/// <summary>
/// Gets information about the <see cref="CoolerMasterRGBDevice"/>.
/// </summary>
public override IRGBDeviceInfo DeviceInfo { get; }
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="CoolerMasterRGBDevice"/> class.
/// </summary>
/// <param name="info">The generic information provided by CoolerMaster for the device.</param>
protected CoolerMasterRGBDevice(IRGBDeviceInfo info)
{
this.DeviceInfo = info;
}
#endregion
#region Methods
/// <summary>
/// Initializes the device.
/// </summary>
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);
}
}
/// <summary>
/// Initializes the <see cref="Led"/> and <see cref="Size"/> of the device.
/// </summary>
protected abstract void InitializeLayout();
/// <summary>
/// Applies the given layout.
/// </summary>
/// <param name="layoutPath">The file containing the layout.</param>
/// <param name="imageLayout">The name of the layout used to get the images of the leds.</param>
/// <param name="imageBasePath">The path images for this device are collected in.</param>
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)
{
CoolerMasterLedIds ledId;
if (Enum.TryParse(layoutLed.Id, true, out ledId))
{
Led led;
if (LedMapping.TryGetValue(new CoolerMasterLedId(this, ledId), out 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);
}
}
}
}
}
/// <inheritdoc />
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate)
{
List<Led> leds = ledsToUpdate.Where(x => x.Color.A > 0).ToList();
if (leds.Count > 0)
{
_CoolerMasterSDK.SetControlDevice(((CoolerMasterRGBDeviceInfo)DeviceInfo).DeviceIndex);
foreach (Led led in leds)
{
CoolerMasterLedId ledId = (CoolerMasterLedId)led.Id;
_CoolerMasterSDK.SetLedColor(ledId.Row, ledId.Column, led.Color.R, led.Color.G, led.Color.B);
}
_CoolerMasterSDK.RefreshLed(false);
}
}
/// <inheritdoc />
public override void Dispose()
{
_CoolerMasterSDK.SetControlDevice(((CoolerMasterRGBDeviceInfo)DeviceInfo).DeviceIndex);
_CoolerMasterSDK.EnableLedControl(false);
base.Dispose();
}
#endregion
}
}

View File

@ -0,0 +1,53 @@
using System;
using RGB.NET.Core;
using RGB.NET.Devices.CoolerMaster.Helper;
namespace RGB.NET.Devices.CoolerMaster
{
/// <summary>
/// Represents a generic information for a Corsair-<see cref="IRGBDevice"/>.
/// </summary>
public class CoolerMasterRGBDeviceInfo : IRGBDeviceInfo
{
#region Properties & Fields
/// <inheritdoc />
public RGBDeviceType DeviceType { get; }
/// <inheritdoc />
public string Manufacturer => "Cooler Master";
/// <inheritdoc />
public string Model { get; }
/// <inheritdoc />
public Uri Image { get; protected set; }
/// <inheritdoc />
public RGBDeviceLighting Lighting => RGBDeviceLighting.Key;
/// <summary>
/// Gets the <see cref="CoolerMasterDevicesIndexes"/> of the <see cref="CoolerMasterRGBDevice"/>.
/// </summary>
public CoolerMasterDevicesIndexes DeviceIndex { get; }
#endregion
#region Constructors
/// <summary>
/// Internal constructor of managed <see cref="CoolerMasterRGBDeviceInfo"/>.
/// </summary>
/// <param name="deviceType">The type of the <see cref="IRGBDevice"/>.</param>
/// <param name="deviceIndex">The <see cref="CoolerMasterDevicesIndexes"/> of the <see cref="IRGBDevice"/>.</param>
internal CoolerMasterRGBDeviceInfo(RGBDeviceType deviceType, CoolerMasterDevicesIndexes deviceIndex)
{
this.DeviceType = deviceType;
this.DeviceIndex = deviceIndex;
Model = deviceIndex.GetDescription();
}
#endregion
}
}

View File

@ -0,0 +1,44 @@
using System;
using System.Globalization;
using System.Runtime.InteropServices;
namespace RGB.NET.Devices.CoolerMaster.Helper
{
/// <summary>
/// Offers some helper-methods for culture related things.
/// </summary>
internal static class CultureHelper
{
#region DLLImports
[DllImport("user32.dll")]
private static extern IntPtr GetKeyboardLayout(uint thread);
#endregion
#region Constructors
#endregion
#region Methods
/// <summary>
/// Gets the current keyboard-layout from the OS.
/// </summary>
/// <returns>The current keyboard-layout</returns>
internal static CultureInfo GetCurrentCulture()
{
try
{
int keyboardLayout = GetKeyboardLayout(0).ToInt32() & 0xFFFF;
return new CultureInfo(keyboardLayout);
}
catch
{
return new CultureInfo(1033); // en-US on error.
}
}
#endregion
}
}

View File

@ -0,0 +1,54 @@
using System;
using System.ComponentModel;
using System.Reflection;
using RGB.NET.Core;
using RGB.NET.Devices.CoolerMaster.Attributes;
namespace RGB.NET.Devices.CoolerMaster.Helper
{
/// <summary>
/// Offers some extensions and helper-methods for enum related things.
/// </summary>
internal static class EnumExtension
{
/// <summary>
/// Gets the value of the <see cref="DescriptionAttribute"/>.
/// </summary>
/// <param name="source">The enum value to get the description from.</param>
/// <typeparam name="T">The generic enum-type</typeparam>
/// <returns>The value of the <see cref="DescriptionAttribute"/> or the <see cref="Enum.ToString()" /> result of the source.</returns>
internal static string GetDescription<T>(this T source)
where T : struct
{
return source.GetAttribute<DescriptionAttribute, T>()?.Description ?? source.ToString();
}
/// <summary>
/// Gets the value of the <see cref="DeviceTypeAttribute"/>.
/// </summary>
/// <param name="source">The enum value to get the description from.</param>
/// <typeparam name="T">The generic enum-type</typeparam>
/// <returns>The value of the <see cref="DeviceTypeAttribute"/> or the <see cref="Enum.ToString()" /> result of the source.</returns>
internal static RGBDeviceType GetDeviceType<T>(this T source)
where T : struct
{
return source.GetAttribute<DeviceTypeAttribute, T>()?.DeviceType ?? RGBDeviceType.Unknown;
}
/// <summary>
/// Gets the attribute of type T.
/// </summary>
/// <param name="source">The enum value to get the attribute from</param>
/// <typeparam name="T">The generic attribute type</typeparam>
/// <typeparam name="TEnum">The generic enum-type</typeparam>
/// <returns>The <see cref="Attribute"/>.</returns>
private static T GetAttribute<T, TEnum>(this TEnum source)
where T : Attribute
where TEnum : struct
{
FieldInfo fi = source.GetType().GetField(source.ToString());
T[] attributes = (T[])fi.GetCustomAttributes(typeof(T), false);
return attributes.Length > 0 ? attributes[0] : null;
}
}
}

View File

@ -0,0 +1,24 @@
using System.IO;
using System.Reflection;
namespace RGB.NET.Devices.CoolerMaster.Helper
{
/// <summary>
/// Offers some helper-methods for file-path related things.
/// </summary>
internal static class PathHelper
{
/// <summary>
/// Returns an absolute path created from an relative path relatvie to the location of the executung assembly.
/// </summary>
/// <param name="relativePath">The relative path to convert.</param>
/// <returns>The absolute path.</returns>
internal static string GetAbsolutePath(string relativePath)
{
string assemblyLocation = Assembly.GetEntryAssembly()?.Location;
if (assemblyLocation == null) return relativePath;
return Path.Combine(Path.GetDirectoryName(assemblyLocation), relativePath);
}
}
}

View File

@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
namespace RGB.NET.Devices.CoolerMaster
{
/// <summary>
/// Contains all the hardware-id mappings for CoolerMaster devices.
/// </summary>
internal static class CoolerMasterKeyboardLedMappings
{
#region Properties & Fields
private static readonly Dictionary<CoolerMasterLedIds, Tuple<int, int>> MasterKeysL_US = new Dictionary<CoolerMasterLedIds, Tuple<int, int>>
{
{ CoolerMasterLedIds.A, new Tuple<int, int>(3,1) },
{ CoolerMasterLedIds.S, new Tuple<int, int>(3,2) },
{ CoolerMasterLedIds.D, new Tuple<int, int>(3,3) },
{ CoolerMasterLedIds.F, new Tuple<int, int>(3,4) },
};
private static readonly Dictionary<CoolerMasterLedIds, Tuple<int, int>> MasterKeysL_EU = new Dictionary<CoolerMasterLedIds, Tuple<int, int>>
{
{ CoolerMasterLedIds.A, new Tuple<int, int>(3,1) },
{ CoolerMasterLedIds.S, new Tuple<int, int>(3,2) },
{ CoolerMasterLedIds.D, new Tuple<int, int>(3,3) },
{ CoolerMasterLedIds.F, new Tuple<int, int>(3,4) },
};
private static readonly Dictionary<CoolerMasterLedIds, Tuple<int, int>> MasterKeysM_US = new Dictionary<CoolerMasterLedIds, Tuple<int, int>>
{
{ CoolerMasterLedIds.A, new Tuple<int, int>(3,1) },
{ CoolerMasterLedIds.S, new Tuple<int, int>(3,2) },
{ CoolerMasterLedIds.D, new Tuple<int, int>(3,3) },
{ CoolerMasterLedIds.F, new Tuple<int, int>(3,4) },
};
private static readonly Dictionary<CoolerMasterLedIds, Tuple<int, int>> MasterKeysM_EU = new Dictionary<CoolerMasterLedIds, Tuple<int, int>>
{
{ CoolerMasterLedIds.A, new Tuple<int, int>(3,1) },
{ CoolerMasterLedIds.S, new Tuple<int, int>(3,2) },
{ CoolerMasterLedIds.D, new Tuple<int, int>(3,3) },
{ CoolerMasterLedIds.F, new Tuple<int, int>(3,4) },
};
private static readonly Dictionary<CoolerMasterLedIds, Tuple<int, int>> MasterKeysS_US = new Dictionary<CoolerMasterLedIds, Tuple<int, int>>
{
{ CoolerMasterLedIds.A, new Tuple<int, int>(3,1) },
{ CoolerMasterLedIds.S, new Tuple<int, int>(3,2) },
{ CoolerMasterLedIds.D, new Tuple<int, int>(3,3) },
{ CoolerMasterLedIds.F, new Tuple<int, int>(3,4) },
};
private static readonly Dictionary<CoolerMasterLedIds, Tuple<int, int>> MasterKeysS_EU = new Dictionary<CoolerMasterLedIds, Tuple<int, int>>
{
{ CoolerMasterLedIds.A, new Tuple<int, int>(3,1) },
{ CoolerMasterLedIds.S, new Tuple<int, int>(3,2) },
{ CoolerMasterLedIds.D, new Tuple<int, int>(3,3) },
{ CoolerMasterLedIds.F, new Tuple<int, int>(3,4) },
};
/// <summary>
/// Contains all the hardware-id mappings for CoolerMaster devices.
/// </summary>
// ReSharper disable once InconsistentNaming
public static readonly Dictionary<CoolerMasterDevicesIndexes, Dictionary<CoolerMasterPhysicalKeyboardLayout, Dictionary<CoolerMasterLedIds, Tuple<int, int>>>> Mapping =
new Dictionary<CoolerMasterDevicesIndexes, Dictionary<CoolerMasterPhysicalKeyboardLayout, Dictionary<CoolerMasterLedIds, Tuple<int, int>>>>
{
{ CoolerMasterDevicesIndexes.MasterKeys_L, new Dictionary<CoolerMasterPhysicalKeyboardLayout, Dictionary<CoolerMasterLedIds, Tuple<int, int>>>
{
{ CoolerMasterPhysicalKeyboardLayout.US, MasterKeysL_US },
{ CoolerMasterPhysicalKeyboardLayout.EU, MasterKeysL_EU }
}
},
{ CoolerMasterDevicesIndexes.MasterKeys_M, new Dictionary<CoolerMasterPhysicalKeyboardLayout, Dictionary<CoolerMasterLedIds, Tuple<int, int>>>
{
{ CoolerMasterPhysicalKeyboardLayout.US, MasterKeysM_US },
{ CoolerMasterPhysicalKeyboardLayout.EU, MasterKeysM_EU }
}
},
{ CoolerMasterDevicesIndexes.MasterKeys_S, new Dictionary<CoolerMasterPhysicalKeyboardLayout, Dictionary<CoolerMasterLedIds, Tuple<int, int>>>
{
{ CoolerMasterPhysicalKeyboardLayout.US, MasterKeysS_US },
{ CoolerMasterPhysicalKeyboardLayout.EU, MasterKeysS_EU }
}
},
{ CoolerMasterDevicesIndexes.MasterKeys_L_White, new Dictionary<CoolerMasterPhysicalKeyboardLayout, Dictionary<CoolerMasterLedIds, Tuple<int, int>>>
{
{ CoolerMasterPhysicalKeyboardLayout.US, MasterKeysL_US },
{ CoolerMasterPhysicalKeyboardLayout.EU, MasterKeysL_EU }
}
},
{ CoolerMasterDevicesIndexes.MasterKeys_M_White, new Dictionary<CoolerMasterPhysicalKeyboardLayout, Dictionary<CoolerMasterLedIds, Tuple<int, int>>>
{
{ CoolerMasterPhysicalKeyboardLayout.US, MasterKeysM_US },
{ CoolerMasterPhysicalKeyboardLayout.EU, MasterKeysM_EU }
}
},
{ CoolerMasterDevicesIndexes.MasterKeys_S_White, new Dictionary<CoolerMasterPhysicalKeyboardLayout, Dictionary<CoolerMasterLedIds, Tuple<int, int>>>
{
{ CoolerMasterPhysicalKeyboardLayout.US, MasterKeysS_US },
{ CoolerMasterPhysicalKeyboardLayout.EU, MasterKeysS_EU }
}
},
};
#endregion
}
}

View File

@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using RGB.NET.Core;
using RGB.NET.Devices.CoolerMaster.Helper;
namespace RGB.NET.Devices.CoolerMaster
{
/// <summary>
/// Represents a CoolerMaster keyboard.
/// </summary>
public class CoolerMasterKeyboardRGBDevice : CoolerMasterRGBDevice
{
#region Properties & Fields
/// <summary>
/// Gets information about the <see cref="CoolerMasterKeyboardRGBDevice"/>.
/// </summary>
public CoolerMasterKeyboardRGBDeviceInfo KeyboardDeviceInfo { get; }
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="CoolerMasterKeyboardRGBDevice"/> class.
/// </summary>
/// <param name="info">The specific information provided by CoolerMaster for the keyboard</param>
internal CoolerMasterKeyboardRGBDevice(CoolerMasterKeyboardRGBDeviceInfo info)
: base(info)
{
this.KeyboardDeviceInfo = info;
}
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout()
{
Dictionary<CoolerMasterLedIds, Tuple<int, int>> mapping = CoolerMasterKeyboardLedMappings.Mapping[KeyboardDeviceInfo.DeviceIndex][KeyboardDeviceInfo.PhysicalLayout];
foreach (KeyValuePair<CoolerMasterLedIds, Tuple<int, int>> led in mapping)
InitializeLed(new CoolerMasterLedId(this, led.Key, led.Value.Item1, led.Value.Item2),
new Rectangle(led.Value.Item2 * 19, led.Value.Item1 * 19, 19, 19));
string model = KeyboardDeviceInfo.Model.Replace(" ", string.Empty).ToUpper();
ApplyLayoutFromFile(PathHelper.GetAbsolutePath(
$@"Layouts\CoolerMaster\Keyboards\{model}\{KeyboardDeviceInfo.PhysicalLayout.ToString().ToUpper()}.xml"),
KeyboardDeviceInfo.LogicalLayout.ToString(), PathHelper.GetAbsolutePath($@"Images\CoolerMaster\Keyboards"));
}
#endregion
}
}

View File

@ -0,0 +1,58 @@
using System;
using System.Globalization;
using RGB.NET.Core;
using RGB.NET.Devices.CoolerMaster.Helper;
namespace RGB.NET.Devices.CoolerMaster
{
/// <summary>
/// Represents a generic information for a <see cref="CoolerMasterKeyboardRGBDevice"/>.
/// </summary>
public class CoolerMasterKeyboardRGBDeviceInfo : CoolerMasterRGBDeviceInfo
{
#region Properties & Fields
/// <summary>
/// Gets the <see cref="CoolerMasterPhysicalKeyboardLayout"/> of the <see cref="CoolerMasterKeyboardRGBDevice"/>.
/// </summary>
public CoolerMasterPhysicalKeyboardLayout PhysicalLayout { get; private set; }
/// <summary>
/// Gets the <see cref="CoolerMasterLogicalKeyboardLayout"/> of the <see cref="CoolerMasterKeyboardRGBDevice"/>.
/// </summary>
public CoolerMasterLogicalKeyboardLayout LogicalLayout { get; private set; }
#endregion
#region Constructors
/// <summary>
/// Internal constructor of managed <see cref="CoolerMasterKeyboardRGBDeviceInfo"/>.
/// </summary>
/// <param name="deviceIndex">The index of the <see cref="CoolerMasterKeyboardRGBDevice"/>.</param>
/// <param name="physicalKeyboardLayout">The <see cref="CoolerMasterPhysicalKeyboardLayout" /> of the <see cref="CoolerMasterKeyboardRGBDevice"/>.</param>
/// <param name="culture">The <see cref="CultureInfo"/> of the layout this keyboard is using</param>
internal CoolerMasterKeyboardRGBDeviceInfo(CoolerMasterDevicesIndexes deviceIndex, CoolerMasterPhysicalKeyboardLayout physicalKeyboardLayout, CultureInfo culture)
: base(RGBDeviceType.Keyboard, deviceIndex)
{
this.PhysicalLayout = physicalKeyboardLayout;
SetLayouts(culture.KeyboardLayoutId);
Image = new Uri(PathHelper.GetAbsolutePath($@"Images\Logitech\Keyboards\{Model.Replace(" ", string.Empty).ToUpper()}.png"), UriKind.Absolute);
}
private void SetLayouts(int keyboardLayoutId)
{
switch (keyboardLayoutId)
{
//TODO DarthAffe 02.04.2017: Check all available keyboards and there layout-ids
default:
LogicalLayout = CoolerMasterLogicalKeyboardLayout.DE;
break;
}
}
#endregion
}
}

View File

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
namespace RGB.NET.Devices.CoolerMaster
{
/// <summary>
/// Contains all the hardware-id mappings for CoolerMaster devices.
/// </summary>
internal static class CoolerMasterMouseLedMappings
{
#region Properties & Fields
/// <summary>
/// Contains all the hardware-id mappings for CoolerMaster devices.
/// </summary>
// ReSharper disable once InconsistentNaming
public static readonly Dictionary<CoolerMasterDevicesIndexes, Dictionary<CoolerMasterLedIds, Tuple<int, int>>> Mapping =
new Dictionary<CoolerMasterDevicesIndexes, Dictionary<CoolerMasterLedIds, Tuple<int, int>>>
{
{ CoolerMasterDevicesIndexes.MasterMouse_L, new Dictionary<CoolerMasterLedIds, Tuple<int, int>>
{
{ CoolerMasterLedIds.Side1, new Tuple<int, int>(0,0) },
{ CoolerMasterLedIds.Side2, new Tuple<int, int>(1,0) },
{ CoolerMasterLedIds.Side3, new Tuple<int, int>(2,0) },
{ CoolerMasterLedIds.Back1, new Tuple<int, int>(3,0) },
}
},
{ CoolerMasterDevicesIndexes.MasterMouse_S, new Dictionary<CoolerMasterLedIds, Tuple<int, int>>
{
{ CoolerMasterLedIds.Back1, new Tuple<int, int>(0,0) },
{ CoolerMasterLedIds.Wheel, new Tuple<int, int>(1,0) },
{ CoolerMasterLedIds.Side3, new Tuple<int, int>(2,0) },
{ CoolerMasterLedIds.Back1, new Tuple<int, int>(3,0) },
}
},
};
#endregion
}
}

View File

@ -0,0 +1,177 @@
// ReSharper disable UnusedMethodReturnValue.Global
// ReSharper disable UnusedMember.Global
using System;
using System.IO;
using System.Runtime.InteropServices;
using RGB.NET.Core.Exceptions;
namespace RGB.NET.Devices.CoolerMaster.Native
{
// ReSharper disable once InconsistentNaming
internal static class _CoolerMasterSDK
{
#region Libary Management
private static IntPtr _dllHandle = IntPtr.Zero;
/// <summary>
/// Gets the loaded architecture (x64/x86).
/// </summary>
internal static string LoadedArchitecture { get; private set; }
/// <summary>
/// Reloads the SDK.
/// </summary>
internal static void Reload()
{
UnloadCMSDK();
LoadCMSDK();
}
private static void LoadCMSDK()
{
if (_dllHandle != IntPtr.Zero) return;
// HACK: Load library at runtime to support both, x86 and x64 with one managed dll
string dllPath = (LoadedArchitecture = Environment.Is64BitProcess ? "x64" : "x86") + "/CMSDK.dll";
if (!File.Exists(dllPath))
throw new RGBDeviceException($"Can't find the CoolerMaster-SDK at the expected location '{Path.GetFullPath(dllPath)}'");
_dllHandle = LoadLibrary(dllPath);
_getSDKVersionPointer = (GetSDKVersionPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "GetCM_SDK_DllVer"), typeof(GetSDKVersionPointer));
_setControlDevicenPointer = (SetControlDevicePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "SetControlDevice"), typeof(SetControlDevicePointer));
_isDevicePlugPointer = (IsDevicePlugPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "IsDevicePlug"), typeof(IsDevicePlugPointer));
_getDeviceLayoutPointer = (GetDeviceLayoutPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "GetDeviceLayout"), typeof(GetDeviceLayoutPointer));
_enableLedControlPointer = (EnableLedControlPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "EnableLedControl"), typeof(EnableLedControlPointer));
_refreshLedPointer = (RefreshLedPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "RefreshLed"), typeof(RefreshLedPointer));
_setLedColorPointer = (SetLedColorPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "SetLedColor"), typeof(SetLedColorPointer));
}
private static void UnloadCMSDK()
{
if (_dllHandle == IntPtr.Zero) return;
// ReSharper disable once EmptyEmbeddedStatement - DarthAffe 20.02.2016: 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 GetSDKVersionPointer _getSDKVersionPointer;
private static SetControlDevicePointer _setControlDevicenPointer;
private static IsDevicePlugPointer _isDevicePlugPointer;
private static GetDeviceLayoutPointer _getDeviceLayoutPointer;
private static EnableLedControlPointer _enableLedControlPointer;
private static RefreshLedPointer _refreshLedPointer;
private static SetLedColorPointer _setLedColorPointer;
#endregion
#region Delegates
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int GetSDKVersionPointer();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void SetControlDevicePointer(CoolerMasterDevicesIndexes devicesIndexes);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool IsDevicePlugPointer();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate CoolerMasterPhysicalKeyboardLayout GetDeviceLayoutPointer();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool EnableLedControlPointer(bool value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool RefreshLedPointer(bool autoRefresh);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool SetLedColorPointer(int row, int column, byte r, byte g, byte b);
#endregion
// ReSharper disable EventExceptionNotDocumented
/// <summary>
/// CM-SDK: Get SDK Dll's Version.
/// </summary>
internal static int GetSDKVersion()
{
return _getSDKVersionPointer();
}
/// <summary>
/// CM-SDK: set operating device
/// </summary>
internal static void SetControlDevice(CoolerMasterDevicesIndexes devicesIndexes)
{
_setControlDevicenPointer(devicesIndexes);
}
/// <summary>
/// CM-SDK: verify if the deviced is plugged in
/// </summary>
internal static bool IsDevicePlugged()
{
return _isDevicePlugPointer();
}
/// <summary>
/// CM-SDK: Obtain current device layout
/// </summary>
internal static CoolerMasterPhysicalKeyboardLayout GetDeviceLayout()
{
return _getDeviceLayoutPointer();
}
/// <summary>
/// CM-SDK: set control over devices LED
/// </summary>
internal static bool EnableLedControl(bool value)
{
return _enableLedControlPointer(value);
}
/// <summary>
/// CM-SDK: Print out the lights setting from Buffer to LED
/// </summary>
internal static bool RefreshLed(bool autoRefresh)
{
return _refreshLedPointer(autoRefresh);
}
/// <summary>
/// CM-SDK: Set single Key LED color
/// </summary>
internal static bool SetLedColor(int row, int column, byte r, byte g, byte b)
{
return _setLedColorPointer(row, column, r, g, b);
}
// ReSharper restore EventExceptionNotDocumented
#endregion
}
}

View File

@ -47,6 +47,24 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Attributes\DeviceTypeAttribute.cs" />
<Compile Include="CoolerMasterDeviceProvider.cs" />
<Compile Include="Enum\CoolerMasterLedIds.cs" />
<Compile Include="Enum\CoolerMasterPhysicalKeyboardLayout.cs" />
<Compile Include="Enum\CoolerMasterDevicesIndexes.cs" />
<Compile Include="Enum\CoolerMasterEffects.cs" />
<Compile Include="Enum\CoolerMasterLogicalKeyboardLayout.cs" />
<Compile Include="Generic\CoolerMasterLedId.cs" />
<Compile Include="Generic\CoolerMasterRGBDevice.cs" />
<Compile Include="Generic\CoolerMasterRGBDeviceInfo.cs" />
<Compile Include="Helper\CultureHelper.cs" />
<Compile Include="Helper\EnumExtension.cs" />
<Compile Include="Helper\PathHelper.cs" />
<Compile Include="Keyboard\CoolerMasterKeyboardRGBDevice.cs" />
<Compile Include="Keyboard\CoolerMasterKeyboardRGBDeviceInfo.cs" />
<Compile Include="Keyboard\CoolerMasterKeyboardLedMappings.cs" />
<Compile Include="Mouse\CoolerMasterMouseLedMappings.cs" />
<Compile Include="Native\_CoolerMasterSDK.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
@ -61,8 +79,8 @@
<Folder Include="Layouts\CoolerMaster\" />
</ItemGroup>
<ItemGroup>
<Content Include="libs\x64\SDKDLL.dll" />
<Content Include="libs\x86\SDKDLL.dll" />
<Content Include="libs\x64\CMSDK.dll" />
<Content Include="libs\x86\CMSDK.dll" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@ -0,0 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=enum/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=generic/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=keyboard/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=mouse/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -256,6 +256,8 @@
<s:Boolean x:Key="/Default/CodeStyle/IntroduceVariableUseVar/UseVarForIntroduceVariableRefactoringEvident/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AFBG/@EntryIndexedValue">AFBG</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=BWZ/@EntryIndexedValue">BWZ</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CM/@EntryIndexedValue">CM</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CMSDK/@EntryIndexedValue">CMSDK</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CUESDK/@EntryIndexedValue">CUESDK</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DB/@EntryIndexedValue">DB</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DG/@EntryIndexedValue">DG</s:String>