diff --git a/client.go b/client.go index 52e1cf9..8f9c65a 100644 --- a/client.go +++ b/client.go @@ -113,6 +113,9 @@ func (b *Barnard) connect(reconnect bool) bool { b.FileStreamMutex.Unlock() b.Connected = true + // Dial delivers OnConnect before connect creates the OpenAL stream, so + // start auto-transmit here as well for initial connections and reconnects. + b.startAutoTransmit() return true } @@ -156,17 +159,20 @@ func (b *Barnard) OnConnect(e *gumble.ConnectEvent) { b.AddOutputLine(fmt.Sprintf("Welcome message: %s", wmsg)) } - // Auto-start transmission if requested - if b.AutoTransmit && b.Stream != nil && !b.Tx { - err := b.Stream.StartSource(b.UserConfig.GetInputDevice()) - if err != nil { - b.AddOutputLine(fmt.Sprintf("auto-transmit failed: %s", err.Error())) - } else { - b.Tx = true - b.UpdateGeneralStatus(" AutoTx ", true) - b.AddOutputLine("Auto-transmit started") - } + b.startAutoTransmit() +} + +func (b *Barnard) startAutoTransmit() { + if !b.AutoTransmit || b.Stream == nil || b.Tx { + return } + if err := b.Stream.StartSource(b.UserConfig.GetInputDevice()); err != nil { + b.AddOutputLine(fmt.Sprintf("auto-transmit failed: %s", err.Error())) + return + } + b.Tx = true + b.UpdateGeneralStatus(" AutoTx ", true) + b.AddOutputLine("Auto-transmit started") } func (b *Barnard) OnDisconnect(e *gumble.DisconnectEvent) { @@ -232,7 +238,11 @@ func (b *Barnard) OnTextMessage(e *gumble.TextMessageEvent) { } } if public { - b.Notify("msg", e.Sender.Name, e.Message) + sender := "Server" + if e.Sender != nil { + sender = e.Sender.Name + } + b.Notify("msg", sender, e.Message) b.AddOutputMessage(e.Sender, e.Message) } else { var sender string diff --git a/client_notification_test.go b/client_notification_test.go index 86d2c37..28f7987 100644 --- a/client_notification_test.go +++ b/client_notification_test.go @@ -69,6 +69,28 @@ func TestNotificationExpansionIsSinglePassAndNotifyDoesNotBlock(t *testing.T) { } } +func TestPublicServerMessageDoesNotPanic(t *testing.T) { + channel := &gumble.Channel{ID: 1, Name: "Current"} + b := &Barnard{ + Client: &gumble.Client{Self: &gumble.User{Channel: channel}}, + notifyChannel: make(chan []string, 1), + } + + b.OnTextMessage(&gumble.TextMessageEvent{ + Client: b.Client, + TextMessage: gumble.TextMessage{ + Channels: []*gumble.Channel{channel}, + Message: "server announcement", + }, + }) + + got := <-b.notifyChannel + want := []string{"msg", "Server", "server announcement"} + if len(got) != len(want) || got[0] != want[0] || got[1] != want[1] || got[2] != want[2] { + t.Fatalf("notification = %#v, want %#v", got, want) + } +} + // Regression: reconnect replaced Stream without destroying the old capture // and renderer resources. Cleanup must be safe for repeated disconnects. // Regression: user and channel names in the navigation tree bypassed message