feat: initial implementation, refs NOISSUE

This commit is contained in:
2025-10-30 17:19:06 +01:00
commit 39bd8150e1
4 changed files with 100 additions and 0 deletions

82
volume_remapper.py Executable file
View File

@@ -0,0 +1,82 @@
#!/usr/bin/env python3
"""
volume_remapper.py
------------------
Listen for VolumeUp key events and emit a different key code
(“Ctrl+Shift+M” by default) so the focused application receives it.
Dependencies: pythonevdev (pip install evdev)
"""
import sys
import os
import argparse
from evdev import InputDevice, categorize, ecodes, UInput, list_devices
import time
# ------------------------------------------------------------------ #
# Helpers
# ------------------------------------------------------------------ #
def find_device(name_substr="volume"):
"""Return the first InputDevice that contains a KEY_VOLUMEUP event."""
for dev_path in [d.path for d in list_devices()]:
dev = InputDevice(dev_path)
caps = dev.capabilities()
if ecodes.EV_KEY in caps and ecodes.KEY_VOLUMEUP in caps[ecodes.EV_KEY]:
if name_substr.lower() in dev.name.lower():
return dev
return None
# ------------------------------------------------------------------ #
# Core logic
# ------------------------------------------------------------------ #
def main(remap_keys, device=None):
"""
:param remap_keys: tuple of ecodes.KEY_* codes to emit (e.g. (ecodes.KEY_LCTRL, ecodes.KEY_LSHIFT, ecodes.KEY_M))
:param device: path to /dev/input/eventX or None to autodetect
"""
if device is None:
dev = find_device()
if dev is None:
print("⚠️ No device with a VolumeUp key found.", file=sys.stderr)
sys.exit(1)
else:
dev = InputDevice(device)
print(f"[INFO] Listening on {dev.path} ({dev.name}) ...")
print(f"[INFO] Remapping to: {', '.join(ecodes.KEY.get(k) for k in remap_keys)}")
# Create a virtual keyboard (uinput)
ui = UInput(events=[
ecodes.EV_KEY, # only key events
ecodes.EV_SYN
], name='volumeremapper')
try:
for event in dev.read_loop():
if event.type == ecodes.EV_KEY:
if event.code == ecodes.KEY_VOLUMEUP and event.value == 1: # key_down
# Emit the mapped key sequence
for key in remap_keys:
ui.write(ecodes.EV_KEY, key, 1) # key down
ui.write(ecodes.EV_KEY, key, 0) # key up
ui.syn()
print(f"✅ Mapped VolumeUp → {', '.join(ecodes.KEY.get(k) for k in remap_keys)}")
except KeyboardInterrupt:
print("\n[INFO] Stopping …")
finally:
ui.close()
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Remap VolumeUp to any key combo.")
parser.add_argument("--device", help="Optional /dev/input/eventX path to listen on.")
parser.add_argument("--to", nargs="+", default=["KEY_LCTRL", "KEY_LSHIFT", "KEY_M"],
help="Spaceseparated key names to emit. Default: Ctrl+Shift+M")
args = parser.parse_args()
# Convert key names to ecodes
remap = [ecodes.KEY[code.upper()] for code in args.to]
main(remap_keys=remap, device=args.device)