package main import ( "fmt" "net" "time" "git.stormux.org/storm/barnard/gumble/gumble" "git.stormux.org/storm/barnard/gumble/gumbleopenal" "git.stormux.org/storm/barnard/gumble/gumbleutil" ) func (b *Barnard) start() { b.Config.Attach(gumbleutil.AutoBitrate) b.Config.Attach(b) b.Config.Address = b.Address // test Audio _, err := gumbleopenal.New(b.Client, b.UserConfig.GetInputDevice(), b.UserConfig.GetOutputDevice(), true) if err != nil { b.exitWithError(err) return } //connect, not reconnect b.connect(false) } func (b *Barnard) exitWithError(err error) { b.Ui.Close() b.exitStatus = 1 b.exitMessage = err.Error() } func (b *Barnard) connect(reconnect bool) bool { var err error _, err = gumble.DialWithDialer(new(net.Dialer), b.Config, &b.TLSConfig) if err != nil { if reconnect { b.Log(err.Error()) } else { b.exitWithError(err) } return false } stream, err := gumbleopenal.New(b.Client, b.UserConfig.GetInputDevice(), b.UserConfig.GetOutputDevice(), false) if err != nil { b.exitWithError(err) return false } b.Stream = stream b.Stream.AttachStream(b.Client) b.Connected = true return true } func (b *Barnard) OnConnect(e *gumble.ConnectEvent) { b.Client = e.Client // Reset muted channels state on connect b.MutedChannels = make(map[uint32]bool) b.Ui.SetActive(uiViewInput) b.UiTree.Rebuild() b.Ui.Refresh() for _, u := range b.Client.Users { b.UserConfig.UpdateUser(u) } b.UpdateInputStatus(fmt.Sprintf("[%s]", e.Client.Self.Channel.Name)) b.AddOutputLine(fmt.Sprintf("Connected to %s", b.Client.Conn.RemoteAddr())) wmsg := "" if e.WelcomeMessage != nil { wmsg = esc(*e.WelcomeMessage) } b.Notify("connect", "me", wmsg) if wmsg != "" { b.AddOutputLine(fmt.Sprintf("Welcome message: %s", wmsg)) } b.Ui.Refresh() } func (b *Barnard) OnDisconnect(e *gumble.DisconnectEvent) { var reason string switch e.Type { case gumble.DisconnectError: reason = "connection error" } b.Notify("disconnect", "me", reason) if reason == "" { b.AddOutputLine("Disconnected") } else { b.AddOutputLine("Disconnected: " + reason) } b.Tx = false b.Connected = false b.UiTree.Rebuild() b.Ui.Refresh() go b.reconnectGoroutine() } func (b *Barnard) reconnectGoroutine() { for { res := b.connect(true) if res == true { break } time.Sleep(15 * time.Second) } } func (b *Barnard) Log(s string) { b.AddOutputMessage(nil, s) } func (b *Barnard) OnTextMessage(e *gumble.TextMessageEvent) { var public = false for _, c := range e.Channels { if c.Name == b.Client.Self.Channel.Name { public = true break } } if public { b.Notify("msg", e.Sender.Name, e.Message) b.AddOutputMessage(e.Sender, e.Message) } else { var sender string if e.Sender == nil { sender = "Server" } else { sender = e.Sender.Name } b.Notify("pm", sender, e.Message) b.AddOutputPrivateMessage(e.Sender, b.Client.Self, e.Message) } } func (b *Barnard) OnUserChange(e *gumble.UserChangeEvent) { if e.User != nil { b.UserConfig.UpdateUser(e.User) // Check if user is joining a muted channel if e.Type.Has(gumble.UserChangeConnected) || e.Type.Has(gumble.UserChangeChannel) { // If the channel is muted, mute the new user if b.MutedChannels[e.User.Channel.ID] { b.UserConfig.ToggleMute(e.User) if e.User.AudioSource != nil { e.User.AudioSource.SetGain(0) } } } } var s = "unknown" var t = "unknown" if e.Type.Has(gumble.UserChangeConnected) { s = "joined" t = "join" } if e.Type.Has(gumble.UserChangeDisconnected) { s = "left" t = "leave" if e.User == b.selectedUser { b.SetSelectedUser(nil) } } if e.User.Channel.Name == b.Client.Self.Channel.Name { b.Notify(t, e.User.Name, e.User.Channel.Name) b.AddOutputLine(fmt.Sprintf("%s %s %s", e.User.Name, s, e.User.Channel.Name)) } if e.Type.Has(gumble.UserChangeChannel) && e.User == b.Client.Self { b.UpdateInputStatus(fmt.Sprintf("[%s]", e.User.Channel.Name)) } b.UiTree.Rebuild() b.Ui.Refresh() } func (b *Barnard) OnChannelChange(e *gumble.ChannelChangeEvent) { b.UpdateInputStatus(fmt.Sprintf("[%s]", e.Channel.Name)) b.UiTree.Rebuild() b.Ui.Refresh() } func (b *Barnard) OnPermissionDenied(e *gumble.PermissionDeniedEvent) { var info string switch e.Type { case gumble.PermissionDeniedOther: info = e.String case gumble.PermissionDeniedPermission: info = "insufficient permissions" case gumble.PermissionDeniedSuperUser: info = "cannot modify SuperUser" case gumble.PermissionDeniedInvalidChannelName: info = "invalid channel name" case gumble.PermissionDeniedTextTooLong: info = "text too long" case gumble.PermissionDeniedTemporaryChannel: info = "temporary channel" case gumble.PermissionDeniedMissingCertificate: info = "missing certificate" case gumble.PermissionDeniedInvalidUserName: info = "invalid user name" case gumble.PermissionDeniedChannelFull: info = "channel full" case gumble.PermissionDeniedNestingLimit: info = "nesting limit" } b.AddOutputLine(fmt.Sprintf("Permission denied: %s", info)) } func (b *Barnard) OnUserList(e *gumble.UserListEvent) { //for _,u := range e.UserList { //b.UserConfig.UpdateUser(u) //} } func (b *Barnard) OnACL(e *gumble.ACLEvent) { } func (b *Barnard) OnBanList(e *gumble.BanListEvent) { } func (b *Barnard) OnContextActionChange(e *gumble.ContextActionChangeEvent) { } func (b *Barnard) OnServerConfig(e *gumble.ServerConfigEvent) { }