diff --git a/audio/audio.go b/audio/audio.go index f915fd0bb..4f2fc2c69 100644 --- a/audio/audio.go +++ b/audio/audio.go @@ -44,8 +44,8 @@ import ( "github.com/hajimehoshi/oto" - "github.com/hajimehoshi/ebiten/internal/audiobinding" "github.com/hajimehoshi/ebiten/internal/clock" + "github.com/hajimehoshi/ebiten/internal/hooks" "github.com/hajimehoshi/ebiten/internal/sync" "github.com/hajimehoshi/ebiten/internal/web" ) @@ -155,7 +155,9 @@ type Context struct { initedCh chan struct{} pingCount int sampleRate int - m sync.Mutex + err error + + m sync.Mutex } var ( @@ -163,6 +165,15 @@ var ( theContextLock sync.Mutex ) +func init() { + hooks.AppendHookOnUpdate(func() error { + theContext.m.Lock() + err := theContext.err + theContext.m.Unlock() + return err + }) +} + // NewContext creates a new audio context with the given sample rate. // // The sample rate is also used for decoding MP3 with audio/mp3 package @@ -234,7 +245,7 @@ func (c *Context) loop() { // but there are some known environment that is too short (e.g. Windows on Parallels, iOS). p, err := oto.NewPlayer(c.sampleRate, channelNum, bytesPerSample, 8192) if err != nil { - audiobinding.SetError(err) + c.err = err return } defer p.Close() @@ -256,7 +267,7 @@ func (c *Context) loop() { const n = 4096 if _, err := io.CopyN(p, c.players, n); err != nil { - audiobinding.SetError(err) + c.err = err return } diff --git a/graphicscontext.go b/graphicscontext.go index 5691c8920..6470378de 100644 --- a/graphicscontext.go +++ b/graphicscontext.go @@ -17,8 +17,8 @@ package ebiten import ( "math" - "github.com/hajimehoshi/ebiten/internal/audiobinding" "github.com/hajimehoshi/ebiten/internal/clock" + "github.com/hajimehoshi/ebiten/internal/hooks" "github.com/hajimehoshi/ebiten/internal/restorable" "github.com/hajimehoshi/ebiten/internal/ui" "github.com/hajimehoshi/ebiten/internal/web" @@ -98,11 +98,6 @@ func drawWithFittingScale(dst *Image, src *Image) { } func (c *graphicsContext) Update(afterFrameUpdate func()) error { - select { - case err := <-audiobinding.Error(): - return err - default: - } updateCount := clock.Update() if err := c.initializeIfNeeded(); err != nil { @@ -111,6 +106,9 @@ func (c *graphicsContext) Update(afterFrameUpdate func()) error { for i := 0; i < updateCount; i++ { restorable.ClearVolatileImages() setRunningSlowly(i < updateCount-1) + if err := hooks.Run(); err != nil { + return err + } if err := c.f(c.offscreen); err != nil { return err } diff --git a/internal/audiobinding/error.go b/internal/hooks/hooks.go similarity index 58% rename from internal/audiobinding/error.go rename to internal/hooks/hooks.go index 21eea3af8..4d2f8cade 100644 --- a/internal/audiobinding/error.go +++ b/internal/hooks/hooks.go @@ -1,4 +1,4 @@ -// Copyright 2017 The Ebiten Authors +// Copyright 2018 The Ebiten Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,14 +12,21 @@ // See the License for the specific language governing permissions and // limitations under the License. -package audiobinding +package hooks -var ch = make(chan error, 1) +var onUpdateHooks = []func() error{} -func Error() <-chan error { - return ch +// AppendHookOnUpdate appends a hook function that is run before the main update function +// every frame. +func AppendHookOnUpdate(f func() error) { + onUpdateHooks = append(onUpdateHooks, f) } -func SetError(err error) { - ch <- err +func Run() error { + for _, f := range onUpdateHooks { + if err := f(); err != nil { + return err + } + } + return nil }