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

Wooting device provider

This commit is contained in:
SpoinkyNL 2019-12-11 22:34:19 +01:00
parent cd45fdfb99
commit 7690a49e43
15 changed files with 955 additions and 2 deletions

View File

@ -0,0 +1,21 @@
// ReSharper disable InconsistentNaming
// ReSharper disable UnusedMember.Global
using System.ComponentModel;
#pragma warning disable 1591 // Missing XML comment for publicly visible type or member
namespace RGB.NET.Devices.Wooting.Enum
{
/// <summary>
/// Contains a list of available device-indexes.
/// </summary>
public enum WootingDevicesIndexes
{
[Description("Wooting One")]
WootingOne = 0,
[Description("Wooting Two")]
WootingTwo = 1
}
}

View File

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

View File

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

View File

@ -0,0 +1,12 @@
using RGB.NET.Core;
namespace RGB.NET.Devices.Wooting.Generic
{
/// <summary>
/// Represents a Wooting RGB-device.
/// </summary>
internal interface IWootingRGBDevice : IRGBDevice
{
void Initialize(UpdateQueue updateQueue);
}
}

View File

@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Linq;
using RGB.NET.Core;
using RGB.NET.Devices.Wooting.Native;
namespace RGB.NET.Devices.Wooting.Generic
{
/// <inheritdoc cref="AbstractRGBDevice{TDeviceInfo}" />
/// <inheritdoc cref="IWootingRGBDevice" />
/// <summary>
/// Represents a Wooting-device
/// </summary>
public abstract class WootingRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceInfo>, IWootingRGBDevice
where TDeviceInfo : WootingRGBDeviceInfo
{
#region Properties & Fields
/// <inheritdoc />
/// <summary>
/// Gets information about the <see cref="T:RGB.NET.Devices.Wooting.WootingRGBDevice" />.
/// </summary>
public override TDeviceInfo DeviceInfo { get; }
/// <summary>
/// Gets or sets the update queue performing updates for this device.
/// </summary>
// ReSharper disable once MemberCanBePrivate.Global
protected UpdateQueue UpdateQueue { get; set; }
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="WootingRGBDevice{TDeviceInfo}"/> class.
/// </summary>
/// <param name="info">The generic information provided by Wooting for the device.</param>
protected WootingRGBDevice(TDeviceInfo info)
{
this.DeviceInfo = info;
}
#endregion
#region Methods
/// <summary>
/// Initializes the device.
/// </summary>
public void Initialize(UpdateQueue updateQueue)
{
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);
}
UpdateQueue = updateQueue;
}
/// <summary>
/// Initializes the <see cref="Led"/> and <see cref="Size"/> of the device.
/// </summary>
protected abstract void InitializeLayout();
#endregion
}
}

View File

@ -0,0 +1,62 @@
using System;
using RGB.NET.Core;
using RGB.NET.Devices.Wooting.Enum;
using RGB.NET.Devices.Wooting.Helper;
namespace RGB.NET.Devices.Wooting.Generic
{
/// <inheritdoc />
/// <summary>
/// Represents a generic information for a Wooting-<see cref="T:RGB.NET.Core.IRGBDevice" />.
/// </summary>
public class WootingRGBDeviceInfo : IRGBDeviceInfo
{
#region Properties & Fields
/// <inheritdoc />
public RGBDeviceType DeviceType { get; }
/// <inheritdoc />
public string DeviceName { get; }
/// <inheritdoc />
public string Manufacturer => "Wooting";
/// <inheritdoc />
public string Model { get; }
/// <inheritdoc />
public Uri Image { get; set; }
/// <inheritdoc />
public RGBDeviceLighting Lighting => RGBDeviceLighting.Key;
/// <inheritdoc />
public bool SupportsSyncBack => false;
/// <summary>
/// Gets the <see cref="WootingDevicesIndexes"/> of the <see cref="WootingRGBDevice{TDeviceInfo}"/>.
/// </summary>
public WootingDevicesIndexes DeviceIndex { get; }
#endregion
#region Constructors
/// <summary>
/// Internal constructor of managed <see cref="WootingRGBDeviceInfo"/>.
/// </summary>
/// <param name="deviceType">The type of the <see cref="IRGBDevice"/>.</param>
/// <param name="deviceIndex">The <see cref="WootingDevicesIndexes"/> of the <see cref="IRGBDevice"/>.</param>
internal WootingRGBDeviceInfo(RGBDeviceType deviceType, WootingDevicesIndexes deviceIndex)
{
this.DeviceType = deviceType;
this.DeviceIndex = deviceIndex;
Model = deviceIndex.GetDescription();
DeviceName = $"{Manufacturer} {Model}";
}
#endregion
}
}

View File

@ -0,0 +1,41 @@
using System;
using System.ComponentModel;
using System.Reflection;
using RGB.NET.Core;
namespace RGB.NET.Devices.Wooting.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 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,262 @@
// ReSharper disable InconsistentNaming
using System.Collections.Generic;
using RGB.NET.Core;
using RGB.NET.Devices.Wooting.Enum;
namespace RGB.NET.Devices.Wooting.Keyboard
{
/// <summary>
/// Contains all the hardware-id mappings for Wooting devices.
/// </summary>
internal static class WootingKeyboardLedMappings
{
#region Properties & Fields
#region Wooting One
private static readonly Dictionary<LedId, (int row, int column)> WootingOne_US = new Dictionary<LedId, (int row, int column)>
{
{ LedId.Keyboard_Escape, (0,0) },
{ LedId.Keyboard_F1, (0,2) },
{ LedId.Keyboard_F2, (0,3) },
{ LedId.Keyboard_F3, (0,4) },
{ LedId.Keyboard_F4, (0,5) },
{ LedId.Keyboard_F5, (0,6) },
{ LedId.Keyboard_F6, (0,7) },
{ LedId.Keyboard_F7, (0,8) },
{ LedId.Keyboard_F8, (0,9) },
{ LedId.Keyboard_F9, (0,10) },
{ LedId.Keyboard_F10, (0,11) },
{ LedId.Keyboard_F11, (0,12) },
{ LedId.Keyboard_F12, (0,13) },
{ LedId.Keyboard_PrintScreen, (0,14) },
{ LedId.Keyboard_PauseBreak, (0,15) },
{ LedId.Keyboard_Custom1, (0,20) }, // TODO: Make sure it is not 0,16
{ LedId.Keyboard_GraveAccentAndTilde, (1,0) },
{ LedId.Keyboard_1, (1,1) },
{ LedId.Keyboard_2, (1,2) },
{ LedId.Keyboard_3, (1,3) },
{ LedId.Keyboard_4, (1,4) },
{ LedId.Keyboard_5, (1,5) },
{ LedId.Keyboard_6, (1,6) },
{ LedId.Keyboard_7, (1,7) },
{ LedId.Keyboard_8, (1,8) },
{ LedId.Keyboard_9, (1,9) },
{ LedId.Keyboard_0, (1,10) },
{ LedId.Keyboard_MinusAndUnderscore, (1,11) },
{ LedId.Keyboard_EqualsAndPlus, (1,12) },
{ LedId.Keyboard_Backspace, (1,13) },
{ LedId.Keyboard_Insert, (1,14) },
{ LedId.Keyboard_Home, (1,15) },
{ LedId.Keyboard_PageUp, (1,16) },
{ LedId.Keyboard_Tab, (2,0) },
{ LedId.Keyboard_Q, (2,1) },
{ LedId.Keyboard_W, (2,2) },
{ LedId.Keyboard_E, (2,3) },
{ LedId.Keyboard_R, (2,4) },
{ LedId.Keyboard_T, (2,5) },
{ LedId.Keyboard_Y, (2,6) },
{ LedId.Keyboard_U, (2,7) },
{ LedId.Keyboard_I, (2,8) },
{ LedId.Keyboard_O, (2,9) },
{ LedId.Keyboard_P, (2,10) },
{ LedId.Keyboard_BracketLeft, (2,11) },
{ LedId.Keyboard_BracketRight, (2,12) },
{ LedId.Keyboard_Backslash, (2,13) },
{ LedId.Keyboard_Delete, (2,14) },
{ LedId.Keyboard_End, (2,15) },
{ LedId.Keyboard_PageDown, (2,16) },
{ LedId.Keyboard_CapsLock, (3,0) },
{ LedId.Keyboard_A, (3,1) },
{ LedId.Keyboard_S, (3,2) },
{ LedId.Keyboard_D, (3,3) },
{ LedId.Keyboard_F, (3,4) },
{ LedId.Keyboard_G, (3,5) },
{ LedId.Keyboard_H, (3,6) },
{ LedId.Keyboard_J, (3,7) },
{ LedId.Keyboard_K, (3,8) },
{ LedId.Keyboard_L, (3,9) },
{ LedId.Keyboard_SemicolonAndColon, (3,10) },
{ LedId.Keyboard_ApostropheAndDoubleQuote, (3,11) },
{ LedId.Keyboard_Enter, (3,13) },
{ LedId.Keyboard_LeftShift, (4,0) },
{ LedId.Keyboard_NonUsBackslash, (4,1) },
{ LedId.Keyboard_Z, (4,2) },
{ LedId.Keyboard_X, (4,3) },
{ LedId.Keyboard_C, (4,4) },
{ LedId.Keyboard_V, (4,5) },
{ LedId.Keyboard_B, (4,6) },
{ LedId.Keyboard_N, (4,7) },
{ LedId.Keyboard_M, (4,8) },
{ LedId.Keyboard_CommaAndLessThan, (4,9) },
{ LedId.Keyboard_PeriodAndBiggerThan, (4,10) },
{ LedId.Keyboard_SlashAndQuestionMark, (4,11) },
{ LedId.Keyboard_RightShift, (4,13) },
{ LedId.Keyboard_ArrowUp, (4,15) },
{ LedId.Keyboard_LeftCtrl, (5,0) },
{ LedId.Keyboard_LeftGui, (5,1) },
{ LedId.Keyboard_LeftAlt, (5,2) },
{ LedId.Keyboard_Space, (5,6) },
{ LedId.Keyboard_RightAlt, (5,10) },
{ LedId.Keyboard_RightGui, (5,11) },
{ LedId.Keyboard_Application, (5,12) },
{ LedId.Keyboard_RightCtrl, (5,13) },
{ LedId.Keyboard_ArrowLeft, (5,14) },
{ LedId.Keyboard_ArrowDown, (5,15) },
{ LedId.Keyboard_ArrowRight, (5,16) }
};
#endregion
#region Wooting Two
private static readonly Dictionary<LedId, (int row, int column)> WootingTwo_US = new Dictionary<LedId, (int row, int column)>
{
{ LedId.Keyboard_Escape, (0,0) },
{ LedId.Keyboard_F1, (0,2) },
{ LedId.Keyboard_F2, (0,3) },
{ LedId.Keyboard_F3, (0,4) },
{ LedId.Keyboard_F4, (0,5) },
{ LedId.Keyboard_F5, (0,6) },
{ LedId.Keyboard_F6, (0,7) },
{ LedId.Keyboard_F7, (0,8) },
{ LedId.Keyboard_F8, (0,9) },
{ LedId.Keyboard_F9, (0,10) },
{ LedId.Keyboard_F10, (0,11) },
{ LedId.Keyboard_F11, (0,12) },
{ LedId.Keyboard_F12, (0,13) },
{ LedId.Keyboard_PrintScreen, (0,14) },
{ LedId.Keyboard_PauseBreak, (0,15) },
{ LedId.Keyboard_ScrollLock, (0,16) },
{ LedId.Keyboard_Custom1, (0,17) },
{ LedId.Keyboard_Custom2, (0,18) },
{ LedId.Keyboard_Custom3, (0,19) },
{ LedId.Keyboard_Custom4, (0,20) },
{ LedId.Keyboard_GraveAccentAndTilde, (1,0) },
{ LedId.Keyboard_1, (1,1) },
{ LedId.Keyboard_2, (1,2) },
{ LedId.Keyboard_3, (1,3) },
{ LedId.Keyboard_4, (1,4) },
{ LedId.Keyboard_5, (1,5) },
{ LedId.Keyboard_6, (1,6) },
{ LedId.Keyboard_7, (1,7) },
{ LedId.Keyboard_8, (1,8) },
{ LedId.Keyboard_9, (1,9) },
{ LedId.Keyboard_0, (1,10) },
{ LedId.Keyboard_MinusAndUnderscore, (1,11) },
{ LedId.Keyboard_EqualsAndPlus, (1,12) },
{ LedId.Keyboard_Backspace, (1,13) },
{ LedId.Keyboard_Insert, (1,14) },
{ LedId.Keyboard_Home, (1,15) },
{ LedId.Keyboard_PageUp, (1,16) },
{ LedId.Keyboard_NumLock, (1,17) },
{ LedId.Keyboard_NumSlash, (1,18) },
{ LedId.Keyboard_NumAsterisk, (1,19) },
{ LedId.Keyboard_NumMinus, (1,20) },
{ LedId.Keyboard_Tab, (2,0) },
{ LedId.Keyboard_Q, (2,1) },
{ LedId.Keyboard_W, (2,2) },
{ LedId.Keyboard_E, (2,3) },
{ LedId.Keyboard_R, (2,4) },
{ LedId.Keyboard_T, (2,5) },
{ LedId.Keyboard_Y, (2,6) },
{ LedId.Keyboard_U, (2,7) },
{ LedId.Keyboard_I, (2,8) },
{ LedId.Keyboard_O, (2,9) },
{ LedId.Keyboard_P, (2,10) },
{ LedId.Keyboard_BracketLeft, (2,11) },
{ LedId.Keyboard_BracketRight, (2,12) },
{ LedId.Keyboard_Backslash, (2,13) },
{ LedId.Keyboard_Delete, (2,14) },
{ LedId.Keyboard_End, (2,15) },
{ LedId.Keyboard_PageDown, (2,16) },
{ LedId.Keyboard_Num7, (2,17) },
{ LedId.Keyboard_Num8, (2,18) },
{ LedId.Keyboard_Num9, (2,19) },
{ LedId.Keyboard_NumPlus, (2,20) },
{ LedId.Keyboard_CapsLock, (3,0) },
{ LedId.Keyboard_A, (3,1) },
{ LedId.Keyboard_S, (3,2) },
{ LedId.Keyboard_D, (3,3) },
{ LedId.Keyboard_F, (3,4) },
{ LedId.Keyboard_G, (3,5) },
{ LedId.Keyboard_H, (3,6) },
{ LedId.Keyboard_J, (3,7) },
{ LedId.Keyboard_K, (3,8) },
{ LedId.Keyboard_L, (3,9) },
{ LedId.Keyboard_SemicolonAndColon, (3,10) },
{ LedId.Keyboard_ApostropheAndDoubleQuote, (3,11) },
{ LedId.Keyboard_Enter, (3,13) },
{ LedId.Keyboard_Num4, (3,17) },
{ LedId.Keyboard_Num5, (3,18) },
{ LedId.Keyboard_Num6, (3,19) },
{ LedId.Keyboard_LeftShift, (4,0) },
{ LedId.Keyboard_NonUsBackslash, (4,1) },
{ LedId.Keyboard_Z, (4,2) },
{ LedId.Keyboard_X, (4,3) },
{ LedId.Keyboard_C, (4,4) },
{ LedId.Keyboard_V, (4,5) },
{ LedId.Keyboard_B, (4,6) },
{ LedId.Keyboard_N, (4,7) },
{ LedId.Keyboard_M, (4,8) },
{ LedId.Keyboard_CommaAndLessThan, (4,9) },
{ LedId.Keyboard_PeriodAndBiggerThan, (4,10) },
{ LedId.Keyboard_SlashAndQuestionMark, (4,11) },
{ LedId.Keyboard_RightShift, (4,13) },
{ LedId.Keyboard_ArrowUp, (4,15) },
{ LedId.Keyboard_Num1, (4,17) },
{ LedId.Keyboard_Num2, (4,18) },
{ LedId.Keyboard_Num3, (4,19) },
{ LedId.Keyboard_NumEnter, (4,20) },
{ LedId.Keyboard_LeftCtrl, (5,0) },
{ LedId.Keyboard_LeftGui, (5,1) },
{ LedId.Keyboard_LeftAlt, (5,2) },
{ LedId.Keyboard_Space, (5,6) },
{ LedId.Keyboard_RightAlt, (5,10) },
{ LedId.Keyboard_RightGui, (5,11) },
{ LedId.Keyboard_Application, (5,12) },
{ LedId.Keyboard_RightCtrl, (5,13) },
{ LedId.Keyboard_ArrowLeft, (5,14) },
{ LedId.Keyboard_ArrowDown, (5,15) },
{ LedId.Keyboard_ArrowRight, (5,16) },
{ LedId.Keyboard_Num0, (5,18) },
{ LedId.Keyboard_NumPeriodAndDelete, (5,19) }
};
#endregion
/// <summary>
/// Contains all the hardware-id mappings for Wooting devices.
/// </summary>
public static readonly Dictionary<WootingDevicesIndexes, Dictionary<WootingPhysicalKeyboardLayout, Dictionary<LedId, (int row, int column)>>> Mapping =
new Dictionary<WootingDevicesIndexes, Dictionary<WootingPhysicalKeyboardLayout, Dictionary<LedId, (int row, int column)>>>
{
{ WootingDevicesIndexes.WootingOne, new Dictionary<WootingPhysicalKeyboardLayout, Dictionary<LedId, (int row, int column)>>
{
{ WootingPhysicalKeyboardLayout.US, WootingOne_US },
{ WootingPhysicalKeyboardLayout.EU, WootingOne_US }
}
},
{ WootingDevicesIndexes.WootingTwo, new Dictionary<WootingPhysicalKeyboardLayout, Dictionary<LedId, (int row, int column)>>
{
{ WootingPhysicalKeyboardLayout.US, WootingTwo_US },
{ WootingPhysicalKeyboardLayout.EU, WootingTwo_US }
}
}
};
#endregion
}
}

View File

@ -0,0 +1,53 @@
using System.Collections.Generic;
using System.Linq;
using RGB.NET.Core;
using RGB.NET.Devices.Wooting.Generic;
namespace RGB.NET.Devices.Wooting.Keyboard
{
/// <inheritdoc />
/// <summary>
/// Represents a Wooting keyboard.
/// </summary>
public class WootingKeyboardRGBDevice : WootingRGBDevice<WootingKeyboardRGBDeviceInfo>
{
#region Constructors
/// <inheritdoc />
/// <summary>
/// Initializes a new instance of the <see cref="T:RGB.NET.Devices.Wooting.Keyboard.WootingKeyboardRGBDevice" /> class.
/// </summary>
/// <param name="info">The specific information provided by Wooting for the keyboard</param>
internal WootingKeyboardRGBDevice(WootingKeyboardRGBDeviceInfo info)
: base(info)
{ }
#endregion
#region Methods
/// <inheritdoc />
protected override void InitializeLayout()
{
Dictionary<LedId, (int row, int column)> mapping = WootingKeyboardLedMappings.Mapping[DeviceInfo.DeviceIndex][DeviceInfo.PhysicalLayout];
foreach (KeyValuePair<LedId, (int row, int column)> led in mapping)
{
InitializeLed(led.Key, new Point(led.Value.column * 19, led.Value.row * 19), new Size(19,19));
}
string model = DeviceInfo.Model.Replace(" ", string.Empty).ToUpper();
ApplyLayoutFromFile(PathHelper.GetAbsolutePath(this, $@"Layouts\Wooting\Keyboards\{model}", $"{DeviceInfo.PhysicalLayout.ToString().ToUpper()}.xml"),
DeviceInfo.LogicalLayout.ToString());
}
/// <inheritdoc />
protected override void UpdateLeds(IEnumerable<Led> ledsToUpdate) => UpdateQueue.SetData(ledsToUpdate.Where(x => x.Color.A > 0));
/// <inheritdoc />
protected override object CreateLedCustomData(LedId ledId) => WootingKeyboardLedMappings.Mapping[DeviceInfo.DeviceIndex][DeviceInfo.PhysicalLayout][ledId];
#endregion
}
}

View File

@ -0,0 +1,57 @@
using System;
using System.Globalization;
using RGB.NET.Core;
using RGB.NET.Devices.Wooting.Enum;
using RGB.NET.Devices.Wooting.Generic;
namespace RGB.NET.Devices.Wooting.Keyboard
{
/// <inheritdoc />
/// <summary>
/// Represents a generic information for a <see cref="T:RGB.NET.Devices.Wooting.Keyboard.WootingKeyboardRGBDevice" />.
/// </summary>
public class WootingKeyboardRGBDeviceInfo : WootingRGBDeviceInfo
{
#region Properties & Fields
/// <summary>
/// Gets the <see cref="WootingPhysicalKeyboardLayout"/> of the <see cref="WootingKeyboardRGBDevice"/>.
/// </summary>
public WootingPhysicalKeyboardLayout PhysicalLayout { get; }
/// <summary>
/// Gets the <see cref="WootingLogicalKeyboardLayout"/> of the <see cref="WootingKeyboardRGBDevice"/>.
/// </summary>
public WootingLogicalKeyboardLayout LogicalLayout { get; private set; }
#endregion
#region Constructors
/// <inheritdoc />
/// <summary>
/// Internal constructor of managed <see cref="T:RGB.NET.Devices.Wooting.WootingKeyboardRGBDeviceInfo" />.
/// </summary>
/// <param name="deviceIndex">The index of the <see cref="T:RGB.NET.Devices.Wooting.WootingKeyboardRGBDevice" />.</param>
/// <param name="physicalKeyboardLayout">The <see cref="T:RGB.NET.Devices.Wooting.WootingPhysicalKeyboardLayout" /> of the <see cref="T:RGB.NET.Devices.Wooting.WootingKeyboardRGBDevice" />.</param>
/// <param name="culture">The <see cref="T:System.Globalization.CultureInfo" /> of the layout this keyboard is using</param>
internal WootingKeyboardRGBDeviceInfo(WootingDevicesIndexes deviceIndex, WootingPhysicalKeyboardLayout physicalKeyboardLayout, CultureInfo culture)
: base(RGBDeviceType.Keyboard, deviceIndex)
{
this.PhysicalLayout = physicalKeyboardLayout;
// For now just go for this
switch (physicalKeyboardLayout)
{
case WootingPhysicalKeyboardLayout.US:
this.LogicalLayout = WootingLogicalKeyboardLayout.US;
break;
case WootingPhysicalKeyboardLayout.EU:
this.LogicalLayout = WootingLogicalKeyboardLayout.EU;
break;
}
}
#endregion
}
}

View File

@ -0,0 +1,123 @@
// 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 System.Text;
using RGB.NET.Core;
namespace RGB.NET.Devices.Wooting.Native
{
// ReSharper disable once InconsistentNaming
public class _WootingSDK
{
#region Library 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()
{
UnloadWootingSDK();
LoadWootingSDK();
}
private static void LoadWootingSDK()
{
if (_dllHandle != IntPtr.Zero) return;
// HACK: Load library at runtime to support both, x86 and x64 with one managed dll
List<string> possiblePathList = Environment.Is64BitProcess ? WootingDeviceProvider.PossibleX64NativePaths : WootingDeviceProvider.PossibleX86NativePaths;
string dllPath = possiblePathList.FirstOrDefault(File.Exists);
if (dllPath == null) throw new RGBDeviceException($"Can't find the Wooting-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);
_isWootingOnePointer = (IsWootingOnePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "wooting_rgb_kbd_is_wooting_one"), typeof(IsWootingOnePointer));
_isWootingTwoPointer = (IsWootingTwoPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "wooting_rgb_kbd_is_wooting_two"), typeof(IsWootingTwoPointer));
_keyboardConnectedPointer = (KeyboardConnectedPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "wooting_rgb_kbd_connected"), typeof(KeyboardConnectedPointer));
_resetPointer = (ResetPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "wooting_rgb_reset"), typeof(ResetPointer));
_arrayUpdateKeyboardPointer = (ArrayUpdateKeyboardPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "wooting_rgb_array_update_keyboard"), typeof(ArrayUpdateKeyboardPointer));
_arraySetSinglePointer = (ArraySetSinglePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "wooting_rgb_array_set_single"), typeof(ArraySetSinglePointer));
}
private static void UnloadWootingSDK()
{
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 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 IsWootingOnePointer _isWootingOnePointer;
private static IsWootingTwoPointer _isWootingTwoPointer;
private static KeyboardConnectedPointer _keyboardConnectedPointer;
private static ResetPointer _resetPointer;
private static ArrayUpdateKeyboardPointer _arrayUpdateKeyboardPointer;
private static ArraySetSinglePointer _arraySetSinglePointer;
#endregion
#region Delegates
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool IsWootingOnePointer();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool IsWootingTwoPointer();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool KeyboardConnectedPointer();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool ResetPointer();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool ArrayUpdateKeyboardPointer();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool ArraySetSinglePointer(byte row, byte column, byte red, byte green, byte blue);
#endregion
internal static bool IsWootingOne() => _isWootingOnePointer();
internal static bool IsWootingTwo() => _isWootingTwoPointer();
internal static bool KeyboardConnected() => _keyboardConnectedPointer();
internal static bool Reset() => _resetPointer();
internal static bool ArrayUpdateKeyboard() => _arrayUpdateKeyboardPointer();
internal static bool ArraySetSingle(byte row, byte column, byte red, byte green, byte blue) => _arraySetSinglePointer(row, column, red, green, blue);
#endregion
}
}

View File

@ -0,0 +1,68 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net45</TargetFrameworks>
<RuntimeIdentifiers>win7-x86;win7-x64</RuntimeIdentifiers>
<Authors>Darth Affe</Authors>
<Company>Wyrez</Company>
<Language>en-US</Language>
<NeutralLanguage>en-US</NeutralLanguage>
<Title>RGB.NET.Devices.Wooting</Title>
<AssemblyName>RGB.NET.Devices.Wooting</AssemblyName>
<AssemblyTitle>RGB.NET.Devices.Wooting</AssemblyTitle>
<PackageId>RGB.NET.Devices.Wooting</PackageId>
<RootNamespace>RGB.NET.Devices.Wooting</RootNamespace>
<Description>Wooting-Device-Implementations of RGB.NET</Description>
<Summary>Wooting-Device-Implementations of RGB.NET, a C# (.NET) library for accessing various RGB-peripherals</Summary>
<Copyright>Copyright © Wyrez 2017</Copyright>
<PackageCopyright>Copyright © Wyrez 2017</PackageCopyright>
<PackageIconUrl>http://lib.arge.be/icon.png</PackageIconUrl>
<PackageProjectUrl>https://github.com/DarthAffe/RGB.NET</PackageProjectUrl>
<PackageLicenseUrl>https://raw.githubusercontent.com/DarthAffe/RGB.NET/master/LICENSE</PackageLicenseUrl>
<RepositoryType>Github</RepositoryType>
<RepositoryUrl>https://github.com/DarthAffe/RGB.NET</RepositoryUrl>
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
<PackageReleaseNotes></PackageReleaseNotes>
<Version>0.0.1</Version>
<AssemblyVersion>0.0.1</AssemblyVersion>
<FileVersion>0.0.1</FileVersion>
<OutputPath>..\bin\</OutputPath>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<IncludeSource>True</IncludeSource>
<IncludeSymbols>True</IncludeSymbols>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<DefineConstants>NETCORE;NETSTANDARD;NETSTANDARD2_0</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'net45'">
<DefineConstants>NET45;NETFULL</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<DefineConstants>$(DefineConstants);TRACE;DEBUG</DefineConstants>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<NoWarn>$(NoWarn);CS1591;CS1572;CS1573</NoWarn>
<DefineConstants>$(DefineConstants);RELEASE</DefineConstants>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\RGB.NET.Core\RGB.NET.Core.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net45'">
<PackageReference Include="System.ValueTuple" Version="4.4.0" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using RGB.NET.Core;
using RGB.NET.Devices.Wooting.Native;
namespace RGB.NET.Devices.Wooting
{
/// <inheritdoc />
/// <summary>
/// Represents a device provider responsible for Wooting devices.
/// </summary>
public class WootingDeviceProvider : IRGBDeviceProvider
{
#region Properties & Fields
private static WootingDeviceProvider _instance;
/// <summary>
/// Gets the singleton <see cref="WootingDeviceProvider"/> instance.
/// </summary>
public static WootingDeviceProvider Instance => _instance ?? new WootingDeviceProvider();
/// <summary>
/// Gets a modifiable list of paths used to find the native SDK-dlls for x86 applications.
/// The first match will be used.
/// </summary>
public static List<string> PossibleX86NativePaths { get; } = new List<string> { "x86/wooting-rgb-sdk.dll" };
/// <summary>
/// Gets a modifiable list of paths used to find the native SDK-dlls for x64 applications.
/// The first match will be used.
/// </summary>
public static List<string> PossibleX64NativePaths { get; } = new List<string> { "x64/wooting-rgb-sdk64.dll" };
/// <inheritdoc />
/// <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 => _WootingSDK.LoadedArchitecture;
/// <inheritdoc />
/// <summary>
/// Gets whether the application has exclusive access to the SDK or not.
/// </summary>
public bool HasExclusiveAccess => false;
/// <inheritdoc />
public IEnumerable<IRGBDevice> Devices { get; private set; }
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="WootingDeviceProvider"/> class.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown if this constructor is called even if there is already an instance of this class.</exception>
public WootingDeviceProvider()
{
if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(WootingDeviceProvider)}");
_instance = this;
}
#endregion
#region Methods
/// <inheritdoc />
/// <exception cref="RGBDeviceException">Thrown if the SDK failed to initialize</exception>
public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool exclusiveAccessIfPossible = false, bool throwExceptions = false)
{
IsInitialized = false;
try
{
_WootingSDK.Reload();
IList<IRGBDevice> devices = new List<IRGBDevice>();
if (_WootingSDK.KeyboardConnected())
{
if (_WootingSDK.IsWootingOne())
{
}
else if (_WootingSDK.IsWootingTwo())
{
}
}
Devices = new ReadOnlyCollection<IRGBDevice>(devices);
IsInitialized = true;
}
catch
{
if (throwExceptions) throw;
return false;
}
return true;
}
/// <inheritdoc />
public void ResetDevices()
{ }
/// <inheritdoc />
public void Dispose()
{
try { _WootingSDK.Reset(); }
catch { /* Unlucky.. */}
}
#endregion
}
}

View File

@ -0,0 +1,24 @@
using RGB.NET.Core;
namespace RGB.NET.Devices.Wooting
{
/// <summary>
/// Represents a device provider loaded used to dynamically load Wooting devices into an application.
/// </summary>
public class WootingDeviceProviderLoader : IRGBDeviceProviderLoader
{
#region Properties & Fields
/// <inheritdoc />
public bool RequiresInitialization => false;
#endregion
#region Methods
/// <inheritdoc />
public IRGBDeviceProvider GetDeviceProvider() => WootingDeviceProvider.Instance;
#endregion
}
}

View File

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27703.2035
# Visual Studio Version 16
VisualStudioVersion = 16.0.29424.173
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Devices", "Devices", "{D13032C6-432E-4F43-8A32-071133C22B16}"
EndProject
@ -47,6 +47,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RGB.NET.Core.Tests", "Tests
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RGB.NET.Devices.Asus", "RGB.NET.Devices.Asus\RGB.NET.Devices.Asus.csproj", "{E0732B34-3F96-4DD9-AFD5-0E34B833AD6D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RGB.NET.Devices.Wooting", "RGB.NET.Devices.Wooting\RGB.NET.Devices.Wooting.csproj", "{DD46DB2D-85BE-4962-86AE-E38C9053A548}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -129,6 +131,10 @@ Global
{E0732B34-3F96-4DD9-AFD5-0E34B833AD6D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E0732B34-3F96-4DD9-AFD5-0E34B833AD6D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E0732B34-3F96-4DD9-AFD5-0E34B833AD6D}.Release|Any CPU.Build.0 = Release|Any CPU
{DD46DB2D-85BE-4962-86AE-E38C9053A548}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DD46DB2D-85BE-4962-86AE-E38C9053A548}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DD46DB2D-85BE-4962-86AE-E38C9053A548}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DD46DB2D-85BE-4962-86AE-E38C9053A548}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -152,6 +158,7 @@ Global
{FFDE4387-60F2-47B6-9704-3A57D02B8C64} = {D13032C6-432E-4F43-8A32-071133C22B16}
{A3FD5AD7-040A-47CA-A278-53493A25FF8A} = {92D7C263-D4C9-4D26-93E2-93C1F9C2CD16}
{E0732B34-3F96-4DD9-AFD5-0E34B833AD6D} = {D13032C6-432E-4F43-8A32-071133C22B16}
{DD46DB2D-85BE-4962-86AE-E38C9053A548} = {D13032C6-432E-4F43-8A32-071133C22B16}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7F222AD4-1F9E-4AAB-9D69-D62372D4C1BA}