mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 11:18:54 +01:00
audio: Bug fix: Test failures on browsers
This commit is contained in:
parent
a17fea39a1
commit
07c10880f4
@ -144,7 +144,24 @@ func NewContext(sampleRate int) *Context {
|
||||
theContext.m.Unlock()
|
||||
}
|
||||
theContextLock.Unlock()
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Now reader players cannot call removePlayers from themselves in the current implementation.
|
||||
// Underlying playering can be the pause state after fishing its playing,
|
||||
// but there is no way to notify this to readerPlayers so far.
|
||||
// Instead, let's check the states proactively every frame.
|
||||
for p := range c.players {
|
||||
rp, ok := p.(*readerPlayer)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
if !rp.IsPlaying() {
|
||||
delete(c.players, p)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
return c
|
||||
|
@ -30,7 +30,7 @@ func setup() {
|
||||
}
|
||||
|
||||
func teardown() {
|
||||
ResetContext()
|
||||
ResetContextForTesting()
|
||||
context = nil
|
||||
}
|
||||
|
||||
|
@ -16,31 +16,109 @@ package audio
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type (
|
||||
dummyDriver struct{}
|
||||
dummyPlayer struct{}
|
||||
dummyWriterPlayerDriver struct{}
|
||||
dummyWriterPlayer struct{}
|
||||
)
|
||||
|
||||
func (d *dummyDriver) NewPlayer() io.WriteCloser {
|
||||
return &dummyPlayer{}
|
||||
func (d *dummyWriterPlayerDriver) NewPlayer() io.WriteCloser {
|
||||
return &dummyWriterPlayer{}
|
||||
}
|
||||
|
||||
func (d *dummyDriver) Close() error {
|
||||
func (d *dummyWriterPlayerDriver) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *dummyPlayer) Write(b []byte) (int, error) {
|
||||
func (p *dummyWriterPlayer) Write(b []byte) (int, error) {
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
func (p *dummyPlayer) Close() error {
|
||||
func (p *dummyWriterPlayer) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
writerDriverForTesting = &dummyDriver{}
|
||||
writerDriverForTesting = &dummyWriterPlayerDriver{}
|
||||
}
|
||||
|
||||
type (
|
||||
dummyReaderPlayerDriver struct{}
|
||||
dummyReaderPlayer struct {
|
||||
r io.Reader
|
||||
playing bool
|
||||
volume float64
|
||||
m sync.Mutex
|
||||
}
|
||||
)
|
||||
|
||||
func (d *dummyReaderPlayerDriver) NewPlayer(r io.Reader) readerDriverPlayer {
|
||||
return &dummyReaderPlayer{
|
||||
r: r,
|
||||
volume: 1,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *dummyReaderPlayerDriver) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *dummyReaderPlayer) Pause() {
|
||||
p.m.Lock()
|
||||
p.playing = false
|
||||
p.m.Unlock()
|
||||
}
|
||||
|
||||
func (p *dummyReaderPlayer) Play() {
|
||||
p.m.Lock()
|
||||
p.playing = true
|
||||
p.m.Unlock()
|
||||
go func() {
|
||||
if _, err := ioutil.ReadAll(p.r); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
p.m.Lock()
|
||||
p.playing = false
|
||||
p.m.Unlock()
|
||||
}()
|
||||
}
|
||||
|
||||
func (p *dummyReaderPlayer) IsPlaying() bool {
|
||||
p.m.Lock()
|
||||
defer p.m.Unlock()
|
||||
return p.playing
|
||||
}
|
||||
|
||||
func (p *dummyReaderPlayer) Reset() {
|
||||
p.m.Lock()
|
||||
defer p.m.Unlock()
|
||||
p.playing = false
|
||||
}
|
||||
|
||||
func (p *dummyReaderPlayer) Volume() float64 {
|
||||
return p.volume
|
||||
}
|
||||
|
||||
func (p *dummyReaderPlayer) SetVolume(volume float64) {
|
||||
p.volume = volume
|
||||
}
|
||||
|
||||
func (p *dummyReaderPlayer) UnplayedBufferSize() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (p *dummyReaderPlayer) Close() error {
|
||||
p.m.Lock()
|
||||
defer p.m.Unlock()
|
||||
p.playing = false
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
readerDriverForTesting = &dummyReaderPlayerDriver{}
|
||||
}
|
||||
|
||||
type dummyHook struct {
|
||||
@ -78,6 +156,6 @@ func PlayersNumForTesting() int {
|
||||
return n
|
||||
}
|
||||
|
||||
func ResetContext() {
|
||||
func ResetContextForTesting() {
|
||||
theContext = nil
|
||||
}
|
||||
|
@ -60,17 +60,23 @@ type readerPlayerFactory struct {
|
||||
sampleRate int
|
||||
}
|
||||
|
||||
var readerDriverForTesting readerDriver
|
||||
|
||||
func newReaderPlayerFactory(sampleRate int) *readerPlayerFactory {
|
||||
return &readerPlayerFactory{
|
||||
f := &readerPlayerFactory{
|
||||
sampleRate: sampleRate,
|
||||
}
|
||||
if readerDriverForTesting != nil {
|
||||
f.driver = readerDriverForTesting
|
||||
}
|
||||
// TODO: Consider the hooks.
|
||||
return f
|
||||
}
|
||||
|
||||
type readerPlayer struct {
|
||||
context *Context
|
||||
player readerDriverPlayer
|
||||
src *timeStream
|
||||
stream *timeStream
|
||||
factory *readerPlayerFactory
|
||||
m sync.Mutex
|
||||
}
|
||||
@ -84,7 +90,7 @@ func (f *readerPlayerFactory) newPlayerImpl(context *Context, src io.Reader) (pl
|
||||
|
||||
p := &readerPlayer{
|
||||
context: context,
|
||||
src: s,
|
||||
stream: s,
|
||||
factory: f,
|
||||
}
|
||||
return p, nil
|
||||
@ -104,7 +110,7 @@ func (p *readerPlayer) ensurePlayer() error {
|
||||
p.factory.driver = d
|
||||
}
|
||||
if p.player == nil {
|
||||
p.player = p.factory.driver.NewPlayer(p.src)
|
||||
p.player = p.factory.driver.NewPlayer(p.stream)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -131,7 +137,8 @@ func (p *readerPlayer) Pause() {
|
||||
|
||||
n := p.player.UnplayedBufferSize()
|
||||
p.player.Pause()
|
||||
p.src.Unread(int(n))
|
||||
p.stream.Unread(int(n))
|
||||
p.context.removePlayer(p)
|
||||
}
|
||||
|
||||
func (p *readerPlayer) IsPlaying() bool {
|
||||
@ -171,8 +178,8 @@ func (p *readerPlayer) Close() error {
|
||||
p.m.Lock()
|
||||
defer p.m.Unlock()
|
||||
|
||||
p.context.removePlayer(p)
|
||||
if p.player != nil {
|
||||
p.player.Pause()
|
||||
return p.player.Close()
|
||||
}
|
||||
return nil
|
||||
@ -186,7 +193,7 @@ func (p *readerPlayer) Current() time.Duration {
|
||||
return 0
|
||||
}
|
||||
|
||||
sample := (p.src.Current() - p.player.UnplayedBufferSize()) / bytesPerSample
|
||||
sample := (p.stream.Current() - p.player.UnplayedBufferSize()) / bytesPerSample
|
||||
return time.Duration(sample) * time.Second / time.Duration(p.factory.sampleRate)
|
||||
}
|
||||
|
||||
@ -206,11 +213,11 @@ func (p *readerPlayer) Seek(offset time.Duration) error {
|
||||
}
|
||||
p.player.Reset()
|
||||
}
|
||||
return p.src.Seek(offset)
|
||||
return p.stream.Seek(offset)
|
||||
}
|
||||
|
||||
func (p *readerPlayer) source() io.Reader {
|
||||
return p.src
|
||||
return p.stream.r
|
||||
}
|
||||
|
||||
type timeStream struct {
|
||||
|
Loading…
Reference in New Issue
Block a user