// Copyright (c) 2026 Storm Dragon // Authors: Storm Dragon, Angus Kola // SPDX-License-Identifier: GPL-3.0-or-later package app import ( "context" "unicode" "unicode/utf8" ) func capitalCharacter(text string) bool { letter, size := utf8.DecodeRuneInString(text) return size == len(text) && unicode.IsUpper(letter) } func capitalVoice(customEcho bool) string { if customEcho { return "uppercase-echo" } return "uppercase" } // Called only by serialized speech delivery, after mode and context handling. // No cue outlives its owning request's cancellation context. func (worker *speechWorker) present_capital(ctx context.Context, request speechRequest) error { if worker.capitalization == nil { return nil } beep, sayCap := worker.capitalization() if beep && worker.capitalBeep != nil { if err := worker.capitalBeep(ctx); err != nil { if ctx.Err() != nil { return ctx.Err() } worker.logger.Warn("capital letter beep", "error", err) } } if err := ctx.Err(); err != nil { return err } if sayCap { if voice, ok := worker.speaker.(interface { SpeakVoiceAndWait(context.Context, string, string, func()) error }); ok { return voice.SpeakVoiceAndWait(ctx, "cap", capitalVoice(request.CustomEcho), nil) } return worker.speaker.Speak(ctx, "cap") } return nil }