fix(audio): a cancelled announcement really stops; oto's Close is a no-op

Clicking Cancel reached the daemon and the queue cancelled the item, but
the sound played on to the end: oto v3's Player.Close only relies on the
garbage collector's finalizer, so the player stayed in the mix. Pause takes
it out immediately; only the device buffer (about 100 ms) drains. Same fix
covers talk cancel and daemon shutdown.

Direct speech via spd-say: killing the waiting client did not stop
speech-dispatcher either; on cancel it now sends `spd-say -S`.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
m3ta-chironandClaude Fable 5.1 committed 2026-10-24 12:26:38 +02:00
1 parent 00eb76128b
commit a0f91c2d64
2 files changed
+12 -1

No files matched your search

+6 -1
View File
@@ -91,7 +91,12 @@ func (OtoSink) Play(ctx context.Context, data []byte) error {
player.Play()
for player.IsPlaying() {
if err := ctx.Err(); err != nil {
player.Close()
// Cancel: stop the sound NOW. oto's Close is a no-op that
// relies on the garbage collector's finalizer, so a cancelled
// announcement would play on to its end; Pause takes the
// player out of the mix immediately (only the device buffer,
// about 100 ms, drains).
player.Pause()
return err
}
if err := player.Err(); err != nil {