From b887f6ea95d12f64779935a22f6ad00e73ef39bb Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Wed, 28 Oct 2026 18:17:06 -0400 Subject: [PATCH] Improve sound initialization. --- README.md | 8 +++++--- internal/sound/pulse.go | 4 ++-- internal/sound/service.go | 7 ++++--- internal/sound/service_test.go | 6 +++--- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index bd364cc2..e2e682b4 100644 --- a/README.md +++ b/README.md @@ -75,9 +75,11 @@ server or ALSA device. The [PulseAudio](tools/configure_pulse.sh) and [PipeWire](tools/configure_pipewire.sh) configuration scripts are included for systems that need root audio access. -The default sound driver tries the user session first, then the system-wide -PulseAudio-compatible socket at `/run/pulse/native`, including when provided by -PipeWire. Set `PULSE_SERVER` to select a different socket or server explicitly. +The default sound driver tries the user session first, then `/tmp/pulse.sock` +created by the PipeWire configuration script, then the system-wide +PulseAudio-compatible socket at `/run/pulse/native`. Set `PULSE_SERVER` to select +a different socket or server explicitly. The sound driver does not read +PulseAudio's `client.conf`. Speech output uses Speech Dispatcher's own audio configuration. ### X11 terminal diff --git a/internal/sound/pulse.go b/internal/sound/pulse.go index 1f996202..8a126215 100644 --- a/internal/sound/pulse.go +++ b/internal/sound/pulse.go @@ -29,8 +29,8 @@ import ( func open_pulse(s *Service, _ string) error { options := []pulse.ClientOption{pulse.ClientApplicationName("Fenrir sounds"), pulse.ClientTimeout(500 * time.Millisecond)} - // Try the invoking user's session, then the system-wide service, unless - // PULSE_SERVER explicitly selects a server. + // Try the invoking user's session, then the bundled PipeWire helper's + // socket and the system-wide service, unless PULSE_SERVER selects a server. options = append(options, pulse.ClientServerString(Server(os.Getenv("PULSE_SERVER"), os.Getenv("SUDO_UID")))) client, err := pulse.NewClient(options...) if err != nil { diff --git a/internal/sound/service.go b/internal/sound/service.go index 5161653f..7e4d6e17 100644 --- a/internal/sound/service.go +++ b/internal/sound/service.go @@ -86,8 +86,9 @@ func (s *Service) Set_volume(volume float64) { s.volume.Store(math.Float32bits(float32(volume))) } -// Server returns PulseAudio protocol addresses in connection order. PipeWire's -// PulseAudio service can expose the system-wide /run/pulse/native socket. +// Server returns PulseAudio protocol addresses in connection order. The bundled +// PipeWire helper exposes /tmp/pulse.sock for console clients; system-wide +// PulseAudio services can expose /run/pulse/native. // The client library tries each address, including after authentication errors. func Server(explicit, sudoUID string) string { if explicit != "" { @@ -99,7 +100,7 @@ func Server(explicit, sudoUID string) string { } else if runtimeDir == "" { runtimeDir = fmt.Sprintf("/run/user/%d", os.Getuid()) } - return "unix:" + filepath.Join(runtimeDir, "pulse/native") + " unix:/run/pulse/native" + return "unix:" + filepath.Join(runtimeDir, "pulse/native") + " unix:/tmp/pulse.sock unix:/run/pulse/native" } // Play only replaces a mailbox pointer. Startup has its own slot so initial diff --git a/internal/sound/service_test.go b/internal/sound/service_test.go index 3f22880a..f4a89124 100644 --- a/internal/sound/service_test.go +++ b/internal/sound/service_test.go @@ -270,11 +270,11 @@ func TestSoundServerFollowsExplicitAndSudoSession(t *testing.T) { if got := Server("unix:/tmp/example-pulse", "1000"); got != "unix:/tmp/example-pulse" { t.Fatal(got) } - if got := Server("", "1000"); got != "unix:/run/user/1000/pulse/native unix:/run/pulse/native" { + if got := Server("", "1000"); got != "unix:/run/user/1000/pulse/native unix:/tmp/pulse.sock unix:/run/pulse/native" { t.Fatal(got) } for _, uid := range []string{"", "invalid", "../other"} { - if got := Server("", uid); got != "unix:/run/user/2000/pulse/native unix:/run/pulse/native" { + if got := Server("", uid); got != "unix:/run/user/2000/pulse/native unix:/tmp/pulse.sock unix:/run/pulse/native" { t.Fatal(got) } } @@ -282,7 +282,7 @@ func TestSoundServerFollowsExplicitAndSudoSession(t *testing.T) { func TestSoundServerWithoutRuntimeDirectoryUsesCurrentUserAndSystemFallback(t *testing.T) { t.Setenv("XDG_RUNTIME_DIR", "") - want := fmt.Sprintf("unix:/run/user/%d/pulse/native unix:/run/pulse/native", os.Getuid()) + want := fmt.Sprintf("unix:/run/user/%d/pulse/native unix:/tmp/pulse.sock unix:/run/pulse/native", os.Getuid()) if got := Server("", ""); got != want { t.Fatalf("Server() = %q, want %q", got, want) }