mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-26 03:38:55 +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()
|
theContext.m.Unlock()
|
||||||
}
|
}
|
||||||
theContextLock.Unlock()
|
theContextLock.Unlock()
|
||||||
|
if err != nil {
|
||||||
return err
|
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
|
return c
|
||||||
|
@ -30,7 +30,7 @@ func setup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func teardown() {
|
func teardown() {
|
||||||
ResetContext()
|
ResetContextForTesting()
|
||||||
context = nil
|
context = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,31 +16,109 @@ package audio
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
dummyDriver struct{}
|
dummyWriterPlayerDriver struct{}
|
||||||
dummyPlayer struct{}
|
dummyWriterPlayer struct{}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (d *dummyDriver) NewPlayer() io.WriteCloser {
|
func (d *dummyWriterPlayerDriver) NewPlayer() io.WriteCloser {
|
||||||
return &dummyPlayer{}
|
return &dummyWriterPlayer{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *dummyDriver) Close() error {
|
func (d *dummyWriterPlayerDriver) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *dummyPlayer) Write(b []byte) (int, error) {
|
func (p *dummyWriterPlayer) Write(b []byte) (int, error) {
|
||||||
return len(b), nil
|
return len(b), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *dummyPlayer) Close() error {
|
func (p *dummyWriterPlayer) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
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 {
|
type dummyHook struct {
|
||||||
@ -78,6 +156,6 @@ func PlayersNumForTesting() int {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func ResetContext() {
|
func ResetContextForTesting() {
|
||||||
theContext = nil
|
theContext = nil
|
||||||
}
|
}
|
||||||
|
@ -60,17 +60,23 @@ type readerPlayerFactory struct {
|
|||||||
sampleRate int
|
sampleRate int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var readerDriverForTesting readerDriver
|
||||||
|
|
||||||
func newReaderPlayerFactory(sampleRate int) *readerPlayerFactory {
|
func newReaderPlayerFactory(sampleRate int) *readerPlayerFactory {
|
||||||
return &readerPlayerFactory{
|
f := &readerPlayerFactory{
|
||||||
sampleRate: sampleRate,
|
sampleRate: sampleRate,
|
||||||
}
|
}
|
||||||
|
if readerDriverForTesting != nil {
|
||||||
|
f.driver = readerDriverForTesting
|
||||||
|
}
|
||||||
// TODO: Consider the hooks.
|
// TODO: Consider the hooks.
|
||||||
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
type readerPlayer struct {
|
type readerPlayer struct {
|
||||||
context *Context
|
context *Context
|
||||||
player readerDriverPlayer
|
player readerDriverPlayer
|
||||||
src *timeStream
|
stream *timeStream
|
||||||
factory *readerPlayerFactory
|
factory *readerPlayerFactory
|
||||||
m sync.Mutex
|
m sync.Mutex
|
||||||
}
|
}
|
||||||
@ -84,7 +90,7 @@ func (f *readerPlayerFactory) newPlayerImpl(context *Context, src io.Reader) (pl
|
|||||||
|
|
||||||
p := &readerPlayer{
|
p := &readerPlayer{
|
||||||
context: context,
|
context: context,
|
||||||
src: s,
|
stream: s,
|
||||||
factory: f,
|
factory: f,
|
||||||
}
|
}
|
||||||
return p, nil
|
return p, nil
|
||||||
@ -104,7 +110,7 @@ func (p *readerPlayer) ensurePlayer() error {
|
|||||||
p.factory.driver = d
|
p.factory.driver = d
|
||||||
}
|
}
|
||||||
if p.player == nil {
|
if p.player == nil {
|
||||||
p.player = p.factory.driver.NewPlayer(p.src)
|
p.player = p.factory.driver.NewPlayer(p.stream)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -131,7 +137,8 @@ func (p *readerPlayer) Pause() {
|
|||||||
|
|
||||||
n := p.player.UnplayedBufferSize()
|
n := p.player.UnplayedBufferSize()
|
||||||
p.player.Pause()
|
p.player.Pause()
|
||||||
p.src.Unread(int(n))
|
p.stream.Unread(int(n))
|
||||||
|
p.context.removePlayer(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *readerPlayer) IsPlaying() bool {
|
func (p *readerPlayer) IsPlaying() bool {
|
||||||
@ -171,8 +178,8 @@ func (p *readerPlayer) Close() error {
|
|||||||
p.m.Lock()
|
p.m.Lock()
|
||||||
defer p.m.Unlock()
|
defer p.m.Unlock()
|
||||||
|
|
||||||
p.context.removePlayer(p)
|
|
||||||
if p.player != nil {
|
if p.player != nil {
|
||||||
|
p.player.Pause()
|
||||||
return p.player.Close()
|
return p.player.Close()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -186,7 +193,7 @@ func (p *readerPlayer) Current() time.Duration {
|
|||||||
return 0
|
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)
|
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()
|
p.player.Reset()
|
||||||
}
|
}
|
||||||
return p.src.Seek(offset)
|
return p.stream.Seek(offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *readerPlayer) source() io.Reader {
|
func (p *readerPlayer) source() io.Reader {
|
||||||
return p.src
|
return p.stream.r
|
||||||
}
|
}
|
||||||
|
|
||||||
type timeStream struct {
|
type timeStream struct {
|
||||||
|
Loading…
Reference in New Issue
Block a user