Harden UDP audio transport and logging

This commit is contained in:
Brandon McGinty (chatgpt)
2026-08-09 13:14:48 -04:00
committed by Brandon McGinty
parent 64d0ef6f0f
commit 7d7d59649b
11 changed files with 348 additions and 207 deletions
+29 -10
View File
@@ -1,6 +1,7 @@
package fileplayback
import (
"context"
"encoding/binary"
"errors"
"io"
@@ -18,6 +19,8 @@ type Player struct {
filename string
audioChan chan gumble.AudioBuffer
stopChan chan struct{}
ctx context.Context
cancel context.CancelFunc
mutex sync.Mutex
playing bool
errorFunc func(error)
@@ -73,6 +76,7 @@ func (p *Player) PlayFile(filename string) error {
// Start the file reading goroutine
p.playing = true
p.stopChan = make(chan struct{})
p.ctx, p.cancel = context.WithCancel(context.Background())
go p.readFileAudio()
return nil
@@ -88,17 +92,23 @@ func (p *Player) Stop() error {
}
close(p.stopChan)
if p.cancel != nil {
p.cancel()
p.cancel = nil
}
p.playing = false
localPlayback := p.localPlayback
p.mutex.Unlock()
if p.localPlayback != nil {
p.localPlayback(nil)
if localPlayback != nil {
localPlayback(nil)
}
// Drain the audio channel
// Drain the audio channel.
for len(p.audioChan) > 0 {
<-p.audioChan
}
p.mutex.Lock()
return nil
}
@@ -138,7 +148,10 @@ func (p *Player) readFileAudio() {
args := []string{"-loglevel", "error", "-i", p.filename}
args = append(args, "-ac", "2", "-ar", strconv.Itoa(gumble.AudioSampleRate), "-f", "s16le", "-")
cmd := exec.Command("ffmpeg", args...)
p.mutex.Lock()
ctx := p.ctx
p.mutex.Unlock()
cmd := exec.CommandContext(ctx, "ffmpeg", args...)
pipe, err := cmd.StdoutPipe()
if err != nil {
p.mutex.Lock()
@@ -171,15 +184,21 @@ func (p *Player) readFileAudio() {
case <-ticker.C:
n, err := io.ReadFull(pipe, byteBuffer)
if err != nil || n != len(byteBuffer) {
// File finished playing
select {
case <-p.stopChan:
cmd.Wait()
return
default:
}
// File finished playing.
p.mutex.Lock()
p.playing = false
if p.localPlayback != nil {
p.localPlayback(nil)
}
localPlayback := p.localPlayback
p.mutex.Unlock()
if localPlayback != nil {
localPlayback(nil)
}
cmd.Wait()
// Notify that file finished
p.reportError(errors.New("file playback finished"))
return
}