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:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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():
|
||||
|
||||
Reference in New Issue
Block a user