fix: ptt auto-detect falls back to toggle mode

Textual does not expose key-release events, so KittyPtt
hold-mode never received key_up and stayed transmitting.
Auto-detect now tries evdev first, then falls back to
toggle (press-on/press-off). Default mode changed to toggle.
This commit is contained in:
Username
2026-02-24 12:50:40 +01:00
parent bc0da57625
commit 31ac90d2c9
5 changed files with 21 additions and 18 deletions

View File

@@ -18,8 +18,8 @@ tuimble --host mumble.example.com --user myname
## Push-to-Talk Modes
- **hold** — hold key to transmit, release to stop (default)
- **toggle** — press to start, press again to stop
- **toggle** — press to start, press again to stop (default)
- **hold** — hold key to transmit, release to stop (requires evdev)
## Configuration

View File

@@ -410,18 +410,15 @@ class TuimbleApp(App):
def on_key(self, event: events.Key) -> None:
"""Handle PTT key events."""
ptt_key = self._config.ptt.key
if event.key != self._config.ptt.key:
return
if isinstance(self._ptt, KittyPtt):
if event.key == ptt_key:
is_release = getattr(event, "key_type", None)
if is_release == "release":
self._ptt.key_up()
else:
self._ptt.key_down()
elif isinstance(self._ptt, TogglePtt):
if event.key == ptt_key:
self._ptt.toggle()
if isinstance(self._ptt, TogglePtt):
self._ptt.toggle()
elif isinstance(self._ptt, KittyPtt):
# Kitty hold-mode requires key-release events that Textual
# does not expose; kept for explicit backend="kitty" only.
self._ptt.key_down()
def _on_ptt_change(self, transmitting: bool) -> None:
self._audio.capturing = transmitting

View File

@@ -29,7 +29,7 @@ class AudioConfig:
@dataclass
class PttConfig:
key: str = "f4"
mode: str = "hold" # hold | toggle
mode: str = "toggle" # toggle | hold (hold requires evdev)
backend: str = "auto" # auto | kitty | evdev | toggle

View File

@@ -139,6 +139,12 @@ def detect_backend(callback: Callback, preference: str = "auto") -> PttBackend:
if preference == "toggle":
return TogglePtt(callback)
# auto: try kitty first (will be validated at runtime by the app),
# then evdev, then toggle
return KittyPtt(callback)
# auto: Textual does not expose key-release events, so kitty
# hold-mode is not viable. Try evdev, fall back to toggle.
try:
import evdev as _evdev # noqa: F811
_ = _evdev.list_devices()
return EvdevPtt(callback)
except Exception:
return TogglePtt(callback)

View File

@@ -8,7 +8,7 @@ def test_default_config():
assert cfg.server.host == "localhost"
assert cfg.server.port == 64738
assert cfg.audio.sample_rate == 48000
assert cfg.ptt.mode == "hold"
assert cfg.ptt.mode == "toggle"
def test_server_config():