// Copyright (c) 2026 Storm Dragon // SPDX-License-Identifier: GPL-3.0-or-later package speech import ( "context" "fmt" "time" ) // Test_hardware opens a temporary client; it never replaces the reader's // transport. Keep the connection while the device speaks: Close cancels its // buffer, and these devices provide no speech-completion acknowledgement. func Test_hardware(ctx context.Context, driverID string, options Options, text string) error { driver, err := Find_driver(driverID) if err != nil { return err } if !driver.Hardware { return fmt.Errorf("selected driver is not a hardware synthesizer") } ctx, cancel := context.WithTimeout(ctx, 30*time.Second) defer cancel() if err := ctx.Err(); err != nil { return err } client, err := Open_driver(driverID, options) if err != nil { return err } stop, stopped := make(chan struct{}), make(chan struct{}) go func() { defer close(stopped) select { case <-ctx.Done(): _ = client.Cancel() case <-stop: } }() defer func() { close(stop); <-stopped; client.Close() }() if err := ctx.Err(); err != nil { return err } if err := client.Say(text); err != nil { return err } if err := ctx.Err(); err != nil { return err } <-ctx.Done() if ctx.Err() == context.DeadlineExceeded { return nil } return ctx.Err() }