internal/hooks: Enable to return error at suspend/resume audio

This commit is contained in:
Hajime Hoshi 2021-05-04 22:24:31 +09:00
parent bcf8ef85b6
commit 58843b68f9
9 changed files with 77 additions and 41 deletions

View File

@ -125,17 +125,19 @@ func NewContext(sampleRate int) *Context {
theContext = c
h := getHook()
h.OnSuspendAudio(func() {
h.OnSuspendAudio(func() error {
c.semaphore <- struct{}{}
if s, ok := np.(interface{ suspend() }); ok {
s.suspend()
}
return nil
})
h.OnResumeAudio(func() {
h.OnResumeAudio(func() error {
<-c.semaphore
if s, ok := np.(interface{ resume() }); ok {
s.resume()
}
return nil
})
h.AppendHookOnBeforeUpdate(func() error {
@ -423,8 +425,8 @@ func (p *Player) SetVolume(volume float64) {
}
type hook interface {
OnSuspendAudio(f func())
OnResumeAudio(f func())
OnSuspendAudio(f func() error)
OnResumeAudio(f func() error)
AppendHookOnBeforeUpdate(f func() error)
}
@ -439,11 +441,11 @@ func getHook() hook {
type hookImpl struct{}
func (h *hookImpl) OnSuspendAudio(f func()) {
func (h *hookImpl) OnSuspendAudio(f func() error) {
hooks.OnSuspendAudio(f)
}
func (h *hookImpl) OnResumeAudio(f func()) {
func (h *hookImpl) OnResumeAudio(f func() error) {
hooks.OnResumeAudio(f)
}

View File

@ -141,10 +141,10 @@ type dummyHook struct {
updates []func() error
}
func (h *dummyHook) OnSuspendAudio(f func()) {
func (h *dummyHook) OnSuspendAudio(f func() error) {
}
func (h *dummyHook) OnResumeAudio(f func()) {
func (h *dummyHook) OnResumeAudio(f func() error) {
}
func (h *dummyHook) AppendHookOnBeforeUpdate(f func() error) {

View File

@ -313,7 +313,11 @@ const objcM = `// Code generated by ebitenmobile. DO NOT EDIT.
@synchronized(self) {
active_ = false;
EbitenmobileviewSuspend();
NSError* err = nil;
EbitenmobileviewSuspend(&err);
if (err != nil) {
[self onErrorOnGameUpdate:err];
}
}
}
@ -322,7 +326,11 @@ const objcM = `// Code generated by ebitenmobile. DO NOT EDIT.
@synchronized(self) {
active_ = true;
EbitenmobileviewResume();
NSError* err = nil;
EbitenmobileviewResume(&err);
if (err != nil) {
[self onErrorOnGameUpdate:err];
}
}
}
@ -689,7 +697,11 @@ public class EbitenView extends ViewGroup implements InputManager.InputDeviceLis
public void suspendGame() {
this.inputManager.unregisterInputDeviceListener(this);
this.ebitenSurfaceView.onPause();
Ebitenmobileview.suspend();
try {
Ebitenmobileview.suspend();
} catch (final Exception e) {
onErrorOnGameUpdate(e);
}
}
// resumeGame resumes the game.
@ -698,7 +710,11 @@ public class EbitenView extends ViewGroup implements InputManager.InputDeviceLis
public void resumeGame() {
this.inputManager.registerInputDeviceListener(this, null);
this.ebitenSurfaceView.onResume();
Ebitenmobileview.resume();
try {
Ebitenmobileview.resume();
} catch (final Exception e) {
onErrorOnGameUpdate(e);
}
}
// onErrorOnGameUpdate is called on the main thread when an error happens when updating a game.

File diff suppressed because one or more lines are too long

View File

@ -44,42 +44,44 @@ func RunBeforeUpdateHooks() error {
var (
audioSuspended bool
onSuspendAudio func()
onResumeAudio func()
onSuspendAudio func() error
onResumeAudio func() error
)
func OnSuspendAudio(f func()) {
func OnSuspendAudio(f func() error) {
m.Lock()
onSuspendAudio = f
m.Unlock()
}
func OnResumeAudio(f func()) {
func OnResumeAudio(f func() error) {
m.Lock()
onResumeAudio = f
m.Unlock()
}
func SuspendAudio() {
func SuspendAudio() error {
m.Lock()
defer m.Unlock()
if audioSuspended {
return
return nil
}
audioSuspended = true
if onSuspendAudio != nil {
onSuspendAudio()
return onSuspendAudio()
}
return nil
}
func ResumeAudio() {
func ResumeAudio() error {
m.Lock()
defer m.Unlock()
if !audioSuspended {
return
return nil
}
audioSuspended = false
if onResumeAudio != nil {
onResumeAudio()
return onResumeAudio()
}
return nil
}

View File

@ -916,12 +916,16 @@ func (u *UserInterface) update() (float64, float64, bool, error) {
u.input.update(u.window, u.context)
for !u.isRunnableOnUnfocused() && u.window.GetAttrib(glfw.Focused) == 0 && !u.window.ShouldClose() {
hooks.SuspendAudio()
if err := hooks.SuspendAudio(); err != nil {
return 0, 0, false, err
}
// Wait for an arbitrary period to avoid busy loop.
time.Sleep(time.Second / 60)
glfw.PollEvents()
}
hooks.ResumeAudio()
if err := hooks.ResumeAudio(); err != nil {
return 0, 0, false, err
}
return outsideWidth, outsideHeight, outsideSizeChanged, nil
}

View File

@ -258,10 +258,11 @@ func (u *UserInterface) isFocused() bool {
func (u *UserInterface) update() error {
if u.suspended() {
hooks.SuspendAudio()
return nil
return hooks.SuspendAudio()
}
if err := hooks.ResumeAudio(); err != nil {
return err
}
hooks.ResumeAudio()
return u.updateImpl(false)
}
@ -284,7 +285,7 @@ func (u *UserInterface) updateImpl(force bool) error {
func (u *UserInterface) loop(context driver.UIContext) <-chan error {
u.context = context
errCh := make(chan error)
errCh := make(chan error, 1)
reqStopAudioCh := make(chan struct{})
resStopAudioCh := make(chan struct{})
@ -300,7 +301,6 @@ func (u *UserInterface) loop(context driver.UIContext) <-chan error {
<-resStopAudioCh
errCh <- err
close(errCh)
return
}
if u.vsync {
@ -344,9 +344,15 @@ func (u *UserInterface) loop(context driver.UIContext) <-chan error {
select {
case <-t.C:
if u.suspended() {
hooks.SuspendAudio()
if err := hooks.SuspendAudio(); err != nil {
errCh <- err
return
}
} else {
hooks.ResumeAudio()
if err := hooks.ResumeAudio(); err != nil {
errCh <- err
return
}
}
case <-reqStopAudioCh:
return

View File

@ -136,7 +136,10 @@ func (u *UserInterface) appMain(a app.App) {
case lifecycle.Event:
switch e.Crosses(lifecycle.StageVisible) {
case lifecycle.CrossOn:
u.SetForeground(true)
if err := u.SetForeground(true); err != nil {
// There are no other ways than panicking here.
panic(err)
}
restorable.OnContextLost()
glctx, _ = e.DrawContext.(gl.Context)
// Assume that glctx is always a same instance.
@ -147,7 +150,10 @@ func (u *UserInterface) appMain(a app.App) {
}
a.Send(paint.Event{})
case lifecycle.CrossOff:
u.SetForeground(false)
if err := u.SetForeground(false); err != nil {
// There are no other ways than panicking here.
panic(err)
}
glctx = nil
}
case size.Event:
@ -213,7 +219,7 @@ func (u *UserInterface) appMain(a app.App) {
}
}
func (u *UserInterface) SetForeground(foreground bool) {
func (u *UserInterface) SetForeground(foreground bool) error {
var v int32
if foreground {
v = 1
@ -221,9 +227,9 @@ func (u *UserInterface) SetForeground(foreground bool) {
atomic.StoreInt32(&u.foreground, v)
if foreground {
hooks.ResumeAudio()
return hooks.ResumeAudio()
} else {
hooks.SuspendAudio()
return hooks.SuspendAudio()
}
}

View File

@ -75,12 +75,12 @@ func Update() error {
return mobile.Get().Update()
}
func Suspend() {
mobile.Get().SetForeground(false)
func Suspend() error {
return mobile.Get().SetForeground(false)
}
func Resume() {
mobile.Get().SetForeground(true)
func Resume() error {
return mobile.Get().SetForeground(true)
}
func OnContextLost() {