Broadcast microphone muted event on every mute state change#4
Conversation
LVA never broadcast the muted bool to peripheral_api clients. The ``muted`` event signalled "we just entered the muted display state" but no event ever signalled "we just left it" — only the generic ``idle`` did, and peripherals can't infer mute state from an idle event since idle fires in many other situations (post-TTS, post wake word, after errors). As a result the ReSpeaker 2-Mic peripheral script's cached ``muted`` flag flipped to True on the first mute and stayed True forever. Its button handler keyed off that flag (``muted → unmute_mic``, ``unmuted → mute_mic``), so after the very first mute the button could only ever emit ``unmute_mic``: the user could unmute but never re-mute. The ``volume_muted`` event was already declared in the protocol and already handled by the peripheral script — it just had no emitter. Hook one into ``_set_muted`` so every mute transition (both directions) ships the boolean. The peripheral's existing handler clears its cached ``muted`` and switches the animator state back to IDLE automatically.
42ae3d1 to
5eacd46
Compare
|
@genericJE Is the purpose to emit the muted microphone event which is |
|
You're right that this overloads A cleaner fix in the same spirit would be either to extend |
|
@genericJE I think this recent commit should fix your issue, just make sure that your peripheral script is up to date with the latest changes. https://github.com/omaramin-2000/linux-voice-assistant/tree/leds-and-buttons-events |
…fix/broadcast-volume-muted
c523617 switched LVA to emit `muted` carrying {"muted": bool} in place of the dedicated `volume_muted` event. The ReSpeaker `muted` handler still hardcoded `muted=True`, so it set the flag on mute but never cleared it on unmute. The cached state stuck on, the muted indicator stayed latched, and the button toggle fell out of sync after the first mute (every later press read as already muted). Read `data["muted"]` instead, mirroring the existing `volume_muted` handler, and default to True so a bare `muted` event still reads as muted. Update the peripheral_api docstring, the event and command tables, and the reference handler in peripheral_api.md to document the new payload.
|
Pushed a small follow-up so the One question on |
@genericJE Do you think your change that fires the |
|
|
||
| # Carry the boolean back to peripherals. MUTED and IDLE below | ||
| # only describe the animator state. | ||
| self._emit(LVAEvent.VOLUME_MUTED, {"muted": self.state.muted}) |
There was a problem hiding this comment.
This event for the silent audio when the media player volume is set to 0 which is different from the muted microphone event. So this _set_muted function is for muting the mic.
|
|
||
| if self.state.muted: | ||
| # voice_assistant.stop behavior | ||
| _LOGGER.debug("Muting voice assistant (voice_assistant.stop)") | ||
| self._is_streaming_audio = False | ||
| self.state.tts_player.stop() | ||
| # Stop any ongoing voice processing | ||
| self.state.stop_word.is_active = False # type: ignore[attr-defined] | ||
| self.state.tts_player.play(self.state.mute_sound) | ||
| self._emit(LVAEvent.MUTED) | ||
| else: | ||
| # voice_assistant.start_continuous behavior | ||
| _LOGGER.debug("Unmuting voice assistant (voice_assistant.start_continuous)") | ||
| self.state.tts_player.play(self.state.unmute_sound) | ||
| self._emit(LVAEvent.IDLE) |
There was a problem hiding this comment.
Also as you can see in line 420 that it emits the LVAEvent.MUTED when muting. So, do you think it makes sense when adding another one in line 410?
acf2b39
into
omaramin-2000:leds-and-buttons-events
Hi Omar, second small fix from the same smoke test on the Pi Zero 2 W with the ReSpeaker 2-Mic HAT.
MUTEDis declared in theLVAEventenum and documented in theperipheral_apidocstring, but nothing in LVA actually emits it. Peripherals that maintain a local copy ofstate.mutedonly ever see two signals: the snapshot on connect, and theMUTEDevent. TheMUTEDevent flips the cache toTrue, but there is no matching event when LVA unmutes (only the genericIDLEevent fires, andIDLEcan come from many situations, so a peripheral cannot infer mute state from it).I noticed this while testing the centre button on the ReSpeaker. The button reads peripheral
state.mutedto decide whether to sendmute_micorunmute_mic. After the first successful mute, that local flag was stuck onTrue, so every subsequent press sentunmute_mic. From the user's side it looked like unmute kept working and mute did not. Fixing this fully on the peripheral side felt like working around the missing event, since the protocol already hasmutedfor exactly this purpose.The change just adds one emit in
_set_mutedthat carries the new boolean. The peripheral's existingmutedhandler (already in the docs example and in my smoke test peripheral) clears or sets its cache automatically, and the LEDs follow. Verified end to end: idle press mutes, muted press unmutes, repeated for several cycles without losing sync.Happy to put it somewhere else if you'd prefer, or to wrap it in a separate helper.