diff options
author | Sven Gothel <[email protected]> | 2013-01-31 23:21:05 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-01-31 23:21:05 +0100 |
commit | b827223da34ae4d2970a7b27f9bc0efa96bcac5a (patch) | |
tree | 416a33b3ab14b8a556191fed374a768a2a247e48 /src | |
parent | 034a6d264385e89e289713cb7f43a7020d6d3c46 (diff) |
Android Build & Test ; WavLoader/Data javax.audio separation (part-1)
Diffstat (limited to 'src')
12 files changed, 1054 insertions, 106 deletions
diff --git a/src/java/com/jogamp/openal/JoalVersion.java b/src/java/com/jogamp/openal/JoalVersion.java new file mode 100644 index 0000000..41c333a --- /dev/null +++ b/src/java/com/jogamp/openal/JoalVersion.java @@ -0,0 +1,87 @@ +/** + * Copyright 2013 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``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 JogAmp Community 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. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.openal; + +import com.jogamp.common.GlueGenVersion; + +import com.jogamp.common.os.Platform; +import com.jogamp.common.util.VersionUtil; +import com.jogamp.common.util.JogampVersion; + +import java.util.jar.Manifest; + +public class JoalVersion extends JogampVersion { + protected static volatile JoalVersion jogampCommonVersionInfo; + + protected JoalVersion(String packageName, Manifest mf) { + super(packageName, mf); + } + + public static JoalVersion getInstance() { + if(null == jogampCommonVersionInfo) { // volatile: ok + synchronized(JoalVersion.class) { + if( null == jogampCommonVersionInfo ) { + final String packageName = "com.jogamp.openal"; + final Manifest mf = VersionUtil.getManifest(JoalVersion.class.getClassLoader(), packageName); + jogampCommonVersionInfo = new JoalVersion(packageName, mf); + } + } + } + return jogampCommonVersionInfo; + } + + public StringBuilder toString(StringBuilder sb) { + sb = super.toString(sb).append(Platform.getNewline()); + // getGLInfo(gl, sb); + return sb; + } + + public String toString() { + return toString(null).toString(); + } + + public StringBuilder getBriefOSALBuildInfo(StringBuilder sb) { + if(null==sb) { + sb = new StringBuilder(); + } + sb.append("OS: ").append(Platform.getOSName()).append(", version ").append(Platform.getOSVersion()).append(", arch ").append(Platform.getArchName()); + sb.append(Platform.getNewline()); + sb.append("JOAL GIT sha1 ").append(getImplementationCommit()); + sb.append(Platform.getNewline()); + return sb; + } + + public static void main(String args[]) { + System.err.println(VersionUtil.getPlatformInfo()); + System.err.println(GlueGenVersion.getInstance()); + // System.err.println(NativeWindowVersion.getInstance()); + System.err.println(JoalVersion.getInstance()); + } +} + diff --git a/src/java/com/jogamp/openal/UnsupportedAudioFileException.java b/src/java/com/jogamp/openal/UnsupportedAudioFileException.java new file mode 100644 index 0000000..a371191 --- /dev/null +++ b/src/java/com/jogamp/openal/UnsupportedAudioFileException.java @@ -0,0 +1,21 @@ +package com.jogamp.openal; + +public class UnsupportedAudioFileException extends Exception { + + public UnsupportedAudioFileException (String message) { + super(message); + } + + public UnsupportedAudioFileException () { + super(); + } + + public UnsupportedAudioFileException (String message, Throwable cause) { + super(message, cause); + } + + public UnsupportedAudioFileException (Throwable cause) { + super(cause); + } + +} diff --git a/src/java/com/jogamp/openal/sound3d/AudioSystem3D.java b/src/java/com/jogamp/openal/sound3d/AudioSystem3D.java index 1070d21..4d7b2b1 100644 --- a/src/java/com/jogamp/openal/sound3d/AudioSystem3D.java +++ b/src/java/com/jogamp/openal/sound3d/AudioSystem3D.java @@ -33,15 +33,20 @@ package com.jogamp.openal.sound3d; -import com.jogamp.openal.*; +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; + +import com.jogamp.openal.AL; +import com.jogamp.openal.ALC; +import com.jogamp.openal.ALCcontext; +import com.jogamp.openal.ALCdevice; +import com.jogamp.openal.ALException; +import com.jogamp.openal.ALFactory; +import com.jogamp.openal.UnsupportedAudioFileException; import com.jogamp.openal.util.WAVData; import com.jogamp.openal.util.WAVLoader; -import java.io.*; - -import javax.sound.sampled.UnsupportedAudioFileException; - - /** * The AudioSystem3D class provides a set of methods for creating and * manipulating a 3D audio environment. diff --git a/src/java/com/jogamp/openal/util/WAVData.java b/src/java/com/jogamp/openal/util/WAVData.java index 345c675..d470643 100644 --- a/src/java/com/jogamp/openal/util/WAVData.java +++ b/src/java/com/jogamp/openal/util/WAVData.java @@ -1,5 +1,6 @@ /** * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. +* Copyright (c) 2011 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -33,13 +34,21 @@ package com.jogamp.openal.util; +import java.io.IOException; +import java.io.InputStream; import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import com.jogamp.openal.ALConstants; +import com.jogamp.openal.UnsupportedAudioFileException; /** - * This class is a holder for WAV (.wav )file Data returned from the WavLoader + * This class is a holder for WAV (.wav ) file Data returned from the WavLoader, + * or directly via {@link #loadFromStream(InputStream, int, int, int)}. * - * @author Athomas Goldberg + * @author Athomas Goldberg, et.al. */ public final class WAVData { /** The audio data */ @@ -65,11 +74,67 @@ public final class WAVData { /** flag indicating whether or not the sound in the data should loop */ public final boolean loop; - WAVData(ByteBuffer data, int format, int size, int freq, boolean loop) { + public WAVData(ByteBuffer data, int format, int size, int freq, boolean loop) { this.data = data; this.format = format; this.size = size; this.freq = freq; this.loop = loop; } + + /** + * This method loads a (.wav) file into a WAVData object. + * + * @param stream An InputStream for the .WAV stream + * @param numChannels + * @param bits + * @param sampleRate + * + * @return a WAVData object containing the audio data + * + * @throws UnsupportedAudioFileException if the format of the audio if not + * supported. + * @throws IOException If the file can no be found or some other IO error + * occurs + */ + public static WAVData loadFromStream(InputStream aIn, int numChannels, int bits, int sampleRate) + throws IOException { + ReadableByteChannel aChannel = Channels.newChannel(aIn); + int format = ALConstants.AL_FORMAT_MONO8; + + if ((bits == 8) && (numChannels == 1)) { + format = ALConstants.AL_FORMAT_MONO8; + } else if ((bits == 16) && (numChannels == 1)) { + format = ALConstants.AL_FORMAT_MONO16; + } else if ((bits == 8) && (numChannels == 2)) { + format = ALConstants.AL_FORMAT_STEREO8; + } else if ((bits == 16) && (numChannels == 2)) { + format = ALConstants.AL_FORMAT_STEREO16; + } + + int size = aIn.available(); + ByteBuffer buffer = ByteBuffer.allocateDirect(size); + while (buffer.remaining() > 0) { + aChannel.read(buffer); + } + buffer.rewind(); + + // Must byte swap on big endian platforms + // Thanks to swpalmer on javagaming.org forums for hint at fix + if ((bits == 16) && (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN)) { + int len = buffer.remaining(); + for (int i = 0; i < len; i += 2) { + byte a = buffer.get(i); + byte b = buffer.get(i+1); + buffer.put(i, b); + buffer.put(i+1, a); + } + } + + WAVData result = new WAVData(buffer, format, size, sampleRate, false); + aIn.close(); + + return result; + } + } diff --git a/src/java/com/jogamp/openal/util/WAVLoader.java b/src/java/com/jogamp/openal/util/WAVLoader.java index 4ee2305..40ad99e 100644 --- a/src/java/com/jogamp/openal/util/WAVLoader.java +++ b/src/java/com/jogamp/openal/util/WAVLoader.java @@ -1,5 +1,6 @@ /** * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. +* Copyright (c) 2011 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -33,21 +34,24 @@ package com.jogamp.openal.util; -import java.io.*; -import java.nio.*; -import java.nio.channels.*; -import javax.sound.sampled.*; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; -import com.jogamp.openal.*; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; + +import com.jogamp.openal.UnsupportedAudioFileException; /** * A Loader utility for (.wav) files. Creates a WAVData object containing the * data used by the AL.alBufferData method. * - * @author Athomas Goldberg + * @author Athomas Goldberg, et.al */ -public class WAVLoader implements ALConstants { - private static final int BUFFER_SIZE = 128000; +public class WAVLoader { + // private static final int BUFFER_SIZE = 128000; /** * This method loads a (.wav) file into a WAVData object. @@ -63,16 +67,19 @@ public class WAVLoader implements ALConstants { */ public static WAVData loadFromFile(String filename) throws UnsupportedAudioFileException, IOException { - WAVData result = null; File soundFile = new File(filename); - AudioInputStream aIn = AudioSystem.getAudioInputStream(soundFile); - return readFromStream(aIn); + try { + AudioInputStream aIn = AudioSystem.getAudioInputStream(soundFile); + return loadFromStreamImpl(aIn); + } catch (javax.sound.sampled.UnsupportedAudioFileException e) { + throw new UnsupportedAudioFileException(e); + } } /** * This method loads a (.wav) file into a WAVData object. * - * @param stream An InputStream for the .WAV file. + * @param stream An InputStream for the .WAV stream. * * @return a WAVData object containing the audio data * @@ -83,53 +90,20 @@ public class WAVLoader implements ALConstants { */ public static WAVData loadFromStream(InputStream stream) throws UnsupportedAudioFileException, IOException { - WAVData result = null; - AudioInputStream aIn = AudioSystem.getAudioInputStream(stream); - return readFromStream(aIn); + AudioInputStream aIn; + try { + aIn = AudioSystem.getAudioInputStream(stream); + return loadFromStreamImpl(aIn); + } catch (javax.sound.sampled.UnsupportedAudioFileException e) { + throw new UnsupportedAudioFileException(e); + } } - private static WAVData readFromStream(AudioInputStream aIn) + private static WAVData loadFromStreamImpl(AudioInputStream aIn) throws UnsupportedAudioFileException, IOException { - ReadableByteChannel aChannel = Channels.newChannel(aIn); - AudioFormat fmt = aIn.getFormat(); - int numChannels = fmt.getChannels(); - int bits = fmt.getSampleSizeInBits(); - int format = AL_FORMAT_MONO8; - - if ((bits == 8) && (numChannels == 1)) { - format = AL_FORMAT_MONO8; - } else if ((bits == 16) && (numChannels == 1)) { - format = AL_FORMAT_MONO16; - } else if ((bits == 8) && (numChannels == 2)) { - format = AL_FORMAT_STEREO8; - } else if ((bits == 16) && (numChannels == 2)) { - format = AL_FORMAT_STEREO16; - } - - int freq = Math.round(fmt.getSampleRate()); - int size = aIn.available(); - ByteBuffer buffer = ByteBuffer.allocateDirect(size); - while (buffer.remaining() > 0) { - aChannel.read(buffer); - } - buffer.rewind(); - - // Must byte swap on big endian platforms - // Thanks to swpalmer on javagaming.org forums for hint at fix - if ((bits == 16) && (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN)) { - int len = buffer.remaining(); - for (int i = 0; i < len; i += 2) { - byte a = buffer.get(i); - byte b = buffer.get(i+1); - buffer.put(i, b); - buffer.put(i+1, a); - } - } - - WAVData result = new WAVData(buffer, format, size, freq, false); - aIn.close(); - - return result; + final AudioFormat fmt = aIn.getFormat(); + return WAVData.loadFromStream(aIn, fmt.getChannels(), fmt.getSampleSizeInBits(), Math.round(fmt.getSampleRate())); } + } diff --git a/src/test/com/jogamp/openal/test/android/BaseActivity.java b/src/test/com/jogamp/openal/test/android/BaseActivity.java new file mode 100644 index 0000000..9aec18a --- /dev/null +++ b/src/test/com/jogamp/openal/test/android/BaseActivity.java @@ -0,0 +1,115 @@ +/** + * Copyright 2013 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``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 JogAmp Community 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. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.openal.test.android; + +import android.app.Activity; +import android.os.Bundle; +import android.util.Log; + +public class BaseActivity extends Activity { + boolean isDelegatedActivity; + Activity rootActivity; + boolean setThemeCalled = false; + + public BaseActivity() { + super(); + isDelegatedActivity = false; + rootActivity = this; + } + + public void setRootActivity(Activity rootActivity) { + this.rootActivity = rootActivity; + this.isDelegatedActivity = this != rootActivity; + } + + public final boolean isDelegatedActivity() { + return isDelegatedActivity; + } + + public final Activity getActivity() { + return rootActivity; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + Log.d(MD.TAG, "onCreate"); + if(!isDelegatedActivity()) { + super.onCreate(savedInstanceState); + } + jogamp.common.os.android.StaticContext.init(rootActivity.getApplicationContext()); + } + + @Override + public void onStart() { + Log.d(MD.TAG, "onStart"); + if(!isDelegatedActivity()) { + super.onStart(); + } + } + + @Override + public void onRestart() { + Log.d(MD.TAG, "onRestart"); + if(!isDelegatedActivity()) { + super.onRestart(); + } + } + + @Override + public void onResume() { + Log.d(MD.TAG, "onResume"); + if(!isDelegatedActivity()) { + super.onResume(); + } + } + + @Override + public void onPause() { + Log.d(MD.TAG, "onPause"); + if(!isDelegatedActivity()) { + super.onPause(); + } + } + + @Override + public void onStop() { + Log.d(MD.TAG, "onStop"); + if(!isDelegatedActivity()) { + super.onStop(); + } + } + + @Override + public void onDestroy() { + Log.d(MD.TAG, "onDestroy"); + jogamp.common.os.android.StaticContext.clear(); + if(!isDelegatedActivity()) { + super.onDestroy(); + } + } +} diff --git a/src/test/com/jogamp/openal/test/android/LauncherUtil.java b/src/test/com/jogamp/openal/test/android/LauncherUtil.java new file mode 100644 index 0000000..d416e5d --- /dev/null +++ b/src/test/com/jogamp/openal/test/android/LauncherUtil.java @@ -0,0 +1,430 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``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 JogAmp Community 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. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.openal.test.android; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.util.Log; + +/** + * Helper class to parse Uri's and programmatically add package names and properties to create an Uri or Intend. + * <p> + * The order of the Uri segments (any arguments) is preserved. + * </p> + */ +public class LauncherUtil { + + /** Default launch mode. */ + public static final String LAUNCH_ACTIVITY_NORMAL = "org.jogamp.launcher.action.LAUNCH_ACTIVITY_NORMAL"; + + /** Transparent launch mode. Note: This seems to be required to achieve translucency, since setTheme(..) doesn't work. */ + public static final String LAUNCH_ACTIVITY_TRANSPARENT = "org.jogamp.launcher.action.LAUNCH_ACTIVITY_TRANSPARENT"; + + /** FIXME: TODO */ + public static final String LAUNCH_MAIN = "org.jogamp.launcher.action.LAUNCH_MAIN"; + + /** FIXME: TODO */ + public static final String LAUNCH_JUNIT = "org.jogamp.launcher.action.LAUNCH_JUNIT"; + + /** The protocol <code>launch</code> */ + public static final String SCHEME = "launch"; + + /** The host <code>jogamp.org</code> */ + public static final String HOST = "jogamp.org"; + + static final String SYS_PKG = "sys"; + + static final String USR_PKG = "pkg"; + + static final String ARG = "arg"; + + public static abstract class BaseActivityLauncher extends Activity { + final OrderedProperties props = new OrderedProperties(); + final ArrayList<String> args = new ArrayList<String>(); + /** + * Returns the default {@link LauncherUtil#LAUNCH_ACTIVITY_NORMAL} action. + * <p> + * Should be overridden for other action, eg. {@link LauncherUtil#LAUNCH_ACTIVITY_TRANSPARENT}. + * </p> + */ + public String getAction() { return LAUNCH_ACTIVITY_NORMAL; } + + /** + * Returns the properties, which are being propagated to the target activity. + * <p> + * Maybe be used to set custom properties. + * </p> + */ + public final OrderedProperties getProperties() { return props; } + + /** + * Returns the commandline arguments, which are being propagated to the target activity. + * <p> + * Maybe be used to set custom commandline arguments. + * </p> + */ + public final ArrayList<String> getArguments() { return args; } + + /** Custom initialization hook which can be overriden to setup data, e.g. fill the properties retrieved by {@link #getProperties()}. */ + public void init() { } + + /** Returns true if this launcher activity shall end after starting the downstream activity. Defaults to <code>true</code>, override to change behavior. */ + public boolean finishAfterDelegate() { return true; } + + /** Must return the downstream Activity class name */ + public abstract String getActivityName(); + + /** Must return a list of required user packages, at least one containing the activity. */ + public abstract List<String> getUsrPackages(); + + /** Return a list of required system packages w/ native libraries, may return null or a zero sized list. */ + public abstract List<String> getSysPackages(); + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + init(); + + final DataSet data = new DataSet(); + data.setActivityName(getActivityName()); + data.addAllSysPackages(getSysPackages()); + data.addAllUsrPackages(getUsrPackages()); + data.addAllProperties(props); + data.addAllArguments(args); + + final Intent intent = LauncherUtil.getIntent(getAction(), data); + Log.d(getClass().getSimpleName(), "Launching Activity: "+intent); + startActivity (intent); + + if(finishAfterDelegate()) { + finish(); // done + } + } + } + + public static class OrderedProperties { + HashMap<String, String> map = new HashMap<String, String>(); + ArrayList<String> keyList = new ArrayList<String>(); + + public final void setProperty(String key, String value) { + if(key.equals(SYS_PKG)) { + throw new IllegalArgumentException("Illegal property key, '"+SYS_PKG+"' is reserved"); + } + if(key.equals(USR_PKG)) { + throw new IllegalArgumentException("Illegal property key, '"+USR_PKG+"' is reserved"); + } + if(key.equals(ARG)) { + throw new IllegalArgumentException("Illegal property key, '"+ARG+"' is reserved"); + } + final String oval = map.put(key, value); + if(null != oval) { + map.put(key, oval); // restore + throw new IllegalArgumentException("Property overwriting not allowed: "+key+": "+oval+" -> "+value); + } + keyList.add(key); // new key + } + + public final void addAll(OrderedProperties props) { + Iterator<String> argKeys = props.keyList.iterator(); + while(argKeys.hasNext()) { + final String key = argKeys.next(); + setProperty(key, props.map.get(key)); + } + } + + public final void setSystemProperties() { + Iterator<String> argKeys = keyList.iterator(); + while(argKeys.hasNext()) { + final String key = argKeys.next(); + System.setProperty(key, map.get(key)); + } + } + public final void clearSystemProperties() { + Iterator<String> argKeys = keyList.iterator(); + while(argKeys.hasNext()) { + System.clearProperty(argKeys.next()); + } + } + + public final String getProperty(String key) { return map.get(key); } + public final Map<String, String> getProperties() { return map; } + + /** Returns the list of property keys in the order, as they were added. */ + public final List<String> getPropertyKeys() { return keyList; } + } + + /** + * Data set to transfer from and to launch URI consisting out of: + * <ul> + * <li>system packages w/ native libraries used on Android, which may use a cached ClassLoader, see {@link DataSet#getSysPackages()}.</li> + * <li>user packages w/o native libraries used on Android, which do not use a cached ClassLoader, see {@link DataSet#getUsrPackages()}.</li> + * <li>activity name, used to launch an Android activity, see {@link DataSet#getActivityName()}.</li> + * <li>properties, which will be added to the system properties, see {@link DataSet#getProperties()}.</li> + * <li>arguments, used to launch a class main-entry, see {@link DataSet#getArguments()}.</li> + * </ul> + * {@link DataSet#getUri()} returns a URI representation of all components. + */ + public static class DataSet { + static final char SLASH = '/'; + static final char QMARK = '?'; + static final char AMPER = '&'; + static final char ASSIG = '='; + static final String COLSLASH2 = "://"; + static final String EMPTY = ""; + + String activityName = null; + ArrayList<String> sysPackages = new ArrayList<String>(); + ArrayList<String> usrPackages = new ArrayList<String>(); + OrderedProperties properties = new OrderedProperties(); + ArrayList<String> arguments = new ArrayList<String>(); + + public final void setActivityName(String name) { activityName = name; } + public final String getActivityName() { return activityName; } + + public final void addSysPackage(String p) { + sysPackages.add(p); + } + public final void addAllSysPackages(List<String> plist) { + sysPackages.addAll(plist); + } + public final List<String> getSysPackages() { return sysPackages; } + + public final void addUsrPackage(String p) { + usrPackages.add(p); + } + public final void addAllUsrPackages(List<String> plist) { + usrPackages.addAll(plist); + } + public final List<String> getUsrPackages() { return usrPackages; } + + public final void setProperty(String key, String value) { + properties.setProperty(key, value); + } + public final void addAllProperties(OrderedProperties props) { + properties.addAll(props); + } + public final void setSystemProperties() { + properties.setSystemProperties(); + } + public final void clearSystemProperties() { + properties.clearSystemProperties(); + } + public final String getProperty(String key) { return properties.getProperty(key); } + public final OrderedProperties getProperties() { return properties; } + public final List<String> getPropertyKeys() { return properties.getPropertyKeys(); } + + public final void addArgument(String arg) { arguments.add(arg); } + public final void addAllArguments(List<String> args) { + arguments.addAll(args); + } + public final ArrayList<String> getArguments() { return arguments; } + + public final Uri getUri() { + StringBuilder sb = new StringBuilder(); + sb.append(SCHEME).append(COLSLASH2).append(HOST).append(SLASH).append(getActivityName()); + boolean needsQMark = true; + boolean needsSep = false; + if(sysPackages.size()>0) { + if( needsQMark ) { + sb.append(QMARK); + needsQMark = false; + } + for(int i=0; i<sysPackages.size(); i++) { + if(needsSep) { + sb.append(AMPER); + } + sb.append(SYS_PKG).append(ASSIG).append(sysPackages.get(i)); + needsSep = true; + } + } + if(usrPackages.size()>0) { + if( needsQMark ) { + sb.append(QMARK); + needsQMark = false; + } + for(int i=0; i<usrPackages.size(); i++) { + if(needsSep) { + sb.append(AMPER); + } + sb.append(USR_PKG).append(ASSIG).append(usrPackages.get(i)); + needsSep = true; + } + } + Iterator<String> propKeys = properties.keyList.iterator(); + while(propKeys.hasNext()) { + if( needsQMark ) { + sb.append(QMARK); + needsQMark = false; + } + if(needsSep) { + sb.append(AMPER); + } + final String key = propKeys.next(); + sb.append(key).append(ASSIG).append(properties.map.get(key)); + needsSep = true; + } + Iterator<String> args = arguments.iterator(); + while(args.hasNext()) { + if( needsQMark ) { + sb.append(QMARK); + needsQMark = false; + } + if(needsSep) { + sb.append(AMPER); + } + sb.append(ARG).append(ASSIG).append(args.next()); + needsSep = true; + } + return Uri.parse(sb.toString()); + } + + public static final DataSet create(Uri uri) { + if(!uri.getScheme().equals(SCHEME)) { + return null; + } + if(!uri.getHost().equals(HOST)) { + return null; + } + DataSet data = new DataSet(); + { + String an = uri.getPath(); + if(SLASH == an.charAt(0)) { + an = an.substring(1); + } + if(SLASH == an.charAt(an.length()-1)) { + an = an.substring(0, an.length()-1); + } + data.setActivityName(an); + } + + final String q = uri.getQuery(); + final int q_l = null != q ? q.length() : -1; + int q_e = -1; + while(q_e < q_l) { + int q_b = q_e + 1; // next term + q_e = q.indexOf(AMPER, q_b); + if(0 == q_e) { + // single separator + continue; + } + if(0 > q_e) { + // end + q_e = q_l; + } + // n-part + final String part = q.substring(q_b, q_e); + final int assignment = part.indexOf(ASSIG); + if(0 < assignment) { + // assignment + final String k = part.substring(0, assignment); + final String v = part.substring(assignment+1); + if(k.equals(SYS_PKG)) { + if(v.length()==0) { + throw new IllegalArgumentException("Empty package name: part <"+part+">, query <"+q+"> of "+uri); + } + data.addSysPackage(v); + } else if(k.equals(USR_PKG)) { + if(v.length()==0) { + throw new IllegalArgumentException("Empty package name: part <"+part+">, query <"+q+"> of "+uri); + } + data.addUsrPackage(v); + } else if(k.equals(ARG)) { + if(v.length()==0) { + throw new IllegalArgumentException("Empty argument name: part <"+part+">, query <"+q+"> of "+uri); + } + data.addArgument(v); + } else { + data.setProperty(k, v); + } + } else { + // property key only + if( part.equals(USR_PKG) || part.equals(ARG) ) { + throw new IllegalArgumentException("Reserved key <"+part+"> in query <"+q+"> of "+uri); + } + data.setProperty(part, EMPTY); + } + } + data.validate(); + return data; + } + + public final void validate() { + if(null == activityName) { + throw new RuntimeException("Activity is not NULL"); + } + } + } + + public final static Intent getIntent(String action, DataSet data) { + data.validate(); + return new Intent(action, data.getUri()); + } + + public static void main(String[] args) { + if(args.length==0) { + args = new String[] { + SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+SYS_PKG+"=jogamp.pack1&"+SYS_PKG+"=javax.pack2&"+USR_PKG+"=com.jogamp.pack3&"+USR_PKG+"=com.jogamp.pack4&jogamp.common.debug=true&com.jogamp.test=false", + SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+SYS_PKG+"=jogamp.pack1&jogamp.common.debug=true&com.jogamp.test=false", + SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&jogamp.common.debug=true&com.jogamp.test=false", + SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&"+USR_PKG+"=com.jogamp.pack2", + SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&"+USR_PKG+"=javax.pack2&"+USR_PKG+"=com.jogamp.pack3&jogamp.common.debug=true&com.jogamp.test=false&"+ARG+"=arg1&"+ARG+"=arg2=arg2value&"+ARG+"=arg3", + SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&jogamp.common.debug=true&com.jogamp.test=false&"+ARG+"=arg1&"+ARG+"=arg2=arg2value&"+ARG+"=arg3", + SCHEME+"://"+HOST+"/com.jogamp.TestActivity?"+USR_PKG+"=jogamp.pack1&"+ARG+"=arg1&"+ARG+"=arg2=arg2value&"+ARG+"=arg3" + }; + } + int errors = 0; + for(int i=0; i<args.length; i++) { + String uri_s = args[i]; + Uri uri0 = Uri.parse(uri_s); + DataSet data = DataSet.create(uri0); + if(null == data) { + errors++; + System.err.println("Error: NULL JogAmpLauncherUtil: <"+uri_s+"> -> "+uri0+" -> NULL"); + } else { + Uri uri1 = data.getUri(); + if(!uri0.equals(uri1)) { + errors++; + System.err.println("Error: Not equal: <"+uri_s+"> -> "+uri0+" -> "+uri1); + } else { + System.err.println("OK: "+uri1); + } + } + } + System.err.println("LauncherUtil Self Test: Errors: "+errors); + } + +} diff --git a/src/test/com/jogamp/openal/test/android/MD.java b/src/test/com/jogamp/openal/test/android/MD.java new file mode 100644 index 0000000..113203e --- /dev/null +++ b/src/test/com/jogamp/openal/test/android/MD.java @@ -0,0 +1,53 @@ +/** + * Copyright 2013 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``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 JogAmp Community 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. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.openal.test.android; + +import com.jogamp.common.GlueGenVersion; +import com.jogamp.common.os.Platform; +import com.jogamp.common.util.VersionUtil; +import com.jogamp.openal.JoalVersion; + +public class MD { + public static final String TAG = "JogAmp.JOAL"; + + public static String getInfo() { + StringBuilder sb = new StringBuilder(); + + sb.append(VersionUtil.getPlatformInfo()).append(Platform.NEWLINE) + .append(GlueGenVersion.getInstance()).append(Platform.NEWLINE) + .append(JoalVersion.getInstance()).append(Platform.NEWLINE) + .append(Platform.NEWLINE); + + return sb.toString(); + } + + public static void main(String args[]) { + + System.err.println(getInfo()); + } +} diff --git a/src/test/com/jogamp/openal/test/android/OpenALTestActivity.java b/src/test/com/jogamp/openal/test/android/OpenALTestActivity.java new file mode 100644 index 0000000..960d447 --- /dev/null +++ b/src/test/com/jogamp/openal/test/android/OpenALTestActivity.java @@ -0,0 +1,85 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``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 JogAmp Community 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. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.openal.test.android; + +import com.jogamp.openal.test.manual.OpenALTest; + +import android.os.Bundle; +import android.util.Log; + +public class OpenALTestActivity extends BaseActivity { + static String TAG = "OpenALTestActivity"; + + OpenALTest demo = null; + + @Override + public void onCreate(Bundle savedInstanceState) { + Log.d(TAG, "onCreate - 0"); + super.onCreate(savedInstanceState); + + demo = new OpenALTest(); + try { + demo.init(); + } catch (Exception e) { + e.printStackTrace(); + demo.dispose(); + demo = null; + } + + Log.d(TAG, "onCreate - X"); + } + + @Override + public void onResume() { + Log.d(MD.TAG, "onResume"); + super.onResume(); + if( null != demo ) { + demo.play(); + } + } + + @Override + public void onPause() { + Log.d(MD.TAG, "onPause"); + if( null != demo ) { + demo.pause(); + } + super.onPause(); + } + + @Override + public void onDestroy() { + Log.d(MD.TAG, "onDestroy"); + if( null != demo ) { + demo.dispose(); + demo = null; + } + super.onDestroy(); + } + +} diff --git a/src/test/com/jogamp/openal/test/android/OpenALTestActivityLauncher.java b/src/test/com/jogamp/openal/test/android/OpenALTestActivityLauncher.java new file mode 100644 index 0000000..3ebbd80 --- /dev/null +++ b/src/test/com/jogamp/openal/test/android/OpenALTestActivityLauncher.java @@ -0,0 +1,36 @@ +package com.jogamp.openal.test.android; + +import java.util.Arrays; +import java.util.List; + +import com.jogamp.openal.test.android.LauncherUtil.OrderedProperties; + +public class OpenALTestActivityLauncher extends LauncherUtil.BaseActivityLauncher { + static String demo = "com.jogamp.openal.test.android.OpenALTestActivity"; + static String[] sys_pkgs = new String[] { "com.jogamp.common", "com.jogamp.openal" }; + static String[] usr_pkgs = new String[] { "com.jogamp.openal.test" }; + + @Override + public void init() { + final OrderedProperties props = getProperties(); + props.setProperty("jogamp.debug.JNILibLoader", "true"); + props.setProperty("jogamp.debug.NativeLibrary", "true"); + props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); + props.setProperty("jogamp.debug.IOUtil", "true"); + } + + @Override + public String getActivityName() { + return demo; + } + + @Override + public List<String> getSysPackages() { + return Arrays.asList(sys_pkgs); + } + + @Override + public List<String> getUsrPackages() { + return Arrays.asList(usr_pkgs); + } +} diff --git a/src/test/com/jogamp/openal/test/manual/OpenALTest.java b/src/test/com/jogamp/openal/test/manual/OpenALTest.java index 864a9fd..1bc8b78 100644 --- a/src/test/com/jogamp/openal/test/manual/OpenALTest.java +++ b/src/test/com/jogamp/openal/test/manual/OpenALTest.java @@ -2,6 +2,7 @@ package com.jogamp.openal.test.manual; /** * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright (c) 2011 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -32,45 +33,64 @@ package com.jogamp.openal.test.manual; * You acknowledge that this software is not designed or intended for use in the * design, construction, operation or maintenance of any nuclear facility. */ +import java.io.IOException; +import java.nio.IntBuffer; + import com.jogamp.common.nio.Buffers; import com.jogamp.openal.AL; import com.jogamp.openal.ALC; import com.jogamp.openal.ALCcontext; import com.jogamp.openal.ALCdevice; import com.jogamp.openal.ALFactory; -import java.io.IOException; -import java.nio.*; - -import com.jogamp.openal.eax.*; +import com.jogamp.openal.UnsupportedAudioFileException; +import com.jogamp.openal.eax.EAX; +import com.jogamp.openal.eax.EAXFactory; import com.jogamp.openal.test.resources.ResourceLocation; -import com.jogamp.openal.util.*; -import java.io.InputStream; -import javax.sound.sampled.UnsupportedAudioFileException; +import com.jogamp.openal.util.WAVData; /** - * @author Athomas Goldberg - * @author Michael Bien + * @author Athomas Goldberg, Michael Bien, et.al. */ public class OpenALTest { - public static void main(String[] args) throws InterruptedException, UnsupportedAudioFileException, IOException { - ALC alc = ALFactory.getALC(); - ALCdevice device = alc.alcOpenDevice(null); - ALCcontext context = alc.alcCreateContext(device, null); + private ALC alc = null; + private ALCdevice device = null; + private ALCcontext context = null; + private AL al = null; + private int[] sources = null; + private boolean initialized = false; + + public OpenALTest() { + } + + public void init() throws UnsupportedAudioFileException, IOException { + if( initialized ) { + return; + } + alc = ALFactory.getALC(); + device = alc.alcOpenDevice(null); + context = alc.alcCreateContext(device, null); alc.alcMakeContextCurrent(context); - AL al = ALFactory.getAL(); + al = ALFactory.getAL(); - System.out.println("devices:"); - String[] devices = alc.alcGetDeviceSpecifiers(); - for (String name : devices) { - System.out.println(" "+name); + System.out.println("output devices:"); + { + final String[] outDevices = alc.alcGetDeviceSpecifiers(); + if( null != outDevices ) { + for (String name : outDevices) { + System.out.println(" "+name); + } + } } System.out.println("capture devices:"); - devices = alc.alcGetCaptureDeviceSpecifiers(); - for (String name : devices) { - System.out.println(" "+name); + { + final String[] inDevices = alc.alcGetCaptureDeviceSpecifiers(); + if( null != inDevices ) { + for (String name : inDevices) { + System.out.println(" "+name); + } + } } - boolean eaxPresent = al.alIsExtensionPresent("EAX2.0"); EAX eax = ( eaxPresent ) ? EAXFactory.getEAX() : null; System.err.println("EAX present:" + eaxPresent + ", EAX retrieved: "+ (null != eax)); @@ -78,10 +98,10 @@ public class OpenALTest { int[] buffers = new int[1]; al.alGenBuffers(1, buffers, 0); - WAVData wd = WAVLoader.loadFromStream(ResourceLocation.getTestStream0()); + WAVData wd = WAVData.loadFromStream(ResourceLocation.getTestStream0(), 1, 8, 22050); al.alBufferData(buffers[0], wd.format, wd.data, wd.size, wd.freq); - - int[] sources = new int[1]; + + sources = new int[1]; al.alGenSources(1, sources, 0); al.alSourcei(sources[0], AL.AL_BUFFER, buffers[0]); @@ -98,26 +118,68 @@ public class OpenALTest { env.put(EAX.EAX_ENVIRONMENT_BATHROOM); eax.setListenerProperty(EAX.DSPROPERTY_EAXLISTENER_ENVIRONMENT, env); } - + initialized = true; + } + + public void play() { + if( !initialized ) { + return; + } + System.out.println("play direct"); al.alSourcePlay(sources[0]); - + } + + public void play3f(float x, float y, float z) { + if( !initialized ) { + return; + } + System.out.println("play3f "+x+", "+y+", "+z); + al.alSource3f(sources[0], AL.AL_POSITION, x, y, z); + } + + public void pause() { + if( !initialized ) { + return; + } + al.alSourcePause(sources[0]); + } + + public void dispose() { + if( !initialized ) { + return; + } + if( null != sources ) { + al.alSourceStop(sources[0]); + al.alDeleteSources(1, sources, 0); + sources = null; + } + if( null != context ) { + alc.alcDestroyContext(context); + context = null; + } + if( null != device ) { + alc.alcCloseDevice(device); + device = null; + } + initialized = false; + } + + public static void main(String[] args) throws InterruptedException, UnsupportedAudioFileException, IOException { + OpenALTest demo = new OpenALTest(); + demo.init(); + + demo.play(); Thread.sleep(5000); - al.alSource3f(sources[0], AL.AL_POSITION, 2f, 2f, 2f); - + demo.play3f(2f, 2f, 2f); Thread.sleep(5000); - al.alListener3f(AL.AL_POSITION, 3f, 3f, 3f); - + demo.play3f(3f, 3f, 3f); Thread.sleep(5000); - al.alSource3f(sources[0], AL.AL_POSITION, 0, 0, 0); - + demo.play3f(0f, 0f, 0f); Thread.sleep(10000); - - al.alSourceStop(sources[0]); - al.alDeleteSources(1, sources, 0); - alc.alcDestroyContext(context); - alc.alcCloseDevice(device); + + demo.dispose(); } } diff --git a/src/test/com/jogamp/openal/test/resources/ResourceLocation.java b/src/test/com/jogamp/openal/test/resources/ResourceLocation.java index cc9f29f..9b2eb75 100644 --- a/src/test/com/jogamp/openal/test/resources/ResourceLocation.java +++ b/src/test/com/jogamp/openal/test/resources/ResourceLocation.java @@ -1,8 +1,12 @@ package com.jogamp.openal.test.resources; +import java.io.IOException; import java.io.InputStream; import java.io.BufferedInputStream; +import java.net.URLConnection; + +import com.jogamp.common.util.IOUtil; /** just a tag to locate the resources */ public class ResourceLocation { @@ -24,9 +28,20 @@ public class ResourceLocation { } public static InputStream getInputStream(String fileName, boolean throwException) { - InputStream stream = new BufferedInputStream(rl.getClass().getResourceAsStream(fileName)); - if(throwException && null == stream) { - throw new RuntimeException("File '"+fileName+"' not found"); + URLConnection conn = IOUtil.getResource(rl.getClass(), fileName); + if (conn == null) { + return null; + } + InputStream stream = null; + try { + stream = new BufferedInputStream(conn.getInputStream()); + } catch (IOException e) { + if(throwException && null == stream) { + throw new RuntimeException("File '"+fileName+"' not found: "+e.getMessage()); + } else { + System.err.println("File '"+fileName+"' not found"); + e.printStackTrace(); + } } return stream; } |