audio/internal/readerdriver: Bug fix: Protect playImpl by the mutex on Darwin

This commit is contained in:
Hajime Hoshi 2021-05-16 20:07:51 +09:00
parent 58c1ed0e23
commit cf6edae5b3

View File

@ -199,7 +199,6 @@ type playerImpl struct {
eof bool eof bool
cond *sync.Cond cond *sync.Cond
volume float64 volume float64
playCh chan struct{}
} }
type players struct { type players struct {
@ -308,24 +307,17 @@ func (p *player) Play() {
} }
func (p *playerImpl) Play() { func (p *playerImpl) Play() {
p.cond.L.Lock()
defer p.cond.L.Unlock()
if p.playCh != nil {
// Play is already called and the processing is not done yet.
// Do nothing and return.
return
}
// Call Play asynchronously since AudioQueuePrime and AudioQueuePlay might take long. // Call Play asynchronously since AudioQueuePrime and AudioQueuePlay might take long.
p.playCh = make(chan struct{}) ch := make(chan struct{})
go func() { go func() {
defer func() { p.cond.L.Lock()
close(p.playCh) defer p.cond.L.Unlock()
p.playCh = nil close(ch)
}()
p.playImpl() p.playImpl()
}() }()
// Wait until the mutex is locked in the above goroutine.
<-ch
} }
func (p *playerImpl) playImpl() { func (p *playerImpl) playImpl() {
@ -418,10 +410,6 @@ func (p *playerImpl) Pause() {
p.cond.L.Lock() p.cond.L.Lock()
defer p.cond.L.Unlock() defer p.cond.L.Unlock()
if ch := p.playCh; ch != nil {
<-ch
}
if p.err != nil { if p.err != nil {
return return
} }
@ -448,10 +436,6 @@ func (p *playerImpl) Reset() {
p.cond.L.Lock() p.cond.L.Lock()
defer p.cond.L.Unlock() defer p.cond.L.Unlock()
if ch := p.playCh; ch != nil {
<-ch
}
if p.err != nil { if p.err != nil {
return return
} }
@ -490,9 +474,6 @@ func (p *playerImpl) IsPlaying() bool {
p.cond.L.Lock() p.cond.L.Lock()
defer p.cond.L.Unlock() defer p.cond.L.Unlock()
if ch := p.playCh; ch != nil {
<-ch
}
return p.state == playerPlay return p.state == playerPlay
} }
@ -549,10 +530,6 @@ func (p *playerImpl) closeForReuse() error {
} }
func (p *playerImpl) closeImpl(reuseLater bool) error { func (p *playerImpl) closeImpl(reuseLater bool) error {
if ch := p.playCh; ch != nil {
<-ch
}
if p.audioQueue != nil { if p.audioQueue != nil {
// Even if reuseLater is true, AudioQueuePause is not efficient for reusing. // Even if reuseLater is true, AudioQueuePause is not efficient for reusing.
// AudioQueueStart takes long if the AudioQueueStop is not called. // AudioQueueStart takes long if the AudioQueueStop is not called.