audio: Error on duplicated source

Fixes #853
This commit is contained in:
Hajime Hoshi 2019-04-28 19:39:18 +09:00
parent 70a225fd7e
commit 2bea7d4e1a
3 changed files with 43 additions and 15 deletions

View File

@ -33,7 +33,6 @@ package audio
import (
"bytes"
"errors"
"fmt"
"io"
"runtime"
@ -149,7 +148,9 @@ func (c *Context) loop() {
<-resumeCh
default:
if _, err := io.CopyN(p, c.mux, 2048); err != nil {
c.m.Lock()
c.err = err
c.m.Unlock()
return
}
c.m.Lock()
@ -270,9 +271,9 @@ type proceededValues struct {
//
// NewPlayer takes the ownership of src. Player's Close calls src's Close.
func NewPlayer(context *Context, src io.ReadCloser) (*Player, error) {
if context.mux.hasSource(src) {
return nil, errors.New("audio: src cannot be shared with another Player")
}
//if context.mux.hasSource(src) {
// return nil, errors.New("audio: src cannot be shared with another Player")
//}
p := &Player{
&playerImpl{
mux: context.mux,

View File

@ -64,3 +64,31 @@ func TestGC(t *testing.T) {
}
t.Errorf("time out")
}
// Issue #853
func TestSameSourcePlayers(t *testing.T) {
src := BytesReadSeekCloser(make([]byte, 4))
p0, err := NewPlayer(context, src)
if err != nil {
t.Error(err)
}
p1, err := NewPlayer(context, src)
if err != nil {
t.Error(err)
}
// As the player does not play yet, error doesn't happen.
if err := UpdateForTesting(); err != nil {
t.Error(err)
}
p0.Play()
p1.Play()
// 200[ms] should be enough all the bytes are consumed.
// TODO: This is a darty hack. Would it be possible to use virtual time?
time.Sleep(200 * time.Millisecond)
if err := UpdateForTesting(); err == nil {
t.Errorf("got: nil, want: an error")
}
}

View File

@ -15,6 +15,7 @@
package audio
import (
"errors"
"io"
"runtime"
"sync"
@ -43,6 +44,15 @@ func (m *mux) Read(b []byte) (int, error) {
m.m.Lock()
defer m.m.Unlock()
// Check the source duplication
srcs := map[io.ReadCloser]struct{}{}
for p := range m.ps {
if _, ok := srcs[p.src]; ok {
return 0, errors.New("audio: a same source is used by multiple Player")
}
srcs[p.src] = struct{}{}
}
if len(m.ps) == 0 {
l := len(b)
l &= mask
@ -137,14 +147,3 @@ func (m *mux) hasPlayer(player *playerImpl) bool {
m.m.RUnlock()
return ok
}
func (m *mux) hasSource(src io.ReadCloser) bool {
m.m.RLock()
defer m.m.RUnlock()
for p := range m.ps {
if p.src == src {
return true
}
}
return false
}