Reset master to testing content
This commit is contained in:
1 parent
0f2587b719
commit
42afa2a56c
1483 files changed
+145308
-938069
No files matched your search
@@ -0,0 +1,158 @@
|
||||
// Copyright (c) 2026 Storm Dragon
|
||||
// Authors: Storm Dragon, Angus Kola
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"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 {
|
||||
if request.EchoPreview != "" {
|
||||
return worker.preview_echo_voice(ctx, request)
|
||||
}
|
||||
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) preview_echo_voice(ctx context.Context, request preferences.Request) preferences.Response {
|
||||
response := worker.response("Speech settings previewed.", false)
|
||||
response.Preview = true
|
||||
var value *float64
|
||||
text := ""
|
||||
label := ""
|
||||
switch request.EchoPreview {
|
||||
case "rate":
|
||||
value = request.Values.EchoVoice.Rate
|
||||
label = "Key echo rate"
|
||||
case "pitch":
|
||||
value = request.Values.EchoVoice.AveragePitch
|
||||
label = "Key echo pitch"
|
||||
case "volume":
|
||||
value = request.Values.EchoVoice.Gain
|
||||
label = "Key echo volume"
|
||||
case "synthesizer":
|
||||
label = "Key echo speech synthesizer"
|
||||
text = request.Values.EchoSpeechServer
|
||||
if text == "" {
|
||||
text = "Default"
|
||||
}
|
||||
case "person":
|
||||
label = "Key echo person"
|
||||
text = "Default"
|
||||
if family := request.Values.EchoVoice.Family; family != nil {
|
||||
text = family.Name
|
||||
if language := strings.TrimSuffix(family.Lang+"-"+family.Dialect, "-"); language != "" {
|
||||
text += " (" + language + ")"
|
||||
}
|
||||
}
|
||||
}
|
||||
if value != nil {
|
||||
text = fmt.Sprintf("%.1f", *value)
|
||||
}
|
||||
if !request.Values.UseCustomEchoVoice || text == "" {
|
||||
response.Message = "Choose a custom echo voice and a valid echo control value."
|
||||
return response
|
||||
}
|
||||
// Preview only echo settings. Control labels and ordinary output retain
|
||||
// the active profile's main voice; the draft is never committed here.
|
||||
next := worker.settings
|
||||
next.UseCustomEchoVoice = true
|
||||
next.UseCustomEchoSpeechServer = request.Values.UseCustomEchoSpeechServer
|
||||
next.EchoSpeechServer = request.Values.EchoSpeechServer
|
||||
next.EchoVoice = request.Values.EchoVoice
|
||||
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
|
||||
}
|
||||
if worker.announceEchoPreview != nil {
|
||||
if !request.EchoPreviewFocus {
|
||||
label = ""
|
||||
}
|
||||
worker.announceEchoPreview(label, text)
|
||||
}
|
||||
response.Accepted = true
|
||||
return response
|
||||
}
|
||||
|
||||
func echo_preview_speech(label, value string) speechRequest {
|
||||
parts := []readAllPart{}
|
||||
if label != "" {
|
||||
parts = append(parts, readAllPart{Text: label, VoiceType: "default"})
|
||||
}
|
||||
parts = append(parts, readAllPart{Text: value, VoiceType: "echo"})
|
||||
// Both parts belong to one cancellable request and wait for completion.
|
||||
// No second voice can cancel the first part merely by being queued next.
|
||||
return speechRequest{Text: value, Role: "text", Cause: "echo-voice-preview", ReadAll: parts}
|
||||
}
|
||||
|
||||
func (worker *preferencesWorker) restorePreview(ctx context.Context) preferences.Response {
|
||||
response := worker.response("Speech settings restored.", false)
|
||||
if err := worker.updateSpeech(ctx, worker.effective_settings(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")
|
||||
}
|
||||
Reference in new issue
Block a user