diff --git a/host-app/MacroPad.Host/ActionFactory.cs b/host-app/MacroPad.Host/ActionFactory.cs new file mode 100644 index 0000000..8519c8b --- /dev/null +++ b/host-app/MacroPad.Host/ActionFactory.cs @@ -0,0 +1,12 @@ +public static class ActionFactory +{ + public static IAction? Create(BindingConfig config) + { + return config.Type switch + { + "launch" => new LaunchAction(config.Target), + "url" => new UrlAction(config.Target), + _ => null + }; + } +} \ No newline at end of file diff --git a/host-app/MacroPad.Host/Config.cs b/host-app/MacroPad.Host/Config.cs new file mode 100644 index 0000000..e09e9aa --- /dev/null +++ b/host-app/MacroPad.Host/Config.cs @@ -0,0 +1,10 @@ +public class BindingConfig +{ + public string Type { get; set; } = ""; + public string Target { get; set; } = ""; +} + +public class Config +{ + public Dictionary Bindings { get; set; } = new(); +} \ No newline at end of file diff --git a/host-app/MacroPad.Host/IAction.cs b/host-app/MacroPad.Host/IAction.cs new file mode 100644 index 0000000..b032813 --- /dev/null +++ b/host-app/MacroPad.Host/IAction.cs @@ -0,0 +1,4 @@ +public interface IAction +{ + void Execute(); +} \ No newline at end of file diff --git a/host-app/MacroPad.Host/LaunchAction.cs b/host-app/MacroPad.Host/LaunchAction.cs new file mode 100644 index 0000000..63b174c --- /dev/null +++ b/host-app/MacroPad.Host/LaunchAction.cs @@ -0,0 +1,12 @@ +using System.Diagnostics; + +public class LaunchAction : IAction +{ + private readonly string _target; + public LaunchAction(string target) => _target = target; + + public void Execute() + { + Process.Start(new ProcessStartInfo(_target) { UseShellExecute = true }); + } +} \ No newline at end of file diff --git a/host-app/MacroPad.Host/MacroPad.Host.csproj b/host-app/MacroPad.Host/MacroPad.Host.csproj index 0993416..7900485 100644 --- a/host-app/MacroPad.Host/MacroPad.Host.csproj +++ b/host-app/MacroPad.Host/MacroPad.Host.csproj @@ -11,4 +11,10 @@ + + + PreserveNewest + + + diff --git a/host-app/MacroPad.Host/Program.cs b/host-app/MacroPad.Host/Program.cs index 516264f..140aa97 100644 --- a/host-app/MacroPad.Host/Program.cs +++ b/host-app/MacroPad.Host/Program.cs @@ -1,46 +1,39 @@ -using HidSharp; +using System.Text.Json; +using HidSharp; -var candidates = DeviceList.Local.GetHidDevices(vendorID: 0x2341, productID: 0x8036).ToList(); +var configPath = Path.Combine(AppContext.BaseDirectory, "config.json"); +var configJson = File.ReadAllText(configPath); +var config = JsonSerializer.Deserialize(configJson, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }) + ?? new Config(); -Console.WriteLine($"{candidates.Count} interface(s) trouvée(s) pour ce VID/PID :\n"); -foreach (var d in candidates) +var actions = new Dictionary(); +foreach (var (key, binding) in config.Bindings) { - Console.WriteLine($" {d.DevicePath}"); + var action = ActionFactory.Create(binding); + if (action is not null && int.TryParse(key, out var bit)) + actions[bit] = action; } -Console.WriteLine(); - -var device = candidates.FirstOrDefault(d => !d.DevicePath.Contains("kbd", StringComparison.OrdinalIgnoreCase)); +var device = DeviceList.Local.GetHidDevices(vendorID: 0x2341, productID: 0x8036).FirstOrDefault(); if (device is null) { - Console.WriteLine("Interface Raw HID non trouvée (seule l'interface clavier standard a été détectée)."); + Console.WriteLine("Pad non trouvé. Vérifie qu'il est branché."); return; } -Console.WriteLine($"Ouverture de : {device.DevicePath}\n"); - using var stream = device.Open(); stream.ReadTimeout = Timeout.Infinite; -Console.WriteLine($"MaxInputReportLength: {device.GetMaxInputReportLength()}"); -Console.WriteLine($"MaxOutputReportLength: {device.GetMaxOutputReportLength()}"); - var buffer = new byte[device.GetMaxInputReportLength()]; ushort lastMask = 0; -Console.WriteLine("En écoute... appuie sur chaque bouton un par un (Ctrl+C pour quitter)\n"); +Console.WriteLine("En écoute...\n"); while (true) { int count; - try - { - count = stream.Read(buffer, 0, buffer.Length); - } - catch (TimeoutException) - { - continue; - } + try { count = stream.Read(buffer, 0, buffer.Length); } + catch (TimeoutException) { continue; } int offset = count > 2 ? 1 : 0; ushort mask = (ushort)(buffer[offset] | (buffer[offset + 1] << 8)); @@ -50,10 +43,14 @@ while (true) ushort changed = (ushort)(mask ^ lastMask); for (int bit = 0; bit < 12; bit++) { - if ((changed & (1 << bit)) != 0) + bool bitChanged = (changed & (1 << bit)) != 0; + bool nowPressed = (mask & (1 << bit)) != 0; + + // On déclenche seulement au moment où le bouton est pressé, pas relâché + if (bitChanged && nowPressed && actions.TryGetValue(bit, out var action)) { - bool pressed = (mask & (1 << bit)) != 0; - Console.WriteLine($"Bit {bit}: {(pressed ? "PRESSÉ" : "relâché")}"); + Console.WriteLine($"Bouton {bit} → exécution de l'action"); + action.Execute(); } } lastMask = mask; diff --git a/host-app/MacroPad.Host/UrlAction.cs b/host-app/MacroPad.Host/UrlAction.cs new file mode 100644 index 0000000..b50ef64 --- /dev/null +++ b/host-app/MacroPad.Host/UrlAction.cs @@ -0,0 +1,12 @@ +using System.Diagnostics; + +public class UrlAction : IAction +{ + private readonly string _target; + public UrlAction(string target) => _target = target; + + public void Execute() + { + Process.Start(new ProcessStartInfo(_target) { UseShellExecute = true }); + } +} \ No newline at end of file diff --git a/host-app/MacroPad.Host/config.json b/host-app/MacroPad.Host/config.json new file mode 100644 index 0000000..7a9b5f7 --- /dev/null +++ b/host-app/MacroPad.Host/config.json @@ -0,0 +1,7 @@ +{ + "bindings": { + "0": { "type": "launch", "target": "notepad.exe" }, + "1": { "type": "url", "target": "https://github.com" }, + "2": { "type": "keystroke", "target": "^{c}" } + } +} \ No newline at end of file