You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(ir): add configurable long-press actions for IR remote buttons
Each learned IR button can now carry a second command that fires when the
button is held, so a short tap and a long hold run different actions (like
the physical buttons already do).
IR sends no "released" event, so release is inferred from the repeat-frame
stream: a held button keeps re-sending frames, and once they stop arriving
(IR_HOLD_RELEASE_MS gap) the button counts as released. A button with a
long action fires the long action once the hold passes a configurable
threshold and the short action on release; buttons without a long action
keep their previous instant behavior (volume still ramps while held).
- IrMapping gains a longCmd byte; the NVS blob moves to key "irMap2" with a
one-time migration from the legacy 3-byte "irMap" layout so existing
remotes survive the update (a separate key avoids the 3-vs-4 byte stride
ambiguity).
- Threshold persisted in NVS ("irLongMs", default 600 ms, clamped 200-5000),
configurable via Settings -> IR. Exposed as ir.longPressMs and per-entry
ir.map[].longCmd in settingsToJSON / JSONToSettings, so it round-trips
through GET/POST /settings and the full backup/restore.
- Web UI: second "long press" command column (with a "none" option) plus a
ms threshold input; de/en/fr strings; demo mock + README updated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: README.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -268,6 +268,7 @@ neon logo that doubles as the SVG favicon ([`7be5254`](../../commit/7be5254)):
268
268
| Don't resume a barely-started audiobook: if the card is pulled within the first few seconds (new **"Don't resume if pulled within (sec.)"** general setting, NVS key `minResumeSec`, default 20 s, 0 = off), the resume point is reset to the very start instead of saving the couple of seconds played — so a briefly-sampled card starts cleanly from the beginning next time rather than a few seconds in. Gated to the very first track of the position-saving audiobook modes, so genuine mid-book progress is never discarded |[`7cacec7`](../../commit/7cacec7)|
269
269
| **Smart forward/backward seek with press-coalescing** (`CMD_SMART_FORWARDS` / `CMD_SMART_BACKWARDS`, action codes 190/191; also track-control codes 10/11 for MQTT): on an audiobook that is a single long file these commands seek *inside* the file; on a playlist of several files they fall back to next/previous track. Rapid presses are bundled into one jump so the decoder re-syncs once instead of once per press (the old per-press seek felt sluggish on FLAC and dropped presses during the multi-second resync). A forward jump past the end of a single file **clamps to a few seconds before the end and keeps playing** instead of ending the book (`setAudioPlayTime` instead of `setTimeOffset`'s `stopSong`). On a single-file audiobook this works even in the first second after a tap (before the duration is known), and the target is clamped to the `setAudioPlayTime` 16-bit range so files longer than ~18 h can't wrap. The step is configurable in the web UI (General → options → **"Smart seek step (sec.)"**, NVS key `seekStep`, default 300 s = 5 min). Bind them to physical buttons in the **Buttons** settings tab. The plain `CMD_SEEK_FORWARDS`/`BACKWARDS` 30 s jump (`jumpOffset`) and the upstream next/previous-track behavior are both unchanged | [`ba3628e`](../../commit/ba3628e) |
270
270
|**Infrared remote control** enabled on the complete board: an IR receiver (e.g. VS1838B) on `IRLED_PIN` (GPIO 5) drives play/pause, next/previous, first/last track, volume, mute, shutdown, Bluetooth and FTP via the `RC_*` command codes in `settings-complete.h`. The mapping defaults to empty so an un-learned remote does nothing until its codes are entered |[`9dbe588`](../../commit/9dbe588)|
271
+
|**IR long-press actions**: every learned IR button can carry a **second command that fires when the button is held** — short tap and long hold trigger different actions, just like the physical buttons. IR sends no "released" event, so the firmware infers release from the repeat-frame stream: the long action fires once the hold passes a **configurable threshold** (Settings → IR → **"Long-press threshold"**, default 600 ms, NVS key `irLongMs`), the short action fires on release. Buttons left without a long action keep firing instantly (volume still ramps while held). Set per button in the IR settings tab and carried through backup/restore ||
Copy file name to clipboardExpand all lines: html/locales/de.json
+4Lines changed: 4 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -58,6 +58,9 @@
58
58
"title": "Infrarot-Fernbedienung",
59
59
"intro": "Lerne die Tasten deiner Fernbedienung an und ordne jeder ein Kommando zu. Klicke auf „Anlernen“ und drücke dann die Taste auf der Fernbedienung – der empfangene Code wird automatisch eingetragen. Nicht vergessen zu speichern.",
60
60
"command": "Kommando",
61
+
"longCommand": "Lang drücken",
62
+
"longPressLabel": "Schwelle für langes Drücken",
63
+
"longPressHint": "Wie lange eine Taste gehalten werden muss, um die Lang-Aktion auszulösen (200–5000 ms). Tasten ohne Lang-Aktion reagieren weiterhin sofort.",
61
64
"code": "IR-Code",
62
65
"learn": "Anlernen",
63
66
"learnPrompt": "Drücke jetzt eine Taste auf der Fernbedienung…",
Copy file name to clipboardExpand all lines: html/locales/en.json
+4Lines changed: 4 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -58,6 +58,9 @@
58
58
"title": "Infrared remote control",
59
59
"intro": "Teach the buttons of your remote and assign each one a command. Click “Learn”, then press the button on the remote — the received code is filled in automatically. Don't forget to save.",
60
60
"command": "Command",
61
+
"longCommand": "Long press",
62
+
"longPressLabel": "Long-press threshold",
63
+
"longPressHint": "How long a button must be held to trigger the long-press action (200–5000 ms). Buttons without a long action still react instantly.",
61
64
"code": "IR code",
62
65
"learn": "Learn",
63
66
"learnPrompt": "Press a button on the remote now…",
@@ -68,6 +71,7 @@
68
71
"timeout": "No IR signal received — learning cancelled.",
69
72
"duplicate": "The same code is mapped more than once; the first match wins.",
Copy file name to clipboardExpand all lines: html/locales/fr.json
+4Lines changed: 4 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -58,6 +58,9 @@
58
58
"title": "Télécommande infrarouge",
59
59
"intro": "Apprenez les touches de votre télécommande et associez à chacune une commande. Cliquez sur « Apprendre », puis appuyez sur la touche de la télécommande — le code reçu est rempli automatiquement. N'oubliez pas d'enregistrer.",
60
60
"command": "Commande",
61
+
"longCommand": "Appui long",
62
+
"longPressLabel": "Seuil d’appui long",
63
+
"longPressHint": "Durée pendant laquelle une touche doit être maintenue pour déclencher l’action d’appui long (200–5000 ms). Les touches sans action longue réagissent toujours immédiatement.",
61
64
"code": "Code IR",
62
65
"learn": "Apprendre",
63
66
"learnPrompt": "Appuyez maintenant sur une touche de la télécommande…",
@@ -68,6 +71,7 @@
68
71
"timeout": "Aucun signal IR reçu — apprentissage annulé.",
69
72
"duplicate": "Le même code est associé plusieurs fois ; la première correspondance l'emporte.",
0 commit comments