Speech-dispatcher handling improved.

This commit is contained in:
Storm Dragon committed 2026-10-28 11:34:57 -04:00
1 parent 60abcc37d9
commit ec32c6e4c4
11 files changed
+638 -222

No files matched your search

+39 -31
View File
@@ -20,10 +20,9 @@ package speech
import (
"bufio"
"context"
"fmt"
"net"
"os"
"path/filepath"
"strconv"
"strings"
"sync"
@@ -93,8 +92,27 @@ func (w *wire) command(command string) ([]string, error) {
return w.reply()
}
func connect(path string) (*wire, error) {
conn, err := net.DialTimeout("unix", path, commandTimeout)
// Queries share the address resolver. Only Prepare opts into daemon startup;
// ordinary settings discovery never starts a service.
func connect_options(options Options) (*wire, error) {
endpoint, err := resolve_server_address(options.Socket)
if err != nil {
return nil, err
}
return connect_endpoint(endpoint, options.autospawn)
}
func connect_endpoint(endpoint serverAddress, autospawn bool) (*wire, error) {
ctx, cancel := context.WithTimeout(context.Background(), 3*commandTimeout)
defer cancel()
dialer := &net.Dialer{Timeout: commandTimeout}
var conn net.Conn
var err error
if autospawn {
conn, err = connect_with_autospawn(ctx, endpoint, dialer.DialContext, spawn_server)
} else {
conn, err = dialer.DialContext(ctx, endpoint.network, endpoint.address)
}
if err != nil {
return nil, err
}
@@ -110,14 +128,16 @@ type Client struct {
}
type Options struct {
Socket string
Rate int
Pitch *int
Volume *int
Module string
Language string
Voice string
Hardware HardwareOptions
// Only Prepare enables startup during its prerequisite selection queries.
autospawn bool
Socket string
Rate int
Pitch *int
Volume *int
Module string
Language string
Voice string
Hardware HardwareOptions
}
type Parameters struct {
@@ -131,22 +151,6 @@ func (p Parameters) Validate() error {
return nil
}
func Default_socket() string {
if value := os.Getenv("SPEECHD_ADDRESS"); strings.HasPrefix(value, "unix_socket:") {
return strings.TrimPrefix(value, "unix_socket:")
}
if uid := os.Getenv("SUDO_UID"); uid != "" {
if _, err := strconv.ParseUint(uid, 10, 32); err == nil {
return filepath.Join("/run/user", uid, "speech-dispatcher/speechd.sock")
}
}
runtimeDir := os.Getenv("XDG_RUNTIME_DIR")
if runtimeDir == "" {
runtimeDir = filepath.Join("/run/user", strconv.Itoa(os.Getuid()))
}
return filepath.Join(runtimeDir, "speech-dispatcher/speechd.sock")
}
func Open(options Options) (*Client, error) {
if options.Rate < -100 || options.Rate > 100 {
return nil, fmt.Errorf("speech rate must be between -100 and 100")
@@ -159,9 +163,13 @@ func Open(options Options) (*Client, error) {
if err := Validate_selection(options.Module, options.Language, options.Voice); err != nil {
return nil, err
}
data, err := connect(options.Socket)
endpoint, err := resolve_server_address(options.Socket)
if err != nil {
return nil, fmt.Errorf("connect Speech Dispatcher at %s: %w", options.Socket, err)
return nil, err
}
data, err := connect_endpoint(endpoint, true)
if err != nil {
return nil, fmt.Errorf("connect Speech Dispatcher at %s: %w", endpoint.address, err)
}
client := &Client{data: data}
fail := func(err error) (*Client, error) {
@@ -210,7 +218,7 @@ func Open(options Options) (*Client, error) {
return fail(fmt.Errorf("invalid Speech Dispatcher client ID"))
}
client.id = strconv.FormatUint(id, 10)
client.control, err = connect(options.Socket)
client.control, err = connect_endpoint(endpoint, false)
if err != nil {
return fail(err)
}