Newer
Older
Qwilight / Qwilight / System / IlluminationSystem / K70System.cs
using CUESDK;
using Microsoft.UI;
using System.Buffers;
using Windows.System;
using Windows.UI;

namespace Qwilight
{
    public sealed class K70System : BaseIlluminationSystem
    {
        public static readonly K70System Instance = new();

        static CorsairLedId GetInput(VirtualKey rawInput) => rawInput switch
        {
            VirtualKey.Escape => CorsairLedId.KeyboardEscape,
            VirtualKey.F1 => CorsairLedId.KeyboardF1,
            VirtualKey.F2 => CorsairLedId.KeyboardF2,
            VirtualKey.F3 => CorsairLedId.KeyboardF3,
            VirtualKey.F4 => CorsairLedId.KeyboardF4,
            VirtualKey.F5 => CorsairLedId.KeyboardF5,
            VirtualKey.F6 => CorsairLedId.KeyboardF6,
            VirtualKey.F7 => CorsairLedId.KeyboardF7,
            VirtualKey.F8 => CorsairLedId.KeyboardF8,
            VirtualKey.F9 => CorsairLedId.KeyboardF9,
            VirtualKey.F10 => CorsairLedId.KeyboardF10,
            VirtualKey.F11 => CorsairLedId.KeyboardF11,
            VirtualKey.F12 => CorsairLedId.KeyboardF12,
            VirtualKey.Insert => CorsairLedId.KeyboardInsert,
            VirtualKey.Delete => CorsairLedId.KeyboardDelete,
            (VirtualKey)192 => CorsairLedId.KeyboardGraveAccentAndTilde,
            VirtualKey.Number1 => CorsairLedId.Keyboard1,
            VirtualKey.Number2 => CorsairLedId.Keyboard2,
            VirtualKey.Number3 => CorsairLedId.Keyboard3,
            VirtualKey.Number4 => CorsairLedId.Keyboard4,
            VirtualKey.Number5 => CorsairLedId.Keyboard5,
            VirtualKey.Number6 => CorsairLedId.Keyboard6,
            VirtualKey.Number7 => CorsairLedId.Keyboard7,
            VirtualKey.Number8 => CorsairLedId.Keyboard8,
            VirtualKey.Number9 => CorsairLedId.Keyboard9,
            VirtualKey.Number0 => CorsairLedId.Keyboard0,
            (VirtualKey)189 => CorsairLedId.KeyboardMinusAndUnderscore,
            (VirtualKey)187 => CorsairLedId.KeyboardEqualsAndPlus,
            VirtualKey.Back => CorsairLedId.KeyboardBackspace,
            VirtualKey.Tab => CorsairLedId.KeyboardTab,
            VirtualKey.Q => CorsairLedId.KeyboardQ,
            VirtualKey.W => CorsairLedId.KeyboardW,
            VirtualKey.E => CorsairLedId.KeyboardE,
            VirtualKey.R => CorsairLedId.KeyboardR,
            VirtualKey.T => CorsairLedId.KeyboardT,
            VirtualKey.Y => CorsairLedId.KeyboardY,
            VirtualKey.U => CorsairLedId.KeyboardU,
            VirtualKey.I => CorsairLedId.KeyboardI,
            VirtualKey.O => CorsairLedId.KeyboardO,
            VirtualKey.P => CorsairLedId.KeyboardP,
            (VirtualKey)219 => CorsairLedId.KeyboardBracketLeft,
            (VirtualKey)221 => CorsairLedId.KeyboardBracketRight,
            (VirtualKey)220 => CorsairLedId.KeyboardBackslash,
            VirtualKey.CapitalLock => CorsairLedId.KeyboardCapsLock,
            VirtualKey.A => CorsairLedId.KeyboardA,
            VirtualKey.S => CorsairLedId.KeyboardS,
            VirtualKey.D => CorsairLedId.KeyboardD,
            VirtualKey.F => CorsairLedId.KeyboardF,
            VirtualKey.G => CorsairLedId.KeyboardG,
            VirtualKey.H => CorsairLedId.KeyboardH,
            VirtualKey.J => CorsairLedId.KeyboardJ,
            VirtualKey.K => CorsairLedId.KeyboardK,
            VirtualKey.L => CorsairLedId.KeyboardL,
            (VirtualKey)186 => CorsairLedId.KeyboardSemicolonAndColon,
            (VirtualKey)222 => CorsairLedId.KeyboardApostropheAndDoubleQuote,
            VirtualKey.Enter => CorsairLedId.KeyboardEnter,
            VirtualKey.LeftShift => CorsairLedId.KeyboardLeftShift,
            VirtualKey.Z => CorsairLedId.KeyboardZ,
            VirtualKey.X => CorsairLedId.KeyboardX,
            VirtualKey.C => CorsairLedId.KeyboardC,
            VirtualKey.V => CorsairLedId.KeyboardV,
            VirtualKey.B => CorsairLedId.KeyboardB,
            VirtualKey.N => CorsairLedId.KeyboardN,
            VirtualKey.M => CorsairLedId.KeyboardM,
            (VirtualKey)188 => CorsairLedId.KeyboardCommaAndLessThan,
            (VirtualKey)190 => CorsairLedId.KeyboardPeriodAndBiggerThan,
            (VirtualKey)191 => CorsairLedId.KeyboardSlashAndQuestionMark,
            VirtualKey.RightShift => CorsairLedId.KeyboardRightShift,
            VirtualKey.LeftControl => CorsairLedId.KeyboardLeftCtrl,
            VirtualKey.LeftWindows => CorsairLedId.KeyboardLeftGui,
            VirtualKey.LeftMenu => CorsairLedId.KeyboardLeftAlt,
            VirtualKey.Space => CorsairLedId.KeyboardSpace,
            VirtualKey.RightMenu => CorsairLedId.KeyboardRightAlt,
            VirtualKey.RightControl => CorsairLedId.KeyboardRightCtrl,
            VirtualKey.Left => CorsairLedId.KeyboardLeftArrow,
            VirtualKey.Up => CorsairLedId.KeyboardUpArrow,
            VirtualKey.Down => CorsairLedId.KeyboardDownArrow,
            VirtualKey.Right => CorsairLedId.KeyboardRightArrow,
            VirtualKey.NumberKeyLock => CorsairLedId.KeyboardNumLock,
            VirtualKey.NumberPad0 => CorsairLedId.KeyboardKeypad0,
            VirtualKey.NumberPad1 => CorsairLedId.KeyboardKeypad1,
            VirtualKey.NumberPad2 => CorsairLedId.KeyboardKeypad2,
            VirtualKey.NumberPad3 => CorsairLedId.KeyboardKeypad3,
            VirtualKey.NumberPad4 => CorsairLedId.KeyboardKeypad4,
            VirtualKey.NumberPad5 => CorsairLedId.KeyboardKeypad5,
            VirtualKey.NumberPad6 => CorsairLedId.KeyboardKeypad6,
            VirtualKey.NumberPad7 => CorsairLedId.KeyboardKeypad7,
            VirtualKey.NumberPad8 => CorsairLedId.KeyboardKeypad8,
            VirtualKey.NumberPad9 => CorsairLedId.KeyboardKeypad9,
            VirtualKey.Snapshot => CorsairLedId.KeyboardPrintScreen,
            VirtualKey.Scroll => CorsairLedId.KeyboardScrollLock,
            VirtualKey.Pause => CorsairLedId.KeyboardPauseBreak,
            VirtualKey.Home => CorsairLedId.KeyboardHome,
            VirtualKey.PageUp => CorsairLedId.KeyboardPageUp,
            VirtualKey.End => CorsairLedId.KeyboardEnd,
            VirtualKey.PageDown => CorsairLedId.KeyboardPageDown,
            _ => default,
        };

        readonly CorsairLedId[] _inputs;
        readonly Dictionary<CorsairLedId, uint> _illuminatedIDs = new();
        readonly CorsairLedColor[] _illuminatedColors;
        int _illuminatedCount;

        K70System()
        {
            _inputs = (Enum.GetValues(typeof(CorsairLedId)) as CorsairLedId[]).Where(input => (CorsairLedId.KeyboardEscape <= input && input <= CorsairLedId.KeyboardFn) || input == CorsairLedId.KeyboardLogo || (CorsairLedId.KeyboardLightPipeZone1 <= input && input <= CorsairLedId.KeyboardLightPipeZone19) || (CorsairLedId.KeyboardLightPipeZone20 <= input && input <= CorsairLedId.KeyboardProfile)).ToArray();
            _illuminatedColors = new CorsairLedColor[_inputs.Length];
        }

        public override bool IsAvailable => Configure.Instance.K70;

        public override bool Init()
        {
            CorsairLightingSDK.PerformProtocolHandshake();
            return CorsairLightingSDK.GetLastError() == CorsairError.Success && CorsairLightingSDK.RequestControl(CorsairAccessMode.ExclusiveLightingControl);
        }

        public override void SetInputColor(VirtualKey rawInput, uint value)
        {
            var input = GetInput(rawInput);
            if (input != CorsairLedId.Invalid)
            {
                _illuminatedIDs[input] = value;
            }
        }

        public override void SetStatusColors(double status, uint value0, uint value1, uint value2, uint value3)
        {
        }

        public override void SetEtcColor(uint value)
        {
            _illuminatedIDs[CorsairLedId.KeyboardLogo] = value;
            for (var i = CorsairLedId.KeyboardLightPipeZone19; i >= CorsairLedId.KeyboardLightPipeZone1; --i)
            {
                _illuminatedIDs[i] = value;
            }
            for (var i = CorsairLedId.KeyboardProfile; i >= CorsairLedId.KeyboardLightPipeZone20; --i)
            {
                _illuminatedIDs[i] = value;
            }
        }

        public override void OnBeforeHandle()
        {
            _illuminatedIDs.Clear();
            _illuminatedCount = CorsairLightingSDK.GetDeviceCount();
        }

        public override void OnHandled()
        {
            for (var i = _inputs.Length - 1; i >= 0; --i)
            {
                var input = _inputs[i];
                _illuminatedColors[i] = _illuminatedIDs.TryGetValue(input, out var value) ? new()
                {
                    LedId = input,
                    R = (int)(value & 255),
                    G = (int)((value >> 8) & 255),
                    B = (int)(value >> 16)
                } : new()
                {
                    LedId = input
                };
            }
            for (var i = _illuminatedCount - 1; i >= 0; --i)
            {
                CorsairLightingSDK.SetLedsColorsBufferByDeviceIndex(i, _illuminatedColors);
            }
            CorsairLightingSDK.SetLedsColorsFlushBuffer();
        }

        public override Color GetMeterColor() => Colors.Yellow;

        public override void Dispose()
        {
            lock (IlluminationSystem.Instance.HandlingCSX)
            {
                if (IsHandling)
                {
                    IsHandling = false;
                    CorsairLightingSDK.ReleaseControl(CorsairAccessMode.ExclusiveLightingControl);
                }
            }
        }

        public override void Toggle()
        {
            Configure.Instance.K70 = !Configure.Instance.K70;
            base.Toggle();
        }
    }
}