Attempt to improve over all voice code.

This commit is contained in:
Storm Dragon
2026-08-11 19:47:01 -04:00
parent 30a02eba14
commit eae1d8b99a
17 changed files with 1198 additions and 130 deletions
+107 -3
View File
@@ -78,6 +78,7 @@ func (b *Barnard) OnConnect(e *gumble.ConnectEvent) {
// Reset muted channels state on connect
b.MutedChannels = make(map[uint32]bool)
b.userChannels = make(map[uint32]*gumble.Channel)
b.userAudioStates = make(map[uint32]userAudioState)
b.RecordingMutex.Lock()
b.recordingAllowed = nil
b.recordingStarting = false
@@ -90,6 +91,7 @@ func (b *Barnard) OnConnect(e *gumble.ConnectEvent) {
for _, u := range b.Client.Users {
b.UserConfig.UpdateUser(u)
b.rememberUserChannel(u)
b.rememberUserAudioState(u)
}
b.UpdateInputStatus(fmt.Sprintf("[%s]", e.Client.Self.Channel.Name))
@@ -119,6 +121,17 @@ func (b *Barnard) OnDisconnect(e *gumble.DisconnectEvent) {
reason = e.String
}
b.stopRecordingForDisconnect()
b.FileStreamMutex.Lock()
fileStream := b.FileStream
b.FileStream = nil
b.FileStreamMutex.Unlock()
if fileStream != nil && fileStream.IsPlaying() {
_ = fileStream.Stop()
}
if b.Stream != nil {
b.Stream.Destroy()
b.Stream = nil
}
b.Notify("disconnect", "me", reason)
if reason == "" {
b.AddOutputLine("Disconnected")
@@ -171,19 +184,30 @@ func (b *Barnard) OnTextMessage(e *gumble.TextMessageEvent) {
func (b *Barnard) OnUserChange(e *gumble.UserChangeEvent) {
notification, hasNotification := b.userChangeNotification(e)
audioNotification, hasAudioNotification := b.userAudioChangeNotification(e)
if e.User != nil {
previousLocalMute, previousLocalMuteGeneration := e.User.LocalMuteState()
previousVolume := e.User.Volume
b.UserConfig.UpdateUser(e.User)
localMute, localMuteGeneration := e.User.LocalMuteState()
if b.Stream != nil {
if localMute != previousLocalMute || localMuteGeneration != previousLocalMuteGeneration {
b.Stream.SetUserMuteState(e.User)
} else if e.User.Volume != previousVolume {
b.Stream.SetUserGain(e.User, e.User.Volume)
}
}
// Check if user is joining a muted channel
if e.Type.Has(gumble.UserChangeConnected) || e.Type.Has(gumble.UserChangeChannel) {
// If the channel is muted, ensure the user is muted
if b.MutedChannels[e.User.Channel.ID] {
// Only mute if not already muted
if !e.User.LocallyMuted {
if !e.User.IsLocallyMuted() {
b.UserConfig.ToggleMute(e.User)
}
if e.User.AudioSource != nil {
e.User.AudioSource.SetGain(0)
if b.Stream != nil {
b.Stream.SetUserMuteState(e.User)
}
}
}
@@ -198,6 +222,10 @@ func (b *Barnard) OnUserChange(e *gumble.UserChangeEvent) {
b.Notify(notification.event, notification.who, notification.what)
b.AddOutputLine(notification.line)
}
if hasAudioNotification {
b.Notify(audioNotification.event, audioNotification.who, audioNotification.what)
b.AddOutputLine(audioNotification.line)
}
if e.Type.Has(gumble.UserChangeChannel) && e.User == b.Client.Self {
b.UpdateInputStatus(fmt.Sprintf("[%s]", e.User.Channel.Name))
}
@@ -215,6 +243,7 @@ func (b *Barnard) OnUserChange(e *gumble.UserChangeEvent) {
b.AddOutputLine(formatUserStats(e.User))
}
b.updateUserChannel(e)
b.updateUserAudioState(e)
b.RebuildUserChannelTreePreservingSelection()
b.Ui.Refresh()
}
@@ -226,6 +255,11 @@ type userChangeNotification struct {
line string
}
type userAudioState struct {
selfMuted bool
selfDeafened bool
}
func (b *Barnard) userChangeNotification(e *gumble.UserChangeEvent) (userChangeNotification, bool) {
if e == nil || e.User == nil || b.Client == nil || b.Client.Self == nil || b.Client.Self.Channel == nil {
return userChangeNotification{}, false
@@ -256,6 +290,52 @@ func (b *Barnard) userChangeNotification(e *gumble.UserChangeEvent) (userChangeN
return userChangeNotification{}, false
}
func (b *Barnard) userAudioChangeNotification(e *gumble.UserChangeEvent) (userChangeNotification, bool) {
if e == nil || e.User == nil || !e.Type.Has(gumble.UserChangeAudio) || b.Client == nil || b.Client.Self == nil || b.Client.Self.Channel == nil {
return userChangeNotification{}, false
}
previous, known := b.userAudioStates[e.User.Session]
if !known || !sameChannel(e.User.Channel, b.Client.Self.Channel) {
return userChangeNotification{}, false
}
event := ""
verb := ""
if previous.selfDeafened != e.User.SelfDeafened {
if e.User.SelfDeafened {
event = "deafen"
verb = "deafened"
} else {
event = "undeafen"
verb = "undeafened"
}
} else if previous.selfMuted != e.User.SelfMuted {
if e.User.SelfMuted {
event = "mute"
verb = "muted"
} else {
event = "unmute"
verb = "unmuted"
}
}
if event == "" {
return userChangeNotification{}, false
}
who := e.User.Name
line := fmt.Sprintf("%s %s themselves", e.User.Name, verb)
if e.User.Session == b.Client.Self.Session {
who = "me"
line = fmt.Sprintf("You %s yourself", verb)
}
return userChangeNotification{
event: event,
who: who,
what: e.User.Channel.Name,
line: line,
}, true
}
func buildUserChangeNotification(event string, verb string, user *gumble.User, eventChannel *gumble.Channel, currentChannel *gumble.Channel) (userChangeNotification, bool) {
if !sameChannel(eventChannel, currentChannel) {
return userChangeNotification{}, false
@@ -302,6 +382,30 @@ func (b *Barnard) updateUserChannel(e *gumble.UserChangeEvent) {
b.rememberUserChannel(e.User)
}
func (b *Barnard) rememberUserAudioState(user *gumble.User) {
if user == nil {
return
}
if b.userAudioStates == nil {
b.userAudioStates = make(map[uint32]userAudioState)
}
b.userAudioStates[user.Session] = userAudioState{
selfMuted: user.SelfMuted,
selfDeafened: user.SelfDeafened,
}
}
func (b *Barnard) updateUserAudioState(e *gumble.UserChangeEvent) {
if e == nil || e.User == nil {
return
}
if e.Type.Has(gumble.UserChangeDisconnected) {
delete(b.userAudioStates, e.User.Session)
return
}
b.rememberUserAudioState(e.User)
}
func (b *Barnard) OnChannelChange(e *gumble.ChannelChangeEvent) {
b.UpdateInputStatus(fmt.Sprintf("[%s]", e.Channel.Name))
if e.Type.Has(gumble.ChannelChangeDescription) {