Harden UDP audio transport and logging
This commit is contained in:
committed by
Brandon McGinty
parent
64d0ef6f0f
commit
7d7d59649b
+29
-10
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user