Added mute option. It can work per user or per channel, so covers deafen functionality too.
This commit is contained in:
parent
46d0cbf8f5
commit
a5c0e7a71c
@ -8,6 +8,7 @@ type Hotkeys struct {
|
|||||||
Talk *uiterm.Key
|
Talk *uiterm.Key
|
||||||
VolumeDown *uiterm.Key
|
VolumeDown *uiterm.Key
|
||||||
VolumeUp *uiterm.Key
|
VolumeUp *uiterm.Key
|
||||||
|
MuteToggle *uiterm.Key
|
||||||
Exit *uiterm.Key
|
Exit *uiterm.Key
|
||||||
ToggleTimestamps *uiterm.Key
|
ToggleTimestamps *uiterm.Key
|
||||||
SwitchViews *uiterm.Key
|
SwitchViews *uiterm.Key
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"git.2mb.codes/~cmb/barnard/uiterm"
|
"git.2mb.codes/~cmb/barnard/uiterm"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
// "encoding/yaml"
|
|
||||||
"git.2mb.codes/~cmb/barnard/gumble/gumble"
|
"git.2mb.codes/~cmb/barnard/gumble/gumble"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
@ -39,6 +38,7 @@ type eUser struct {
|
|||||||
Username string
|
Username string
|
||||||
Boost uint16
|
Boost uint16
|
||||||
Volume float32
|
Volume float32
|
||||||
|
LocallyMuted bool // Changed from Muted to LocallyMuted to match User struct
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) SaveConfig() {
|
func (c *Config) SaveConfig() {
|
||||||
@ -68,6 +68,7 @@ func (c *Config) LoadConfig() {
|
|||||||
Talk: key(uiterm.KeyF1),
|
Talk: key(uiterm.KeyF1),
|
||||||
VolumeDown: key(uiterm.KeyF5),
|
VolumeDown: key(uiterm.KeyF5),
|
||||||
VolumeUp: key(uiterm.KeyF6),
|
VolumeUp: key(uiterm.KeyF6),
|
||||||
|
MuteToggle: key(uiterm.KeyF7), // Added mute toggle hotkey
|
||||||
Exit: key(uiterm.KeyF10),
|
Exit: key(uiterm.KeyF10),
|
||||||
ToggleTimestamps: key(uiterm.KeyF3),
|
ToggleTimestamps: key(uiterm.KeyF3),
|
||||||
SwitchViews: key(uiterm.KeyTab),
|
SwitchViews: key(uiterm.KeyTab),
|
||||||
@ -82,9 +83,9 @@ func (c *Config) LoadConfig() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Error parsing \"%s\".\n%s\n", c.fn, err.Error())
|
fmt.Fprintf(os.Stderr, "Error parsing \"%s\".\n%s\n", c.fn, err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
} //panic
|
}
|
||||||
} //if data
|
}
|
||||||
} //if exists
|
}
|
||||||
c.config = &jc
|
c.config = &jc
|
||||||
if c.config.MicVolume == nil {
|
if c.config.MicVolume == nil {
|
||||||
micvol := float32(1.0)
|
micvol := float32(1.0)
|
||||||
@ -152,12 +153,20 @@ func (c *Config) findUser(address string, username string) *eUser {
|
|||||||
Username: username,
|
Username: username,
|
||||||
Boost: uint16(1),
|
Boost: uint16(1),
|
||||||
Volume: 1.0,
|
Volume: 1.0,
|
||||||
|
LocallyMuted: false, // Initialize local mute state
|
||||||
}
|
}
|
||||||
s.Users = append(s.Users, t)
|
s.Users = append(s.Users, t)
|
||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Config) ToggleMute(u *gumble.User) {
|
||||||
|
j := c.findUser(u.GetClient().Config.Address, u.Name)
|
||||||
|
j.LocallyMuted = !j.LocallyMuted
|
||||||
|
u.LocallyMuted = j.LocallyMuted
|
||||||
|
c.SaveConfig()
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Config) SetMicVolume(v float32) {
|
func (c *Config) SetMicVolume(v float32) {
|
||||||
t := float32(v)
|
t := float32(v)
|
||||||
c.config.MicVolume = &t
|
c.config.MicVolume = &t
|
||||||
@ -195,6 +204,7 @@ func (c *Config) UpdateUser(u *gumble.User) {
|
|||||||
j = c.findUser(uc.Config.Address, u.Name)
|
j = c.findUser(uc.Config.Address, u.Name)
|
||||||
u.Boost = j.Boost
|
u.Boost = j.Boost
|
||||||
u.Volume = j.Volume
|
u.Volume = j.Volume
|
||||||
|
u.LocallyMuted = j.LocallyMuted // Update LocallyMuted state from config
|
||||||
if u.Boost < 1 {
|
if u.Boost < 1 {
|
||||||
u.Boost = 1
|
u.Boost = 1
|
||||||
}
|
}
|
||||||
@ -206,6 +216,7 @@ func (c *Config) UpdateConfig(u *gumble.User) {
|
|||||||
j = c.findUser(u.GetClient().Config.Address, u.Name)
|
j = c.findUser(u.GetClient().Config.Address, u.Name)
|
||||||
j.Boost = u.Boost
|
j.Boost = u.Boost
|
||||||
j.Volume = u.Volume
|
j.Volume = u.Volume
|
||||||
|
j.LocallyMuted = u.LocallyMuted // Save LocallyMuted state to config
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConfig(fn *string) *Config {
|
func NewConfig(fn *string) *Config {
|
||||||
@ -267,7 +278,6 @@ func Log(s string) {
|
|||||||
|
|
||||||
func log(s string) {
|
func log(s string) {
|
||||||
s += "\n"
|
s += "\n"
|
||||||
// If the file doesn't exist, create it, or append to the file
|
|
||||||
f, err := os.OpenFile("log.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
f, err := os.OpenFile("log.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -31,6 +31,8 @@ type User struct {
|
|||||||
PrioritySpeaker bool
|
PrioritySpeaker bool
|
||||||
// Is the user recording audio?
|
// Is the user recording audio?
|
||||||
Recording bool
|
Recording bool
|
||||||
|
// Has the user been locally muted by the client?
|
||||||
|
LocallyMuted bool
|
||||||
|
|
||||||
// The user's comment. Contains the empty string if the user does not have a
|
// The user's comment. Contains the empty string if the user does not have a
|
||||||
// comment, or if the comment needs to be requested.
|
// comment, or if the comment needs to be requested.
|
||||||
@ -56,6 +58,11 @@ type User struct {
|
|||||||
Volume float32
|
Volume float32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsMuted returns true if the user is muted either server-side or locally
|
||||||
|
func (u *User) IsMuted() bool {
|
||||||
|
return u.Muted || u.LocallyMuted
|
||||||
|
}
|
||||||
|
|
||||||
func (u *User) GetClient() *Client {
|
func (u *User) GetClient() *Client {
|
||||||
return u.client
|
return u.client
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,13 @@ func (s *Stream) OnAudioStream(e *gumble.AudioStreamEvent) {
|
|||||||
go func(e *gumble.AudioStreamEvent) {
|
go func(e *gumble.AudioStreamEvent) {
|
||||||
var source = openal.NewSource()
|
var source = openal.NewSource()
|
||||||
e.User.AudioSource = &source
|
e.User.AudioSource = &source
|
||||||
|
|
||||||
|
// Set initial gain based on volume and mute state
|
||||||
|
if e.User.LocallyMuted {
|
||||||
|
e.User.AudioSource.SetGain(0)
|
||||||
|
} else {
|
||||||
e.User.AudioSource.SetGain(e.User.Volume)
|
e.User.AudioSource.SetGain(e.User.Volume)
|
||||||
|
}
|
||||||
|
|
||||||
bufferCount := e.Client.Config.Buffers
|
bufferCount := e.Client.Config.Buffers
|
||||||
if bufferCount < 64 {
|
if bufferCount < 64 {
|
||||||
@ -183,6 +189,11 @@ func (s *Stream) OnAudioStream(e *gumble.AudioStreamEvent) {
|
|||||||
var raw [maxBufferSize]byte
|
var raw [maxBufferSize]byte
|
||||||
|
|
||||||
for packet := range e.C {
|
for packet := range e.C {
|
||||||
|
// Skip processing if user is locally muted
|
||||||
|
if e.User.LocallyMuted {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
var boost uint16 = uint16(1)
|
var boost uint16 = uint16(1)
|
||||||
samples := len(packet.AudioBuffer)
|
samples := len(packet.AudioBuffer)
|
||||||
if samples > cap(raw)/2 {
|
if samples > cap(raw)/2 {
|
||||||
@ -192,17 +203,13 @@ func (s *Stream) OnAudioStream(e *gumble.AudioStreamEvent) {
|
|||||||
boost = e.User.Boost
|
boost = e.User.Boost
|
||||||
|
|
||||||
// Check if sample count suggests stereo data
|
// Check if sample count suggests stereo data
|
||||||
// If it's not a multiple of 2, it must be mono
|
|
||||||
// If it's more than standard frameSize, it's likely stereo
|
|
||||||
isStereo := samples > gumble.AudioDefaultFrameSize && samples%2 == 0
|
isStereo := samples > gumble.AudioDefaultFrameSize && samples%2 == 0
|
||||||
format := openal.FormatMono16
|
format := openal.FormatMono16
|
||||||
if isStereo {
|
if isStereo {
|
||||||
format = openal.FormatStereo16
|
format = openal.FormatStereo16
|
||||||
// Adjust samples to represent stereo frame count
|
|
||||||
samples = samples / 2
|
samples = samples / 2
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process samples
|
|
||||||
rawPtr := 0
|
rawPtr := 0
|
||||||
if isStereo {
|
if isStereo {
|
||||||
// Process stereo samples as pairs
|
// Process stereo samples as pairs
|
||||||
@ -244,7 +251,6 @@ func (s *Stream) OnAudioStream(e *gumble.AudioStreamEvent) {
|
|||||||
buffer := emptyBufs[last]
|
buffer := emptyBufs[last]
|
||||||
emptyBufs = emptyBufs[:last]
|
emptyBufs = emptyBufs[:last]
|
||||||
|
|
||||||
// Set buffer data with correct format
|
|
||||||
buffer.SetData(format, raw[:rawPtr], gumble.AudioSampleRate)
|
buffer.SetData(format, raw[:rawPtr], gumble.AudioSampleRate)
|
||||||
source.QueueBuffer(buffer)
|
source.QueueBuffer(buffer)
|
||||||
|
|
||||||
|
66
ui_tree.go
66
ui_tree.go
@ -1,8 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
//"math"
|
|
||||||
// "fmt"
|
|
||||||
"git.2mb.codes/~cmb/barnard/gumble/gumble"
|
"git.2mb.codes/~cmb/barnard/gumble/gumble"
|
||||||
"git.2mb.codes/~cmb/barnard/uiterm"
|
"git.2mb.codes/~cmb/barnard/uiterm"
|
||||||
"sort"
|
"sort"
|
||||||
@ -15,6 +13,9 @@ type TreeItem struct {
|
|||||||
|
|
||||||
func (ti TreeItem) String() string {
|
func (ti TreeItem) String() string {
|
||||||
if ti.User != nil {
|
if ti.User != nil {
|
||||||
|
if ti.User.LocallyMuted {
|
||||||
|
return "[MUTED] " + ti.User.Name
|
||||||
|
}
|
||||||
return ti.User.Name
|
return ti.User.Name
|
||||||
}
|
}
|
||||||
if ti.Channel != nil {
|
if ti.Channel != nil {
|
||||||
@ -50,11 +51,7 @@ func (b *Barnard) changeVolume(users []*gumble.User, change float32) {
|
|||||||
cv = au.GetGain() + curboost
|
cv = au.GetGain() + curboost
|
||||||
ng = cv + change
|
ng = cv + change
|
||||||
boost = uint16(1)
|
boost = uint16(1)
|
||||||
//b.AddOutputLine(fmt.Sprintf("cv %.2f change %.2f ng %.2f",cv,change,ng))
|
|
||||||
if ng > 1.0 {
|
if ng > 1.0 {
|
||||||
//1.0 will give volume of one and boost of 1
|
|
||||||
//1.1 will give volume of 1 and boost of 2
|
|
||||||
//b.AddOutputLine(fmt.Sprintf("partperc %.2f",(ng*10)))
|
|
||||||
perc := uint16((ng * 10)) - 10
|
perc := uint16((ng * 10)) - 10
|
||||||
perc += 1
|
perc += 1
|
||||||
boost = perc
|
boost = perc
|
||||||
@ -63,10 +60,11 @@ func (b *Barnard) changeVolume(users []*gumble.User, change float32) {
|
|||||||
if ng < 0 {
|
if ng < 0 {
|
||||||
ng = 0.0
|
ng = 0.0
|
||||||
}
|
}
|
||||||
//b.AddOutputLine(fmt.Sprintf("boost %d ng %.2f",boost,ng))
|
|
||||||
u.Boost = boost
|
u.Boost = boost
|
||||||
u.Volume = ng
|
u.Volume = ng
|
||||||
|
if !u.LocallyMuted {
|
||||||
au.SetGain(ng)
|
au.SetGain(ng)
|
||||||
|
}
|
||||||
b.UserConfig.UpdateConfig(u)
|
b.UserConfig.UpdateConfig(u)
|
||||||
}
|
}
|
||||||
b.UserConfig.SaveConfig()
|
b.UserConfig.SaveConfig()
|
||||||
@ -95,28 +93,58 @@ func (b *Barnard) TreeItemKeyPress(ui *uiterm.Ui, tree *uiterm.Tree, item uiterm
|
|||||||
} else {
|
} else {
|
||||||
b.SetSelectedUser(treeItem.User)
|
b.SetSelectedUser(treeItem.User)
|
||||||
b.GotoChat()
|
b.GotoChat()
|
||||||
} //select
|
}
|
||||||
} //if user and not selected
|
}
|
||||||
} //if enter key
|
}
|
||||||
|
|
||||||
|
// Handle mute toggle
|
||||||
if treeItem.Channel != nil {
|
if treeItem.Channel != nil {
|
||||||
var c = treeItem.Channel
|
if key == *b.Hotkeys.MuteToggle {
|
||||||
|
// Toggle mute for all users in channel
|
||||||
|
users := makeUsersArray(treeItem.Channel.Users)
|
||||||
|
for _, u := range users {
|
||||||
|
b.UserConfig.ToggleMute(u)
|
||||||
|
if u.AudioSource != nil {
|
||||||
|
if u.LocallyMuted {
|
||||||
|
u.AudioSource.SetGain(0)
|
||||||
|
} else {
|
||||||
|
u.AudioSource.SetGain(u.Volume)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.UiTree.Rebuild()
|
||||||
|
b.Ui.Refresh()
|
||||||
|
}
|
||||||
if key == *b.Hotkeys.VolumeDown {
|
if key == *b.Hotkeys.VolumeDown {
|
||||||
b.changeVolume(makeUsersArray(c.Users), -0.1)
|
b.changeVolume(makeUsersArray(treeItem.Channel.Users), -0.1)
|
||||||
}
|
}
|
||||||
if key == *b.Hotkeys.VolumeUp {
|
if key == *b.Hotkeys.VolumeUp {
|
||||||
b.changeVolume(makeUsersArray(c.Users), 0.1)
|
b.changeVolume(makeUsersArray(treeItem.Channel.Users), 0.1)
|
||||||
}
|
}
|
||||||
} //set volume
|
}
|
||||||
|
|
||||||
if treeItem.User != nil {
|
if treeItem.User != nil {
|
||||||
var u = treeItem.User
|
if key == *b.Hotkeys.MuteToggle {
|
||||||
|
// Toggle mute for single user
|
||||||
|
b.UserConfig.ToggleMute(treeItem.User)
|
||||||
|
if treeItem.User.AudioSource != nil {
|
||||||
|
if treeItem.User.LocallyMuted {
|
||||||
|
treeItem.User.AudioSource.SetGain(0)
|
||||||
|
} else {
|
||||||
|
treeItem.User.AudioSource.SetGain(treeItem.User.Volume)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.UiTree.Rebuild()
|
||||||
|
b.Ui.Refresh()
|
||||||
|
}
|
||||||
if key == *b.Hotkeys.VolumeDown {
|
if key == *b.Hotkeys.VolumeDown {
|
||||||
b.changeVolume([]*gumble.User{u}, -0.1)
|
b.changeVolume([]*gumble.User{treeItem.User}, -0.1)
|
||||||
}
|
}
|
||||||
if key == *b.Hotkeys.VolumeUp {
|
if key == *b.Hotkeys.VolumeUp {
|
||||||
b.changeVolume([]*gumble.User{u}, 0.1)
|
b.changeVolume([]*gumble.User{treeItem.User}, 0.1)
|
||||||
}
|
}
|
||||||
} //user highlighted
|
}
|
||||||
} //func
|
}
|
||||||
|
|
||||||
func (b *Barnard) TreeItemBuild(item uiterm.TreeItem) []uiterm.TreeItem {
|
func (b *Barnard) TreeItemBuild(item uiterm.TreeItem) []uiterm.TreeItem {
|
||||||
if b.Client == nil {
|
if b.Client == nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user