85 lines
2.4 KiB
Go
85 lines
2.4 KiB
Go
// Copyright (c) 2026 Storm Dragon
|
|
// Authors: Storm Dragon, Angus Kola
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
package speech
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type serverAddress struct {
|
|
network string
|
|
address string
|
|
}
|
|
|
|
// DefaultSocketAddress follows the default used by the Python speechd client.
|
|
func DefaultSocketAddress() string {
|
|
runtimeDirectory := os.Getenv("XDG_RUNTIME_DIR")
|
|
if runtimeDirectory == "" {
|
|
runtimeDirectory = os.Getenv("XDG_CACHE_HOME")
|
|
}
|
|
if runtimeDirectory == "" {
|
|
cacheDirectory, err := os.UserCacheDir()
|
|
if err == nil {
|
|
runtimeDirectory = cacheDirectory
|
|
}
|
|
}
|
|
return filepath.Join(runtimeDirectory, "speech-dispatcher", "speechd.sock")
|
|
}
|
|
|
|
// resolveServerAddress gives an explicit CLI socket priority over speechd's
|
|
// standard address variables. SPEECHD_SOCKET is the older Unix-only setting.
|
|
func resolveServerAddress(socket string) (serverAddress, error) {
|
|
if socket != "" {
|
|
return serverAddress{network: "unix", address: socket}, nil
|
|
}
|
|
if address := os.Getenv("SPEECHD_ADDRESS"); address != "" {
|
|
return parseServerAddress(address)
|
|
}
|
|
if socket := os.Getenv("SPEECHD_SOCKET"); socket != "" {
|
|
return serverAddress{network: "unix", address: socket}, nil
|
|
}
|
|
return serverAddress{network: "unix", address: DefaultSocketAddress()}, nil
|
|
}
|
|
|
|
func parseServerAddress(address string) (serverAddress, error) {
|
|
method, value, _ := strings.Cut(address, ":")
|
|
switch method {
|
|
case "unix_socket":
|
|
if value == "" {
|
|
value = DefaultSocketAddress()
|
|
}
|
|
if !filepath.IsAbs(value) {
|
|
return serverAddress{}, fmt.Errorf("Speech Dispatcher Unix socket must be an absolute path: %q", value)
|
|
}
|
|
return serverAddress{network: "unix", address: value}, nil
|
|
case "inet_socket":
|
|
host, port := "127.0.0.1", 6560
|
|
if value != "" {
|
|
parts := strings.Split(value, ":")
|
|
if len(parts) > 2 {
|
|
return serverAddress{}, fmt.Errorf("invalid Speech Dispatcher address %q", address)
|
|
}
|
|
if parts[0] != "" {
|
|
host = parts[0]
|
|
}
|
|
if len(parts) == 2 {
|
|
parsed, err := strconv.Atoi(parts[1])
|
|
if err != nil || parsed < 1 || parsed > 65535 {
|
|
return serverAddress{}, fmt.Errorf("invalid Speech Dispatcher port in %q", address)
|
|
}
|
|
port = parsed
|
|
}
|
|
}
|
|
return serverAddress{network: "tcp4", address: net.JoinHostPort(host, strconv.Itoa(port))}, nil
|
|
default:
|
|
return serverAddress{}, fmt.Errorf("unsupported Speech Dispatcher address %q", address)
|
|
}
|
|
}
|