Adds a TCP client for lircd's classic protocol: play/pause/next/prev/ volume/mute map to the same intents every other front-end already emits, and number keys 0-9 play an assigned album/audiobook from the start or a podcast show's newest episode, resolved fresh on every press. The mapping is configured in config.yml and editable from the frontend: a small "Taste zuweisen" button on the play screen (or the A+digit keyboard shortcut) opens a 10-key picker to assign whatever is currently playing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
38 lines
1005 B
Python
38 lines
1005 B
Python
"""lircd's classic network protocol: one line per button press or repeat.
|
|
|
|
A line looks like::
|
|
|
|
0000000000001781 00 BTN_1 Hauppauge
|
|
|
|
that is ``<code> <repeat, hex> <button name> <remote name>``. ``repeat`` is ``00`` for
|
|
the first press and increments while the button is held - lircd has no separate
|
|
key-up event, just repeats stopping.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
|
|
__all__ = ["LircButtonEvent", "parse_line"]
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class LircButtonEvent:
|
|
code: str
|
|
repeat: int
|
|
button: str
|
|
remote: str
|
|
|
|
|
|
def parse_line(line: str) -> LircButtonEvent | None:
|
|
"""One broadcast line, or ``None`` if it does not look like one."""
|
|
parts = line.strip().split()
|
|
if len(parts) != 4:
|
|
return None
|
|
code, repeat_hex, button, remote = parts
|
|
try:
|
|
repeat = int(repeat_hex, 16)
|
|
except ValueError:
|
|
return None
|
|
return LircButtonEvent(code=code, repeat=repeat, button=button, remote=remote)
|