From 24e93750951ffde2a403144e0041f6a0287f1eac Mon Sep 17 00:00:00 2001 From: Jeroen Schweitzer Date: Wed, 15 Jul 2026 21:50:53 +0200 Subject: [PATCH] fix(firmware): don't let the feedback gong swallow return-to-idle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A spoken volume command left the face stuck in the thinking spinner. The gateway sends state:thinking -> command -> state:idle, but the device's state:idle handler is gated on !audio_is_playing(), and the feedback gong had been setting s_playing for its (up to 5 s) duration — so the idle was ignored and nothing re-sent it. The gong is a UI cue, not reply playback, so it no longer sets s_playing. This also drops the 5 s wake-gate the gong was imposing. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01LKPbR6DY2JygHbyLjxm7Uu --- CHANGELOG.md | 6 ++++++ firmware/main/audio.c | 7 ++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a80562b..8cb3107 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,12 @@ until the first tagged release. ## [Unreleased] +### Fixed + +- A spoken volume command no longer leaves the face stuck in the thinking + spinner — the feedback gong is a UI cue and no longer holds the busy state, + so the return-to-idle isn't swallowed. + ## [0.2.0] — 2026-07-15 ### Added diff --git a/firmware/main/audio.c b/firmware/main/audio.c index 6f71462..a37c25a 100644 --- a/firmware/main/audio.c +++ b/firmware/main/audio.c @@ -161,8 +161,10 @@ static void audio_task(void *arg) * returns, preventing a playback-boundary false wake. */ if (job == JOB_GONG && s_gong != NULL) { /* Play in chunks so a new request (a fresh volume change) cuts the - * current gong off and restarts, instead of queueing another 5 s. */ - s_playing = true; + * current gong off and restarts, instead of queueing another 5 s. + * Note: the gong is a UI cue, not "playback" — it deliberately does + * NOT set s_playing, so a following state:idle isn't swallowed (that + * guard is for reply audio) and it doesn't gate wake for 5 s. */ uint32_t gen; do { gen = s_gong_gen; @@ -172,7 +174,6 @@ static void audio_task(void *arg) esp_codec_dev_write(s_spk, s_gong + off, n * sizeof(int16_t)); } } while (s_gong_gen != gen); /* a new request arrived mid-play → restart */ - s_playing = false; s_gong_active = false; } else if (job == JOB_CHIME && s_chime != NULL) { s_playing = true;