mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-27 03:02:49 +01:00
audio/internal/go2cpp: Recreate the underlying audio player when resetting
This commit is contained in:
parent
a66097df19
commit
2f8172f819
@ -38,16 +38,14 @@ func (c *Context) NewPlayer(r io.Reader) *Player {
|
|||||||
cond.Signal()
|
cond.Signal()
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
v := c.v.Call("createPlayer", onwritten)
|
|
||||||
p := &Player{
|
p := &Player{
|
||||||
|
context: c,
|
||||||
src: r,
|
src: r,
|
||||||
v: v,
|
volume: 1,
|
||||||
cond: cond,
|
cond: cond,
|
||||||
onWritten: onwritten,
|
onWritten: onwritten,
|
||||||
}
|
}
|
||||||
runtime.SetFinalizer(p, (*Player).Close)
|
runtime.SetFinalizer(p, (*Player).Close)
|
||||||
|
|
||||||
go p.loop()
|
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,15 +59,16 @@ const (
|
|||||||
playerStatePaused playerState = iota
|
playerStatePaused playerState = iota
|
||||||
playerStatePlaying
|
playerStatePlaying
|
||||||
playerStateClosed
|
playerStateClosed
|
||||||
playerStateError
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Player struct {
|
type Player struct {
|
||||||
src io.Reader
|
context *Context
|
||||||
v js.Value
|
src io.Reader
|
||||||
state playerState
|
v js.Value
|
||||||
cond *sync.Cond
|
state playerState
|
||||||
err error
|
volume float64
|
||||||
|
cond *sync.Cond
|
||||||
|
err error
|
||||||
|
|
||||||
onWritten js.Func
|
onWritten js.Func
|
||||||
}
|
}
|
||||||
@ -81,6 +80,10 @@ func (p *Player) Pause() {
|
|||||||
if p.state == playerStateClosed {
|
if p.state == playerStateClosed {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if !p.v.Truthy() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
p.v.Call("pause")
|
p.v.Call("pause")
|
||||||
p.state = playerStatePaused
|
p.state = playerStatePaused
|
||||||
p.cond.Signal()
|
p.cond.Signal()
|
||||||
@ -93,6 +96,12 @@ func (p *Player) Play() {
|
|||||||
if p.state == playerStateClosed {
|
if p.state == playerStateClosed {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if !p.v.Truthy() {
|
||||||
|
p.v = p.context.v.Call("createPlayer", p.onWritten)
|
||||||
|
p.v.Set("volume", p.volume)
|
||||||
|
go p.loop()
|
||||||
|
}
|
||||||
|
|
||||||
p.v.Call("play")
|
p.v.Call("play")
|
||||||
p.state = playerStatePlaying
|
p.state = playerStatePlaying
|
||||||
p.cond.Signal()
|
p.cond.Signal()
|
||||||
@ -105,45 +114,63 @@ func (p *Player) Reset() {
|
|||||||
if p.state == playerStateClosed {
|
if p.state == playerStateClosed {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if !p.v.Truthy() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
p.v.Call("reset")
|
p.v.Call("close", true)
|
||||||
|
p.v = js.Undefined()
|
||||||
p.cond.Signal()
|
p.cond.Signal()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) Volume() float64 {
|
func (p *Player) Volume() float64 {
|
||||||
|
if !p.v.Truthy() {
|
||||||
|
return p.volume
|
||||||
|
}
|
||||||
return p.v.Get("volume").Float()
|
return p.v.Get("volume").Float()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) SetVolume(volume float64) {
|
func (p *Player) SetVolume(volume float64) {
|
||||||
|
if !p.v.Truthy() {
|
||||||
|
return
|
||||||
|
}
|
||||||
p.v.Set("volume", volume)
|
p.v.Set("volume", volume)
|
||||||
|
p.volume = volume
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) Close() error {
|
func (p *Player) Close() error {
|
||||||
runtime.SetFinalizer(p, nil)
|
runtime.SetFinalizer(p, nil)
|
||||||
|
return p.close(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Player) close(remove bool) error {
|
||||||
p.cond.L.Lock()
|
p.cond.L.Lock()
|
||||||
defer p.cond.L.Unlock()
|
defer p.cond.L.Unlock()
|
||||||
|
|
||||||
if p.state == playerStateError {
|
if p.state == playerStateClosed {
|
||||||
return p.err
|
return p.err
|
||||||
}
|
}
|
||||||
|
|
||||||
p.v.Call("close")
|
p.v.Call("close", false)
|
||||||
p.state = playerStateClosed
|
p.v = js.Undefined()
|
||||||
|
if remove {
|
||||||
|
p.state = playerStateClosed
|
||||||
|
p.onWritten.Release()
|
||||||
|
} else {
|
||||||
|
p.state = playerStatePaused
|
||||||
|
}
|
||||||
p.cond.Signal()
|
p.cond.Signal()
|
||||||
p.onWritten.Release()
|
return p.err
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) setError(err error) {
|
func (p *Player) setError(err error) {
|
||||||
p.cond.L.Lock()
|
p.cond.L.Lock()
|
||||||
defer p.cond.L.Unlock()
|
defer p.cond.L.Unlock()
|
||||||
|
|
||||||
if p.state == playerStateError {
|
if p.state != playerStateClosed && p.v.Truthy() {
|
||||||
return
|
p.v.Call("close", true)
|
||||||
|
p.v = js.Undefined()
|
||||||
}
|
}
|
||||||
|
|
||||||
p.v.Call("close")
|
|
||||||
p.err = err
|
p.err = err
|
||||||
p.state = playerStateClosed
|
p.state = playerStateClosed
|
||||||
p.cond.Signal()
|
p.cond.Signal()
|
||||||
@ -153,10 +180,10 @@ func (p *Player) waitUntilUnpaused() bool {
|
|||||||
p.cond.L.Lock()
|
p.cond.L.Lock()
|
||||||
defer p.cond.L.Unlock()
|
defer p.cond.L.Unlock()
|
||||||
|
|
||||||
for p.state == playerStatePaused || (p.state == playerStatePlaying && !p.v.Call("isWritable").Bool()) {
|
for p.v.Truthy() && (p.state == playerStatePaused || (p.state == playerStatePlaying && !p.v.Call("isWritable").Bool())) {
|
||||||
p.cond.Wait()
|
p.cond.Wait()
|
||||||
}
|
}
|
||||||
return p.state == playerStatePlaying
|
return p.v.Truthy() && p.state == playerStatePlaying
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) loop() {
|
func (p *Player) loop() {
|
||||||
@ -181,8 +208,7 @@ func (p *Player) loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
// TODO: This should be Pause instead of Close for Rewind
|
p.close(false)
|
||||||
p.Close()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user