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

Wooting - Added Multi device support

This commit is contained in:
Diogo Trindade 2022-08-09 12:35:33 +01:00
parent f17c18e5ec
commit 819e6ef1df
5 changed files with 50 additions and 37 deletions

View File

@ -16,9 +16,9 @@ public abstract class WootingRGBDevice<TDeviceInfo> : AbstractRGBDevice<TDeviceI
/// Initializes a new instance of the <see cref="WootingRGBDevice{TDeviceInfo}"/> class. /// Initializes a new instance of the <see cref="WootingRGBDevice{TDeviceInfo}"/> class.
/// </summary> /// </summary>
/// <param name="info">The generic information provided by Wooting for the device.</param> /// <param name="info">The generic information provided by Wooting for the device.</param>
/// <param name="updateTrigger">The update trigger used to update this device.</param> /// <param name="updateQueue">The update queue used to update this device.</param>
protected WootingRGBDevice(TDeviceInfo info, IDeviceUpdateTrigger updateTrigger) protected WootingRGBDevice(TDeviceInfo info, IUpdateQueue updateQueue)
: base(info, new WootingUpdateQueue(updateTrigger)) : base(info, updateQueue)
{ } { }
#endregion #endregion

View File

@ -10,15 +10,20 @@ namespace RGB.NET.Devices.Wooting.Generic;
/// </summary> /// </summary>
public class WootingUpdateQueue : UpdateQueue public class WootingUpdateQueue : UpdateQueue
{ {
#region Properties & Fields
private readonly byte _deviceid;
#endregion
#region Constructors #region Constructors
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="WootingUpdateQueue"/> class. /// Initializes a new instance of the <see cref="WootingUpdateQueue"/> class.
/// </summary> /// </summary>
/// <param name="updateTrigger">The update trigger used by this queue.</param> /// <param name="updateTrigger">The update trigger used by this queue.</param>
public WootingUpdateQueue(IDeviceUpdateTrigger updateTrigger) public WootingUpdateQueue(IDeviceUpdateTrigger updateTrigger, byte deviceId)
: base(updateTrigger) : base(updateTrigger)
{ {
_deviceid = deviceId;
} }
#endregion #endregion
@ -30,6 +35,8 @@ public class WootingUpdateQueue : UpdateQueue
{ {
lock (_WootingSDK.SdkLock) lock (_WootingSDK.SdkLock)
{ {
_WootingSDK.SelectDevice(_deviceid);
foreach ((object key, Color color) in dataSet) foreach ((object key, Color color) in dataSet)
{ {
(int row, int column) = ((int, int))key; (int row, int column) = ((int, int))key;

View File

@ -24,8 +24,8 @@ public class WootingKeyboardRGBDevice : WootingRGBDevice<WootingKeyboardRGBDevic
/// </summary> /// </summary>
/// <param name="info">The specific information provided by Wooting for the keyboard</param> /// <param name="info">The specific information provided by Wooting for the keyboard</param>
/// <param name="updateTrigger">The update trigger used to update this device.</param> /// <param name="updateTrigger">The update trigger used to update this device.</param>
internal WootingKeyboardRGBDevice(WootingKeyboardRGBDeviceInfo info, IDeviceUpdateTrigger updateTrigger) internal WootingKeyboardRGBDevice(WootingKeyboardRGBDeviceInfo info, IUpdateQueue updateQueue)
: base(info, updateTrigger) : base(info, updateQueue)
{ {
InitializeLayout(); InitializeLayout();
} }

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using RGB.NET.Core; using RGB.NET.Core;
@ -15,7 +16,7 @@ internal static class _WootingSDK
{ {
#region Library management #region Library management
private static IntPtr _dllHandle = IntPtr.Zero; private static IntPtr _handle = IntPtr.Zero;
internal static object SdkLock = new(); internal static object SdkLock = new();
/// <summary> /// <summary>
@ -29,7 +30,7 @@ internal static class _WootingSDK
private static void LoadWootingSDK() private static void LoadWootingSDK()
{ {
if (_dllHandle != IntPtr.Zero) return; if (_handle != IntPtr.Zero) return;
// HACK: Load library at runtime to support both, x86 and x64 with one managed dll // HACK: Load library at runtime to support both, x86 and x64 with one managed dll
List<string> possiblePathList = (Environment.Is64BitProcess ? WootingDeviceProvider.PossibleX64NativePaths : WootingDeviceProvider.PossibleX86NativePaths) List<string> possiblePathList = (Environment.Is64BitProcess ? WootingDeviceProvider.PossibleX64NativePaths : WootingDeviceProvider.PossibleX86NativePaths)
@ -38,22 +39,24 @@ internal static class _WootingSDK
string? dllPath = possiblePathList.FirstOrDefault(File.Exists); 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))}'"); 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))!);
_handle = NativeLibrary.Load(dllPath);
_dllHandle = LoadLibrary(dllPath); if (_handle == IntPtr.Zero) throw new RGBDeviceException($"Wooting LoadLibrary failed with error code {Marshal.GetLastWin32Error()}");
if (_dllHandle == IntPtr.Zero) throw new RGBDeviceException($"Wooting LoadLibrary failed with error code {Marshal.GetLastWin32Error()}");
_getDeviceInfoPointer = (GetDeviceInfoPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "wooting_rgb_device_info"), typeof(GetDeviceInfoPointer));
_getDeviceInfoPointer = (GetDeviceInfoPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "wooting_rgb_device_info"), typeof(GetDeviceInfoPointer)); _keyboardConnectedPointer = (KeyboardConnectedPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "wooting_rgb_kbd_connected"), typeof(KeyboardConnectedPointer));
_keyboardConnectedPointer = (KeyboardConnectedPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "wooting_rgb_kbd_connected"), typeof(KeyboardConnectedPointer)); _resetPointer = (ResetPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "wooting_rgb_reset_rgb"), typeof(ResetPointer));
_resetPointer = (ResetPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "wooting_rgb_reset_rgb"), typeof(ResetPointer)); _closePointer = (ClosePointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "wooting_rgb_close"), typeof(ClosePointer));
_closePointer = (ClosePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "wooting_rgb_close"), typeof(ClosePointer)); _arrayUpdateKeyboardPointer = (ArrayUpdateKeyboardPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "wooting_rgb_array_update_keyboard"), typeof(ArrayUpdateKeyboardPointer));
_arrayUpdateKeyboardPointer = (ArrayUpdateKeyboardPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "wooting_rgb_array_update_keyboard"), typeof(ArrayUpdateKeyboardPointer)); _arraySetSinglePointer = (ArraySetSinglePointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "wooting_rgb_array_set_single"), typeof(ArraySetSinglePointer));
_arraySetSinglePointer = (ArraySetSinglePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "wooting_rgb_array_set_single"), typeof(ArraySetSinglePointer)); _getDeviceCountPointer = (GetDeviceCountPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "wooting_usb_keyboard_count"), typeof(GetDeviceCountPointer));
_selectDevicePointer = (SelectDevicePointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "wooting_usb_select_device"), typeof(SelectDevicePointer));
} }
internal static void UnloadWootingSDK() internal static void UnloadWootingSDK()
{ {
if (_dllHandle == IntPtr.Zero) return; if (_handle == IntPtr.Zero) return;
Reset(); Reset();
Close(); Close();
@ -66,22 +69,10 @@ internal static class _WootingSDK
_closePointer = null; _closePointer = null;
// 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 // 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)) ; NativeLibrary.Free(_handle);
_dllHandle = IntPtr.Zero; _handle = 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 #endregion
#region SDK-METHODS #region SDK-METHODS
@ -94,6 +85,8 @@ internal static class _WootingSDK
private static ClosePointer? _closePointer; private static ClosePointer? _closePointer;
private static ArrayUpdateKeyboardPointer? _arrayUpdateKeyboardPointer; private static ArrayUpdateKeyboardPointer? _arrayUpdateKeyboardPointer;
private static ArraySetSinglePointer? _arraySetSinglePointer; private static ArraySetSinglePointer? _arraySetSinglePointer;
private static GetDeviceCountPointer? _getDeviceCountPointer;
private static SelectDevicePointer? _selectDevicePointer;
#endregion #endregion
@ -117,6 +110,12 @@ internal static class _WootingSDK
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool ArraySetSinglePointer(byte row, byte column, byte red, byte green, byte blue); private delegate bool ArraySetSinglePointer(byte row, byte column, byte red, byte green, byte blue);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate byte GetDeviceCountPointer();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void SelectDevicePointer(byte index);
#endregion #endregion
internal static IntPtr GetDeviceInfo() => (_getDeviceInfoPointer ?? throw new RGBDeviceException("The Wooting-SDK is not initialized.")).Invoke(); internal static IntPtr GetDeviceInfo() => (_getDeviceInfoPointer ?? throw new RGBDeviceException("The Wooting-SDK is not initialized.")).Invoke();
@ -125,6 +124,7 @@ internal static class _WootingSDK
internal static bool Close() => (_closePointer ?? throw new RGBDeviceException("The Wooting-SDK is not initialized.")).Invoke(); internal static bool Close() => (_closePointer ?? throw new RGBDeviceException("The Wooting-SDK is not initialized.")).Invoke();
internal static bool ArrayUpdateKeyboard() => (_arrayUpdateKeyboardPointer ?? throw new RGBDeviceException("The Wooting-SDK is not initialized.")).Invoke(); internal static bool ArrayUpdateKeyboard() => (_arrayUpdateKeyboardPointer ?? throw new RGBDeviceException("The Wooting-SDK is not initialized.")).Invoke();
internal static bool ArraySetSingle(byte row, byte column, byte red, byte green, byte blue) => (_arraySetSinglePointer ?? throw new RGBDeviceException("The Wooting-SDK is not initialized.")).Invoke(row, column, red, green, blue); internal static bool ArraySetSingle(byte row, byte column, byte red, byte green, byte blue) => (_arraySetSinglePointer ?? throw new RGBDeviceException("The Wooting-SDK is not initialized.")).Invoke(row, column, red, green, blue);
internal static byte GetDeviceCount() => (_getDeviceCountPointer ?? throw new RGBDeviceException("The Wooting-SDK is not initialized.")).Invoke();
internal static void SelectDevice(byte index) => (_selectDevicePointer ?? throw new RGBDeviceException("The Wooting-SDK is not initialized.")).Invoke(index);
#endregion #endregion
} }

View File

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using RGB.NET.Core; using RGB.NET.Core;
using RGB.NET.Devices.Wooting.Generic;
using RGB.NET.Devices.Wooting.Keyboard; using RGB.NET.Devices.Wooting.Keyboard;
using RGB.NET.Devices.Wooting.Native; using RGB.NET.Devices.Wooting.Native;
@ -67,9 +68,14 @@ public class WootingDeviceProvider : AbstractRGBDeviceProvider
{ {
if (_WootingSDK.KeyboardConnected()) if (_WootingSDK.KeyboardConnected())
{ {
_WootingDeviceInfo nativeDeviceInfo = (_WootingDeviceInfo)Marshal.PtrToStructure(_WootingSDK.GetDeviceInfo(), typeof(_WootingDeviceInfo))!; for (byte i = 0; i < _WootingSDK.GetDeviceCount(); i++)
{
var updateQueue = new WootingUpdateQueue(GetUpdateTrigger(), i);
_WootingSDK.SelectDevice(i);
_WootingDeviceInfo nativeDeviceInfo = (_WootingDeviceInfo)Marshal.PtrToStructure(_WootingSDK.GetDeviceInfo(), typeof(_WootingDeviceInfo))!;
yield return new WootingKeyboardRGBDevice(new WootingKeyboardRGBDeviceInfo(nativeDeviceInfo), GetUpdateTrigger()); yield return new WootingKeyboardRGBDevice(new WootingKeyboardRGBDeviceInfo(nativeDeviceInfo), updateQueue);
}
} }
} }
} }