mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-27 03:02:49 +01:00
audio/internal/oboe: Bug fix: Player must be protected by a mutex
As Close can be invoked by the finalizer, Player must be concurrent safe. Especially the member player must be synced. Updates #1549 Updates #1656
This commit is contained in:
parent
040fcd930f
commit
0f5aa315d6
23
audio/internal/oboe/binding_android.go
vendored
23
audio/internal/oboe/binding_android.go
vendored
@ -27,6 +27,7 @@ import "C"
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"sync"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -47,6 +48,10 @@ func Resume() error {
|
|||||||
type Player struct {
|
type Player struct {
|
||||||
player C.PlayerID
|
player C.PlayerID
|
||||||
onWritten func()
|
onWritten func()
|
||||||
|
|
||||||
|
// m is the mutex for this player.
|
||||||
|
// This is necessary as Close can be invoked from the finalizer goroutine.
|
||||||
|
m sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPlayer(sampleRate, channelNum, bitDepthInBytes int, volume float64, onWritten func()) *Player {
|
func NewPlayer(sampleRate, channelNum, bitDepthInBytes int, volume float64, onWritten func()) *Player {
|
||||||
@ -65,10 +70,15 @@ func onWrittenCallback(player C.uintptr_t) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) IsPlaying() bool {
|
func (p *Player) IsPlaying() bool {
|
||||||
|
p.m.Lock()
|
||||||
|
defer p.m.Unlock()
|
||||||
return bool(C.ebiten_oboe_Player_IsPlaying(p.player))
|
return bool(C.ebiten_oboe_Player_IsPlaying(p.player))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) AppendBuffer(buf []byte) {
|
func (p *Player) AppendBuffer(buf []byte) {
|
||||||
|
p.m.Lock()
|
||||||
|
defer p.m.Unlock()
|
||||||
|
|
||||||
ptr := C.CBytes(buf)
|
ptr := C.CBytes(buf)
|
||||||
defer C.free(ptr)
|
defer C.free(ptr)
|
||||||
|
|
||||||
@ -76,6 +86,9 @@ func (p *Player) AppendBuffer(buf []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) Play() error {
|
func (p *Player) Play() error {
|
||||||
|
p.m.Lock()
|
||||||
|
defer p.m.Unlock()
|
||||||
|
|
||||||
if p.player == 0 {
|
if p.player == 0 {
|
||||||
return fmt.Errorf("oboe: player is already closed at Play")
|
return fmt.Errorf("oboe: player is already closed at Play")
|
||||||
}
|
}
|
||||||
@ -86,6 +99,9 @@ func (p *Player) Play() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) Pause() error {
|
func (p *Player) Pause() error {
|
||||||
|
p.m.Lock()
|
||||||
|
defer p.m.Unlock()
|
||||||
|
|
||||||
if p.player == 0 {
|
if p.player == 0 {
|
||||||
return fmt.Errorf("oboe: player is already closed at Pause")
|
return fmt.Errorf("oboe: player is already closed at Pause")
|
||||||
}
|
}
|
||||||
@ -96,10 +112,15 @@ func (p *Player) Pause() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) SetVolume(volume float64) {
|
func (p *Player) SetVolume(volume float64) {
|
||||||
|
p.m.Lock()
|
||||||
|
defer p.m.Unlock()
|
||||||
C.ebiten_oboe_Player_SetVolume(p.player, C.double(volume))
|
C.ebiten_oboe_Player_SetVolume(p.player, C.double(volume))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) Close() error {
|
func (p *Player) Close() error {
|
||||||
|
p.m.Lock()
|
||||||
|
defer p.m.Unlock()
|
||||||
|
|
||||||
runtime.SetFinalizer(p, nil)
|
runtime.SetFinalizer(p, nil)
|
||||||
if p.player == 0 {
|
if p.player == 0 {
|
||||||
return fmt.Errorf("oboe: player is already closed at Close")
|
return fmt.Errorf("oboe: player is already closed at Close")
|
||||||
@ -112,5 +133,7 @@ func (p *Player) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Player) UnplayedBufferSize() int {
|
func (p *Player) UnplayedBufferSize() int {
|
||||||
|
p.m.Lock()
|
||||||
|
defer p.m.Unlock()
|
||||||
return int(C.ebiten_oboe_Player_UnplayedBufferSize(p.player))
|
return int(C.ebiten_oboe_Player_UnplayedBufferSize(p.player))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user