From 4497d4107745be04f74a11e14ba77bc195f5e5c6 Mon Sep 17 00:00:00 2001 From: "Brandon McGinty (chatgpt)" Date: Sun, 9 Aug 2026 14:37:06 -0400 Subject: [PATCH] Persist microphone mute and volume settings --- client.go | 1 + config/user_config.go | 7 +++++++ config/user_config_test.go | 11 +++++++++++ fix.txt | 2 +- gumble/gumbleopenal/stream.go | 7 ++----- ui.go | 6 ++++++ 6 files changed, 28 insertions(+), 6 deletions(-) diff --git a/client.go b/client.go index a31c197..429fec9 100644 --- a/client.go +++ b/client.go @@ -80,6 +80,7 @@ func (b *Barnard) connect(reconnect bool) bool { return false } b.Stream = stream + b.Stream.SetMicVolume(b.UserConfig.GetMicVolume(), false) b.Stream.AttachStream(b.Client) b.Stream.SetNoiseProcessor(b.NoiseSuppressor) b.Stream.SetErrorFunc(func(err error) { diff --git a/config/user_config.go b/config/user_config.go index 460cecd..c280cd8 100644 --- a/config/user_config.go +++ b/config/user_config.go @@ -265,6 +265,13 @@ func (c *Config) SetMicVolume(v float32) { c.config.MicVolume = &t } +func (c *Config) GetMicVolume() float32 { + if c.config.MicVolume == nil { + return 1.0 + } + return *c.config.MicVolume +} + func (c *Config) GetHotkeys() *Hotkeys { return c.config.Hotkeys } diff --git a/config/user_config_test.go b/config/user_config_test.go index 6f3123b..514df37 100644 --- a/config/user_config_test.go +++ b/config/user_config_test.go @@ -50,6 +50,17 @@ func TestMakeHostPortHandlesIPv6AndMalformedAddress(t *testing.T) { } } +// Regression: a stored zero mic volume was treated as an uninitialized value, +// so a persisted mute became full volume after reconnecting. +func TestMicVolumeAllowsPersistedMute(t *testing.T) { + path := filepath.Join(t.TempDir(), "barnard.toml") + cfg := NewConfig(&path) + cfg.SetMicVolume(0) + if got := cfg.GetMicVolume(); got != 0 { + t.Fatalf("got %v, want mute", got) + } +} + func TestConfigUsesHomeEnvironmentForDefaultPath(t *testing.T) { dir := t.TempDir() t.Setenv("HOME", dir) diff --git a/fix.txt b/fix.txt index b1bd1d3..938dd31 100644 --- a/fix.txt +++ b/fix.txt @@ -203,7 +203,7 @@ Priority 2: protocol and data correctness Priority 3: configuration, UI, and binding hardening ------------------------------------------------------ -26. Persisted microphone volume is unused and zero is impossible +[x] 26. Persisted microphone volume is unused and zero is impossible Files: config/user_config.go, ui.go, gumble/gumbleopenal/stream.go MicVolume is stored but never applied when a Stream is created; UI changes do not call SaveConfig. GetMicVolume treats stored zero bits as diff --git a/gumble/gumbleopenal/stream.go b/gumble/gumbleopenal/stream.go index 46697db..ae6cac9 100644 --- a/gumble/gumbleopenal/stream.go +++ b/gumble/gumbleopenal/stream.go @@ -131,6 +131,7 @@ func New(client *gumble.Client, inputDevice *string, outputDevice *string, test sourceFrameSize: frmsz, micAGC: audio.NewAGC(), // Always enable AGC for outgoing mic } + s.micVolume.Store(math.Float32bits(1.0)) if sourceChannels == 2 { s.micAGCRight = audio.NewAGC() } @@ -331,11 +332,7 @@ func (s *Stream) StopSource() error { } func (s *Stream) GetMicVolume() float32 { - bits := s.micVolume.Load() - if bits == 0 { - return 1.0 // default on first access - } - return math.Float32frombits(bits) + return math.Float32frombits(s.micVolume.Load()) } func (s *Stream) SetMicVolume(change float32, relative bool) { diff --git a/ui.go b/ui.go index fe1f48b..1bb7b49 100644 --- a/ui.go +++ b/ui.go @@ -315,6 +315,9 @@ func (b *Barnard) OnMicVolumeDown(ui *uiterm.Ui, key uiterm.Key) { } b.Stream.SetMicVolume(-0.1, true) b.UserConfig.SetMicVolume(b.Stream.GetMicVolume()) + if err := b.UserConfig.SaveConfig(); err != nil { + b.AddOutputLine("Microphone: could not save volume: " + err.Error()) + } } func (b *Barnard) OnMicVolumeUp(ui *uiterm.Ui, key uiterm.Key) { @@ -323,6 +326,9 @@ func (b *Barnard) OnMicVolumeUp(ui *uiterm.Ui, key uiterm.Key) { } b.Stream.SetMicVolume(0.1, true) b.UserConfig.SetMicVolume(b.Stream.GetMicVolume()) + if err := b.UserConfig.SaveConfig(); err != nil { + b.AddOutputLine("Microphone: could not save volume: " + err.Error()) + } } func (b *Barnard) OnQuitPress(ui *uiterm.Ui, key uiterm.Key) {