// ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedMember.Global using System.Collections.Generic; using System.Collections.ObjectModel; using System.Runtime.InteropServices; using RGB.NET.Core; using RGB.NET.Core.Exceptions; using RGB.NET.Devices.Corsair.Native; namespace RGB.NET.Devices.Corsair { /// /// Represents a device provider responsible for corsair (CUE) devices. /// public class CorsairDeviceProvider : IRGBDeviceProvider { #region Properties & Fields /// /// Gets the singleton instance. /// public static CorsairDeviceProvider Instance { get; } = new CorsairDeviceProvider(); /// /// 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 => _CUESDK.LoadedArchitecture; /// /// Gets the protocol details for the current SDK-connection. /// public CorsairProtocolDetails ProtocolDetails { get; private set; } /// /// Gets whether the application has exclusive access to the SDK or not. /// public bool HasExclusiveAccess { get; private set; } /// /// Gets the last error documented by CUE. /// public CorsairError LastError => _CUESDK.CorsairGetLastError(); /// public IEnumerable Devices { get; private set; } #endregion #region Constructors private CorsairDeviceProvider() { } #endregion #region Methods /// /// Thrown if the SDK is already initialized or if the SDK is not compatible to CUE. /// Thrown if the CUE-SDK provides an error. public bool Initialize(bool exclusiveAccessIfPossible = false, bool throwExceptions = false) { IsInitialized = false; try { _CUESDK.Reload(); } catch { if (throwExceptions) throw; else return false; } ProtocolDetails = new CorsairProtocolDetails(_CUESDK.CorsairPerformProtocolHandshake()); CorsairError error = LastError; if (error != CorsairError.Success) { Reset(); if (throwExceptions) throw new CUEException(error); else return false; } if (ProtocolDetails.BreakingChanges) { Reset(); if (throwExceptions) throw new RGBDeviceException("The SDK currently used isn't compatible with the installed version of CUE.\r\n" + $"CUE-Version: {ProtocolDetails.ServerVersion} (Protocol {ProtocolDetails.ServerProtocolVersion})\r\n" + $"SDK-Version: {ProtocolDetails.SdkVersion} (Protocol {ProtocolDetails.SdkProtocolVersion})"); else return false; } if (exclusiveAccessIfPossible) { if (!_CUESDK.CorsairRequestControl(CorsairAccessMode.ExclusiveLightingControl)) { Reset(); if (throwExceptions) throw new CUEException(LastError); else return false; } HasExclusiveAccess = true; } else HasExclusiveAccess = false; IList devices = new List(); int deviceCount = _CUESDK.CorsairGetDeviceCount(); for (int i = 0; i < deviceCount; i++) { _CorsairDeviceInfo nativeDeviceInfo = (_CorsairDeviceInfo)Marshal.PtrToStructure(_CUESDK.CorsairGetDeviceInfo(i), typeof(_CorsairDeviceInfo)); CorsairRGBDeviceInfo info = new CorsairRGBDeviceInfo(i, RGBDeviceType.Unknown, nativeDeviceInfo); if (!info.CapsMask.HasFlag(CorsairDeviceCaps.Lighting)) continue; // Everything that doesn't support lighting control is useless CorsairRGBDevice device; switch (info.CorsairDeviceType) { case CorsairDeviceType.Keyboard: device = new CorsairKeyboardRGBDevice(new CorsairKeyboardRGBDeviceInfo(i, nativeDeviceInfo)); break; case CorsairDeviceType.Mouse: device = new CorsairMouseRGBDevice(new CorsairMouseRGBDeviceInfo(i, nativeDeviceInfo)); break; case CorsairDeviceType.Headset: device = new CorsairHeadsetRGBDevice(new CorsairHeadsetRGBDeviceInfo(i, nativeDeviceInfo)); break; case CorsairDeviceType.Mousemat: device = new CorsairMousematRGBDevice(new CorsairMousematRGBDeviceInfo(i, nativeDeviceInfo)); break; // ReSharper disable once RedundantCaseLabel case CorsairDeviceType.Unknown: default: if (throwExceptions) throw new RGBDeviceException("Unknown Device-Type"); else continue; } try { device.Initialize(); } catch { if (throwExceptions) throw; else continue; } devices.Add(device); error = LastError; if (error != CorsairError.Success) { Reset(); if (throwExceptions) throw new CUEException(error); else return false; } } Devices = new ReadOnlyCollection(devices); IsInitialized = true; return true; } /// public void ResetDevices() { if (IsInitialized) try { _CUESDK.Reload(); } catch { // shit happens ... } } private void Reset() { ProtocolDetails = null; HasExclusiveAccess = false; Devices = null; IsInitialized = false; } #endregion } }