mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-26 03:38:55 +01:00
audio/internal/readerdriver: Bug fix: Avoid AudioQueueReset
Instead, call AudioQueueStop and discard the current AudioQueue. Closes #1680 Updates #1650
This commit is contained in:
parent
4ce90a564b
commit
371bbfc0f2
@ -33,7 +33,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func IsAvailable() bool {
|
func IsAvailable() bool {
|
||||||
return false
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
type audioQueuePoolItem struct {
|
type audioQueuePoolItem struct {
|
||||||
@ -495,20 +495,11 @@ func (p *playerImpl) resetImpl() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(p.unqueuedBufs) < 2 {
|
// AudioQueueReset is not efficient (#1650, #1680).
|
||||||
if osstatus := C.AudioQueuePause(p.audioQueue); osstatus != C.noErr && p.err == nil {
|
// Discard the current AudioQueue and recreate one when playing this player again.
|
||||||
p.setErrorImpl(fmt.Errorf("readerdriver: AudioQueuePause failed: %d", osstatus))
|
if err := p.closeAudioQueue(); err != nil {
|
||||||
return
|
p.setErrorImpl(err)
|
||||||
}
|
return
|
||||||
// AudioQueueReset invokes the callback directry.
|
|
||||||
q := p.audioQueue
|
|
||||||
p.m.Unlock()
|
|
||||||
osstatus := C.AudioQueueReset(q)
|
|
||||||
p.m.Lock()
|
|
||||||
if osstatus != C.noErr && p.err == nil {
|
|
||||||
p.setErrorImpl(fmt.Errorf("readerdriver: AudioQueueReset failed: %d", osstatus))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p.state = playerPaused
|
p.state = playerPaused
|
||||||
@ -575,35 +566,45 @@ func (p *playerImpl) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *playerImpl) closeImpl() error {
|
func (p *playerImpl) closeImpl() error {
|
||||||
if p.audioQueue != nil {
|
if err := p.closeAudioQueue(); err != nil && p.err == nil {
|
||||||
// Even if reuseLater is true, AudioQueuePause is not efficient for reusing.
|
// setErrorImpl calls closeImpl. Do not call this.
|
||||||
// AudioQueueStart takes long if the AudioQueueStop is not called.
|
p.err = err
|
||||||
|
|
||||||
// AudioQueueStop might invoke AudioQueueReset. Unlock the mutex here to avoid a deadlock.
|
|
||||||
q := p.audioQueue
|
|
||||||
p.m.Unlock()
|
|
||||||
osstatus := C.AudioQueueStop(q, C.true)
|
|
||||||
p.m.Lock()
|
|
||||||
|
|
||||||
if osstatus != C.noErr && p.err == nil {
|
|
||||||
// setErrorImpl calls closeImpl. Do not call this.
|
|
||||||
p.err = fmt.Errorf("readerdriver: AudioQueueStop failed: %d", osstatus)
|
|
||||||
}
|
|
||||||
|
|
||||||
// All the AudioQueueBuffers are already dequeued. It is safe to dispose the AudioQueue and its buffers.
|
|
||||||
if err := p.context.audioQueuePool.Put(p.audioQueue); err != nil && p.err == nil {
|
|
||||||
p.err = err
|
|
||||||
}
|
|
||||||
p.m.Unlock()
|
|
||||||
thePlayers.remove(p.audioQueue)
|
|
||||||
p.m.Lock()
|
|
||||||
p.audioQueue = nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
p.state = playerClosed
|
p.state = playerClosed
|
||||||
return p.err
|
return p.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *playerImpl) closeAudioQueue() error {
|
||||||
|
if p.audioQueue == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Even if reuseLater is true, AudioQueuePause is not efficient for reusing.
|
||||||
|
// AudioQueueStart takes long if the AudioQueueStop is not called.
|
||||||
|
|
||||||
|
// AudioQueueStop might invoke AudioQueueReset. Unlock the mutex here to avoid a deadlock.
|
||||||
|
q := p.audioQueue
|
||||||
|
p.m.Unlock()
|
||||||
|
osstatus := C.AudioQueueStop(q, C.true)
|
||||||
|
p.m.Lock()
|
||||||
|
|
||||||
|
if osstatus != C.noErr && p.err == nil {
|
||||||
|
return fmt.Errorf("readerdriver: AudioQueueStop failed: %d", osstatus)
|
||||||
|
}
|
||||||
|
|
||||||
|
// All the AudioQueueBuffers are already dequeued. It is safe to dispose the AudioQueue and its buffers.
|
||||||
|
if err := p.context.audioQueuePool.Put(p.audioQueue); err != nil && p.err == nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
p.m.Unlock()
|
||||||
|
thePlayers.remove(p.audioQueue)
|
||||||
|
p.m.Lock()
|
||||||
|
p.audioQueue = nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
//export ebiten_readerdriver_render
|
//export ebiten_readerdriver_render
|
||||||
func ebiten_readerdriver_render(inUserData unsafe.Pointer, inAQ C.AudioQueueRef, inBuffer C.AudioQueueBufferRef) {
|
func ebiten_readerdriver_render(inUserData unsafe.Pointer, inAQ C.AudioQueueRef, inBuffer C.AudioQueueBufferRef) {
|
||||||
p := thePlayers.get(inAQ)
|
p := thePlayers.get(inAQ)
|
||||||
|
Loading…
Reference in New Issue
Block a user