Files

173 lines
5.3 KiB
Go

// Copyright (c) 2026 Storm Dragon
// Authors: Storm Dragon, Angus Kola
// SPDX-License-Identifier: GPL-3.0-or-later
package preferences
/*
#include <stdlib.h>
#include "native.h"
*/
import "C"
import (
"sort"
"strings"
"unsafe"
"git.stormux.org/storm/cthulhu/internal/config"
)
func echoChecks(values *Values) []struct {
id string
value *bool
} {
return []struct {
id string
value *bool
}{
{"keyEchoCheckButton", &values.EnableKeyEcho},
{"enableAlphabeticKeysCheckButton", &values.EnableAlphabeticKeys},
{"enableNumericKeysCheckButton", &values.EnableNumericKeys},
{"enablePunctuationKeysCheckButton", &values.EnablePunctuationKeys},
{"enableSpaceCheckButton", &values.EnableSpace},
{"enableModifierKeysCheckButton", &values.EnableModifierKeys},
{"enableFunctionKeysCheckButton", &values.EnableFunctionKeys},
{"enableActionKeysCheckButton", &values.EnableActionKeys},
{"enableNavigationKeysCheckButton", &values.EnableNavigationKeys},
{"enableDiacriticalKeysCheckButton", &values.EnableDiacriticalKeys},
{"enableEchoByCharacterCheckButton", &values.EnableEchoByCharacter},
{"enableEchoByWordCheckButton", &values.EnableEchoByWord},
{"enableEchoBySentenceCheckButton", &values.EnableEchoBySentence},
{"useCustomEchoVoiceCheckButton", &values.UseCustomEchoVoice},
{"useCustomEchoSpeechServerCheckButton", &values.UseCustomEchoSpeechServer},
{"useCustomEchoForKeyCheckButton", &values.UseCustomEchoForKey},
{"useCustomEchoForCharacterCheckButton", &values.UseCustomEchoForCharacter},
{"useCustomEchoForWordCheckButton", &values.UseCustomEchoForWord},
{"useCustomEchoForSentenceCheckButton", &values.UseCustomEchoForSentence},
}
}
func (session *uiSession) setEchoVoice(values Values) {
session.echoModules = []string{""}
for module := range session.catalog {
if module != "" {
session.echoModules = append(session.echoModules, module)
}
}
sort.Strings(session.echoModules[1:])
selected := 0
if values.EchoSpeechServer != "" {
selected = -1
for i, module := range session.echoModules {
if module == values.EchoSpeechServer {
selected = i
}
}
if selected < 0 {
selected = len(session.echoModules)
session.echoModules = append(session.echoModules, values.EchoSpeechServer)
}
}
labels := append([]string(nil), session.echoModules...)
labels[0] = "Default"
comboItems("echoSpeechServers", labels, selected)
// The toggle state is installed by setValues before the next GTK iteration.
module := ""
if values.UseCustomEchoSpeechServer {
module = values.EchoSpeechServer
}
session.populateEchoFamilies(module, values.EchoVoice.Family)
for _, item := range []struct {
id string
value *float64
fallback float64
}{
{"echoRateScale", values.EchoVoice.Rate, voiceFallback(values.Rate, 50)},
{"echoPitchScale", values.EchoVoice.AveragePitch, voiceFallback(values.Pitch, 5)},
{"echoVolumeScale", values.EchoVoice.Gain, voiceFallback(values.Volume, 10)},
} {
id := C.CString(item.id)
C.prefs_range_set(id, C.double(voiceFallback(item.value, item.fallback)))
C.free(unsafe.Pointer(id))
}
}
func voiceFallback(value *float64, fallback float64) float64 {
if value != nil {
return *value
}
return fallback
}
func (session *uiSession) populateEchoFamilies(module string, selected *config.VoiceFamily) {
session.activeEchoModule = module
session.echoFamilies = []*config.VoiceFamily{nil}
labels := []string{"Default"}
index := 0
for _, voice := range session.default_voices(module) {
family := &config.VoiceFamily{Name: voice.Name, Lang: voice.Language, Variant: voice.Variant}
session.echoFamilies = append(session.echoFamilies, family)
labels = append(labels, voice.Name+" ("+voice.Language+")")
if selected != nil && selected.Name == voice.Name && strings.EqualFold(strings.TrimSuffix(selected.Lang+"-"+selected.Dialect, "-"), voice.Language) {
index = len(labels) - 1
}
}
if selected != nil && index == 0 {
index = len(labels)
session.echoFamilies = append(session.echoFamilies, selected)
labels = append(labels, selected.Name+" ("+selected.Lang+")")
}
comboItems("echoSpeechFamilies", labels, index)
}
func (session *uiSession) selectedEchoModule() string {
i := getCombo("echoSpeechServers")
if i >= 0 && i < len(session.echoModules) {
return session.echoModules[i]
}
return ""
}
func (session *uiSession) refreshEchoVoices() {
module := ""
if getCheck("useCustomEchoSpeechServerCheckButton") {
module = session.selectedEchoModule()
}
if module != session.activeEchoModule {
session.populateEchoFamilies(module, nil)
}
}
func (session *uiSession) getEchoVoice() (config.Voice, string) {
var voice config.Voice
for _, item := range []struct {
id string
target **float64
}{
{"echoRateScale", &voice.Rate}, {"echoPitchScale", &voice.AveragePitch}, {"echoVolumeScale", &voice.Gain},
} {
id := C.CString(item.id)
value := float64(C.prefs_number_value(id))
C.free(unsafe.Pointer(id))
*item.target = &value
}
i := getCombo("echoSpeechFamilies")
if i >= 0 && i < len(session.echoFamilies) {
voice.Family = session.echoFamilies[i]
}
return voice, session.selectedEchoModule()
}
func set_echo_checks(values Values) {
for _, check := range echoChecks(&values) {
setCheck(check.id, *check.value)
}
}
func get_echo_checks(values *Values) {
for _, check := range echoChecks(values) {
*check.value = getCheck(check.id)
}
}