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