Example #1
0
        public int GetNumMacros(KeyboardLayer layer)
        {
            List <Layer> layers = new List <Layer>();
            Layer        userLayer;

            if (Layers.TryGetValue(layer, out userLayer))
            {
                layers.Add(userLayer);
            }
            if (FnLayers.TryGetValue(layer, out userLayer))
            {
                layers.Add(userLayer);
            }
            HashSet <byte> macroIds = new HashSet <byte>();

            foreach (Layer l in layers)
            {
                foreach (uint key in l.Keys.Values)
                {
                    if (KeyValues.GetKeyType(key) == DriverValueType.Macro)
                    {
                        macroIds.Add(KeyValues.GetKeyData2(key));
                    }
                }
            }
            return(macroIds.Count);
        }
Example #2
0
        static void Main(string[] args)
        {
            BasePath     = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
            DataBasePath = Path.Combine(BasePath, DataBasePath);
            UserDataPath = Path.Combine(BasePath, UserDataPath);

            if (!Localization.Load())
            {
                LogFatalError("Failed to load localization data");
                return;
            }
            if (!KeyValues.Load())
            {
                LogFatalError("Failed to load the key data");
                return;
            }
            if (!KeyboardState.Load())
            {
                LogFatalError("Failed to load keyboard data");
                return;
            }

#if COMMAND_LOGGER_ENABLED
            if (args.Length > 0 && args[0].ToLower() == "clog")
            {
                CommandLogger.Run();
                return;
            }
#endif

            KeyboardDeviceManager.Connected += (KeyboardDevice device) =>
            {
                Log("Connected to device '" + device.State.ModelName + "' model:" + device.State.ModelId +
                    " fw:" + device.State.FirmwareVersion);
                WebGUI.UpdateDeviceList();

                string file = GetUserDataFile(device);
                if (!string.IsNullOrEmpty(file))
                {
                    try
                    {
                        string dir = Path.GetDirectoryName(file);
                        if (!Directory.Exists(dir))

                        {
                            Directory.CreateDirectory(dir);
                        }
                        if (!File.Exists(file))
                        {
                            File.WriteAllText(file, string.Empty, Encoding.UTF8);
                        }
                    }
                    catch
                    {
                    }
                }
            };
            KeyboardDeviceManager.Disconnected += (KeyboardDevice device) =>
            {
                Log("Disconnected from device '" + device.State.ModelName + "'");
                WebGUI.UpdateDeviceList();
            };
            KeyboardDeviceManager.StartListener();

            bool running      = true;
            bool hasNullInput = false;
            while (running)
            {
                string line = Console.ReadLine();
                if (line == null)
                {
                    // Handler for potential issue where ReadLine() returns null - see https://github.com/pixeltris/GK6X/issues/8
                    if (hasNullInput)
                    {
                        Console.WriteLine("Cannot read from command line. Exiting.");
                        break;
                    }
                    hasNullInput = true;
                    continue;
                }
                hasNullInput = false;
                string[] splitted = line.Split();
                switch (splitted[0].ToLower())
                {
                case "close":
                case "exit":
                case "quit":
                    running = false;
                    break;

                case "cls":
                case "clear":
                    Console.Clear();
                    break;

                case "update_data":
                    if (splitted.Length > 1)
                    {
                        string path      = line.TrimStart();
                        int    spaceChar = path.IndexOf(' ');
                        if (spaceChar > 0)
                        {
                            path = path.Substring(spaceChar).Trim();
                        }
                        bool isValidPath = false;
                        try
                        {
                            if (Directory.Exists(path))
                            {
                                isValidPath = true;
                            }
                        }
                        catch
                        {
                        }
                        if (isValidPath)
                        {
                            UpdateDataFiles(path);
                            Log("done");
                        }
                        else
                        {
                            Log("Couldn't find path '" + path + "'");
                        }
                    }
                    else
                    {
                        Log("Bad input. Expected folder name.");
                    }
                    break;

                case "gui":
                    WebGUI.Run();
                    break;

                case "gui_le":
                {
                    string userDataPath = WebGUI.UserDataPath;
                    string leName       = line.Trim();
                    int    spaceIndex   = leName.IndexOf(' ');
                    if (spaceIndex > 0)
                    {
                        leName = leName.Substring(spaceIndex).Trim();
                    }
                    else
                    {
                        leName = null;
                    }
                    if (!string.IsNullOrEmpty(leName))
                    {
                        if (!string.IsNullOrEmpty(userDataPath) && Directory.Exists(userDataPath))
                        {
                            string leDir      = Path.Combine(userDataPath, "Account", "0", "LE");
                            string leListFile = Path.Combine(leDir, "lelist.json");
                            if (File.Exists(leListFile))
                            {
                                bool          foundFile = false;
                                List <object> leList    = MiniJSON.Json.Deserialize(File.ReadAllText(leListFile)) as List <object>;
                                if (leList != null)
                                {
                                    foreach (object item in leList)
                                    {
                                        Dictionary <string, object> guidName = item as Dictionary <string, object>;
                                        if (guidName["Name"].ToString() == leName)
                                        {
                                            string leFileName = Path.Combine(leDir, guidName["GUID"].ToString() + ".le");
                                            if (File.Exists(leFileName))
                                            {
                                                foreach (char c in System.IO.Path.GetInvalidFileNameChars())
                                                {
                                                    leName = leName.Replace(c, '_');
                                                }
                                                string effectString = Encoding.UTF8.GetString(CMFile.Load(leFileName));
                                                effectString = CMFile.FormatJson(effectString);
                                                File.WriteAllText(Path.Combine(DataBasePath, "lighting", leName + ".le"), effectString);
                                                Program.Log("Copied '" + leName + "'");
                                                foundFile = true;
                                            }
                                        }
                                    }
                                }
                                if (!foundFile)
                                {
                                    Program.Log("Failed to find lighting effect '" + leName + "' (it's case sensitive)");
                                }
                            }
                            else
                            {
                                Program.Log("Failed to find file '" + leListFile + "'");
                            }
                        }
                    }
                    else
                    {
                        Program.Log("Invalid input. Expected lighting effect name.");
                    }
                }
                break;

                case "findkeys":
                {
                    Log(string.Empty);
                    Log("This is used to identify keys. Press keys to see their values. Missing keys will generally show up as '(null)' and they need to be mapped in the data files Data/devuces/YOUR_MODEL_ID/");
                    Log("The 'S' values are what you want to use to map keys in your UserData file.");
                    Log(string.Empty);
                    Log("Entering 'driver' mode and mapping all keys to callbacks.");
                    Log(string.Empty);
                    KeyboardDevice[] devices;
                    if (TryGetDevices(out devices))
                    {
                        foreach (KeyboardDevice device in devices)
                        {
                            device.SetLayer(KeyboardLayer.Driver);
                            device.SetIdentifyDriverMacros();
                        }
                    }
                }
                break;

                case "map":
                case "unmap":
                {
                    bool             map = splitted[0].ToLower() == "map";
                    KeyboardDevice[] devices;
                    KeyboardLayer    targetLayer;
                    bool             targetLayerIsFn;
                    TryParseLayer(splitted, 1, out targetLayer, out targetLayerIsFn);
                    bool hasTargetLayer = targetLayer != KeyboardLayer.Invalid;
                    if (TryGetDevices(out devices))
                    {
                        foreach (KeyboardDevice device in devices)
                        {
                            UserDataFile userData = UserDataFile.Load(device.State, GetUserDataFile(device));
                            if (userData == null)
                            {
                                Log("Couldn't find user data file '" + GetUserDataFile(device) + "'");
                                continue;
                            }

                            foreach (KeyValuePair <KeyboardLayer, KeyboardStateLayer> layer in device.State.Layers)
                            {
                                if (layer.Key == KeyboardLayer.Driver)
                                {
                                    continue;
                                }

                                if (hasTargetLayer && layer.Key != targetLayer)
                                {
                                    continue;
                                }

                                device.SetLighting(layer.Key, userData);
                                device.SetMacros(layer.Key, userData);

                                for (int i = 0; i < 2; i++)
                                {
                                    bool fn = i == 1;
                                    if (targetLayer != KeyboardLayer.Invalid && fn != targetLayerIsFn)
                                    {
                                        continue;
                                    }

                                    // Setting keys to 0xFFFFFFFF is preferable compared to using what is defined in
                                    // files as this will use what is defined in the firmware.
                                    uint[] driverValues = new uint[device.State.MaxLogicCode];
                                    for (int j = 0; j < driverValues.Length; j++)
                                    {
                                        driverValues[j] = KeyValues.UnusedKeyValue;
                                    }

                                    if (map)
                                    {
                                        UserDataFile.Layer userDataLayer;
                                        if (fn)
                                        {
                                            userData.FnLayers.TryGetValue(layer.Key, out userDataLayer);
                                        }
                                        else
                                        {
                                            userData.Layers.TryGetValue(layer.Key, out userDataLayer);
                                        }
                                        if (userDataLayer != null)
                                        {
                                            for (int j = 0; j < driverValues.Length; j++)
                                            {
                                                KeyboardState.Key key = device.State.GetKeyByLogicCode(j);
                                                if (key != null)
                                                {
                                                    driverValues[j] = userDataLayer.GetKey(key);
                                                }
                                            }
                                        }
                                    }
                                    device.SetKeys(layer.Key, driverValues, fn);
                                }
                            }

                            // This is required to "refresh" the keyboard with the updated key info
                            if (hasTargetLayer)
                            {
                                device.SetLayer(targetLayer);
                            }
                            else
                            {
                                device.SetLayer(KeyboardLayer.Base);
                            }
                            Log("Done");
                        }
                    }
                }
                break;

                case "dumpkeys":
                {
                    int targetRow = -1;
                    if (splitted.Length > 1)
                    {
                        if (!int.TryParse(splitted[1], out targetRow))
                        {
                            targetRow = -1;
                        }
                    }
                    bool showLocationCodeInfo = false;
                    if (splitted.Length > 2)
                    {
                        showLocationCodeInfo = splitted[2] == "ex";
                    }

                    KeyboardDevice[] devices;
                    if (TryGetDevices(out devices))
                    {
                        foreach (KeyboardDevice device in devices)
                        {
                            Log("====== " + device.State.ModelId + " ======");
                            bool foundKey = false;
                            int  lastLeft = int.MinValue;
                            int  row      = 1;
                            foreach (KeyboardState.Key key in device.State.KeysByLocationCode.Values.OrderBy(
                                         x => x.Position.Top).ThenBy(x => x.Position.Left))
                            {
                                if (key.Position.Left >= 0)
                                {
                                    if (lastLeft > key.Position.Left && foundKey)
                                    {
                                        if (targetRow == -1)
                                        {
                                            Log("--------");
                                        }
                                        foundKey = false;
                                        row++;
                                    }
                                    lastLeft = key.Position.Left;
                                }

                                if (string.IsNullOrEmpty(key.KeyName) || !key.KeyName.StartsWith("LED-"))
                                {
                                    if (targetRow == -1 || row == targetRow)
                                    {
                                        Log(key.KeyName + " = " + key.DriverValueName +
                                            (showLocationCodeInfo ? " (" + key.LocationCode + ")" : string.Empty));
                                    }
                                    foundKey = true;
                                }
                            }
                        }
                    }
                }
                break;
                }
            }

            KeyboardDeviceManager.StopListener();
        }
Example #3
0
        private void Load(KeyboardState keyboard, string file, params GroupType[] groups)
        {
            GroupType       currentGroup  = GroupType.None;
            Macro           currentMacro  = null;
            HashSet <Layer> currentLayers = new HashSet <Layer>();

            string[] lines = File.ReadAllLines(file);
            for (int i = 0; i < lines.Length; i++)
            {
                string line = lines[i].Trim();
                if (line.StartsWith("#"))
                {
                    continue;
                }
                if (line.StartsWith("["))
                {
                    currentGroup = GroupType.None;
                    currentLayers.Clear();

                    int endBrace = line.IndexOf(']');
                    if (endBrace > 1)
                    {
                        string   fullGroupName     = line.Substring(1, endBrace - 1).Trim();
                        string[] groupNames        = null;
                        string   innerName         = null;
                        string[] innerNameSplitted = null;
                        int      openParenth       = fullGroupName.IndexOf('(');
                        int      closeParenth      = fullGroupName.IndexOf(')');
                        if (openParenth > 0 && closeParenth > openParenth)
                        {
                            innerName         = fullGroupName.Substring(openParenth + 1, closeParenth - (openParenth + 1));
                            innerNameSplitted = innerName.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                            innerName         = innerNameSplitted.Length > 0 ? innerNameSplitted[0] : null;
                            for (int j = 0; j < innerNameSplitted.Length; j++)
                            {
                                innerNameSplitted[j] = innerNameSplitted[j].Trim();
                            }
                            if (!string.IsNullOrEmpty(innerName))
                            {
                                innerName = innerName.Trim();
                            }

                            groupNames = new string[] { fullGroupName.Substring(0, openParenth).Trim() };
                        }
                        else
                        {
                            // This is for layers (not macro / lighting)
                            groupNames = fullGroupName.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                            for (int j = 0; j < groupNames.Length; j++)
                            {
                                groupNames[j] = groupNames[j].Trim();
                            }
                        }
                        foreach (string groupName in groupNames)
                        {
                            switch (groupName.ToLower())
                            {
                            case "base":
                                if (groups.Contains(GroupType.Layer))
                                {
                                    currentGroup = GroupType.Layer;
                                    currentLayers.Add(FindOrAddLayer(KeyboardLayer.Base, false));
                                }
                                break;

                            case "layer1":
                                if (groups.Contains(GroupType.Layer))
                                {
                                    currentGroup = GroupType.Layer;
                                    currentLayers.Add(FindOrAddLayer(KeyboardLayer.Layer1, false));
                                }
                                break;

                            case "layer2":
                                if (groups.Contains(GroupType.Layer))
                                {
                                    currentGroup = GroupType.Layer;
                                    currentLayers.Add(FindOrAddLayer(KeyboardLayer.Layer2, false));
                                }
                                break;

                            case "layer3":
                                if (groups.Contains(GroupType.Layer))
                                {
                                    currentGroup = GroupType.Layer;
                                    currentLayers.Add(FindOrAddLayer(KeyboardLayer.Layer3, false));
                                }
                                break;

                            case "fnbase":
                                if (groups.Contains(GroupType.Layer))
                                {
                                    currentGroup = GroupType.Layer;
                                    currentLayers.Add(FindOrAddLayer(KeyboardLayer.Base, true));
                                }
                                break;

                            case "fnlayer1":
                                if (groups.Contains(GroupType.Layer))
                                {
                                    currentGroup = GroupType.Layer;
                                    currentLayers.Add(FindOrAddLayer(KeyboardLayer.Layer1, true));
                                }
                                break;

                            case "fnlayer2":
                                if (groups.Contains(GroupType.Layer))
                                {
                                    currentGroup = GroupType.Layer;
                                    currentLayers.Add(FindOrAddLayer(KeyboardLayer.Layer2, true));
                                }
                                break;

                            case "fnlayer3":
                                if (groups.Contains(GroupType.Layer))
                                {
                                    currentGroup = GroupType.Layer;
                                    currentLayers.Add(FindOrAddLayer(KeyboardLayer.Layer3, true));
                                }
                                break;

                            case "macro":
                                if (groups.Contains(GroupType.Macro) && !string.IsNullOrEmpty(innerName))
                                {
                                    currentGroup      = GroupType.Macro;
                                    currentMacro      = new Macro(innerName);
                                    Macros[innerName] = currentMacro;
                                    if (innerNameSplitted.Length > 1)
                                    {
                                        ushort.TryParse(innerNameSplitted[1], out currentMacro.DefaultDelay);
                                    }
                                    if (innerNameSplitted.Length > 2)
                                    {
                                        if (!Enum.TryParse <MacroRepeatType>(innerNameSplitted[2], true, out currentMacro.RepeatType))
                                        {
                                            currentMacro.RepeatType = MacroRepeatType.RepeatXTimes;
                                        }
                                    }
                                    if (innerNameSplitted.Length > 3)
                                    {
                                        byte.TryParse(innerNameSplitted[3], out currentMacro.RepeatCount);
                                    }
                                    if (innerNameSplitted.Length > 4)
                                    {
                                        bool.TryParse(innerNameSplitted[4], out currentMacro.UseTrailingDelay);
                                    }
                                    if (currentMacro.RepeatCount == 0)
                                    {
                                        // No point in having a macro which doesn't even run...
                                        currentMacro.RepeatCount = 1;
                                    }
                                }
                                break;

                            case "lighting":
                                if (groups.Contains(GroupType.Lighting) && !string.IsNullOrEmpty(innerName))
                                {
                                    currentGroup = GroupType.Lighting;
                                    LightingEffect lightingEffect = null;
                                    if (!LightingEffects.TryGetValue(innerName, out lightingEffect))
                                    {
                                        lightingEffect = new LightingEffect(innerName);
                                    }
                                    if (lightingEffect.Load(keyboard))
                                    {
                                        LightingEffects[innerName] = lightingEffect;

                                        for (int j = 1; j < innerNameSplitted.Length; j++)
                                        {
                                            KeyboardLayer layer;
                                            if (Enum.TryParse(innerNameSplitted[j], out layer))
                                            {
                                                lightingEffect.Layers.Add(layer);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        Program.Log("Failed to load lighting effect '" + innerName + "'");
                                    }
                                }
                                break;

                            case "nolighting":
                                if (innerNameSplitted != null)
                                {
                                    for (int j = 0; j < innerNameSplitted.Length; j++)
                                    {
                                        KeyboardLayer layer;
                                        if (Enum.TryParse(innerNameSplitted[j], out layer))
                                        {
                                            NoLightingLayers.Add(layer);
                                        }
                                    }
                                }
                                else
                                {
                                    NoLighting = true;
                                }
                                break;
                            }
                        }
                    }
                }
                else
                {
                    switch (currentGroup)
                    {
                    case GroupType.Layer:
                    {
                        string[] splitted = line.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                        if (splitted.Length > 1)
                        {
                            string[] keysSplittedSrc = splitted[0].Split(new char[] { '+' }, StringSplitOptions.RemoveEmptyEntries);
                            string[] keysSplittedDst = splitted[1].Split(new char[] { '+' }, StringSplitOptions.RemoveEmptyEntries);

                            uint srcValue = 0;
                            uint dstValue = 0;

                            foreach (string str in keysSplittedSrc)
                            {
                                if (str.StartsWith("0x"))
                                {
                                    uint.TryParse(str, NumberStyles.HexNumber, null, out srcValue);
                                }
                                else
                                {
                                    DriverValue value;
                                    if (Enum.TryParse(str, out value))
                                    {
                                        srcValue = (uint)value;
                                    }
                                }
                            }

                            if (srcValue != 0)
                            {
                                foreach (string str in keysSplittedDst)
                                {
                                    if (str.StartsWith("0x"))
                                    {
                                        uint.TryParse(str, NumberStyles.HexNumber, null, out dstValue);
                                    }
                                    else if (str.ToLower().StartsWith("macro"))
                                    {
                                        int openParenth  = str.IndexOf('(');
                                        int closeParenth = str.IndexOf(')');
                                        if (openParenth > 0 && closeParenth > openParenth)
                                        {
                                            string macroName = str.Substring(openParenth + 1, closeParenth - (openParenth + 1));
                                            Macro  macro     = GetMacro(macroName);
                                            if (macro != null)
                                            {
                                                Debug.Assert(macro.Id >= 0 && macro.Id <= byte.MaxValue);
                                                dstValue = (uint)(0x0A010000 + macro.Id);
                                            }
                                            else
                                            {
                                                Program.Log("Failed to find macro '" + macroName + "' bound to key " + (DriverValue)srcValue);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        DriverValue value;
                                        if (Enum.TryParse(str, out value))
                                        {
                                            switch (KeyValues.GetKeyType((uint)value))
                                            {
                                            case DriverValueType.Key:
                                                // TODO: Extra validation (this only makes sense for modifiers)
                                                dstValue |= (uint)value;
                                                break;

                                            default:
                                                dstValue = (uint)value;
                                                break;
                                            }
                                        }
                                    }
                                }
                                foreach (Layer currentLayer in currentLayers)
                                {
                                    currentLayer.Keys[srcValue] = dstValue;
                                }
                            }
                        }
                    }
                    break;

                    case GroupType.Macro:
                    {
                        string[] splitted = line.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                        if (splitted.Length > 1)
                        {
                            string[] keysSplitted = splitted[1].Split(new char[] { '+' }, StringSplitOptions.RemoveEmptyEntries);

                            ushort delay = currentMacro.DefaultDelay;
                            if (splitted.Length > 2)
                            {
                                if (!ushort.TryParse(splitted[2], out delay))
                                {
                                    delay = currentMacro.DefaultDelay;
                                }
                            }

                            MacroKeyState[] states = null;
                            switch (splitted[0].ToLower())
                            {
                            case "press":
                                states = new MacroKeyState[] { MacroKeyState.Down, MacroKeyState.Up };
                                break;

                            case "down":
                                states = new MacroKeyState[] { MacroKeyState.Down };
                                break;

                            case "up":
                                states = new MacroKeyState[] { MacroKeyState.Up };
                                break;
                            }
                            for (int j = 0; j < states.Length; j++)
                            {
                                MacroKeyState state = states[j];
                                for (int k = 0; k < keysSplitted.Length; k++)
                                {
                                    string       str    = keysSplitted[k];
                                    Macro.Action action = new Macro.Action();
                                    action.State = state;
                                    if (j == states.Length - 1 && k == keysSplitted.Length - 1)
                                    {
                                        // Only set the delay on the last listed key for each macro line entry
                                        action.Delay = delay;
                                    }
                                    else
                                    {
                                        action.Delay = 0;
                                    }

                                    DriverValue value;
                                    if (Enum.TryParse(str, out value))
                                    {
                                        switch (value)
                                        {
                                        case DriverValue.LCtrl:
                                            action.Type     = MacroKeyType.Key;
                                            action.Modifier = DriverValueModifer.LCtrl;
                                            //action.KeyCode = (byte)DriverValueModifer.LCtrl;
                                            break;

                                        case DriverValue.LShift:
                                            action.Type     = MacroKeyType.Key;
                                            action.Modifier = DriverValueModifer.LShift;
                                            //action.KeyCode = (byte)DriverValueModifer.LShift;
                                            break;

                                        case DriverValue.LAlt:
                                            action.Type     = MacroKeyType.Key;
                                            action.Modifier = DriverValueModifer.LAlt;
                                            //action.KeyCode = (byte)DriverValueModifer.LAlt;
                                            break;

                                        case DriverValue.LWin:
                                            action.Type     = MacroKeyType.Key;
                                            action.Modifier = DriverValueModifer.LWin;
                                            //action.KeyCode = (byte)DriverValueModifer.LWin;
                                            break;

                                        case DriverValue.RCtrl:
                                            action.Type     = MacroKeyType.Key;
                                            action.Modifier = DriverValueModifer.RCtrl;
                                            //action.KeyCode = (byte)DriverValueModifer.RCtrl;
                                            break;

                                        case DriverValue.RShift:
                                            action.Type     = MacroKeyType.Key;
                                            action.Modifier = DriverValueModifer.RShift;
                                            //action.KeyCode = (byte)DriverValueModifer.RShift;
                                            break;

                                        case DriverValue.RAlt:
                                            action.Type     = MacroKeyType.Key;
                                            action.Modifier = DriverValueModifer.RAlt;
                                            //action.KeyCode = (byte)DriverValueModifer.RAlt;
                                            break;

                                        case DriverValue.RWin:
                                            action.Type     = MacroKeyType.Key;
                                            action.Modifier = DriverValueModifer.RWin;
                                            //action.KeyCode = (byte)DriverValueModifer.RWin;
                                            break;

                                        case DriverValue.MouseLClick:
                                            action.Type    = MacroKeyType.Mouse;
                                            action.KeyCode = (byte)DriverValueMouseButton.LButton;
                                            break;

                                        case DriverValue.MouseRClick:
                                            action.Type    = MacroKeyType.Mouse;
                                            action.KeyCode = (byte)DriverValueMouseButton.RButton;
                                            break;

                                        case DriverValue.MouseMClick:
                                            action.Type    = MacroKeyType.Mouse;
                                            action.KeyCode = (byte)DriverValueMouseButton.MButton;
                                            break;

                                        case DriverValue.MouseBack:
                                            action.Type    = MacroKeyType.Mouse;
                                            action.KeyCode = (byte)DriverValueMouseButton.Back;
                                            break;

                                        case DriverValue.MouseAdvance:
                                            action.Type    = MacroKeyType.Mouse;
                                            action.KeyCode = (byte)DriverValueMouseButton.Advance;
                                            break;

                                        default:
                                            action.Type    = MacroKeyType.Key;
                                            action.KeyCode = (byte)KeyValues.GetShortDriverValue((uint)value);
                                            break;
                                        }
                                    }

                                    currentMacro.Actions.Add(action);
                                }
                            }
                        }
                    }
                    break;
                    }
                }
            }
        }
Example #4
0
        static void Run(bool asGUI)
        {
            BasePath     = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
            DataBasePath = Path.Combine(BasePath, DataBasePath);
            UserDataPath = Path.Combine(BasePath, UserDataPath);

            if (!Localization.Load())
            {
                LogFatalError("Failed to load localization data");
                return;
            }
            if (!KeyValues.Load())
            {
                LogFatalError("Failed to load the key data");
                return;
            }
            if (!KeyboardState.Load())
            {
                LogFatalError("Failed to load keyboard data");
                return;
            }

#if COMMAND_LOGGER_ENABLED
            if (args.Length > 0 && args[0].ToLower() == "clog")
            {
                CommandLogger.Run();
                return;
            }
#endif

            KeyboardDeviceManager.Connected += (KeyboardDevice device) =>
            {
                Log("Connected to device '" + device.State.ModelName + "' model:" + device.State.ModelId +
                    " fw:" + device.State.FirmwareVersion);
                WebGUI.UpdateDeviceList();

                string file = GetUserDataFile(device);
                if (!string.IsNullOrEmpty(file))
                {
                    try
                    {
                        string dir = Path.GetDirectoryName(file);
                        if (!Directory.Exists(dir))
                        {
                            Directory.CreateDirectory(dir);
                        }
                        if (!File.Exists(file))
                        {
                            File.WriteAllText(file, string.Empty, Encoding.UTF8);
                        }
                    }
                    catch
                    {
                    }
                }
            };
            KeyboardDeviceManager.Disconnected += (KeyboardDevice device) =>
            {
                Log("Disconnected from device '" + device.State.ModelName + "'");
                WebGUI.UpdateDeviceList();
            };
            KeyboardDeviceManager.StartListener();

            if (asGUI)
            {
                Process   currentProc = Process.GetCurrentProcess();
                Process[] procs       = Process.GetProcessesByName(currentProc.ProcessName);
                try
                {
                    foreach (Process proc in procs)
                    {
                        try
                        {
                            if (proc != currentProc && proc.Id != currentProc.Id)
                            {
                                proc.Kill();
                            }
                        }
                        catch
                        {
                        }
                    }
                }
                finally
                {
                    foreach (Process proc in procs)
                    {
                        proc.Close();
                    }
                }
                currentProc.Close();

                WebGUI.Run();
                while (WebGUI.LastPing > DateTime.Now - WebGUI.PingTimeout)
                {
                    Thread.Sleep(1000);
                }
                return;
            }

            bool running      = true;
            bool hasNullInput = false;
            while (running)
            {
                string line = Console.ReadLine();
                if (line == null)
                {
                    // Handler for potential issue where ReadLine() returns null - see https://github.com/pixeltris/GK6X/issues/8
                    if (hasNullInput)
                    {
                        Console.WriteLine("Cannot read from command line. Exiting.");
                        break;
                    }
                    hasNullInput = true;
                    continue;
                }
                hasNullInput = false;
                string[] splitted = line.Split();
                switch (splitted[0].ToLower())
                {
                case "close":
                case "exit":
                case "quit":
                    running = false;
                    break;

                case "cls":
                case "clear":
                    Console.Clear();
                    break;

                case "update_data":
                    if (splitted.Length > 1)
                    {
                        string path      = line.TrimStart();
                        int    spaceChar = path.IndexOf(' ');
                        if (spaceChar > 0)
                        {
                            path = path.Substring(spaceChar).Trim();
                        }
                        bool isValidPath = false;
                        try
                        {
                            if (Directory.Exists(path))
                            {
                                isValidPath = true;
                            }
                        }
                        catch
                        {
                        }
                        if (isValidPath)
                        {
                            UpdateDataFiles(path);
                            Log("done");
                        }
                        else
                        {
                            Log("Couldn't find path '" + path + "'");
                        }
                    }
                    else
                    {
                        Log("Bad input. Expected folder name.");
                    }
                    break;

                case "gui":
                    WebGUI.Run();
                    break;

                case "gui_to_txt":
                {
                    if (string.IsNullOrEmpty(WebGUI.UserDataPath))
                    {
                        Log("Load GUI first");
                    }
                    else
                    {
                        string userDataPath = WebGUI.UserDataPath;
                        int    accountId    = 0;
                        string accountDir   = Path.Combine(userDataPath, "Account", accountId.ToString());
                        if (Directory.Exists(accountDir))
                        {
                            foreach (KeyboardDevice device in KeyboardDeviceManager.GetConnectedDevices())
                            {
                                string deviceDir = Path.Combine(userDataPath, "Account", accountId.ToString(), "Devices", device.State.ModelId.ToString());
                                if (Directory.Exists(deviceDir))
                                {
                                    Dictionary <int, UserDataFile.Macro> macrosById = new Dictionary <int, UserDataFile.Macro>();
                                    UserDataFile userDataFile = new UserDataFile();
                                    foreach (string file in Directory.GetFiles(deviceDir, "*.cmf"))
                                    {
                                        string config = Encoding.UTF8.GetString(CMFile.Load(file));
                                        Dictionary <string, object> data = MiniJSON.Json.Deserialize(config) as Dictionary <string, object>;
                                        int           modelIndex         = (int)Convert.ChangeType(data["ModeIndex"], typeof(int));
                                        KeyboardLayer layer = (KeyboardLayer)modelIndex;

                                        //////////////////////////////////////////
                                        // Keys / macros (NOTE: Macros on different layers might wipe each other. look into.)
                                        //////////////////////////////////////////
                                        for (int i = 0; i < 2; i++)
                                        {
                                            string setStr = i == 0 ? "KeySet" : "FnKeySet";
                                            if (data.ContainsKey(setStr))
                                            {
                                                List <object> keys = data[setStr] as List <object>;
                                                foreach (object keyObj in keys)
                                                {
                                                    Dictionary <string, object> key = keyObj as Dictionary <string, object>;
                                                    int    keyIndex       = (int)Convert.ChangeType(key["Index"], typeof(int));
                                                    uint   driverValue    = KeyValues.UnusedKeyValue;
                                                    string driverValueStr = (string)key["DriverValue"];
                                                    if (driverValueStr.StartsWith("0x"))
                                                    {
                                                        if (uint.TryParse(driverValueStr.Substring(2), System.Globalization.NumberStyles.HexNumber, null, out driverValue))
                                                        {
                                                            if (KeyValues.GetKeyType(driverValue) == DriverValueType.Macro && key.ContainsKey("Task"))
                                                            {
                                                                Dictionary <string, object> task = key["Task"] as Dictionary <string, object>;
                                                                if (task != null && (string)task["Type"] == "Macro")
                                                                {
                                                                    Dictionary <string, object> taskData = task["Data"] as Dictionary <string, object>;
                                                                    string macroGuid = (string)taskData["GUID"];
                                                                    string macroFile = Path.Combine(userDataPath, "Account", accountId.ToString(), "Macro", macroGuid + ".cms");
                                                                    if (File.Exists(macroFile))
                                                                    {
                                                                        UserDataFile.Macro macro = new UserDataFile.Macro(null);
                                                                        macro.LoadFile(macroFile);
                                                                        macro.RepeatCount              = (byte)Convert.ChangeType(taskData["Repeats"], typeof(byte));
                                                                        macro.RepeatType               = (MacroRepeatType)(byte)Convert.ChangeType(taskData["StopMode"], typeof(byte));
                                                                        macro.Id                       = KeyValues.GetKeyData2(driverValue);
                                                                        macrosById[macro.Id]           = macro;
                                                                        userDataFile.Macros[macroGuid] = macro;
                                                                    }
                                                                }
                                                            }
                                                        }
                                                        else
                                                        {
                                                            driverValue = KeyValues.UnusedKeyValue;
                                                        }
                                                    }
                                                    if (keyIndex >= 0 && keyIndex < device.State.MaxLogicCode && driverValue != KeyValues.UnusedKeyValue)
                                                    {
                                                        KeyboardState.Key keyInfo = device.State.GetKeyByLogicCode(keyIndex);
                                                        if (keyInfo != null)
                                                        {
                                                            Dictionary <string, uint> vals = userDataFile.FindOrAddLayer(layer, i > 0).Keys;
                                                            if (Enum.IsDefined(typeof(DriverValue), driverValue))
                                                            {
                                                                vals[keyInfo.DriverValueName.ToLower()] = driverValue;
                                                            }
                                                            else
                                                            {
                                                                Log("Failed to map index " + keyIndex + " to " + driverValue + " on layer " + layer +
                                                                    (i > 0 ? " fn" : string.Empty));
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }

                                        //////////////////////////////////////////
                                        // Lighting
                                        //////////////////////////////////////////
                                        Dictionary <string, UserDataFile.LightingEffect> effects = new Dictionary <string, UserDataFile.LightingEffect>();
                                        string[] leHeaders = { "ModeLE", "DriverLE" };
                                        foreach (string leHeader in leHeaders)
                                        {
                                            if (data.ContainsKey(leHeader))
                                            {
                                                List <object> leEntries = data[leHeader] as List <object>;
                                                if (leEntries == null)
                                                {
                                                    // There's only one ModeLE
                                                    leEntries = new List <object>();
                                                    leEntries.Add(data[leHeader]);
                                                }
                                                foreach (object entry in leEntries)
                                                {
                                                    Dictionary <string, object> modeLE = entry as Dictionary <string, object>;
                                                    string leGuid = (string)modeLE["GUID"];
                                                    if (!string.IsNullOrEmpty(leGuid))
                                                    {
                                                        string filePath = Path.Combine(userDataPath, "Account", accountId.ToString(), "LE", leGuid + ".le");
                                                        if (!effects.ContainsKey(leGuid) && File.Exists(filePath))
                                                        {
                                                            UserDataFile.LightingEffect le = new UserDataFile.LightingEffect(userDataFile, null);
                                                            le.Load(device.State, Encoding.UTF8.GetString(CMFile.Load(filePath)));
                                                            le.Layers.Add(layer);
                                                            userDataFile.LightingEffects[leGuid] = le;
                                                            effects[leGuid] = le;
                                                        }
                                                    }
                                                    else
                                                    {
                                                        object leDataObj;
                                                        if (modeLE.TryGetValue("LEData", out leDataObj))
                                                        {
                                                            Dictionary <string, object> leData = leDataObj as Dictionary <string, object>;
                                                            if (leData != null)
                                                            {
                                                                // This should be static lighting data only
                                                                UserDataFile.LightingEffect le = new UserDataFile.LightingEffect(userDataFile, null);
                                                                le.LoadStatic(device.State, leData);
                                                                le.Layers.Add(layer);
                                                                userDataFile.LightingEffects[Guid.NewGuid().ToString()] = le;
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    userDataFile.SaveFromGUI(device.State, Path.Combine(UserDataPath, device.State.ModelId + "_exported.txt"));
                                    Log("Done");
                                    break;
                                }
                            }
                        }
                        else
                        {
                            Log("Account settings not found for account id " + accountId);
                        }
                    }
                }
                break;

                case "gui_le":
                {
                    string userDataPath = WebGUI.UserDataPath;
                    string leName       = line.Trim();
                    int    spaceIndex   = leName.IndexOf(' ');
                    if (spaceIndex > 0)
                    {
                        leName = leName.Substring(spaceIndex).Trim();
                    }
                    else
                    {
                        leName = null;
                    }
                    if (!string.IsNullOrEmpty(leName))
                    {
                        if (!string.IsNullOrEmpty(userDataPath) && Directory.Exists(userDataPath))
                        {
                            string leDir      = Path.Combine(userDataPath, "Account", "0", "LE");
                            string leListFile = Path.Combine(leDir, "lelist.json");
                            if (File.Exists(leListFile))
                            {
                                bool          foundFile = false;
                                List <object> leList    = MiniJSON.Json.Deserialize(File.ReadAllText(leListFile)) as List <object>;
                                if (leList != null)
                                {
                                    foreach (object item in leList)
                                    {
                                        Dictionary <string, object> guidName = item as Dictionary <string, object>;
                                        if (guidName["Name"].ToString() == leName)
                                        {
                                            string leFileName = Path.Combine(leDir, guidName["GUID"].ToString() + ".le");
                                            if (File.Exists(leFileName))
                                            {
                                                foreach (char c in System.IO.Path.GetInvalidFileNameChars())
                                                {
                                                    leName = leName.Replace(c, '_');
                                                }
                                                string effectString = Encoding.UTF8.GetString(CMFile.Load(leFileName));
                                                effectString = CMFile.FormatJson(effectString);
                                                File.WriteAllText(Path.Combine(DataBasePath, "lighting", leName + ".le"), effectString);
                                                Program.Log("Copied '" + leName + "'");
                                                foundFile = true;
                                            }
                                        }
                                    }
                                }
                                if (!foundFile)
                                {
                                    Program.Log("Failed to find lighting effect '" + leName + "' (it's case sensitive)");
                                }
                            }
                            else
                            {
                                Program.Log("Failed to find file '" + leListFile + "'");
                            }
                        }
                    }
                    else
                    {
                        Program.Log("Invalid input. Expected lighting effect name.");
                    }
                }
                break;

                case "findkeys":
                {
                    Log(string.Empty);
                    Log("This is used to identify keys. Press keys to see their values. Missing keys will generally show up as '(null)' and they need to be mapped in the data files Data/devuces/YOUR_MODEL_ID/");
                    Log("The 'S' values are what you want to use to map keys in your UserData file.");
                    Log(string.Empty);
                    Log("Entering 'driver' mode and mapping all keys to callbacks.");
                    Log(string.Empty);
                    KeyboardDevice[] devices;
                    if (TryGetDevices(out devices))
                    {
                        foreach (KeyboardDevice device in devices)
                        {
                            device.SetLayer(KeyboardLayer.Driver);
                            device.SetIdentifyDriverMacros();
                        }
                    }
                }
                break;

                case "map":
                case "unmap":
                {
                    bool             map = splitted[0].ToLower() == "map";
                    KeyboardDevice[] devices;
                    KeyboardLayer    targetLayer;
                    bool             targetLayerIsFn;
                    TryParseLayer(splitted, 1, out targetLayer, out targetLayerIsFn);
                    bool hasTargetLayer = targetLayer != KeyboardLayer.Invalid;
                    if (TryGetDevices(out devices))
                    {
                        foreach (KeyboardDevice device in devices)
                        {
                            UserDataFile userData = UserDataFile.Load(device.State, GetUserDataFile(device));
                            if (userData == null)
                            {
                                Log("Couldn't find user data file '" + GetUserDataFile(device) + "'");
                                continue;
                            }

                            foreach (KeyValuePair <KeyboardLayer, KeyboardStateLayer> layer in device.State.Layers)
                            {
                                if (layer.Key == KeyboardLayer.Driver)
                                {
                                    continue;
                                }

                                if (hasTargetLayer && layer.Key != targetLayer)
                                {
                                    continue;
                                }

                                device.SetLighting(layer.Key, userData);
                                device.SetMacros(layer.Key, userData);

                                for (int i = 0; i < 2; i++)
                                {
                                    bool fn = i == 1;
                                    if (targetLayer != KeyboardLayer.Invalid && fn != targetLayerIsFn)
                                    {
                                        continue;
                                    }

                                    // Setting keys to 0xFFFFFFFF is preferable compared to using what is defined in
                                    // files as this will use what is defined in the firmware.
                                    uint[] driverValues = new uint[device.State.MaxLogicCode];
                                    for (int j = 0; j < driverValues.Length; j++)
                                    {
                                        driverValues[j] = KeyValues.UnusedKeyValue;
                                    }

                                    if (map)
                                    {
                                        UserDataFile.Layer userDataLayer;
                                        if (fn)
                                        {
                                            userData.FnLayers.TryGetValue(layer.Key, out userDataLayer);
                                        }
                                        else
                                        {
                                            userData.Layers.TryGetValue(layer.Key, out userDataLayer);
                                        }
                                        if (userDataLayer != null)
                                        {
                                            for (int j = 0; j < driverValues.Length; j++)
                                            {
                                                KeyboardState.Key key = device.State.GetKeyByLogicCode(j);
                                                if (key != null)
                                                {
                                                    driverValues[j] = userDataLayer.GetKey(key);
                                                }
                                            }
                                        }
                                    }
                                    device.SetKeys(layer.Key, driverValues, fn);
                                }
                            }

                            // This is required to "refresh" the keyboard with the updated key info
                            if (hasTargetLayer)
                            {
                                device.SetLayer(targetLayer);
                            }
                            else
                            {
                                device.SetLayer(KeyboardLayer.Base);
                            }
                            Log("Done");
                        }
                    }
                }
                break;

                case "dumpkeys":
                {
                    int targetRow = -1;
                    if (splitted.Length > 1)
                    {
                        if (!int.TryParse(splitted[1], out targetRow))
                        {
                            targetRow = -1;
                        }
                    }
                    bool showLocationCodeInfo = false;
                    if (splitted.Length > 2)
                    {
                        showLocationCodeInfo = splitted[2] == "ex";
                    }

                    KeyboardDevice[] devices;
                    if (TryGetDevices(out devices))
                    {
                        foreach (KeyboardDevice device in devices)
                        {
                            Log("====== " + device.State.ModelId + " ======");
                            bool foundKey = false;
                            int  lastLeft = int.MinValue;
                            int  row      = 1;
                            foreach (KeyboardState.Key key in device.State.KeysByLocationCode.Values.OrderBy(
                                         x => x.Position.Top).ThenBy(x => x.Position.Left))
                            {
                                if (key.Position.Left >= 0)
                                {
                                    if (lastLeft > key.Position.Left && foundKey)
                                    {
                                        if (targetRow == -1)
                                        {
                                            Log("--------");
                                        }
                                        foundKey = false;
                                        row++;
                                    }
                                    lastLeft = key.Position.Left;
                                }

                                if (string.IsNullOrEmpty(key.KeyName) || !key.KeyName.StartsWith("LED-"))
                                {
                                    if (targetRow == -1 || row == targetRow)
                                    {
                                        Log(key.KeyName + " = " + key.DriverValueName +
                                            (showLocationCodeInfo ? " (" + key.LocationCode + ")" : string.Empty));
                                    }
                                    foundKey = true;
                                }
                            }
                        }
                    }
                }
                break;
                }
            }
        }
Example #5
0
        static void Main(string[] args)
        {
            if (!Localization.Load())
            {
                LogFatalError("Failed to load localization data");
                return;
            }
            if (!KeyValues.Load())
            {
                LogFatalError("Failed to load the key data");
                return;
            }
            if (!KeyboardState.Load())
            {
                LogFatalError("Failed to load keyboard data");
                return;
            }

            if (args.Length > 0 && args[0].ToLower() == "clog")
            {
                CommandLogger.Run();
                return;
            }

            KeyboardDeviceManager.Connected += (KeyboardDevice device) =>
            {
                Log("Connected to device '" + device.State.ModelName + "' model:" + device.State.ModelId +
                    " fw:" + device.State.FirmwareVersion);

                string file = GetUserDataFile(device);
                if (!string.IsNullOrEmpty(file))
                {
                    try
                    {
                        string dir = Path.GetDirectoryName(file);
                        if (!Directory.Exists(dir))

                        {
                            Directory.CreateDirectory(dir);
                        }
                        if (!File.Exists(file))
                        {
                            File.WriteAllText(file, string.Empty, Encoding.UTF8);
                        }
                    }
                    catch
                    {
                    }
                }
            };
            KeyboardDeviceManager.Disconnected += (KeyboardDevice device) =>
            {
                Log("Disconnected from device '" + device.State.ModelName + "'");
            };
            KeyboardDeviceManager.StartListener();

            bool running = true;

            while (running)
            {
                string   line     = Console.ReadLine();
                string[] splitted = line.Split();
                switch (splitted[0].ToLower())
                {
                case "close":
                case "exit":
                case "quit":
                    running = false;
                    break;

                case "cls":
                case "clear":
                    Console.Clear();
                    break;

                case "map":
                case "unmap":
                {
                    bool             map = splitted[0].ToLower() == "map";
                    KeyboardDevice[] devices;
                    KeyboardLayer    targetLayer;
                    bool             targetLayerIsFn;
                    TryParseLayer(splitted, 1, out targetLayer, out targetLayerIsFn);
                    bool hasTargetLayer = targetLayer != KeyboardLayer.Invalid;
                    if (TryGetDevices(out devices))
                    {
                        foreach (KeyboardDevice device in devices)
                        {
                            UserDataFile userData = UserDataFile.Load(device.State, GetUserDataFile(device));
                            if (userData == null)
                            {
                                Log("Couldn't find user data file '" + GetUserDataFile(device) + "'");
                                continue;
                            }

                            foreach (KeyValuePair <KeyboardLayer, KeyboardStateLayer> layer in device.State.Layers)
                            {
                                if (layer.Key == KeyboardLayer.Driver)
                                {
                                    continue;
                                }

                                if (hasTargetLayer && layer.Key != targetLayer)
                                {
                                    continue;
                                }

                                device.SetLighting(layer.Key, userData);
                                device.SetMacros(layer.Key, userData);

                                for (int i = 0; i < 2; i++)
                                {
                                    bool fn = i == 1;
                                    if (targetLayer != KeyboardLayer.Invalid && fn != targetLayerIsFn)
                                    {
                                        continue;
                                    }

                                    // Setting keys to 0xFFFFFFFF is preferable compared to using what is defined in
                                    // files as this will use what is defined in the firmware.
                                    uint[] driverValues = new uint[device.State.MaxLogicCode];
                                    for (int j = 0; j < driverValues.Length; j++)
                                    {
                                        driverValues[j] = KeyValues.UnusedKeyValue;
                                    }

                                    if (map)
                                    {
                                        UserDataFile.Layer userDataLayer;
                                        if (fn)
                                        {
                                            userData.FnLayers.TryGetValue(layer.Key, out userDataLayer);
                                        }
                                        else
                                        {
                                            userData.Layers.TryGetValue(layer.Key, out userDataLayer);
                                        }
                                        if (userDataLayer != null)
                                        {
                                            for (int j = 0; j < driverValues.Length; j++)
                                            {
                                                KeyboardState.Key key = device.State.GetKeyByLogicCode(j);
                                                if (key != null)
                                                {
                                                    driverValues[j] = userDataLayer.GetKey(key.DriverValue);
                                                }
                                            }
                                        }
                                    }
                                    device.SetKeys(layer.Key, driverValues, fn);
                                }
                            }

                            // This is required to "refresh" the keyboard with the updated key info
                            if (hasTargetLayer)
                            {
                                device.SetLayer(targetLayer);
                            }
                            else
                            {
                                device.SetLayer(KeyboardLayer.Base);
                            }
                            Log("Done");
                        }
                    }
                }
                break;

                case "dumpkeys":
                {
                    int targetRow = -1;
                    if (splitted.Length > 1)
                    {
                        if (!int.TryParse(splitted[1], out targetRow))
                        {
                            targetRow = -1;
                        }
                    }
                    bool showLocationCodeInfo = false;
                    if (splitted.Length > 2)
                    {
                        showLocationCodeInfo = splitted[2] == "ex";
                    }

                    KeyboardDevice[] devices;
                    if (TryGetDevices(out devices))
                    {
                        foreach (KeyboardDevice device in devices)
                        {
                            Log("====== " + device.State.ModelId + " ======");
                            bool foundKey = false;
                            int  lastLeft = int.MinValue;
                            int  row      = 1;
                            foreach (KeyboardState.Key key in device.State.KeysByLocationCode.Values.OrderBy(
                                         x => x.Position.Top).ThenBy(x => x.Position.Left))
                            {
                                if (key.Position.Left >= 0)
                                {
                                    if (lastLeft > key.Position.Left && foundKey)
                                    {
                                        if (targetRow == -1)
                                        {
                                            Log("--------");
                                        }
                                        foundKey = false;
                                        row++;
                                    }
                                    lastLeft = key.Position.Left;
                                }

                                if (string.IsNullOrEmpty(key.KeyName) || !key.KeyName.StartsWith("LED-"))
                                {
                                    if (targetRow == -1 || row == targetRow)
                                    {
                                        Log(key.KeyName + " = " + (DriverValue)key.DriverValue +
                                            (showLocationCodeInfo ? " (" + key.LocationCode + ")" : string.Empty));
                                    }
                                    foundKey = true;
                                }
                            }
                        }
                    }
                }
                break;
                }
            }

            KeyboardDeviceManager.StopListener();
        }