OSDN Git Service

Android: Added first prototype of AndroidAudioRenderer
authorkimxilxyong <kimxilxyong@75d07b2b-3a1a-0410-a2c5-0572b91ccdca>
Fri, 24 Jun 2011 20:11:27 +0000 (20:11 +0000)
committerkimxilxyong <kimxilxyong@75d07b2b-3a1a-0410-a2c5-0572b91ccdca>
Fri, 24 Jun 2011 20:11:27 +0000 (20:11 +0000)
git-svn-id: http://jmonkeyengine.googlecode.com/svn/trunk@7723 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

engine/src/android/com/jme3/app/AndroidHarness.java
engine/src/android/com/jme3/asset/AndroidAssetManager.java
engine/src/android/com/jme3/audio/android/AndroidAudioData.java [new file with mode: 0644]
engine/src/android/com/jme3/audio/android/AndroidAudioRenderer.java [new file with mode: 0644]
engine/src/android/com/jme3/audio/plugins/AndroidAudioLoader.java [new file with mode: 0644]
engine/src/android/com/jme3/system/JmeSystem.java
engine/src/android/com/jme3/system/android/AndroidConfigChooser.java
engine/src/android/com/jme3/system/android/OGLESContext.java

index 3639733..d292daf 100644 (file)
@@ -46,6 +46,11 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
      * ConfigType.BEST is RGBA8888 or better if supported by the hardware\r
      */\r
     protected ConfigType eglConfigType = ConfigType.FASTEST;\r
+    \r
+    /**\r
+     * If true all valid and not valid egl configs are logged\r
+     */\r
+    protected boolean eglConfigVerboseLogging = false;\r
 \r
     /**\r
      * Title of the exit dialog, default is "Do you want to exit?"\r
@@ -68,6 +73,7 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
         super.onCreate(savedInstanceState);\r
 \r
         JmeSystem.setResources(getResources());\r
+        JmeSystem.setActivity(this);\r
 \r
         requestWindowFeature(Window.FEATURE_NO_TITLE);\r
         getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,\r
@@ -88,7 +94,7 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
         app.setSettings(settings);\r
         app.start();    \r
         ctx = (OGLESContext) app.getContext();\r
-        view = ctx.createView(input, eglConfigType);\r
+        view = ctx.createView(input, eglConfigType, eglConfigVerboseLogging);\r
                setContentView(view);                   \r
     }\r
 \r
@@ -129,8 +135,8 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
 \r
     @Override\r
     protected void onDestroy(){\r
-        super.onDestroy();        \r
-        app.stop();\r
+        app.stop(true);\r
+        super.onDestroy();                \r
         logger.info("onDestroy");\r
     }\r
 \r
@@ -138,6 +144,7 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
     {\r
         return app;\r
     }\r
+    \r
     /**\r
      * Called when an error has occured. This is typically\r
      * invoked when an uncought exception is thrown in the render thread.\r
@@ -186,7 +193,7 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
     {        \r
         if (whichButton != -2)\r
         {\r
-            app.stop();\r
+            app.stop(true);\r
             this.finish();\r
         }\r
     }\r
index d9e8720..88f24ff 100644 (file)
@@ -39,6 +39,7 @@ import java.util.logging.Logger;
 
 import com.jme3.asset.plugins.AndroidLocator;
 import com.jme3.asset.plugins.ClasspathLocator;
+import com.jme3.audio.plugins.AndroidAudioLoader;
 
 /**
  * <code>AndroidAssetManager</code> is an implementation of DesktopAssetManager for Android
@@ -72,7 +73,8 @@ public class AndroidAssetManager extends DesktopAssetManager {
        // Set Default Android config                  
         this.registerLocator("", AndroidLocator.class);                
         this.registerLocator("", ClasspathLocator.class);
-        this.registerLoader(AndroidImageLoader.class, "jpg", "bmp", "gif", "png", "jpeg");        
+        this.registerLoader(AndroidImageLoader.class, "jpg", "bmp", "gif", "png", "jpeg");
+        this.registerLoader(AndroidAudioLoader.class, "ogg", "mp3");
         this.registerLoader(com.jme3.material.plugins.J3MLoader.class, "j3m");
         this.registerLoader(com.jme3.material.plugins.J3MLoader.class, "j3md");
         this.registerLoader(com.jme3.font.plugins.BitmapFontLoader.class, "fnt");
diff --git a/engine/src/android/com/jme3/audio/android/AndroidAudioData.java b/engine/src/android/com/jme3/audio/android/AndroidAudioData.java
new file mode 100644 (file)
index 0000000..39f7291
--- /dev/null
@@ -0,0 +1,54 @@
+package com.jme3.audio.android;
+
+import com.jme3.asset.AssetKey;
+import com.jme3.audio.AudioData;
+import com.jme3.audio.AudioRenderer;
+
+public class AndroidAudioData extends AudioData 
+{
+    protected AssetKey assetKey;
+    protected int soundId = 0;
+    
+    public AssetKey getAssetKey() {
+        return assetKey;
+    }
+
+    public void setAssetKey(AssetKey assetKey) {
+        this.assetKey = assetKey;
+    }
+
+    public int getSoundId() {
+        return soundId;
+    }
+
+    public void setSoundId(int soundId) {
+        this.soundId = soundId;
+    }
+
+    @Override
+    public DataType getDataType() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public float getDuration() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public void resetObject() {
+        // TODO Auto-generated method stub
+        
+    }
+
+    @Override
+    public void deleteObject(AudioRenderer r) {
+        // TODO Auto-generated method stub
+        
+    }
+    
+    
+
+}
diff --git a/engine/src/android/com/jme3/audio/android/AndroidAudioRenderer.java b/engine/src/android/com/jme3/audio/android/AndroidAudioRenderer.java
new file mode 100644 (file)
index 0000000..b9afae0
--- /dev/null
@@ -0,0 +1,518 @@
+/*
+ * Copyright (c) 2009-2010 jMonkeyEngine
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
+ *   may be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.jme3.audio.android;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.AssetManager;
+import android.media.AudioManager;
+import android.media.SoundPool;
+
+import com.jme3.audio.ListenerParam;
+import com.jme3.audio.AudioParam;
+import com.jme3.audio.AudioBuffer;
+import com.jme3.audio.AudioData;
+import com.jme3.audio.AudioRenderer;
+import com.jme3.audio.AudioNode;
+import com.jme3.audio.AudioNode.Status;
+import com.jme3.audio.AudioStream;
+import com.jme3.audio.Environment;
+import com.jme3.audio.Filter;
+import com.jme3.audio.Listener;
+import com.jme3.audio.LowPassFilter;
+import com.jme3.math.Vector3f;
+import com.jme3.util.BufferUtils;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+
+/**
+ * This class is the android implementation for {@link AudioRenderer}
+ * @author larynx
+ *
+ */
+public class AndroidAudioRenderer implements AudioRenderer, SoundPool.OnLoadCompleteListener
+{
+
+    private static final Logger logger = Logger.getLogger(AndroidAudioRenderer.class.getName());
+    private final static int MAX_NUM_CHANNELS = 16;
+    
+    private SoundPool soundPool = null;
+    private final AudioManager manager;
+    private final Context context;
+    private final AssetManager am;
+    
+    private HashMap<Integer, AudioNode> mapLoadingAudioNodes = new HashMap<Integer, AudioNode>();
+    
+    private final AtomicBoolean lastLoadCompleted = new AtomicBoolean();
+     
+
+    private Listener listener;
+    private boolean audioDisabled = false;
+
+   
+
+    public AndroidAudioRenderer(Activity context)
+    {
+        this.context = context;
+        manager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
+        context.setVolumeControlStream(AudioManager.STREAM_MUSIC);
+        am = context.getAssets();
+    }
+    
+    @Override
+    public void initialize()
+    {
+        soundPool = new SoundPool(MAX_NUM_CHANNELS, AudioManager.STREAM_MUSIC, 0);  
+        soundPool.setOnLoadCompleteListener(this);
+    }
+    
+
+    private void updateFilter(Filter f)
+    {
+        throw new UnsupportedOperationException("Filter type unsupported: " + f.getClass().getName());
+    }
+
+    @Override
+    public void updateSourceParam(AudioNode src, AudioParam param)
+    {
+            if (audioDisabled)
+                return;
+            if (src.getChannel() < 0) 
+                return;
+           
+            assert src.getChannel() >= 0;
+
+            
+            switch (param){
+                case Position:
+                    if (!src.isPositional())
+                        return;
+
+                    Vector3f pos = src.getWorldTranslation();
+                    break;
+                case Velocity:
+                    if (!src.isPositional())
+                        return;
+                    
+                    Vector3f vel = src.getVelocity();
+                    break;
+                case MaxDistance:
+                    if (!src.isPositional())
+                        return;
+                    break;
+                case RefDistance:
+                    if (!src.isPositional())
+                        return;
+                    break;
+                case ReverbFilter:
+                    if (!src.isPositional() || !src.isReverbEnabled())
+                        return;
+                    break;
+                case ReverbEnabled:
+                    if (!src.isPositional())
+                        return;
+
+                    if (src.isReverbEnabled()){
+                        updateSourceParam(src, AudioParam.ReverbFilter);
+                    }
+                    break;
+                case IsPositional:
+                    break;
+                case Direction:
+                    if (!src.isDirectional())
+                        return;
+
+                    Vector3f dir = src.getDirection();                   
+                    break;
+                case InnerAngle:
+                    if (!src.isDirectional())
+                        return;
+                    break;
+                case OuterAngle:
+                    if (!src.isDirectional())
+                        return;
+                    break;
+                case IsDirectional:
+                    if (src.isDirectional()){
+                        updateSourceParam(src, AudioParam.Direction);
+                        updateSourceParam(src, AudioParam.InnerAngle);
+                        updateSourceParam(src, AudioParam.OuterAngle);
+                    }else{
+                    }
+                    break;
+                case DryFilter:
+                    if (src.getDryFilter() != null){
+                        Filter f = src.getDryFilter();
+                        if (f.isUpdateNeeded()){
+                            updateFilter(f);
+
+                        }
+                    }
+                    break;
+                case Looping:
+                    if (src.isLooping()){
+                    }
+                    break;
+                case Volume:
+                    
+                    soundPool.setVolume(src.getChannel(), src.getVolume(), src.getVolume());
+
+                    break;
+                case Pitch:
+
+                    break;
+            }
+        
+    }
+    
+    @Override
+    public void updateListenerParam(Listener listener, ListenerParam param)
+    {
+            if (audioDisabled)
+                return;
+            
+            switch (param){
+                case Position:
+                    Vector3f pos = listener.getLocation();
+
+                    break;
+                case Rotation:
+                    Vector3f dir = listener.getDirection();
+                    Vector3f up  = listener.getUp();
+
+                    break;
+                case Velocity:
+                    Vector3f vel = listener.getVelocity();
+
+                    break;
+                case Volume:
+                    //alListenerf(AL_GAIN, listener.getVolume());
+                    break;
+            }
+
+    }
+
+
+    public void update(float tpf)
+    {
+        // does nothing
+    }
+
+    public void updateInThread(float tpf)
+    {
+        if (audioDisabled)
+            return;
+        if (!audioDisabled)
+            return;
+
+    }
+
+    public void setListener(Listener listener) 
+    {
+            if (audioDisabled)
+                return;
+
+            if (this.listener != null){
+                // previous listener no longer associated with current
+                // renderer
+                this.listener.setRenderer(null);
+            }
+            
+            this.listener = listener;
+            this.listener.setRenderer(this);            
+
+    }
+    
+    @Override
+    public void onLoadComplete(SoundPool soundPool, int sampleId, int status)
+    {
+        //lastLoadCompleted.set(true);
+        
+        if (status == 0)
+        {
+            AudioNode src = mapLoadingAudioNodes.get(sampleId);
+            if (src.getAudioData() instanceof AndroidAudioData)
+            {
+                AndroidAudioData audioData = (AndroidAudioData)src.getAudioData();
+                
+                int channelIndex;
+                channelIndex = soundPool.play(audioData.getSoundId(), 1f, 1f, 1, -1, 1f);
+                src.setChannel(channelIndex);
+                // Playing started ?
+                if (src.getChannel() > 0)
+                {
+                    src.setStatus(Status.Playing);
+                }
+            }
+            else
+            {
+                throw new IllegalArgumentException("AudioData is not of type AndroidAudioData for AudioNode " + src.toString());
+            }
+        }
+    }
+    
+    @Override
+    public void cleanup()
+    {
+        if (soundPool != null)
+        {
+            for (AudioNode src: mapLoadingAudioNodes.values())
+            {
+                if ((src.getStatus() == Status.Playing) && (src.getChannel() > 0))
+                {
+                    soundPool.stop(src.getChannel());
+                }
+                
+                if (src.getAudioData() instanceof AndroidAudioData)
+                {
+                    AndroidAudioData audioData = (AndroidAudioData)src.getAudioData();
+                    if (audioData.getSoundId() > 0)
+                    {
+                        soundPool.unload(audioData.getSoundId());
+                    }                
+                }                        
+            }
+        
+            soundPool.release();
+            soundPool = null;
+        }
+    }
+
+    public void playSourceInstance(AudioNode src)
+    {
+            if (audioDisabled)
+                return;
+            
+            AndroidAudioData audioData;
+            int soundId = 0;
+            
+            if (src.getAudioData() instanceof AndroidAudioData)
+            {
+                audioData = (AndroidAudioData)src.getAudioData();
+                if (audioData.isUpdateNeeded() || (audioData.getSoundId() == 0))
+                {
+                    if (audioData.getSoundId() > 0)
+                    {
+                        if (src.getChannel() > 0)
+                        {
+                            soundPool.stop(src.getChannel());
+                            src.setChannel(-1);
+                        }
+                        soundPool.unload(audioData.getSoundId());
+                    }
+                                                          
+                    try 
+                    {                                           
+                        soundId = soundPool.load(am.openFd(audioData.getAssetKey().getName()), 1);   
+                    } 
+                    catch (IOException e) 
+                    {
+                        logger.log(Level.SEVERE, "Failed to load sound " + audioData.getAssetKey().getName(), e);
+                        soundId = -1;
+                    }
+                    audioData.setSoundId(soundId);                    
+                }
+            }
+            else
+            {
+                throw new IllegalArgumentException("AudioData is not of type AndroidAudioData for AudioNode " + src.toString());
+            }
+            
+            // Sound failed to load ?
+            if (audioData.getSoundId() <= 0)
+            {
+                throw new IllegalArgumentException("Failed to load: " + audioData.getAssetKey().getName());
+            }
+            else
+            {
+                int channelIndex;
+                channelIndex = soundPool.play(audioData.getSoundId(), 1f, 1f, 1, -1, 1f);
+                if (channelIndex == 0)
+                {
+                    // Loading is not finished
+                    // Store the soundId and the AudioNode for async loading and later play start
+                    mapLoadingAudioNodes.put(audioData.getSoundId(), src);
+                }                
+                src.setChannel(channelIndex);
+            }
+            
+            // Playing started ?
+            if (src.getChannel() > 0)
+            {
+                src.setStatus(Status.Playing);
+            }
+    }
+
+    
+    public void playSource(AudioNode src) 
+    {
+            if (audioDisabled)
+                return;
+
+            //assert src.getStatus() == Status.Stopped || src.getChannel() == -1;
+
+            if (src.getStatus() == Status.Playing)
+            {
+                return;
+            }
+            else if (src.getStatus() == Status.Stopped)
+            {
+                playSourceInstance(src);                
+            }
+            
+        
+    }
+
+    
+    public void pauseSource(AudioNode src) 
+    {
+            if (audioDisabled)
+                return;
+            
+            if (src.getStatus() == Status.Playing)
+            {
+                assert src.getChannel() != -1;
+
+                if (src.getChannel() > 0)
+                {
+                    soundPool.pause(src.getChannel());
+                }
+                src.setStatus(Status.Paused);
+            }
+
+    }
+
+    
+    public void stopSource(AudioNode src) 
+    {
+            if (audioDisabled)
+                return;
+            
+            if (src.getStatus() != Status.Stopped){
+                int chan = src.getChannel();
+                assert chan != -1; // if it's not stopped, must have id
+                
+                if (src.getChannel() > 0)
+                {
+                    soundPool.stop(src.getChannel());
+                    src.setChannel(-1);
+                }
+
+                src.setStatus(Status.Stopped);                                
+            }
+            
+            AndroidAudioData audioData;                       
+            if (src.getAudioData() instanceof AndroidAudioData)
+            {
+                audioData = (AndroidAudioData)src.getAudioData();
+                if (audioData.getSoundId() > 0)
+                {
+                    soundPool.unload(audioData.getSoundId());
+                }
+                audioData.setSoundId(0);
+                
+            }
+            else
+            {
+                throw new IllegalArgumentException("AudioData is not of type AndroidAudioData for AudioNode " + src.toString());
+            }
+            
+
+    }
+
+    private int convertFormat(AudioData ad)
+    {
+        /*
+        switch (ad.getBitsPerSample()){
+            case 8:
+                if (ad.getChannels() == 1)
+                    return AL_FORMAT_MONO8;
+                else if (ad.getChannels() == 2)
+                    return AL_FORMAT_STEREO8;
+
+                break;
+            case 16:
+                if (ad.getChannels() == 1)
+                    return AL_FORMAT_MONO16;
+                else
+                    return AL_FORMAT_STEREO16;
+        }
+        */
+        throw new UnsupportedOperationException("Unsupported channels/bits combination: "+
+                                                "bits="+ad.getBitsPerSample()+", channels="+ad.getChannels());
+    }
+
+    public void updateAudioData(AndroidAudioData data)
+    {
+        throw new UnsupportedOperationException("updateAudioData");
+    }
+
+    @Override
+    public void deleteAudioData(AudioData ad) 
+    {                     
+        if (ad instanceof AndroidAudioData)
+        {
+            if (((AndroidAudioData)ad).getSoundId() > 0)
+            {
+                soundPool.unload(((AndroidAudioData)ad).getSoundId());
+            }
+            ((AndroidAudioData)ad).setSoundId(0);
+            
+        }
+        else
+        {
+            throw new IllegalArgumentException("AudioData is not of type AndroidAudioData in deleteAudioData");
+        }        
+    }
+
+    @Override
+    public void setEnvironment(Environment env) {
+        // TODO Auto-generated method stub
+        
+    }
+
+
+
+
+}
diff --git a/engine/src/android/com/jme3/audio/plugins/AndroidAudioLoader.java b/engine/src/android/com/jme3/audio/plugins/AndroidAudioLoader.java
new file mode 100644 (file)
index 0000000..4c20619
--- /dev/null
@@ -0,0 +1,27 @@
+package com.jme3.audio.plugins;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import com.jme3.asset.AssetInfo;
+import com.jme3.asset.AssetLoader;
+import com.jme3.audio.android.AndroidAudioData;
+
+public class AndroidAudioLoader implements AssetLoader 
+{
+
+    @Override
+    public Object load(AssetInfo assetInfo) throws IOException 
+    {
+
+        InputStream in = assetInfo.openStream();
+        if (in != null)
+        {            
+            in.close();
+        }
+        AndroidAudioData result = new AndroidAudioData();
+        result.setAssetKey( assetInfo.getKey() );
+        return result;
+    }
+
+}
index 2628b31..a7481e9 100644 (file)
@@ -1,6 +1,7 @@
 package com.jme3.system;\r
 \r
 \r
+import android.app.Activity;\r
 import android.content.res.Resources;\r
 import com.jme3.util.AndroidLogHandler;\r
 import com.jme3.asset.AndroidAssetManager;\r
@@ -12,6 +13,7 @@ import com.jme3.audio.AudioRenderer;
 import com.jme3.audio.Environment;\r
 import com.jme3.audio.Listener;\r
 import com.jme3.audio.ListenerParam;\r
+import com.jme3.audio.android.AndroidAudioRenderer;\r
 //import com.jme3.audio.DummyAudioRenderer;\r
 import com.jme3.system.JmeContext.Type;\r
 import com.jme3.system.android.OGLESContext;\r
@@ -93,9 +95,11 @@ public class JmeSystem
     private static boolean initialized = false;\r
     private static boolean lowPermissions = false;\r
     private static Resources res;\r
+    private static Activity activity;\r
 \r
     public static void initialize(AppSettings settings)\r
     {\r
+        \r
         if (initialized)\r
             return;\r
 \r
@@ -116,7 +120,7 @@ public class JmeSystem
 \r
     public static String getFullName()\r
     {\r
-        return "jMonkey Engine 3 ALPHA 0.6 Android";\r
+        return "jMonkey Engine 3 ALPHA 0.7 Android";\r
     }\r
     \r
     public static void setLowPermissions(boolean lowPerm)\r
@@ -137,28 +141,7 @@ public class JmeSystem
 \r
     public static AudioRenderer newAudioRenderer(AppSettings settings) \r
     {\r
-               return new AudioRenderer() \r
-                   {\r
-                       public void setListener(Listener listener) {}\r
-                       public void setEnvironment(Environment env) {}\r
-                       public void playSourceInstance(AudioNode src) {}\r
-                       public void playSource(AudioNode src) {}\r
-                       public void pauseSource(AudioNode src) {}\r
-                       public void stopSource(AudioNode src) {}\r
-                       public void deleteAudioData(AudioData ad) {}\r
-                       public void initialize() {}\r
-                       public void update(float tpf) {}\r
-                       public void cleanup() {}\r
-                       public void updateListenerParam(Listener listener,\r
-                                       ListenerParam param) {\r
-                               // TODO Auto-generated method stub\r
-                               \r
-                       }\r
-                       public void updateSourceParam(AudioNode src, AudioParam param) {\r
-                               // TODO Auto-generated method stub\r
-                               \r
-                       }\r
-               };\r
+               return new AndroidAudioRenderer(activity); \r
     }\r
 \r
     public static void setResources(Resources res)\r
@@ -171,6 +154,17 @@ public class JmeSystem
         return res;\r
     }\r
 \r
+    public static void setActivity(Activity activity)\r
+    {\r
+        JmeSystem.activity = activity;\r
+    }\r
+\r
+    public static Activity getActivity()\r
+    {\r
+        return activity;\r
+    }    \r
+    \r
+\r
     public static AssetManager newAssetManager()\r
     {\r
            logger.info("newAssetManager()");\r
index 12d8f59..f082b5f 100644 (file)
@@ -25,6 +25,8 @@ public class AndroidConfigChooser implements EGLConfigChooser
     protected ConfigType type;
     protected int pixelFormat;
     
+    protected boolean verbose = false;
+    
     private final static int EGL_OPENGL_ES2_BIT = 4;
 
     public enum ConfigType 
@@ -39,9 +41,10 @@ public class AndroidConfigChooser implements EGLConfigChooser
         BEST
     }
     
-    public AndroidConfigChooser(ConfigType type)
+    public AndroidConfigChooser(ConfigType type, boolean verbose)
     {
         this.type = type;
+        this.verbose = verbose;
     }
         
     /**
@@ -69,10 +72,15 @@ public class AndroidConfigChooser implements EGLConfigChooser
         //Querying actual configurations
         EGLConfig[] conf = new EGLConfig[configurations];
         egl.eglGetConfigs(display, conf, configurations, num_conf);
-   
-       
+          
         int[] value = new int[1];        
-    
+   
+        
+        if (configurations <= 0)
+        {
+            logger.severe("###ERROR### ZERO EGL Configurations found, This Is a Problem"); 
+        }
+        
         // Loop over all configs to get the best
         for(int i = 0; i < configurations; i++)
         {                    
@@ -94,27 +102,57 @@ public class AndroidConfigChooser implements EGLConfigChooser
                             bestConfig = better(bestConfig, conf[i], egl, display);
                             fastestConfig = faster(fastestConfig, conf[i], egl, display);
                             
-                            logger.info("Supported EGL Configuration #" + i );                            
-                            logEGLConfig(conf[i], display, egl);                                               
+                            if (verbose)
+                            {
+                                logger.info("** Supported EGL Configuration #" + i );                            
+                                logEGLConfig(conf[i], display, egl);
+                            }
+                        }
+                        else
+                        {
+                            if (verbose)
+                            {
+                                logger.info("NOT Supported EGL Configuration #" + i + " EGL_OPENGL_ES2_BIT not set");                            
+                                logEGLConfig(conf[i], display, egl); 
+                            }
+                        }  
+                    }
+                    else
+                    {
+                        if (verbose)
+                        {
+                            logger.info("NOT Supported EGL Configuration #" + i + " EGL_DEPTH_SIZE != 16");                            
+                            logEGLConfig(conf[i], display, egl);
                         }
                     }
                 }
+                else
+                {
+                    if (verbose)
+                    {
+                        logger.info("NOT Supported EGL Configuration #" + i + " EGL_WINDOW_BIT not set");                            
+                        logEGLConfig(conf[i], display, egl);
+                    }
+                }
             }
             else
             {
-                break;
+                logger.severe("###ERROR### EGL Configuration #" + i + " is NULL");
             }
         }
     
         
         if ((type == ConfigType.BEST) && (bestConfig != null))
         {
-            logger.info("### JME3 ### using best EGL configuration available here: ");
+            logger.info("JME3 using best EGL configuration available here: ");
             choosenConfig = bestConfig;
         }
         else
         {
-            logger.info("### JME3 ### using fastest EGL configuration available here: ");
+            if (fastestConfig != null)
+            {
+                logger.info("JME3 using fastest EGL configuration available here: ");
+            }
             choosenConfig = fastestConfig;            
         }
         
@@ -127,7 +165,7 @@ public class AndroidConfigChooser implements EGLConfigChooser
         }
         else
         {
-            logger.severe("Unable to get a valid OpenGL ES 2.0 config");
+            logger.severe("###ERROR### Unable to get a valid OpenGL ES 2.0 config, nether Fastest nor Best found! Bug. Please report this.");
             clientOpenGLESVersion = 1;
             pixelFormat = PixelFormat.UNKNOWN;
             return false;
index a75dd80..bedc9e6 100644 (file)
@@ -75,7 +75,7 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer
     protected final AtomicBoolean created = new AtomicBoolean(false);
     protected final AtomicBoolean renderable = new AtomicBoolean(false);
     protected final AtomicBoolean needClose = new AtomicBoolean(false);
-    protected final Object createdLock = new Object();
+   
     protected final AppSettings settings = new AppSettings(true);
 
        /* >= OpenGL ES 2.0 (Android 2.2+) */
@@ -127,7 +127,7 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer
      */
     public GLSurfaceView createView(AndroidInput view)
     {
-        return createView(view, ConfigType.FASTEST);
+        return createView(view, ConfigType.FASTEST, false);
     }
     
     /**
@@ -136,7 +136,7 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer
      * @param debugflags 0, GLSurfaceView.DEBUG_CHECK_GL_ERROR | GLSurfaceView.DEBUG_LOG_GL_CALLS
      * @return GLSurfaceView The newly created view
      */    
-    public GLSurfaceView createView(AndroidInput view, ConfigType configType)
+    public GLSurfaceView createView(AndroidInput view, ConfigType configType, boolean eglConfigVerboseLogging)
     {                    
         EGL10 egl = (EGL10) EGLContext.getEGL();
         EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
@@ -151,7 +151,7 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer
         this.view = view;    
 
         // Create a config chooser
-        AndroidConfigChooser configChooser = new AndroidConfigChooser(configType);
+        AndroidConfigChooser configChooser = new AndroidConfigChooser(configType, eglConfigVerboseLogging);
         // Init chooser
         if (!configChooser.findConfig(egl, display))
         {
@@ -239,18 +239,24 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer
      * De-initialize in the OpenGL thread.
      */
     protected void deinitInThread()
-    {        
-        if (renderer != null) 
-            renderer.cleanup();
-            
-        listener.destroy();
-        
-        // do android specific cleaning here
-               logger.info("Display destroyed.");              
-               renderable.set(false);
-               created.set(false);
-               renderer = null;
-               timer = null;
+    {   
+        if (renderable.get())
+        {
+            renderable.set(false);
+            if (renderer != null) 
+                renderer.cleanup();
+                
+            listener.destroy();
+                                       
+            listener = null;
+               renderer = null;
+               timer = null;
+               
+            // do android specific cleaning here
+            logger.info("Display destroyed.");      
+
+               created.set(false);
+        }
     }
     
     protected void  applySettingsToRenderer(OGLESShaderRenderer renderer, AppSettings settings) 
@@ -441,12 +447,10 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer
     
     protected void waitFor(boolean createdVal)
     {
-        synchronized (createdLock){
-            while (created.get() != createdVal){
-                try {
-                    createdLock.wait();
-                } catch (InterruptedException ex) {
-                }
+        while (created.get() != createdVal){
+            try {
+                Thread.sleep(10);
+            } catch (InterruptedException ex) {
             }
         }
     }