ソースを参照

standard app dev...

leonsal 8 年 前
コミット
3e3bfb159e
4 ファイル変更482 行追加315 行削除
  1. 6 0
      renderer/renderer.go
  2. 0 314
      util/app/app.go
  3. 475 0
      util/application/application.go
  4. 1 1
      util/app/framerater.go

+ 6 - 0
renderer/renderer.go

@@ -102,6 +102,12 @@ func (r *Renderer) SetGuiPanel3D(panel3D gui.IPanel) {
 	r.panel3D = panel3D
 }
 
+// Panel3D returns the current gui panel over the 3D scene
+func (r *Renderer) Panel3D() gui.IPanel {
+
+	return r.panel3D
+}
+
 // SetScene sets the 3D scene to render
 // If set to nil, no 3D scene will be rendered
 func (r *Renderer) SetScene(scene core.INode) {

+ 0 - 314
util/app/app.go

@@ -1,314 +0,0 @@
-package app
-
-import (
-	"flag"
-	"fmt"
-	"runtime"
-
-	"github.com/g3n/engine/audio/al"
-	"github.com/g3n/engine/audio/ov"
-	"github.com/g3n/engine/audio/vorbis"
-	"github.com/g3n/engine/camera"
-	"github.com/g3n/engine/camera/control"
-	"github.com/g3n/engine/core"
-	"github.com/g3n/engine/gls"
-	"github.com/g3n/engine/gui"
-	"github.com/g3n/engine/light"
-	"github.com/g3n/engine/math32"
-	"github.com/g3n/engine/renderer"
-	"github.com/g3n/engine/util/logger"
-	"github.com/g3n/engine/window"
-)
-
-type App struct {
-	win         window.IWindow        // Application window
-	gl          *gls.GLS              // OpenGL state
-	log         *logger.Logger        // Default application logger
-	renderer    *renderer.Renderer    // Renderer object
-	camPersp    *camera.Perspective   // Perspective camera
-	camOrtho    *camera.Orthographic  // Orthographic camera
-	camera      camera.ICamera        // Current camera
-	orbit       *control.OrbitControl // Camera orbit controller
-	ambLight    *light.Ambient        // Default ambient light
-	audio       bool                  // Audio available
-	vorbis      bool                  // Vorbis decoder available
-	audioEFX    bool                  // Audio effect extension support available
-	audioDev    *al.Device            // Audio player device
-	captureDev  *al.Device            // Audio capture device
-	frameRater  *FrameRater           // Render loop frame rater
-	scene       *core.Node            // Node container for 3D tests
-	guiroot     *gui.Root             // Gui root panel
-	oCpuProfile *string
-}
-
-type Options struct {
-	WinHeight    int  // Initial window height. Uses screen width if 0
-	WinWidth     int  // Initial window width. Uses screen height if 0
-	VersionMajor int  // Application version major
-	VersionMinor int  // Application version minor
-	LogLevel     int  // Initial log level
-	EnableFlags  bool // Enable command line flags
-	TargetFPS    uint // Desired FPS
-}
-
-// appInstance contains the pointer to the single Application instance
-var appInstance *App
-
-// Creates creates and returns the application object using the specified name for
-// the window title and log messages
-// This functions must be called only once.
-func Create(name string, ops Options) (*App, error) {
-
-	if appInstance != nil {
-		return nil, fmt.Errorf("Application already created")
-	}
-	app := new(App)
-
-	if ops.EnableFlags {
-		app.oCpuProfile = flag.String("cpuprofile", "", "Activate cpu profiling writing profile to the specified file")
-		flag.Parse()
-	}
-
-	// Creates application logger
-	app.log = logger.New(name, nil)
-	app.log.AddWriter(logger.NewConsole(false))
-	app.log.SetFormat(logger.FTIME | logger.FMICROS)
-	app.log.SetLevel(ops.LogLevel)
-	app.log.Info("%s v%d.%d starting", name, ops.VersionMajor, ops.VersionMinor)
-
-	// Window event handling must run on the main OS thread
-	runtime.LockOSThread()
-
-	// Creates window and sets it as the current context
-	win, err := window.New("glfw", 10, 10, name, false)
-	if err != nil {
-		return nil, err
-	}
-	// Sets the window size
-	swidth, sheight := win.GetScreenResolution(nil)
-	if ops.WinWidth != 0 {
-		swidth = ops.WinWidth
-	}
-	if ops.WinHeight != 0 {
-		sheight = ops.WinHeight
-	}
-	win.SetSize(swidth, sheight)
-	app.win = win
-
-	// Create OpenGL state
-	gl, err := gls.New()
-	if err != nil {
-		return nil, err
-	}
-	app.gl = gl
-	cc := math32.NewColor("gray")
-	app.gl.ClearColor(cc.R, cc.G, cc.B, 1)
-	app.gl.Clear(gls.DEPTH_BUFFER_BIT | gls.STENCIL_BUFFER_BIT | gls.COLOR_BUFFER_BIT)
-
-	// Creates perspective camera
-	width, height := app.win.GetSize()
-	aspect := float32(width) / float32(height)
-	app.camPersp = camera.NewPerspective(65, aspect, 0.01, 1000)
-
-	// Creates orthographic camera
-	app.camOrtho = camera.NewOrthographic(-2, 2, 2, -2, 0.01, 100)
-	app.camOrtho.SetPosition(0, 0, 3)
-	app.camOrtho.LookAt(&math32.Vector3{0, 0, 0})
-	app.camOrtho.SetZoom(1.0)
-
-	// Default camera is perspective
-	app.camera = app.camPersp
-
-	// Creates orbit camera control
-	// It is important to do this after the root panel subscription
-	// to avoid GUI events being propagated to the orbit control.
-	app.orbit = control.NewOrbitControl(app.camera, app.win)
-
-	// Creates scene for 3D objects
-	app.scene = core.NewNode()
-
-	// Creates gui root panel
-	app.guiroot = gui.NewRoot(app.gl, app.win)
-
-	// Creates renderer
-	app.renderer = renderer.NewRenderer(gl)
-	err = app.renderer.AddDefaultShaders()
-	if err != nil {
-		return nil, fmt.Errorf("Error from AddDefaulShaders:%v", err)
-	}
-	app.renderer.SetScene(app.scene)
-	app.renderer.SetGui(app.guiroot)
-
-	// Adds white ambient light to the scene
-	app.ambLight = light.NewAmbient(&math32.Color{1.0, 1.0, 1.0}, 0.5)
-	app.scene.Add(app.ambLight)
-
-	// Create frame rater
-	app.frameRater = NewFrameRater(60)
-
-	// Subscribe to window resize events
-	app.win.Subscribe(window.OnWindowSize, func(evname string, ev interface{}) {
-		app.OnWindowResize()
-	})
-
-	return app, nil
-}
-
-// App returns the application single instance or nil
-// if the application was not created yet
-func Get() *App {
-
-	return appInstance
-}
-
-// Log returns the application logger
-func (a *App) Log() *logger.Logger {
-
-	return a.log
-}
-
-// Window returns the application window
-func (a *App) Window() window.IWindow {
-
-	return a.win
-}
-
-// Gui returns the current application Gui root panel
-func (app *App) Gui() *gui.Root {
-
-	return app.guiroot
-}
-
-// Scene returns the current application 3D scene
-func (a *App) Scene() *core.Node {
-
-	return a.scene
-}
-
-// SetScene sets the 3D scene to be rendered
-func (a *App) SetScene(scene *core.Node) {
-
-	a.renderer.SetScene(scene)
-}
-
-// SetGui sets the root panel of th3 gui to be rendered
-func (app *App) SetGui(root *gui.Root) {
-
-	app.guiroot = root
-	app.renderer.SetGui(app.guiroot)
-}
-
-// CameraPersp returns the application perspective camera
-func (app *App) CameraPersp() *camera.Perspective {
-
-	return app.camPersp
-}
-
-// Camera returns the current application camera
-func (app *App) Camera() camera.ICamera {
-
-	return app.camera
-}
-
-func (app *App) Renderer() *renderer.Renderer {
-
-	return app.renderer
-}
-
-// Runs runs the application render loop
-func (app *App) Run() error {
-
-	for !app.win.ShouldClose() {
-		// Starts measuring this frame
-		app.frameRater.Start()
-
-		// Renders the current scene and/or gui
-		rendered, err := app.renderer.Render(app.camera)
-		if err != nil {
-			return err
-		}
-		app.log.Error("render stats:%+v", app.renderer.Stats())
-
-		// Poll input events and process them
-		app.win.PollEvents()
-
-		if rendered {
-			app.win.SwapBuffers()
-		}
-
-		// Controls the frame rate and updates the FPS for the user
-		app.frameRater.Wait()
-	}
-	return nil
-}
-
-// Quit ends the application
-func (app *App) Quit() {
-
-	app.win.SetShouldClose(true)
-}
-
-// OnWindowResize is called when the window resize event is received
-func (app *App) OnWindowResize() {
-
-	// Get window size and sets the viewport to the same size
-	width, height := app.win.GetSize()
-	app.gl.Viewport(0, 0, int32(width), int32(height))
-
-	// Sets perspective camera aspect ratio
-	aspect := float32(width) / float32(height)
-	app.camPersp.SetAspect(aspect)
-	app.log.Error("app window resize:%v", aspect)
-
-	// Sets the size of GUI root panel size to the size of the screen
-	if app.guiroot != nil {
-		app.guiroot.SetSize(float32(width), float32(height))
-	}
-}
-
-// LoadAudioLibs try to load audio libraries
-func (a *App) LoadAudioLibs() error {
-
-	// Try to load OpenAL
-	err := al.Load()
-	if err != nil {
-		return err
-	}
-
-	// Opens default audio device
-	a.audioDev, err = al.OpenDevice("")
-	if a.audioDev == nil {
-		return fmt.Errorf("Error: %s opening OpenAL default device", err)
-	}
-
-	// Checks for OpenAL effects extension support
-	if al.IsExtensionPresent("ALC_EXT_EFX") {
-		a.audioEFX = true
-	}
-
-	// Creates audio context with auxiliary sends
-	var attribs []int
-	if a.audioEFX {
-		attribs = []int{al.MAX_AUXILIARY_SENDS, 4}
-	}
-	acx, err := al.CreateContext(a.audioDev, attribs)
-	if err != nil {
-		return fmt.Errorf("Error creating audio context:%s", err)
-	}
-
-	// Makes the context the current one
-	err = al.MakeContextCurrent(acx)
-	if err != nil {
-		return fmt.Errorf("Error setting audio context current:%s", err)
-	}
-	//log.Info("%s version: %s", al.GetString(al.Vendor), al.GetString(al.Version))
-	a.audio = true
-
-	// Ogg Vorbis support
-	err = ov.Load()
-	if err == nil {
-		a.vorbis = true
-		vorbis.Load()
-	}
-	return nil
-}

+ 475 - 0
util/application/application.go

@@ -0,0 +1,475 @@
+package application
+
+import (
+	"flag"
+	"fmt"
+	"os"
+	"runtime"
+	"runtime/pprof"
+	"time"
+
+	"github.com/g3n/engine/audio/al"
+	"github.com/g3n/engine/audio/ov"
+	"github.com/g3n/engine/audio/vorbis"
+	"github.com/g3n/engine/camera"
+	"github.com/g3n/engine/camera/control"
+	"github.com/g3n/engine/core"
+	"github.com/g3n/engine/gls"
+	"github.com/g3n/engine/gui"
+	"github.com/g3n/engine/math32"
+	"github.com/g3n/engine/renderer"
+	"github.com/g3n/engine/util/logger"
+	"github.com/g3n/engine/window"
+)
+
+// Application is a basic standard application object which can be extended.
+// It creates a Window, OpenGL state, default cameras, default scene and Gui and
+// has a method to run the render loop.
+type Application struct {
+	core.Dispatcher                         // Embedded event dispatcher
+	core.TimerManager                       // Embedded timer manager
+	win               window.IWindow        // Application window
+	gl                *gls.GLS              // OpenGL state
+	log               *logger.Logger        // Default application logger
+	renderer          *renderer.Renderer    // Renderer object
+	camPersp          *camera.Perspective   // Perspective camera
+	camOrtho          *camera.Orthographic  // Orthographic camera
+	camera            camera.ICamera        // Current camera
+	orbit             *control.OrbitControl // Camera orbit controller
+	audio             bool                  // Audio available
+	vorbis            bool                  // Vorbis decoder available
+	audioEFX          bool                  // Audio effect extension support available
+	audioDev          *al.Device            // Audio player device
+	captureDev        *al.Device            // Audio capture device
+	frameRater        *FrameRater           // Render loop frame rater
+	scene             *core.Node            // Node container for 3D tests
+	guiroot           *gui.Root             // Gui root panel
+	frameCount        uint64                // Frame counter
+	frameTime         time.Time             // Time at the start of the frame
+	frameDelta        time.Duration         // Time delta from previous frame
+	startTime         time.Time             // Time at the start of the render loop
+	cpuProfile        string                // File to write cpu profile to
+	swapInterval      int                   // Swap interval option
+	targetFPS         uint                  // Target FPS option
+	noglErrors        bool                  // No OpenGL check errors options
+}
+
+// Options defines initial options passed to application creation function
+type Options struct {
+	WinHeight   int  // Initial window height (default is screen width)
+	WinWidth    int  // Initial window width (default is screen height)
+	LogLevel    int  // Initial log level (default = DEBUG)
+	EnableFlags bool // Enable command line flags (default = false)
+	TargetFPS   uint // Desired frames per second rate (default = 60)
+}
+
+// appInstance contains the pointer to the single Application instance
+var appInstance *Application
+
+const (
+	OnBeforeRender = "util.application.OnBeforeRender"
+	OnAfterRender  = "util.application.OnAfterRender"
+)
+
+// Creates creates and returns the application object using the specified name for
+// the window title and log messages
+// This function must be called only once.
+func Create(name string, ops Options) (*Application, error) {
+
+	if appInstance != nil {
+		return nil, fmt.Errorf("Application already created")
+	}
+	app := new(Application)
+	app.Dispatcher.Initialize()
+	app.TimerManager.Initialize()
+	appInstance = app
+
+	// Initialize options default values
+	app.cpuProfile = ""
+	app.swapInterval = -1
+	app.targetFPS = 60
+	if ops.TargetFPS != 0 {
+		app.targetFPS = ops.TargetFPS
+	}
+	app.noglErrors = false
+
+	// Parse standard application command flags if requested
+	if ops.EnableFlags {
+		cpuProfile := flag.String("cpuprofile", "", "Activate cpu profiling writing profile to the specified file")
+		swapInterval := flag.Int("swapinterval", -1, "Sets the swap buffers interval to this value")
+		targetFPS := flag.Uint("targetfps", 60, "Sets the frame rate in frames per second")
+		noglErrors := flag.Bool("noglerrors", false, "Do not check OpenGL errors at each call (may increase FPS)")
+		flag.Parse()
+		app.cpuProfile = *cpuProfile
+		app.swapInterval = *swapInterval
+		app.targetFPS = *targetFPS
+		app.noglErrors = *noglErrors
+	}
+
+	// Creates application logger
+	app.log = logger.New(name, nil)
+	app.log.AddWriter(logger.NewConsole(false))
+	app.log.SetFormat(logger.FTIME | logger.FMICROS)
+	app.log.SetLevel(ops.LogLevel)
+
+	// Window event handling must run on the main OS thread
+	runtime.LockOSThread()
+
+	// Creates window and sets it as the current context
+	win, err := window.New("glfw", 10, 10, name, false)
+	if err != nil {
+		return nil, err
+	}
+	// Sets the window size
+	swidth, sheight := win.GetScreenResolution(nil)
+	if ops.WinWidth != 0 {
+		swidth = ops.WinWidth
+	}
+	if ops.WinHeight != 0 {
+		sheight = ops.WinHeight
+	}
+	win.SetSize(swidth, sheight)
+	app.win = win
+
+	// Create OpenGL state
+	gl, err := gls.New()
+	if err != nil {
+		return nil, err
+	}
+	app.gl = gl
+	app.gl.SetCheckErrors(!app.noglErrors)
+	cc := math32.NewColor("gray")
+	app.gl.ClearColor(cc.R, cc.G, cc.B, 1)
+	app.gl.Clear(gls.DEPTH_BUFFER_BIT | gls.STENCIL_BUFFER_BIT | gls.COLOR_BUFFER_BIT)
+
+	// Creates perspective camera
+	width, height := app.win.GetSize()
+	aspect := float32(width) / float32(height)
+	app.camPersp = camera.NewPerspective(65, aspect, 0.01, 1000)
+
+	// Creates orthographic camera
+	app.camOrtho = camera.NewOrthographic(-2, 2, 2, -2, 0.01, 100)
+	app.camOrtho.SetPosition(0, 0, 3)
+	app.camOrtho.LookAt(&math32.Vector3{0, 0, 0})
+	app.camOrtho.SetZoom(1.0)
+
+	// Default camera is perspective
+	app.camera = app.camPersp
+
+	// Creates orbit camera control
+	// It is important to do this after the root panel subscription
+	// to avoid GUI events being propagated to the orbit control.
+	app.orbit = control.NewOrbitControl(app.camera, app.win)
+
+	// Creates scene for 3D objects
+	app.scene = core.NewNode()
+
+	// Creates gui root panel
+	app.guiroot = gui.NewRoot(app.gl, app.win)
+
+	// Creates renderer
+	app.renderer = renderer.NewRenderer(gl)
+	err = app.renderer.AddDefaultShaders()
+	if err != nil {
+		return nil, fmt.Errorf("Error from AddDefaulShaders:%v", err)
+	}
+	app.renderer.SetScene(app.scene)
+	app.renderer.SetGui(app.guiroot)
+
+	// Create frame rater
+	app.frameRater = NewFrameRater(uint(app.targetFPS))
+
+	return app, nil
+}
+
+// App returns the application single instance or nil
+// if the application was not created yet
+func Get() *Application {
+
+	return appInstance
+}
+
+// Log returns the application logger
+func (app *Application) Log() *logger.Logger {
+
+	return app.log
+}
+
+// Window returns the application window
+func (app *Application) Window() window.IWindow {
+
+	return app.win
+}
+
+// Gl returns the OpenGL state associated
+func (app *Application) Gl() *gls.GLS {
+
+	return app.gl
+}
+
+// Gui returns the current application Gui root panel
+func (app *Application) Gui() *gui.Root {
+
+	return app.guiroot
+}
+
+// Scene returns the current application 3D scene
+func (app *Application) Scene() *core.Node {
+
+	return app.scene
+}
+
+// SetScene sets the 3D scene to be rendered
+func (app *Application) SetScene(scene *core.Node) {
+
+	app.renderer.SetScene(scene)
+}
+
+// SetGui sets the root panel of the gui to be rendered
+func (app *Application) SetGui(root *gui.Root) {
+
+	app.guiroot = root
+	app.renderer.SetGui(app.guiroot)
+}
+
+// SetPanel3D sets the gui panel inside which the 3D scene is shown.
+func (app *Application) SetPanel3D(panel3D gui.IPanel) {
+
+	app.renderer.SetGuiPanel3D(panel3D)
+}
+
+// Panel3D returns the current gui panel where the 3D scene is shown.
+func (app *Application) Panel3D() gui.IPanel {
+
+	return app.renderer.Panel3D()
+}
+
+// CameraPersp returns the application perspective camera
+func (app *Application) CameraPersp() *camera.Perspective {
+
+	return app.camPersp
+}
+
+// CameraOrtho returns the application orthographic camera
+func (app *Application) CameraOrtho() *camera.Orthographic {
+
+	return app.camOrtho
+}
+
+// Camera returns the current application camera
+func (app *Application) Camera() camera.ICamera {
+
+	return app.camera
+}
+
+// SetCamera sets the current application camera
+func (app *Application) SetCamera(cam camera.ICamera) {
+
+	app.camera = cam
+}
+
+// Orbit returns the current camera orbit control
+func (app *Application) Orbit() *control.OrbitControl {
+
+	return app.orbit
+}
+
+// SetOrbit sets the camera orbit control
+func (app *Application) SetOrbit(oc *control.OrbitControl) {
+
+	app.orbit = oc
+}
+
+// FrameRater returns the FrameRater object
+func (app *Application) FrameRater() *FrameRater {
+
+	return app.frameRater
+}
+
+func (app *Application) FrameCount() uint64 {
+
+	return app.frameCount
+}
+
+func (app *Application) FrameDelta() time.Duration {
+
+	return app.frameDelta
+}
+
+func (app *Application) FrameDeltaSeconds() float32 {
+
+	return float32(app.frameDelta.Seconds())
+}
+
+func (app *Application) RunTime() time.Duration {
+
+	return time.Now().Sub(app.startTime)
+}
+
+func (app *Application) RunSeconds() float32 {
+
+	return float32(time.Now().Sub(app.startTime).Seconds())
+}
+
+func (app *Application) Renderer() *renderer.Renderer {
+
+	return app.renderer
+}
+
+func (app *Application) AudioSupport() bool {
+
+	return app.audio
+}
+
+func (app *Application) VorbisSupport() bool {
+
+	return app.vorbis
+}
+
+// SetCpuProfile must be called before Run() and sets the file name for cpu profiling.
+// If set the cpu profiling starts before running the render loop and continues
+// till the end of the application.
+func (app *Application) SetCpuProfile(fname string) {
+
+	app.cpuProfile = fname
+}
+
+// Runs runs the application render loop
+func (app *Application) Run() error {
+
+	// Set swap interval
+	if app.swapInterval >= 0 {
+		app.win.SwapInterval(app.swapInterval)
+		app.log.Debug("Swap interval set to:%v", app.swapInterval)
+	}
+
+	// Start profiling if requested
+	if app.cpuProfile != "" {
+		f, err := os.Create(app.cpuProfile)
+		if err != nil {
+			return err
+		}
+		err = pprof.StartCPUProfile(f)
+		if err != nil {
+			return err
+		}
+		app.log.Info("Started writing CPU profile to:%s", app.cpuProfile)
+		defer pprof.StopCPUProfile()
+	}
+
+	app.startTime = time.Now()
+	app.frameTime = time.Now()
+
+	// Render loop
+	for !app.win.ShouldClose() {
+		// Starts measuring this frame
+		app.frameRater.Start()
+
+		// Updates frame start and time delta in context
+		now := time.Now()
+		app.frameDelta = now.Sub(app.frameTime)
+		app.frameTime = now
+
+		// Process root panel timers
+		if app.Gui() != nil {
+			app.Gui().TimerManager.ProcessTimers()
+		}
+
+		// Process application timers
+		app.ProcessTimers()
+
+		// Dispatch before render event
+		app.Dispatch(OnBeforeRender, nil)
+
+		// Renders the current scene and/or gui
+		rendered, err := app.renderer.Render(app.camera)
+		if err != nil {
+			return err
+		}
+
+		// Poll input events and process them
+		app.win.PollEvents()
+
+		if rendered {
+			app.win.SwapBuffers()
+		}
+
+		// Dispatch after render event
+		app.Dispatch(OnAfterRender, nil)
+
+		// Controls the frame rate and updates the FPS for the user
+		app.frameRater.Wait()
+		app.frameCount++
+	}
+	return nil
+}
+
+// Quit ends the application
+func (app *Application) Quit() {
+
+	app.win.SetShouldClose(true)
+}
+
+// OnWindowResize is default handler for window resize events.
+func (app *Application) OnWindowResize(evname string, ev interface{}) {
+
+	// Get window size and sets the viewport to the same size
+	width, height := app.win.GetSize()
+	app.gl.Viewport(0, 0, int32(width), int32(height))
+
+	// Sets perspective camera aspect ratio
+	aspect := float32(width) / float32(height)
+	app.camPersp.SetAspect(aspect)
+
+	// Sets the size of GUI root panel size to the size of the screen
+	if app.guiroot != nil {
+		app.guiroot.SetSize(float32(width), float32(height))
+	}
+}
+
+// LoadAudioLibs try to load audio libraries
+func (app *Application) LoadAudioLibs() error {
+
+	// Try to load OpenAL
+	err := al.Load()
+	if err != nil {
+		return err
+	}
+
+	// Opens default audio device
+	app.audioDev, err = al.OpenDevice("")
+	if app.audioDev == nil {
+		return fmt.Errorf("Error: %s opening OpenAL default device", err)
+	}
+
+	// Checks for OpenAL effects extension support
+	if al.IsExtensionPresent("ALC_EXT_EFX") {
+		app.audioEFX = true
+	}
+
+	// Creates audio context with auxiliary sends
+	var attribs []int
+	if app.audioEFX {
+		attribs = []int{al.MAX_AUXILIARY_SENDS, 4}
+	}
+	acx, err := al.CreateContext(app.audioDev, attribs)
+	if err != nil {
+		return fmt.Errorf("Error creating audio context:%s", err)
+	}
+
+	// Makes the context the current one
+	err = al.MakeContextCurrent(acx)
+	if err != nil {
+		return fmt.Errorf("Error setting audio context current:%s", err)
+	}
+	app.audio = true
+	app.log.Info("%s version: %s", al.GetString(al.Vendor), al.GetString(al.Version))
+
+	// Ogg Vorbis support
+	err = ov.Load()
+	if err == nil {
+		app.vorbis = true
+		vorbis.Load()
+	}
+	return nil
+}

+ 1 - 1
util/app/framerater.go

@@ -1,4 +1,4 @@
-package app
+package application
 
 import (
 	"time"