Android: Added first prototype of AndroidAudioRenderer
git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7723 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
This commit is contained in:
		
							parent
							
								
									68bac95cd5
								
							
						
					
					
						commit
						a7974ac659
					
				| @ -46,6 +46,11 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt | ||||
|      * ConfigType.BEST is RGBA8888 or better if supported by the hardware | ||||
|      */ | ||||
|     protected ConfigType eglConfigType = ConfigType.FASTEST; | ||||
|      | ||||
|     /** | ||||
|      * If true all valid and not valid egl configs are logged | ||||
|      */ | ||||
|     protected boolean eglConfigVerboseLogging = false; | ||||
| 
 | ||||
|     /** | ||||
|      * Title of the exit dialog, default is "Do you want to exit?" | ||||
| @ -68,6 +73,7 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt | ||||
|         super.onCreate(savedInstanceState); | ||||
| 
 | ||||
|         JmeSystem.setResources(getResources()); | ||||
|         JmeSystem.setActivity(this); | ||||
| 
 | ||||
|         requestWindowFeature(Window.FEATURE_NO_TITLE); | ||||
|         getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, | ||||
| @ -88,7 +94,7 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt | ||||
|         app.setSettings(settings); | ||||
|         app.start();     | ||||
|         ctx = (OGLESContext) app.getContext(); | ||||
|         view = ctx.createView(input, eglConfigType); | ||||
|         view = ctx.createView(input, eglConfigType, eglConfigVerboseLogging); | ||||
|    		setContentView(view);       		 | ||||
|     } | ||||
| 
 | ||||
| @ -129,8 +135,8 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onDestroy(){ | ||||
|         super.onDestroy();         | ||||
|         app.stop(); | ||||
|         app.stop(true); | ||||
|         super.onDestroy();                 | ||||
|         logger.info("onDestroy"); | ||||
|     } | ||||
| 
 | ||||
| @ -138,6 +144,7 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt | ||||
|     { | ||||
|         return app; | ||||
|     } | ||||
|      | ||||
|     /** | ||||
|      * Called when an error has occured. This is typically | ||||
|      * invoked when an uncought exception is thrown in the render thread. | ||||
| @ -186,7 +193,7 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt | ||||
|     {         | ||||
|         if (whichButton != -2) | ||||
|         { | ||||
|             app.stop(); | ||||
|             app.stop(true); | ||||
|             this.finish(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -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"); | ||||
|  | ||||
| @ -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 | ||||
|          | ||||
|     } | ||||
|      | ||||
|      | ||||
| 
 | ||||
| } | ||||
| @ -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 | ||||
|          | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| @ -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; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -1,6 +1,7 @@ | ||||
| package com.jme3.system; | ||||
| 
 | ||||
| 
 | ||||
| import android.app.Activity; | ||||
| import android.content.res.Resources; | ||||
| import com.jme3.util.AndroidLogHandler; | ||||
| import com.jme3.asset.AndroidAssetManager; | ||||
| @ -12,6 +13,7 @@ import com.jme3.audio.AudioRenderer; | ||||
| import com.jme3.audio.Environment; | ||||
| import com.jme3.audio.Listener; | ||||
| import com.jme3.audio.ListenerParam; | ||||
| import com.jme3.audio.android.AndroidAudioRenderer; | ||||
| //import com.jme3.audio.DummyAudioRenderer; | ||||
| import com.jme3.system.JmeContext.Type; | ||||
| import com.jme3.system.android.OGLESContext; | ||||
| @ -93,9 +95,11 @@ public class JmeSystem | ||||
|     private static boolean initialized = false; | ||||
|     private static boolean lowPermissions = false; | ||||
|     private static Resources res; | ||||
|     private static Activity activity; | ||||
| 
 | ||||
|     public static void initialize(AppSettings settings) | ||||
|     { | ||||
|          | ||||
|         if (initialized) | ||||
|             return; | ||||
| 
 | ||||
| @ -116,7 +120,7 @@ public class JmeSystem | ||||
| 
 | ||||
|     public static String getFullName() | ||||
|     { | ||||
|         return "jMonkey Engine 3 ALPHA 0.6 Android"; | ||||
|         return "jMonkey Engine 3 ALPHA 0.7 Android"; | ||||
|     } | ||||
|      | ||||
|     public static void setLowPermissions(boolean lowPerm) | ||||
| @ -137,28 +141,7 @@ public class JmeSystem | ||||
| 
 | ||||
|     public static AudioRenderer newAudioRenderer(AppSettings settings)  | ||||
|     { | ||||
| 		return new AudioRenderer()  | ||||
| 		    { | ||||
| 			public void setListener(Listener listener) {} | ||||
| 			public void setEnvironment(Environment env) {} | ||||
| 			public void playSourceInstance(AudioNode src) {} | ||||
| 			public void playSource(AudioNode src) {} | ||||
| 			public void pauseSource(AudioNode src) {} | ||||
| 			public void stopSource(AudioNode src) {} | ||||
| 			public void deleteAudioData(AudioData ad) {} | ||||
| 			public void initialize() {} | ||||
| 			public void update(float tpf) {} | ||||
| 			public void cleanup() {} | ||||
| 			public void updateListenerParam(Listener listener, | ||||
| 					ListenerParam param) { | ||||
| 				// TODO Auto-generated method stub | ||||
| 				 | ||||
| 			} | ||||
| 			public void updateSourceParam(AudioNode src, AudioParam param) { | ||||
| 				// TODO Auto-generated method stub | ||||
| 				 | ||||
| 			} | ||||
| 		}; | ||||
| 		return new AndroidAudioRenderer(activity);  | ||||
|     } | ||||
| 
 | ||||
|     public static void setResources(Resources res) | ||||
| @ -171,6 +154,17 @@ public class JmeSystem | ||||
|         return res; | ||||
|     } | ||||
| 
 | ||||
|     public static void setActivity(Activity activity) | ||||
|     { | ||||
|         JmeSystem.activity = activity; | ||||
|     } | ||||
| 
 | ||||
|     public static Activity getActivity() | ||||
|     { | ||||
|         return activity; | ||||
|     }     | ||||
|      | ||||
| 
 | ||||
|     public static AssetManager newAssetManager() | ||||
|     { | ||||
| 	    logger.info("newAssetManager()"); | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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) { | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user