static void Stop() { KeyboardDeviceManager.StopListener(); WebGUI.Stop(); Environment.Exit(0);// Ensure any loose threads die... }
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(); }
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(); }