// 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; namespace RGB.NET.Devices.Roccat.Native { // ReSharper disable once InconsistentNaming internal static class _RoccatSDK { #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() { UnloadRoccatSDK(); LoadRoccatSDK(); } private static void LoadRoccatSDK() { if (_dllHandle != IntPtr.Zero) return; // HACK: Load library at runtime to support both, x86 and x64 with one managed dll List possiblePathList = Environment.Is64BitProcess ? RoccatDeviceProvider.PossibleX64NativePaths : RoccatDeviceProvider.PossibleX86NativePaths; string dllPath = possiblePathList.FirstOrDefault(File.Exists); if (dllPath == null) throw new RGBDeviceException($"Can't find the CUE-SDK at one of the expected locations:\r\n '{string.Join("\r\n", possiblePathList.Select(Path.GetFullPath))}'"); _dllHandle = LoadLibrary(dllPath); _initSDKPointer = (InitSDKPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "InitSDK"), typeof(InitSDKPointer)); _unloadSDKPointer = (UnloadSDKPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "UnloadSDK"), typeof(UnloadSDKPointer)); _initRyosTalkPointer = (InitRyosTalkPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "init_ryos_talk"), typeof(InitRyosTalkPointer)); _restoreLedRGBPointer = (RestoreLedRGBPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "RestoreLEDRGB"), typeof(RestoreLedRGBPointer)); _setRyosKbSDKModePointer = (SetRyosKbSDKModePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "set_ryos_kb_SDKmode"), typeof(SetRyosKbSDKModePointer)); _turnOffAllLedsPointer = (TurnOffAllLedsPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "turn_off_all_LEDS"), typeof(TurnOffAllLedsPointer)); _turnOnAllLedsPointer = (TurnOnAllLedsPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "turn_on_all_LEDS"), typeof(TurnOnAllLedsPointer)); _setLedOnPointer = (SetLedOnPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "set_LED_on"), typeof(SetLedOnPointer)); _setLedOffPointer = (SetLedOffPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "set_LED_off"), typeof(SetLedOffPointer)); _setAllLedsPointer = (SetAllLedsPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "Set_all_LEDS"), typeof(SetAllLedsPointer)); _allKeyblinkingPointer = (AllKeyblinkingPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "All_Key_Blinking"), typeof(AllKeyblinkingPointer)); _setLedRGBPointer = (SetLedRGBPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "Set_LED_RGB"), typeof(SetLedRGBPointer)); _setAllLedSfxPointer = (SetAllLedSfxPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "Set_all_LEDSFX"), typeof(SetAllLedSfxPointer)); } internal static void UnloadRoccatSDK() { 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 InitSDKPointer _initSDKPointer; private static UnloadSDKPointer _unloadSDKPointer; private static InitRyosTalkPointer _initRyosTalkPointer; private static RestoreLedRGBPointer _restoreLedRGBPointer; private static SetRyosKbSDKModePointer _setRyosKbSDKModePointer; private static TurnOffAllLedsPointer _turnOffAllLedsPointer; private static TurnOnAllLedsPointer _turnOnAllLedsPointer; private static SetLedOnPointer _setLedOnPointer; private static SetLedOffPointer _setLedOffPointer; private static SetAllLedsPointer _setAllLedsPointer; private static AllKeyblinkingPointer _allKeyblinkingPointer; private static SetLedRGBPointer _setLedRGBPointer; private static SetAllLedSfxPointer _setAllLedSfxPointer; #endregion #region Delegates [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate IntPtr InitSDKPointer(); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void UnloadSDKPointer(IntPtr handle); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate bool InitRyosTalkPointer(IntPtr handle); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void RestoreLedRGBPointer(IntPtr handle); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate bool SetRyosKbSDKModePointer(IntPtr handle, bool state); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void TurnOffAllLedsPointer(IntPtr handle); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void TurnOnAllLedsPointer(IntPtr handle); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void SetLedOnPointer(IntPtr handle, byte position); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void SetLedOffPointer(IntPtr handle, byte position); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void SetAllLedsPointer(IntPtr handle, byte led, byte country); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void AllKeyblinkingPointer(IntPtr handle, int delayTime, int loopTime); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void SetLedRGBPointer(IntPtr handle, byte zone, byte effect, byte speed, byte r, byte g, byte b); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void SetAllLedSfxPointer(IntPtr handle, byte ledOnOff, byte r, byte g, byte b, byte layout); #endregion // ReSharper disable EventExceptionNotDocumented internal static IntPtr InitSDK() => _initSDKPointer(); internal static void UnloadSDK(IntPtr handle) => _unloadSDKPointer(handle); internal static bool InitRyosTalk(IntPtr handle) => _initRyosTalkPointer(handle); internal static void RestoreLedRGB(IntPtr handle) => _restoreLedRGBPointer(handle); internal static bool SetRyosKbSDKMode(IntPtr handle, bool state) => _setRyosKbSDKModePointer(handle, state); internal static void TurnOffAllLeds(IntPtr handle) => _turnOffAllLedsPointer(handle); internal static void TurnOnAllLeds(IntPtr handle) => _turnOnAllLedsPointer(handle); internal static void SetLedOn(IntPtr handle, byte position) => _setLedOnPointer(handle, position); internal static void SetLedOff(IntPtr handle, byte position) => _setLedOffPointer(handle, position); internal static void SetAllLeds(IntPtr handle, byte led, byte country) => _setAllLedsPointer(handle, led, country); internal static void AllKeyblinking(IntPtr handle, int delayTime, int loopTime) => _allKeyblinkingPointer(handle, delayTime, loopTime); internal static void SetLedRGB(IntPtr handle, byte zone, byte effect, byte speed, byte r, byte g, byte b) => _setLedRGBPointer(handle, zone, effect, speed, r, g, b); internal static void SetAllLedSfx(IntPtr handle, byte ledOnOff, byte r, byte g, byte b, byte layout) => _setAllLedSfxPointer(handle, ledOnOff, r, g, b, layout); // ReSharper restore EventExceptionNotDocumented #endregion } }