uiViewController.set_View(graphics);\r
this.graphics.Run();\r
this.uiWindow.MakeKeyAndVisible();\r
- Gdx.app.log("IOSApplication", "created");\r
+ Gdx.app.debug("IOSApplication", "created");\r
return true;\r
}\r
\r
width = (int)bounds.get_Width();\r
height = (int)bounds.get_Height();\r
} \r
- Gdx.app.log("IOSApplication", "View: " + orientation.toString() + " " + width + "x" + height);\r
+ Gdx.app.debug("IOSApplication", "View: " + orientation.toString() + " " + width + "x" + height);\r
\r
// return resulting view size (based on orientation)\r
return new RectangleF(0, 0, width, height);\r
\r
@Override\r
public void OnActivated(UIApplication uiApp) {\r
- Gdx.app.log("IOSApplication", "resumed");\r
+ Gdx.app.debug("IOSApplication", "resumed");\r
if(!firstResume) {\r
graphics.MakeCurrent();\r
listener.resume();\r
\r
@Override\r
public void OnResignActivation(UIApplication uiApp) {\r
- Gdx.app.log("IOSApplication", "paused");\r
+ Gdx.app.debug("IOSApplication", "paused");\r
graphics.MakeCurrent();\r
listener.pause();\r
Gdx.gl.glFlush();\r
\r
@Override\r
public void WillTerminate(UIApplication uiApp) {\r
- Gdx.app.log("IOSApplication", "disposed");\r
+ Gdx.app.debug("IOSApplication", "disposed");\r
graphics.MakeCurrent();\r
listener.dispose();\r
Gdx.gl.glFlush();\r
// setup view and OpenGL
width = (int)bounds.get_Width();
height = (int)bounds.get_Height();
- app.log("IOSGraphics", bounds.get_Width() + "x" + bounds.get_Height() + ", " + UIScreen.get_MainScreen().get_Scale());
+ app.debug("IOSGraphics", bounds.get_Width() + "x" + bounds.get_Height() + ", " + UIScreen.get_MainScreen().get_Scale());
this.app = app;\r
this.input = input;
set_LayerRetainsBacking(false);
ppiY = ppi;\r
ppcX = ppiX / 2.54f;\r
ppcY = ppcY / 2.54f;\r
- app.log("IOSGraphics", "Display: ppi=" + ppi + ", density=" + density);\r
+ app.debug("IOSGraphics", "Display: ppi=" + ppi + ", density=" + density);\r
\r
// time + FPS
lastFrameTime = System.nanoTime();
protected void OnResize(EventArgs event) {
super.OnResize(event);
\r
- // noblemaster: I don't think this method will get called on iOS!? (at least not as of 2012-09-27)\r
- Gdx.app.error("IOSGraphics", "OnResize(...) is not implement.");
+ // not used on iOS\r
+ Gdx.app.debug("IOSGraphics", "iOS OnResize(...) is not implement (don't think it is needed?).");
}
@ExportAttribute.Annotation("layerClass")
public class IOSSound implements Sound {
\r
/** The maximum number of players to instantiate to support simultaneous playback. Bigger? */\r
- private static final int MAX_PLAYERS = 10;\r
+ private static final int MAX_PLAYERS = 8;\r
\r
/** Our sound players. More than one to support simultaneous playback. */\r
private AVAudioPlayer[] players;\r
-\r
+ /** The next player we think should be available for play - we circling through them to find a free one. */\r
+ private int playerIndex;\r
+ \r
+ // one single thread will play sounds outside the rendering low (otherwise our FPS drops!)\r
+ private static class PlayThread extends Thread {\r
+ @Override\r
+ public void run () {\r
+ Gdx.app.debug("IOSSound", "Sound player is running.");\r
+ \r
+ // get the latest play thread\r
+ Thread playThread;\r
+ synchronized (IOSSound.sync) {\r
+ playThread = IOSSound.playThread;\r
+ }\r
+ \r
+ // our temp player list\r
+ List<AVAudioPlayer> playQueueCopy = new ArrayList<AVAudioPlayer>(64);\r
+ \r
+ // our play loop which will continue as long as we are the active thread\r
+ Thread currentThread = Thread.currentThread();\r
+ while (currentThread == playThread) {\r
+ // play songs queued via our own copy to not impact rendering performance\r
+ synchronized (IOSSound.sync) {\r
+ playQueueCopy.addAll(playQueue);\r
+ playQueue.clear();\r
+ }\r
+ for (int i = 0; i < playQueueCopy.size(); i++) {\r
+ playQueueCopy.get(i).Play();\r
+ }\r
+ playQueueCopy.clear();\r
+ \r
+ // sleep \r
+ try {\r
+ Thread.sleep(5);\r
+ }\r
+ catch (InterruptedException e) {\r
+ Gdx.app.error("IOSSound", "Error in sound player thread.", e);\r
+ }\r
+ \r
+ // get the latest play thread\r
+ synchronized (IOSSound.sync) {\r
+ playThread = IOSSound.playThread;\r
+ }\r
+ }\r
+ \r
+ Gdx.app.debug("IOSSound", "Sound player is disposed.");\r
+ } \r
+ }\r
+ private static final Object sync = new Object();\r
+ private static PlayThread playThread = null;\r
+ private static int soundCounter = 0;\r
+ private static List<AVAudioPlayer> playQueue = new ArrayList<AVAudioPlayer>(64);\r
+ \r
\r
/**\r
* Creates a new sound object. We are creating several AVAudioPlayer objects to\r
throw new GdxRuntimeException("Error creating audio player (index: " + i + "): " + error[0].ToString());\r
}\r
}\r
+ playerIndex = 0;\r
+ \r
+ // create the play thread if it doesn't exist yet\r
+ synchronized (sync) {\r
+ soundCounter++;\r
+ \r
+ // create play thread as needed: plays sounds outside the rendering loop (smoother rendering)\r
+ if (playThread == null) {\r
+ playThread = new PlayThread();\r
+ playThread.setPriority(Thread.MIN_PRIORITY);\r
+ playThread.start();\r
+ }\r
+ }\r
}\r
\r
/**\r
*/\r
private int findAvailablePlayer() {\r
for (int i = 0; i < players.length; i++) {\r
- if (!players[i].get_Playing()) {\r
+ int index = (playerIndex + i) % players.length;\r
+ if (!players[index].get_Playing()) {\r
+ // point to the next likely free player\r
+ playerIndex = (index + 1) % players.length; \r
+ \r
+ // return the free player\r
return i;\r
}\r
}\r
player.set_NumberOfLoops(looping ? -1 : 0); // Note: -1 for looping!\r
player.set_Volume(volume);\r
player.set_Pan(pan);\r
- player.Play();\r
+ \r
+ // we let the thread play our song as not to impact rendering performance (FPS)\r
+ synchronized (sync) {\r
+ playQueue.add(player);\r
+ }\r
}\r
\r
// and return the index/id of the player\r
@Override
public void stop() {
+ synchronized (sync) {\r
+ // we clear the player queue so no song is player after call to stop!\r
+ playQueue.clear();\r
+ }\r
+ \r
// stop all players\r
for (int i = 0; i < players.length; i++) {\r
players[i].Stop();\r
}\r
}
-
- @Override
+\r
+ @Override\r
public void dispose() {\r
// dispose all players\r
- for (int i = 0; i < players.length; i++) {
+ for (int i = 0; i < players.length; i++) {\r
players[i].Dispose();\r
players[i] = null;\r
- }
- }
+ }\r
+ \r
+ // dispose play thread if no more sounds are available\r
+ synchronized (sync) {\r
+ soundCounter--;\r
+ \r
+ // no more sounds?\r
+ if (soundCounter == 0) {\r
+ playThread = null;\r
+ }\r
+ }\r
+ }\r
@Override
public void stop(long soundId) {\r