diff --git a/RGB.NET.Devices.Roccat/Native/_ROCCATSDK.cs b/RGB.NET.Devices.Roccat/Native/_ROCCATSDK.cs
new file mode 100644
index 0000000..aa59118
--- /dev/null
+++ b/RGB.NET.Devices.Roccat/Native/_ROCCATSDK.cs
@@ -0,0 +1,163 @@
+// 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()
+ {
+ UnloadCUESDK();
+ LoadCUESDK();
+ }
+
+ private static void LoadCUESDK()
+ {
+ 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));
+ }
+
+ private static void UnloadCUESDK()
+ {
+ 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
+ }
+}
diff --git a/RGB.NET.Devices.Roccat/Properties/AssemblyInfo.cs b/RGB.NET.Devices.Roccat/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..adf4d9a
--- /dev/null
+++ b/RGB.NET.Devices.Roccat/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("RGB.NET.Devices.Roccat")]
+[assembly: AssemblyDescription("Roccat-Device-Implementations of RGB.NET")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Wyrez")]
+[assembly: AssemblyProduct("RGB.NET.Devices.Roccat")]
+[assembly: AssemblyCopyright("Copyright © Wyrez 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("01803e4a-36b8-4675-afb3-7c8968ac4a13")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/RGB.NET.Devices.Roccat/RGB.NET.Devices.Roccat.csproj b/RGB.NET.Devices.Roccat/RGB.NET.Devices.Roccat.csproj
new file mode 100644
index 0000000..33aaed8
--- /dev/null
+++ b/RGB.NET.Devices.Roccat/RGB.NET.Devices.Roccat.csproj
@@ -0,0 +1,66 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {01803E4A-36B8-4675-AFB3-7C8968AC4A13}
+ Library
+ Properties
+ RGB.NET.Devices.Roccat
+ RGB.NET.Devices.Roccat
+ v4.5
+ 512
+
+
+ true
+ full
+ false
+ ..\bin\
+ DEBUG;TRACE
+ prompt
+ 4
+ ..\bin\RGB.NET.Devices.Roccat.xml
+
+
+ pdbonly
+ true
+ ..\bin\
+ TRACE
+ prompt
+ 4
+ ..\bin\RGB.NET.Devices.Roccat.xml
+
+
+
+
+
+ ..\packages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {5a4f9a75-75fe-47cd-90e5-914d5b20d232}
+ RGB.NET.Core
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/RGB.NET.Devices.Roccat/RoccatDeviceProvider.cs b/RGB.NET.Devices.Roccat/RoccatDeviceProvider.cs
new file mode 100644
index 0000000..391a0da
--- /dev/null
+++ b/RGB.NET.Devices.Roccat/RoccatDeviceProvider.cs
@@ -0,0 +1,121 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using RGB.NET.Core;
+using RGB.NET.Devices.Roccat.Native;
+
+namespace RGB.NET.Devices.Roccat
+{
+ ///
+ ///
+ /// Represents a device provider responsible for roccat (TalkFX)devices.
+ ///
+ public class RoccatDeviceProvider : IRGBDeviceProvider
+ {
+ #region Properties & Fields
+
+ private static RoccatDeviceProvider _instance;
+ ///
+ /// Gets the singleton instance.
+ ///
+ public static RoccatDeviceProvider Instance => _instance ?? new RoccatDeviceProvider();
+
+ ///
+ /// Gets a modifiable list of paths used to find the native SDK-dlls for x86 applications.
+ /// The first match will be used.
+ ///
+ public static List PossibleX86NativePaths { get; } = new List { "x86/RoccatTalkSDKWrapper.dll" };
+
+ ///
+ /// Gets a modifiable list of paths used to find the native SDK-dlls for x64 applications.
+ /// The first match will be used.
+ ///
+ public static List PossibleX64NativePaths { get; } = new List { "x64/RoccatTalkSDKWrapper.dll" };
+
+ ///
+ ///
+ /// Indicates if the SDK is initialized and ready to use.
+ ///
+ public bool IsInitialized { get; private set; }
+
+ ///
+ /// Gets the loaded architecture (x64/x86).
+ ///
+ public string LoadedArchitecture => _RoccatSDK.LoadedArchitecture;
+
+ ///
+ ///
+ /// Gets whether the application has exclusive access to the SDK or not.
+ ///
+ public bool HasExclusiveAccess { get; private set; }
+
+ ///
+ public IEnumerable Devices { get; private set; }
+
+ private IntPtr _sdkHandle;
+
+ #endregion
+
+ #region Constructors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Thrown if this constructor is called even if there is already an instance of this class.
+ public RoccatDeviceProvider()
+ {
+ if (_instance != null) throw new InvalidOperationException($"There can be only one instance of type {nameof(RoccatDeviceProvider)}");
+ _instance = this;
+ }
+
+ #endregion
+
+ #region Methods
+
+ ///
+ /// Thrown if the SDK is already initialized or if the SDK is not compatible to CUE.
+ public bool Initialize(RGBDeviceType loadFilter = RGBDeviceType.All, bool exclusiveAccessIfPossible = false, bool throwExceptions = false)
+ {
+ IsInitialized = false;
+
+ try
+ {
+ _sdkHandle = _RoccatSDK.InitSDK();
+
+ IList devices = new List();
+
+ Devices = new ReadOnlyCollection(devices);
+ IsInitialized = true;
+ }
+ catch
+ {
+ if (throwExceptions) throw;
+ return false;
+ }
+
+ return true;
+ }
+
+ ///
+ public void ResetDevices()
+ { }
+
+ ///
+ public void Dispose()
+ {
+ if (_sdkHandle != IntPtr.Zero)
+ {
+ try { _RoccatSDK.RestoreLedRGB(_sdkHandle); }
+ catch { /* We tried our best */}
+
+ try { _RoccatSDK.SetRyosKbSDKMode(_sdkHandle, false); }
+ catch { /* We tried our best */}
+
+ try { _RoccatSDK.UnloadSDK(_sdkHandle); }
+ catch { /* We tried our best */}
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/RGB.NET.Devices.Roccat/packages.config b/RGB.NET.Devices.Roccat/packages.config
new file mode 100644
index 0000000..a59695c
--- /dev/null
+++ b/RGB.NET.Devices.Roccat/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/RGB.NET.sln b/RGB.NET.sln
index 2231348..19fb685 100644
--- a/RGB.NET.sln
+++ b/RGB.NET.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
-VisualStudioVersion = 15.0.27130.2010
+VisualStudioVersion = 15.0.27130.2024
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RGB.NET.Core", "RGB.NET.Core\RGB.NET.Core.csproj", "{5A4F9A75-75FE-47CD-90E5-914D5B20D232}"
EndProject
@@ -68,6 +68,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RGB.NET.Devices.Razer", "RG
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RGB.NET.Devices.Debug", "RGB.NET.Devices.Debug\RGB.NET.Devices.Debug.csproj", "{D013040E-1931-4F0D-9CCA-0F4AE74A507E}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RGB.NET.Devices.Roccat", "RGB.NET.Devices.Roccat\RGB.NET.Devices.Roccat.csproj", "{01803E4A-36B8-4675-AFB3-7C8968AC4A13}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -130,6 +132,10 @@ Global
{D013040E-1931-4F0D-9CCA-0F4AE74A507E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D013040E-1931-4F0D-9CCA-0F4AE74A507E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D013040E-1931-4F0D-9CCA-0F4AE74A507E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {01803E4A-36B8-4675-AFB3-7C8968AC4A13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {01803E4A-36B8-4675-AFB3-7C8968AC4A13}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {01803E4A-36B8-4675-AFB3-7C8968AC4A13}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {01803E4A-36B8-4675-AFB3-7C8968AC4A13}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -149,6 +155,7 @@ Global
{C191D5BE-E1B2-47E4-AB39-D954B277188C} = {06416566-481F-4571-80EE-7BB05B1E0299}
{24FF4ACB-D679-4B2D-86D4-50AB6C02D816} = {33D5E279-1C4E-4AB6-9D1E-6D18109A6C25}
{D013040E-1931-4F0D-9CCA-0F4AE74A507E} = {33D5E279-1C4E-4AB6-9D1E-6D18109A6C25}
+ {01803E4A-36B8-4675-AFB3-7C8968AC4A13} = {33D5E279-1C4E-4AB6-9D1E-6D18109A6C25}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {CDECA6C7-8D18-4AF3-94F7-C70A69B8571B}