feat: add hotkey module with evdev push-to-talk listener
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
"""Hotkey-Listener via evdev für Push-to-Talk."""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Callable, Coroutine
|
||||
|
||||
import evdev
|
||||
from evdev import InputDevice, categorize, ecodes
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
AsyncCallback = Callable[[], Coroutine]
|
||||
|
||||
|
||||
def find_keyboard_device() -> InputDevice:
|
||||
"""Findet das erste Keyboard-Device in /dev/input/."""
|
||||
devices = [InputDevice(path) for path in evdev.list_devices()]
|
||||
for device in devices:
|
||||
capabilities = device.capabilities(verbose=True)
|
||||
for (etype_name, _etype_code), events in capabilities.items():
|
||||
if etype_name == "EV_KEY":
|
||||
key_names = [name for name, _code in events]
|
||||
if "KEY_A" in key_names:
|
||||
logger.info("Keyboard gefunden: %s (%s)", device.name, device.path)
|
||||
return device
|
||||
raise RuntimeError("Kein Keyboard-Device gefunden in /dev/input/")
|
||||
|
||||
|
||||
class HotkeyListener:
|
||||
def __init__(self, key_name: str = "KEY_F12"):
|
||||
self.key_name = key_name
|
||||
self.key_code = ecodes.ecodes.get(key_name)
|
||||
if self.key_code is None:
|
||||
raise ValueError(f"Unbekannter Key-Name: {key_name}")
|
||||
self.on_press: AsyncCallback | None = None
|
||||
self.on_release: AsyncCallback | None = None
|
||||
|
||||
async def _handle_key_event(self, key_down: bool) -> None:
|
||||
"""Ruft den passenden Callback auf."""
|
||||
if key_down and self.on_press:
|
||||
await self.on_press()
|
||||
elif not key_down and self.on_release:
|
||||
await self.on_release()
|
||||
|
||||
async def listen(self) -> None:
|
||||
"""Lauscht auf evdev-Events der konfigurierten Taste."""
|
||||
device = find_keyboard_device()
|
||||
logger.info("Lausche auf %s auf %s", self.key_name, device.name)
|
||||
async for event in device.async_read_loop():
|
||||
if event.type == ecodes.EV_KEY and event.code == self.key_code:
|
||||
if event.value == 1: # Key down
|
||||
logger.debug("%s gedrückt", self.key_name)
|
||||
await self._handle_key_event(key_down=True)
|
||||
elif event.value == 0: # Key up
|
||||
logger.debug("%s losgelassen", self.key_name)
|
||||
await self._handle_key_event(key_down=False)
|
||||
Reference in New Issue
Block a user