Implement per-user audio control (vol/mute) and User View UI

This commit is contained in:
Jose Luis Montañes Ojados
2026-01-17 00:19:49 +01:00
parent 0b6399ed61
commit 5b8e89e9a2
2 changed files with 321 additions and 132 deletions

View File

@@ -26,7 +26,15 @@ type Player struct {
// User buffers for mixing
// map[SenderID] -> AudioQueue
userBuffers map[uint16][]int16
bufferMu sync.Mutex
// User settings
userSettings map[uint16]*UserSettings
bufferMu sync.Mutex
}
type UserSettings struct {
Volume float32 // 0.0 - 1.0 (or higher for boost)
Muted bool
}
const (
@@ -105,6 +113,7 @@ func NewPlayer() (*Player, error) {
muted: false,
stopChan: make(chan struct{}),
userBuffers: make(map[uint16][]int16),
userSettings: make(map[uint16]*UserSettings),
}, nil
}
@@ -162,6 +171,11 @@ func (p *Player) PlayPCM(senderID uint16, samples []int16) {
p.bufferMu.Lock()
defer p.bufferMu.Unlock()
// Check per-user mute
if settings, ok := p.userSettings[senderID]; ok && settings.Muted {
return
}
// Append to user's specific buffer
// This ensures sequential playback for the same user
p.userBuffers[senderID] = append(p.userBuffers[senderID], samples...)
@@ -201,13 +215,45 @@ func (p *Player) SetMuted(muted bool) {
p.mu.Unlock()
}
// IsMuted returns mute state
func (p *Player) IsMuted() bool {
p.mu.Lock()
defer p.mu.Unlock()
return p.muted
}
// SetUserVolume sets volume for a specific user (1.0 is default)
func (p *Player) SetUserVolume(clientID uint16, vol float32) {
p.bufferMu.Lock()
defer p.bufferMu.Unlock()
if _, ok := p.userSettings[clientID]; !ok {
p.userSettings[clientID] = &UserSettings{Volume: 1.0, Muted: false}
}
p.userSettings[clientID].Volume = vol
}
// SetUserMuted sets mute state for a specific user
func (p *Player) SetUserMuted(clientID uint16, muted bool) {
p.bufferMu.Lock()
defer p.bufferMu.Unlock()
if _, ok := p.userSettings[clientID]; !ok {
p.userSettings[clientID] = &UserSettings{Volume: 1.0, Muted: false}
}
p.userSettings[clientID].Muted = muted
}
// GetUserSettings gets current volume and mute state for user
func (p *Player) GetUserSettings(clientID uint16) (float32, bool) {
p.bufferMu.Lock()
defer p.bufferMu.Unlock()
if settings, ok := p.userSettings[clientID]; ok {
return settings.Volume, settings.Muted
}
return 1.0, false
}
func (p *Player) playbackLoop() {
ticker := time.NewTicker(20 * time.Millisecond)
defer ticker.Stop()
@@ -249,7 +295,14 @@ func (p *Player) writeFrame() {
}
for i := 0; i < toTake; i++ {
mixed[i] += int32(buf[i])
sample := int32(buf[i])
// Apply user volume if set
if settings, ok := p.userSettings[id]; ok {
sample = int32(float32(sample) * settings.Volume)
}
mixed[i] += sample
}
// Advance buffer