// Copyright (c) 2026 Storm Dragon // Authors: Storm Dragon, Angus Kola // SPDX-License-Identifier: GPL-3.0-or-later package app import ( "context" "errors" "git.stormux.org/storm/cthulhu/internal/config" "git.stormux.org/storm/cthulhu/internal/preferences" ) func (worker *preferencesWorker) preview(ctx context.Context, request preferences.Request) preferences.Response { next := worker.settings if worker.editingActive { next = worker.editing } next.DefaultVoice.Rate = request.Values.Rate next.DefaultVoice.AveragePitch = request.Values.Pitch next.DefaultVoice.Gain = request.Values.Volume next.SpeechServerFactory = request.Values.SpeechServerFactory next.HardwareSpeechDevice = request.Values.HardwareSpeechDevice next.HardwareSpeechBaudRate = request.Values.HardwareSpeechBaudRate next.SpeechOutputModule = request.Values.SpeechOutputModule next.DefaultVoice.Family = request.Values.SpeechVoiceFamily next.UppercaseVoice = request.Values.UppercaseVoice next.HyperlinkVoice = request.Values.HyperlinkVoice next.SystemVoice = request.Values.SystemVoice // GUI feedback auditions the selected type; Cancel restores the committed // configuration, while Apply receives the complete unmodified draft. if kind := request.Values.VoiceType; kind != "" && kind != "default" { next.DefaultVoice = config.EffectiveVoice(next, kind) next.SystemVoice = config.Voice{} } response := worker.response("Speech settings previewed.", false) response.Preview = true if err := config.Validate(next); err != nil { response.Message = "Speech settings were not previewed: " + err.Error() return response } if err := worker.updateSpeech(ctx, next); err != nil { response.Message = "Speech settings were not previewed: " + err.Error() return response } response.Accepted = true return response } func (worker *preferencesWorker) restorePreview(ctx context.Context) preferences.Response { response := worker.response("Speech settings restored.", false) if err := worker.updateSpeech(ctx, worker.settings); err != nil { response.Message = "Speech settings could not be restored: " + err.Error() return response } response.Accepted = true response.Close = true return response } func (worker *preferencesWorker) updateSpeech(ctx context.Context, next config.Settings) error { if worker.updater == nil { return errors.New("speech is disabled or this backend cannot change settings") } if updater, ok := worker.updater.(interface { UpdateConfiguration(context.Context, config.Settings) error }); ok { return updater.UpdateConfiguration(ctx, next) } if updater, ok := worker.updater.(speechSettingsUpdater); ok { if next.UseCustomEchoVoice { return errors.New("this speech backend cannot use a custom echo voice") } return updater.UpdateSettings(ctx, speechSettingsFromConfig(next)) } return errors.New("this backend cannot change speech settings") }