audio: Simplify error handling

This commit is contained in:
Hajime Hoshi 2017-12-23 04:12:12 +09:00
parent a21571fb57
commit 3addbfce8a

View File

@ -74,13 +74,9 @@ func (p *players) Read(b []byte) (int, error) {
l := len(b) l := len(b)
for player := range p.players { for player := range p.players {
select { if err := player.getReadErr(); err != nil {
case err := <-player.readCh:
if err != nil {
return 0, err return 0, err
} }
default:
}
} }
l &= mask l &= mask
@ -335,12 +331,13 @@ type Player struct {
src ReadSeekCloser src ReadSeekCloser
srcEOF bool srcEOF bool
sampleRate int sampleRate int
reading bool
readErr error
buf []byte buf []byte
pos int64 pos int64
volume float64 volume float64
readCh chan error
closeCh chan struct{} closeCh chan struct{}
closedCh chan struct{} closedCh chan struct{}
@ -450,17 +447,15 @@ func (p *Player) Play() error {
func (p *Player) startRead() { func (p *Player) startRead() {
p.m.Lock() p.m.Lock()
if p.readCh == nil { if !p.reading && p.readErr == nil {
p.readCh = make(chan error) p.reading = true
p.closeCh = make(chan struct{}) p.closeCh = make(chan struct{})
p.closedCh = make(chan struct{}) p.closedCh = make(chan struct{})
p.srcEOF = false p.srcEOF = false
go func() { go func() {
if err := p.readLoop(); err != nil { p.readLoop()
p.readCh <- err
}
p.m.Lock() p.m.Lock()
p.readCh = nil p.reading = false
p.m.Unlock() p.m.Unlock()
close(p.closedCh) close(p.closedCh)
}() }()
@ -468,13 +463,13 @@ func (p *Player) startRead() {
p.m.Unlock() p.m.Unlock()
} }
func (p *Player) readLoop() error { func (p *Player) readLoop() {
t := time.Tick(1 * time.Millisecond) t := time.Tick(1 * time.Millisecond)
for { for {
select { select {
case <-p.closeCh: case <-p.closeCh:
p.closeCh = nil p.closeCh = nil
return nil return
case <-t: case <-t:
p.m.Lock() p.m.Lock()
if len(p.buf) < 4096*16 && !p.srcEOF { if len(p.buf) < 4096*16 && !p.srcEOF {
@ -486,11 +481,12 @@ func (p *Player) readLoop() error {
} }
if p.srcEOF && len(p.buf) == 0 { if p.srcEOF && len(p.buf) == 0 {
p.m.Unlock() p.m.Unlock()
return nil return
} }
if err != nil && err != io.EOF { if err != nil && err != io.EOF {
p.readErr = err
p.m.Unlock() p.m.Unlock()
return err return
} }
} }
p.m.Unlock() p.m.Unlock()
@ -499,12 +495,19 @@ func (p *Player) readLoop() error {
} }
func (p *Player) eof() bool { func (p *Player) eof() bool {
p.m.Lock() p.m.RLock()
r := p.srcEOF && len(p.buf) == 0 r := p.srcEOF && len(p.buf) == 0
p.m.Unlock() p.m.RUnlock()
return r return r
} }
func (p *Player) getReadErr() error {
p.m.RLock()
e := p.readErr
p.m.RUnlock()
return e
}
// IsPlaying returns boolean indicating whether the player is playing. // IsPlaying returns boolean indicating whether the player is playing.
func (p *Player) IsPlaying() bool { func (p *Player) IsPlaying() bool {
return p.players.hasPlayer(p) return p.players.hasPlayer(p)