diff options
Diffstat (limited to 'src/jogl/classes/com/jogamp')
43 files changed, 1627 insertions, 45 deletions
diff --git a/src/jogl/classes/com/jogamp/javafx/audio/windows/waveout/Audio.java b/src/jogl/classes/com/jogamp/javafx/audio/windows/waveout/Audio.java new file mode 100755 index 000000000..fe77c7c48 --- /dev/null +++ b/src/jogl/classes/com/jogamp/javafx/audio/windows/waveout/Audio.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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 Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.javafx.audio.windows.waveout; + +import java.io.*; + +public class Audio { + private static Audio instance = null; + private Mixer mixer; + + public synchronized static Audio getInstance() { + if (instance == null) { + instance = new Audio(); + } + return instance; + } + + private Audio() { + mixer = Mixer.getMixer(); + } + + public Mixer getMixer() { + return mixer; + } + + public Track newTrack(File file) throws IOException + { + Track res = new Track(file); + mixer.add(res); + return res; + } + + public void shutdown() { + mixer.shutdown(); + } +} diff --git a/src/jogl/classes/com/jogamp/javafx/audio/windows/waveout/Mixer.java b/src/jogl/classes/com/jogamp/javafx/audio/windows/waveout/Mixer.java new file mode 100755 index 000000000..59877052f --- /dev/null +++ b/src/jogl/classes/com/jogamp/javafx/audio/windows/waveout/Mixer.java @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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 Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.javafx.audio.windows.waveout; + +import java.io.*; +import java.nio.*; +import java.util.*; + +// Needed only for NIO workarounds on CVM +import java.lang.reflect.*; + +public class Mixer { + // This class is a singleton + private static Mixer mixer; + + private volatile boolean shutdown; + private volatile Object shutdownLock = new Object(); + private volatile boolean shutdownDone; + + // Windows Event object + private long event; + + private volatile ArrayList/*<Track>*/ tracks = new ArrayList(); + + private Vec3f leftSpeakerPosition = new Vec3f(-1, 0, 0); + private Vec3f rightSpeakerPosition = new Vec3f( 1, 0, 0); + + private float falloffFactor = 1.0f; + + static { + mixer = new Mixer(); + } + + private Mixer() { + event = CreateEvent(); + new FillerThread().start(); + MixerThread m = new MixerThread(); + m.setPriority(Thread.MAX_PRIORITY - 1); + m.start(); + } + + public static Mixer getMixer() { + return mixer; + } + + synchronized void add(Track track) { + ArrayList/*<Track>*/ newTracks = (ArrayList) tracks.clone(); + newTracks.add(track); + tracks = newTracks; + } + + synchronized void remove(Track track) { + ArrayList/*<Track>*/ newTracks = (ArrayList) tracks.clone(); + newTracks.remove(track); + tracks = newTracks; + } + + // NOTE: due to a bug on the APX device, we only have mono sounds, + // so we currently only pay attention to the position of the left + // speaker + public void setLeftSpeakerPosition(float x, float y, float z) { + leftSpeakerPosition.set(x, y, z); + } + + // NOTE: due to a bug on the APX device, we only have mono sounds, + // so we currently only pay attention to the position of the left + // speaker + public void setRightSpeakerPosition(float x, float y, float z) { + rightSpeakerPosition.set(x, y, z); + } + + /** This defines a scale factor of sorts -- the higher the number, + the larger an area the sound will affect. Default value is + 1.0f. Valid values are [1.0f, ...]. The formula for the gain + for each channel is +<PRE> + falloffFactor + ------------------- + falloffFactor + r^2 +</PRE> +*/ + public void setFalloffFactor(float factor) { + falloffFactor = factor; + } + + public void shutdown() { + synchronized(shutdownLock) { + shutdown = true; + SetEvent(event); + try { + shutdownLock.wait(); + } catch (InterruptedException e) { + } + } + } + + class FillerThread extends Thread { + FillerThread() { + super("Mixer Thread"); + } + + public void run() { + while (!shutdown) { + List/*<Track>*/ curTracks = tracks; + + for (Iterator iter = curTracks.iterator(); iter.hasNext(); ) { + Track track = (Track) iter.next(); + try { + track.fill(); + } catch (IOException e) { + e.printStackTrace(); + remove(track); + } + } + + try { + // Run ten times per second + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + + class MixerThread extends Thread { + // Temporary mixing buffer + // Interleaved left and right channels + float[] mixingBuffer; + private Vec3f temp = new Vec3f(); + + MixerThread() { + super("Mixer Thread"); + if (!initializeWaveOut(event)) { + throw new InternalError("Error initializing waveout device"); + } + } + + public void run() { + while (!shutdown) { + // Get the next buffer + long mixerBuffer = getNextMixerBuffer(); + if (mixerBuffer != 0) { + ByteBuffer buf = getMixerBufferData(mixerBuffer); + + if (buf == null) { + // This is happening on CVM because + // JNI_NewDirectByteBuffer isn't implemented + // by default and isn't compatible with the + // JSR-239 NIO implementation (apparently) + buf = newDirectByteBuffer(getMixerBufferDataAddress(mixerBuffer), + getMixerBufferDataCapacity(mixerBuffer)); + } + + if (buf == null) { + throw new InternalError("Couldn't wrap the native address with a direct byte buffer"); + } + + // System.out.println("Mixing buffer"); + + // If we don't have enough samples in our mixing buffer, expand it + // FIXME: knowledge of native output rendering format + if ((mixingBuffer == null) || (mixingBuffer.length < (buf.capacity() / 2 /* bytes / sample */))) { + mixingBuffer = new float[buf.capacity() / 2]; + } else { + // Zap it + for (int i = 0; i < mixingBuffer.length; i++) { + mixingBuffer[i] = 0.0f; + } + } + + // This assertion should be in place if we have stereo + if ((mixingBuffer.length % 2) != 0) { + String msg = "FATAL ERROR: odd number of samples in the mixing buffer"; + System.out.println(msg); + throw new InternalError(msg); + } + + // Run down all of the registered tracks mixing them in + List/*<Track>*/ curTracks = tracks; + + for (Iterator iter = curTracks.iterator(); iter.hasNext(); ) { + Track track = (Track) iter.next(); + // Consider only playing tracks + if (track.isPlaying()) { + // First recompute its gain + Vec3f pos = track.getPosition(); + float leftGain = gain(pos, leftSpeakerPosition); + float rightGain = gain(pos, rightSpeakerPosition); + // Now mix it in + int i = 0; + while (i < mixingBuffer.length) { + if (track.hasNextSample()) { + float sample = track.nextSample(); + mixingBuffer[i++] = sample * leftGain; + mixingBuffer[i++] = sample * rightGain; + } else { + // This allows tracks to stall without being abruptly cancelled + if (track.done()) { + remove(track); + } + break; + } + } + } + } + + // Now that we have our data, send it down to the card + int outPos = 0; + for (int i = 0; i < mixingBuffer.length; i++) { + short val = (short) mixingBuffer[i]; + buf.put(outPos++, (byte) val); + buf.put(outPos++, (byte) (val >> 8)); + } + if (!prepareMixerBuffer(mixerBuffer)) { + throw new RuntimeException("Error preparing mixer buffer"); + } + if (!writeMixerBuffer(mixerBuffer)) { + throw new RuntimeException("Error writing mixer buffer to device"); + } + } else { + // System.out.println("No mixer buffer available"); + + // Wait for a buffer to become available + if (!WaitForSingleObject(event)) { + throw new RuntimeException("Error while waiting for event object"); + } + + /* + try { + Thread.sleep(10); + } catch (InterruptedException e) { + } + */ + } + } + + // Need to shut down + shutdownWaveOut(); + synchronized(shutdownLock) { + shutdownLock.notifyAll(); + } + } + + // This defines the 3D spatialization gain function. + // The function is defined as: + // falloffFactor + // ------------------- + // falloffFactor + r^2 + private float gain(Vec3f pos, Vec3f speakerPos) { + temp.sub(pos, speakerPos); + float dotp = temp.dot(temp); + return (falloffFactor / (falloffFactor + dotp)); + } + } + + // Initializes waveout device + private static native boolean initializeWaveOut(long eventObject); + // Shuts down waveout device + private static native void shutdownWaveOut(); + + // Gets the next (opaque) buffer of data to fill from the native + // code, or 0 if none was available yet (it should not happen that + // none is available the way the code is written). + private static native long getNextMixerBuffer(); + // Gets the next ByteBuffer to fill out of the mixer buffer. It + // requires interleaved left and right channel samples, 16 signed + // bits per sample, little endian. Implicit 44.1 kHz sample rate. + private static native ByteBuffer getMixerBufferData(long mixerBuffer); + // We need these to work around the lack of + // JNI_NewDirectByteBuffer in CVM + the JSR 239 NIO classes + private static native long getMixerBufferDataAddress(long mixerBuffer); + private static native int getMixerBufferDataCapacity(long mixerBuffer); + // Prepares this mixer buffer for writing to the device. + private static native boolean prepareMixerBuffer(long mixerBuffer); + // Writes this mixer buffer to the device. + private static native boolean writeMixerBuffer(long mixerBuffer); + + // Helpers to prevent mixer thread from busy waiting + private static native long CreateEvent(); + private static native boolean WaitForSingleObject(long event); + private static native void SetEvent(long event); + private static native void CloseHandle(long handle); + + // We need a reflective hack to wrap a direct ByteBuffer around + // the native memory because JNI_NewDirectByteBuffer doesn't work + // in CVM + JSR-239 NIO + private static Class directByteBufferClass; + private static Constructor directByteBufferConstructor; + private static Map createdBuffers = new HashMap(); // Map Long, ByteBuffer + + private static ByteBuffer newDirectByteBuffer(long address, long capacity) { + Long key = new Long(address); + ByteBuffer buf = (ByteBuffer) createdBuffers.get(key); + if (buf == null) { + buf = newDirectByteBufferImpl(address, capacity); + if (buf != null) { + createdBuffers.put(key, buf); + } + } + return buf; + } + private static ByteBuffer newDirectByteBufferImpl(long address, long capacity) { + if (directByteBufferClass == null) { + try { + directByteBufferClass = Class.forName("java.nio.DirectByteBuffer"); + byte[] tmp = new byte[0]; + directByteBufferConstructor = + directByteBufferClass.getDeclaredConstructor(new Class[] { Integer.TYPE, + tmp.getClass(), + Integer.TYPE }); + directByteBufferConstructor.setAccessible(true); + } catch (Exception e) { + e.printStackTrace(); + } + } + + if (directByteBufferConstructor != null) { + try { + return (ByteBuffer) + directByteBufferConstructor.newInstance(new Object[] { + new Integer((int) capacity), + null, + new Integer((int) address) + }); + } catch (Exception e) { + e.printStackTrace(); + } + } + return null; + } +} diff --git a/src/jogl/classes/com/jogamp/javafx/audio/windows/waveout/SoundBuffer.java b/src/jogl/classes/com/jogamp/javafx/audio/windows/waveout/SoundBuffer.java new file mode 100755 index 000000000..6b75450eb --- /dev/null +++ b/src/jogl/classes/com/jogamp/javafx/audio/windows/waveout/SoundBuffer.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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 Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.javafx.audio.windows.waveout; + +import java.io.*; + +class SoundBuffer { + private byte[] data; + private boolean needsByteSwap; + private int numBytes; + private int bytesPerSample; + private int numSamples; + private boolean playing; + private boolean empty; + + // Note: needsByteSwap argument makes assumptions about the format + SoundBuffer(int size, int bytesPerSample, boolean needsByteSwap) { + this.bytesPerSample = bytesPerSample; + this.needsByteSwap = needsByteSwap; + data = new byte[size * bytesPerSample]; + empty = true; + } + + boolean playing() { + return playing; + } + + void playing(boolean playing) { + this.playing = playing; + } + + boolean empty() { + return empty; + } + + void empty(boolean empty) { + this.empty = empty; + } + + void fill(InputStream input) throws IOException { + synchronized(this) { + if (playing) { + throw new IllegalStateException("Can not fill a buffer that is playing"); + } + } + + empty(true); + int num = input.read(data); + if (num > 0) { + numBytes = num; + numSamples = numBytes / bytesPerSample; + empty(false); + if ((numBytes % bytesPerSample) != 0) { + System.out.println("WARNING: needed integral multiple of " + bytesPerSample + + " bytes, but read " + numBytes + " bytes"); + } + } else { + numBytes = 0; + } + } + + int numSamples() { + return numSamples; + } + + // This is called by the mixer and must be extremely fast + // FIXME: may want to reconsider use of floating point at this point + // FIXME: assumes all sounds are of the same format to avoid normalization + float getSample(int sample) { + int startByte = sample * bytesPerSample; + // FIXME: assumes no more than 4 bytes per sample + int res = 0; + if (needsByteSwap) { + for (int i = startByte + bytesPerSample - 1; i >= startByte; i--) { + res <<= 8; + res |= (data[i] & 0xff); + } + } else { + int endByte = startByte + bytesPerSample - 1; + for (int i = startByte; i <= endByte; i++) { + res <<= 8; + res |= (data[i] & 0xff); + } + } + // Sign extend + if (bytesPerSample == 2) { + res = (short) res; + } else if (bytesPerSample == 1) { + res = (byte) res; + } + + return (float) res; + } +} diff --git a/src/jogl/classes/com/jogamp/javafx/audio/windows/waveout/TestSpatialization.java b/src/jogl/classes/com/jogamp/javafx/audio/windows/waveout/TestSpatialization.java new file mode 100755 index 000000000..38e3bb808 --- /dev/null +++ b/src/jogl/classes/com/jogamp/javafx/audio/windows/waveout/TestSpatialization.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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 Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.javafx.audio.windows.waveout; + +import java.io.*; +import javax.media.nativewindow.NativeWindow; +import javax.media.opengl.GLDrawableFactory; + +public class TestSpatialization { + public static void main(String[] args) { + if (args.length != 1) { + System.out.println("Usage: TestSpatialization [file name]"); + System.exit(1); + } + + try { + // FIXME: this is a hack to get the native library loaded + try { + GLDrawableFactory.getFactory(NativeWindow.class); + } catch (Exception e) {} + // Initialize the audio subsystem + Audio audio = Audio.getInstance(); + // Create a track + Track track = audio.newTrack(new File(args[0])); + track.setPosition(1, 0, 0); + // Run for ten seconds + long startTime = System.currentTimeMillis(); + long duration = 10000; + long curTime = 0; + try { + Thread.sleep(500); + } catch (InterruptedException e) { + } + System.out.println("Playing..."); + track.setLooping(true); + track.play(); + while ((curTime = System.currentTimeMillis()) < startTime + duration) { + // Make one revolution every two seconds + float rads = (float) (((2 * Math.PI) * (((float) (curTime - startTime)) / 1000.0f)) / 2); + track.setPosition((float) Math.cos(rads), 0, (float) Math.sin(rads)); + // Would like to make it go in a circle, but since + // stereo doesn't work now, make it move along a line + // track.setPosition(-1.0f, 0, 2.0f * (float) Math.sin(rads)); + // Sleep a little between updates + try { + Thread.sleep(10); + } catch (InterruptedException e) { + } + } + System.out.println("Shutting down audio subsystem"); + audio.shutdown(); + System.out.println("Exiting."); + System.exit(0); + } catch (Exception e) { + e.printStackTrace(); + System.exit(1); + } + } +} diff --git a/src/jogl/classes/com/jogamp/javafx/audio/windows/waveout/Track.java b/src/jogl/classes/com/jogamp/javafx/audio/windows/waveout/Track.java new file mode 100755 index 000000000..40c39e755 --- /dev/null +++ b/src/jogl/classes/com/jogamp/javafx/audio/windows/waveout/Track.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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 Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.javafx.audio.windows.waveout; + +import java.io.*; +import java.nio.*; + +public class Track { + // Default number of samples per buffer + private static final int BUFFER_SIZE = 32768; + // Number of bytes per sample (FIXME: dependence on audio format) + static final int BYTES_PER_SAMPLE = 2; + // Whether we need byte swapping (FIXME: dependence on audio format) + static final boolean NEEDS_BYTE_SWAP = true; + + // This is the buffer this track is currently playing from + private SoundBuffer activeBuffer; + // This is the sample position in the active buffer + private int samplePosition; + // This is the total number of samples in the file + private int totalSamples; + // This is the total number of samples we have read + private int samplesRead; + // This is the buffer that the background filler thread may be filling + private SoundBuffer fillingBuffer; + // If we're playing the file, this is its input stream + private InputStream input; + // Keep around the file name + private File file; + // Whether we're playing this sound + private boolean playing; + // Whether we're looping this sound + private boolean looping; + // The position of this sound; defaults to being at the origin + private volatile Vec3f position = new Vec3f(); + + Track(File file) throws IOException { + if (!file.getName().endsWith(".rawsound")) { + throw new IOException("Unsupported file format (currently supports only raw sounds)"); + } + + this.file = file; + openInput(); + + // Allocate the buffers + activeBuffer = new SoundBuffer(BUFFER_SIZE, BYTES_PER_SAMPLE, NEEDS_BYTE_SWAP); + fillingBuffer = new SoundBuffer(BUFFER_SIZE, BYTES_PER_SAMPLE, NEEDS_BYTE_SWAP); + + // Fill the first buffer immediately + fill(); + swapBuffers(); + } + + private void openInput() throws IOException { + input = new BufferedInputStream(new FileInputStream(file)); + totalSamples = (int) file.length() / BYTES_PER_SAMPLE; + } + + public File getFile() { + return file; + } + + public synchronized void play() { + if (input == null) { + try { + openInput(); + // Fill it immediately + fill(); + } catch (IOException e) { + e.printStackTrace(); + return; + } + } + + playing = true; + } + + public synchronized boolean isPlaying() { + return playing; + } + + public synchronized void setLooping(boolean looping) { + this.looping = looping; + } + + public synchronized boolean isLooping() { + return looping; + } + + public void setPosition(float x, float y, float z) { + position = new Vec3f(x, y, z); + } + + synchronized void fill() throws IOException { + if (input == null) { + return; + } + SoundBuffer curBuffer = fillingBuffer; + if (!curBuffer.empty()) { + return; + } + curBuffer.fill(input); + if (curBuffer.empty()) { + // End of file + InputStream tmp = null; + synchronized(this) { + tmp = input; + input = null; + } + tmp.close(); + + // If looping, re-open + if (isLooping()) { + openInput(); + // and fill + fill(); + } + } + } + + // These are only for use by the Mixer + private float leftGain; + private float rightGain; + + void setLeftGain(float leftGain) { + this.leftGain = leftGain; + } + + float getLeftGain() { + return leftGain; + } + + void setRightGain(float rightGain) { + this.rightGain = rightGain; + } + + float getRightGain() { + return rightGain; + } + + Vec3f getPosition() { + return position; + } + + // This is called by the mixer and must be extremely fast + // Note this assumes mono sounds (FIXME) + boolean hasNextSample() { + return (!activeBuffer.empty() && samplePosition < activeBuffer.numSamples()); + } + + // This is called by the mixer and must be extremely fast + float nextSample() { + float res = activeBuffer.getSample(samplePosition++); + ++samplesRead; + if (!hasNextSample()) { + swapBuffers(); + samplePosition = 0; + if (done()) { + playing = false; + } + } + return res; + } + + synchronized void swapBuffers() { + SoundBuffer tmp = activeBuffer; + activeBuffer = fillingBuffer; + fillingBuffer = tmp; + fillingBuffer.empty(true); + } + + // This provides a more robust termination condition + boolean done() { + return (samplesRead == totalSamples) && !looping; + } +} diff --git a/src/jogl/classes/com/jogamp/javafx/audio/windows/waveout/Vec3f.java b/src/jogl/classes/com/jogamp/javafx/audio/windows/waveout/Vec3f.java new file mode 100755 index 000000000..5b480a513 --- /dev/null +++ b/src/jogl/classes/com/jogamp/javafx/audio/windows/waveout/Vec3f.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution 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 Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.javafx.audio.windows.waveout; + +/** 3-element single-precision vector */ + +class Vec3f { + public static final Vec3f X_AXIS = new Vec3f( 1, 0, 0); + public static final Vec3f Y_AXIS = new Vec3f( 0, 1, 0); + public static final Vec3f Z_AXIS = new Vec3f( 0, 0, 1); + public static final Vec3f NEG_X_AXIS = new Vec3f(-1, 0, 0); + public static final Vec3f NEG_Y_AXIS = new Vec3f( 0, -1, 0); + public static final Vec3f NEG_Z_AXIS = new Vec3f( 0, 0, -1); + + private float x; + private float y; + private float z; + + public Vec3f() {} + + public Vec3f(Vec3f arg) { + set(arg); + } + + public Vec3f(float x, float y, float z) { + set(x, y, z); + } + + public Vec3f copy() { + return new Vec3f(this); + } + + public void set(Vec3f arg) { + set(arg.x, arg.y, arg.z); + } + + public void set(float x, float y, float z) { + this.x = x; + this.y = y; + this.z = z; + } + + /** Sets the ith component, 0 <= i < 3 */ + public void set(int i, float val) { + switch (i) { + case 0: x = val; break; + case 1: y = val; break; + case 2: z = val; break; + default: throw new IndexOutOfBoundsException(); + } + } + + /** Gets the ith component, 0 <= i < 3 */ + public float get(int i) { + switch (i) { + case 0: return x; + case 1: return y; + case 2: return z; + default: throw new IndexOutOfBoundsException(); + } + } + + public float x() { return x; } + public float y() { return y; } + public float z() { return z; } + + public void setX(float x) { this.x = x; } + public void setY(float y) { this.y = y; } + public void setZ(float z) { this.z = z; } + + public float dot(Vec3f arg) { + return x * arg.x + y * arg.y + z * arg.z; + } + + public float length() { + return (float) Math.sqrt(lengthSquared()); + } + + public float lengthSquared() { + return this.dot(this); + } + + public void normalize() { + float len = length(); + if (len == 0.0f) return; + scale(1.0f / len); + } + + /** Returns this * val; creates new vector */ + public Vec3f times(float val) { + Vec3f tmp = new Vec3f(this); + tmp.scale(val); + return tmp; + } + + /** this = this * val */ + public void scale(float val) { + x *= val; + y *= val; + z *= val; + } + + /** Returns this + arg; creates new vector */ + public Vec3f plus(Vec3f arg) { + Vec3f tmp = new Vec3f(); + tmp.add(this, arg); + return tmp; + } + + /** this = this + b */ + public void add(Vec3f b) { + add(this, b); + } + + /** this = a + b */ + public void add(Vec3f a, Vec3f b) { + x = a.x + b.x; + y = a.y + b.y; + z = a.z + b.z; + } + + /** Returns this + s * arg; creates new vector */ + public Vec3f addScaled(float s, Vec3f arg) { + Vec3f tmp = new Vec3f(); + tmp.addScaled(this, s, arg); + return tmp; + } + + /** this = a + s * b */ + public void addScaled(Vec3f a, float s, Vec3f b) { + x = a.x + s * b.x; + y = a.y + s * b.y; + z = a.z + s * b.z; + } + + /** Returns this - arg; creates new vector */ + public Vec3f minus(Vec3f arg) { + Vec3f tmp = new Vec3f(); + tmp.sub(this, arg); + return tmp; + } + + /** this = this - b */ + public void sub(Vec3f b) { + sub(this, b); + } + + /** this = a - b */ + public void sub(Vec3f a, Vec3f b) { + x = a.x - b.x; + y = a.y - b.y; + z = a.z - b.z; + } + + /** Returns this cross arg; creates new vector */ + public Vec3f cross(Vec3f arg) { + Vec3f tmp = new Vec3f(); + tmp.cross(this, arg); + return tmp; + } + + /** this = a cross b. NOTE: "this" must be a different vector than + both a and b. */ + public void cross(Vec3f a, Vec3f b) { + x = a.y * b.z - a.z * b.y; + y = a.z * b.x - a.x * b.z; + z = a.x * b.y - a.y * b.x; + } + + /** Sets each component of this vector to the product of the + component with the corresponding component of the argument + vector. */ + public void componentMul(Vec3f arg) { + x *= arg.x; + y *= arg.y; + z *= arg.z; + } + + public String toString() { + return "(" + x + ", " + y + ", " + z + ")"; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java index 32a32e322..49045910a 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLContextImpl.java @@ -43,7 +43,7 @@ import java.nio.*; import java.lang.reflect.*; import javax.media.opengl.*; -import com.sun.nativewindow.impl.NWReflection; +import com.jogamp.nativewindow.impl.NWReflection; import com.jogamp.gluegen.runtime.*; import com.jogamp.gluegen.runtime.opengl.*; diff --git a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java index 20d0c8072..eaf29df77 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/GLDrawableFactoryImpl.java @@ -43,7 +43,7 @@ import java.nio.*; import javax.media.nativewindow.*; import javax.media.opengl.*; import com.jogamp.gluegen.runtime.*; -import com.sun.nativewindow.impl.NWReflection; +import com.jogamp.nativewindow.impl.NWReflection; import java.lang.reflect.*; /** Extends GLDrawableFactory with a few methods for handling diff --git a/src/jogl/classes/com/jogamp/opengl/impl/NativeLibLoader.java b/src/jogl/classes/com/jogamp/opengl/impl/NativeLibLoader.java index aa71a37da..0e5885349 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/NativeLibLoader.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/NativeLibLoader.java @@ -46,7 +46,7 @@ import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.HashSet; -import com.sun.nativewindow.impl.NativeLibLoaderBase; +import com.jogamp.nativewindow.impl.NativeLibLoaderBase; public class NativeLibLoader extends NativeLibLoaderBase { public static void loadNEWT() { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/ThreadingImpl.java b/src/jogl/classes/com/jogamp/opengl/impl/ThreadingImpl.java index 2576c8ae8..b32ed51b6 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/ThreadingImpl.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/ThreadingImpl.java @@ -38,7 +38,7 @@ import java.security.AccessController; import java.security.PrivilegedAction; import javax.media.nativewindow.NativeWindowFactory; -import com.sun.nativewindow.impl.NWReflection; +import com.jogamp.nativewindow.impl.NWReflection; import javax.media.opengl.GLException; /** Implementation of the {@link javax.media.opengl.Threading} class. */ diff --git a/src/jogl/classes/com/jogamp/opengl/impl/awt/AWTUtil.java b/src/jogl/classes/com/jogamp/opengl/impl/awt/AWTUtil.java index 306f6cee7..e5570a8ee 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/awt/AWTUtil.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/awt/AWTUtil.java @@ -36,7 +36,7 @@ package com.jogamp.opengl.impl.awt; -import com.sun.nativewindow.impl.jawt.*; +import com.jogamp.nativewindow.impl.jawt.*; import com.jogamp.opengl.impl.*; diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawable.java index e48c78301..f3695ed16 100755 --- a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawable.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawable.java @@ -36,7 +36,7 @@ package com.jogamp.opengl.impl.egl; import com.jogamp.opengl.impl.GLDrawableImpl; -import com.sun.nativewindow.impl.NWReflection; +import com.jogamp.nativewindow.impl.NWReflection; import com.jogamp.gluegen.runtime.DynamicLookupHelper; import javax.media.nativewindow.*; diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawableFactory.java index f6c8b800e..d50f671a3 100755 --- a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawableFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDrawableFactory.java @@ -39,7 +39,7 @@ import java.util.*; import javax.media.nativewindow.*; import javax.media.opengl.*; import com.jogamp.opengl.impl.*; -import com.sun.nativewindow.impl.*; +import com.jogamp.nativewindow.impl.*; import com.jogamp.gluegen.runtime.NativeLibrary; public class EGLDrawableFactory extends GLDrawableFactoryImpl { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDynamicLookupHelper.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDynamicLookupHelper.java index beffb513f..4918acbb3 100755 --- a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDynamicLookupHelper.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLDynamicLookupHelper.java @@ -39,7 +39,7 @@ import java.util.*; import javax.media.nativewindow.*; import javax.media.opengl.*; import com.jogamp.opengl.impl.*; -import com.sun.nativewindow.impl.*; +import com.jogamp.nativewindow.impl.*; import com.jogamp.gluegen.runtime.NativeLibrary; import com.jogamp.gluegen.runtime.DynamicLookupHelper; import java.security.*; diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLES1DynamicLookupHelper.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLES1DynamicLookupHelper.java index 0dc9535ce..5c4da5098 100755 --- a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLES1DynamicLookupHelper.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLES1DynamicLookupHelper.java @@ -39,7 +39,7 @@ import java.util.*; import javax.media.nativewindow.*; import javax.media.opengl.*; import com.jogamp.opengl.impl.*; -import com.sun.nativewindow.impl.*; +import com.jogamp.nativewindow.impl.*; import com.jogamp.gluegen.runtime.NativeLibrary; /** diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLES2DynamicLookupHelper.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLES2DynamicLookupHelper.java index 595ded538..0b499c204 100755 --- a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLES2DynamicLookupHelper.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLES2DynamicLookupHelper.java @@ -39,7 +39,7 @@ import java.util.*; import javax.media.nativewindow.*; import javax.media.opengl.*; import com.jogamp.opengl.impl.*; -import com.sun.nativewindow.impl.*; +import com.jogamp.nativewindow.impl.*; import com.jogamp.gluegen.runtime.NativeLibrary; /** diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfigurationFactory.java index 6546ecab7..0a9edd239 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLGraphicsConfigurationFactory.java @@ -35,7 +35,7 @@ package com.jogamp.opengl.impl.egl; import java.io.PrintStream; import javax.media.nativewindow.*; import javax.media.nativewindow.egl.*; -import com.sun.nativewindow.impl.*; +import com.jogamp.nativewindow.impl.*; import javax.media.opengl.*; import com.jogamp.opengl.impl.*; diff --git a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLOnscreenDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLOnscreenDrawable.java index d37a36fb0..2f5bbf359 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLOnscreenDrawable.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/egl/EGLOnscreenDrawable.java @@ -43,7 +43,7 @@ import javax.media.opengl.*; import javax.media.nativewindow.*; import javax.media.nativewindow.egl.*; import com.jogamp.opengl.impl.*; -import com.sun.nativewindow.impl.NullWindow; +import com.jogamp.nativewindow.impl.NullWindow; public class EGLOnscreenDrawable extends EGLDrawable { protected EGLOnscreenDrawable(EGLDrawableFactory factory, NativeWindow component) throws GLException { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawableFactory.java index c08599964..a3ae6f936 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawableFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLDrawableFactory.java @@ -45,7 +45,7 @@ import java.util.*; import javax.media.nativewindow.*; import javax.media.opengl.*; import com.jogamp.opengl.impl.*; -import com.sun.nativewindow.impl.*; +import com.jogamp.nativewindow.impl.*; import com.jogamp.gluegen.runtime.DynamicLookupHelper; public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl implements DynamicLookupHelper { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java index ab53e49e9..ada5fb1a7 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java @@ -34,7 +34,7 @@ package com.jogamp.opengl.impl.macosx.cgl; import javax.media.nativewindow.*; import javax.media.nativewindow.macosx.*; -import com.sun.nativewindow.impl.*; +import com.jogamp.nativewindow.impl.*; import javax.media.opengl.*; import com.jogamp.opengl.impl.*; diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXExternalCGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXExternalCGLContext.java index 239eedd43..dde77cde6 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXExternalCGLContext.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/MacOSXExternalCGLContext.java @@ -43,7 +43,7 @@ import javax.media.opengl.*; import com.jogamp.opengl.impl.*; import javax.media.nativewindow.*; -import com.sun.nativewindow.impl.NullWindow; +import com.jogamp.nativewindow.impl.NullWindow; public class MacOSXExternalCGLContext extends MacOSXCGLContext { private boolean firstMakeCurrent = true; diff --git a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java index 97d5e8d68..0d59da32e 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/macosx/cgl/awt/MacOSXAWTCGLGraphicsConfigurationFactory.java @@ -43,8 +43,8 @@ import javax.media.opengl.awt.*; import com.jogamp.opengl.impl.*; import com.jogamp.opengl.impl.macosx.cgl.*; -import com.sun.nativewindow.impl.jawt.*; -import com.sun.nativewindow.impl.jawt.macosx.*; +import com.jogamp.nativewindow.impl.jawt.*; +import com.jogamp.nativewindow.impl.jawt.macosx.*; public class MacOSXAWTCGLGraphicsConfigurationFactory extends GraphicsConfigurationFactory { protected static final boolean DEBUG = com.jogamp.opengl.impl.Debug.debug("GraphicsConfiguration"); diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsDummyWGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsDummyWGLDrawable.java index 89a25fe9a..49e646844 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsDummyWGLDrawable.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsDummyWGLDrawable.java @@ -41,7 +41,7 @@ package com.jogamp.opengl.impl.windows.wgl; import javax.media.opengl.*; import com.jogamp.opengl.impl.*; -import com.sun.nativewindow.impl.NullWindow; +import com.jogamp.nativewindow.impl.NullWindow; public class WindowsDummyWGLDrawable extends WindowsWGLDrawable { private long hwnd, hdc; diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLContext.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLContext.java index 25691ab91..da8b70eb8 100755 --- a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLContext.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLContext.java @@ -42,7 +42,7 @@ package com.jogamp.opengl.impl.windows.wgl; import javax.media.opengl.*; import javax.media.nativewindow.*; import com.jogamp.opengl.impl.*; -import com.sun.nativewindow.impl.NullWindow; +import com.jogamp.nativewindow.impl.NullWindow; public class WindowsExternalWGLContext extends WindowsWGLContext { private boolean firstMakeCurrent = true; diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLDrawable.java index f5b89842d..74db45932 100755 --- a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLDrawable.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsExternalWGLDrawable.java @@ -42,7 +42,7 @@ package com.jogamp.opengl.impl.windows.wgl; import javax.media.nativewindow.*; import javax.media.opengl.*; import com.jogamp.opengl.impl.*; -import com.sun.nativewindow.impl.NullWindow; +import com.jogamp.nativewindow.impl.NullWindow; public class WindowsExternalWGLDrawable extends WindowsWGLDrawable { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOffscreenWGLDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOffscreenWGLDrawable.java index 88bfb3b1c..e0c70bd8c 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOffscreenWGLDrawable.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsOffscreenWGLDrawable.java @@ -42,7 +42,7 @@ package com.jogamp.opengl.impl.windows.wgl; import javax.media.opengl.*; import javax.media.nativewindow.*; import com.jogamp.opengl.impl.*; -import com.sun.nativewindow.impl.NullWindow; +import com.jogamp.nativewindow.impl.NullWindow; public class WindowsOffscreenWGLDrawable extends WindowsWGLDrawable { private long origbitmap; diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawableFactory.java index 38b9bac51..6827c755e 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawableFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLDrawableFactory.java @@ -44,9 +44,9 @@ import java.util.*; import javax.media.nativewindow.*; import javax.media.opengl.*; import com.jogamp.opengl.impl.*; -import com.sun.nativewindow.impl.NWReflection; +import com.jogamp.nativewindow.impl.NWReflection; import com.jogamp.gluegen.runtime.DynamicLookupHelper; -import com.sun.nativewindow.impl.NullWindow; +import com.jogamp.nativewindow.impl.NullWindow; public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl implements DynamicLookupHelper { private static final boolean VERBOSE = Debug.verbose(); diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java index 06590a913..b82535bfe 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java @@ -34,7 +34,7 @@ package com.jogamp.opengl.impl.windows.wgl; import javax.media.nativewindow.*; import javax.media.nativewindow.windows.*; -import com.sun.nativewindow.impl.*; +import com.jogamp.nativewindow.impl.*; import javax.media.opengl.*; import com.jogamp.opengl.impl.*; diff --git a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java index 4458fb1ac..02cfd14c3 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/windows/wgl/awt/WindowsAWTWGLGraphicsConfigurationFactory.java @@ -43,8 +43,8 @@ import javax.media.opengl.awt.*; import com.jogamp.opengl.impl.*; import com.jogamp.opengl.impl.windows.wgl.*; -import com.sun.nativewindow.impl.jawt.*; -import com.sun.nativewindow.impl.jawt.windows.*; +import com.jogamp.nativewindow.impl.jawt.*; +import com.jogamp.nativewindow.impl.jawt.windows.*; public class WindowsAWTWGLGraphicsConfigurationFactory extends GraphicsConfigurationFactory { protected static final boolean DEBUG = com.jogamp.opengl.impl.Debug.debug("GraphicsConfiguration"); diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/GLXUtil.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/GLXUtil.java index cbd98014a..99c54332f 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/GLXUtil.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/GLXUtil.java @@ -36,7 +36,7 @@ import javax.media.opengl.*; import com.jogamp.opengl.impl.*; import javax.media.nativewindow.NativeWindowFactory; -import com.sun.nativewindow.impl.x11.*; +import com.jogamp.nativewindow.impl.x11.*; public class GLXUtil { public static boolean isMultisampleAvailable(long display) { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11ExternalGLXContext.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11ExternalGLXContext.java index b94dac1da..783e3278a 100755 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11ExternalGLXContext.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11ExternalGLXContext.java @@ -43,8 +43,8 @@ import javax.media.nativewindow.*; import javax.media.nativewindow.x11.*; import javax.media.opengl.*; import com.jogamp.opengl.impl.*; -import com.sun.nativewindow.impl.NullWindow; -import com.sun.nativewindow.impl.x11.*; +import com.jogamp.nativewindow.impl.NullWindow; +import com.jogamp.nativewindow.impl.x11.*; public class X11ExternalGLXContext extends X11GLXContext { private boolean firstMakeCurrent = true; diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11ExternalGLXDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11ExternalGLXDrawable.java index 261b1b370..44aea0fa7 100755 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11ExternalGLXDrawable.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11ExternalGLXDrawable.java @@ -43,8 +43,8 @@ import javax.media.nativewindow.*; import javax.media.nativewindow.x11.*; import javax.media.opengl.*; import com.jogamp.opengl.impl.*; -import com.sun.nativewindow.impl.NullWindow; -import com.sun.nativewindow.impl.x11.*; +import com.jogamp.nativewindow.impl.NullWindow; +import com.jogamp.nativewindow.impl.x11.*; import com.jogamp.gluegen.runtime.PointerBuffer; diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXContext.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXContext.java index 629bcb0b9..ce846c0a4 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXContext.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXContext.java @@ -46,7 +46,7 @@ import javax.media.nativewindow.*; import javax.media.nativewindow.x11.*; import com.jogamp.opengl.impl.*; import com.jogamp.opengl.impl.x11.glx.*; -import com.sun.nativewindow.impl.x11.*; +import com.jogamp.nativewindow.impl.x11.*; import com.jogamp.gluegen.runtime.ProcAddressTable; public abstract class X11GLXContext extends GLContextImpl { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawable.java index fe030af00..ee807c32a 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawable.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawable.java @@ -42,7 +42,7 @@ package com.jogamp.opengl.impl.x11.glx; import javax.media.nativewindow.*; import javax.media.opengl.*; import com.jogamp.opengl.impl.*; -import com.sun.nativewindow.impl.x11.*; +import com.jogamp.nativewindow.impl.x11.*; import com.jogamp.gluegen.runtime.DynamicLookupHelper; public abstract class X11GLXDrawable extends GLDrawableImpl { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java index 089a516ee..cb25e6723 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXDrawableFactory.java @@ -46,9 +46,9 @@ import com.jogamp.gluegen.runtime.*; import com.jogamp.gluegen.runtime.opengl.*; import com.jogamp.opengl.impl.*; import com.jogamp.opengl.impl.x11.glx.*; -import com.sun.nativewindow.impl.NullWindow; -import com.sun.nativewindow.impl.NWReflection; -import com.sun.nativewindow.impl.x11.*; +import com.jogamp.nativewindow.impl.NullWindow; +import com.jogamp.nativewindow.impl.NWReflection; +import com.jogamp.nativewindow.impl.x11.*; public class X11GLXDrawableFactory extends GLDrawableFactoryImpl implements DynamicLookupHelper { public X11GLXDrawableFactory() { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfiguration.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfiguration.java index 498605594..f127ec2d0 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfiguration.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfiguration.java @@ -39,7 +39,7 @@ import javax.media.opengl.*; import com.jogamp.opengl.impl.*; import com.jogamp.gluegen.runtime.NativeLibrary; import com.jogamp.gluegen.runtime.PointerBuffer; -import com.sun.nativewindow.impl.x11.*; +import com.jogamp.nativewindow.impl.x11.*; public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implements Cloneable { protected static final boolean DEBUG = Debug.debug("GraphicsConfiguration"); diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfigurationFactory.java index 1ddac9013..eca5fede5 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfigurationFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11GLXGraphicsConfigurationFactory.java @@ -34,8 +34,8 @@ package com.jogamp.opengl.impl.x11.glx; import javax.media.nativewindow.*; import javax.media.nativewindow.x11.*; -import com.sun.nativewindow.impl.NativeWindowFactoryImpl; -import com.sun.nativewindow.impl.x11.*; +import com.jogamp.nativewindow.impl.NativeWindowFactoryImpl; +import com.jogamp.nativewindow.impl.x11.*; import javax.media.opengl.*; import com.jogamp.opengl.impl.*; diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OffscreenGLXDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OffscreenGLXDrawable.java index 7d866a200..ea855d28d 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OffscreenGLXDrawable.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11OffscreenGLXDrawable.java @@ -42,7 +42,7 @@ package com.jogamp.opengl.impl.x11.glx; import javax.media.nativewindow.*; import javax.media.opengl.*; import com.jogamp.opengl.impl.*; -import com.sun.nativewindow.impl.x11.*; +import com.jogamp.nativewindow.impl.x11.*; public class X11OffscreenGLXDrawable extends X11GLXDrawable { private long pixmap; diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11PbufferGLXDrawable.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11PbufferGLXDrawable.java index 3e012225e..50b32b9ec 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11PbufferGLXDrawable.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/X11PbufferGLXDrawable.java @@ -43,7 +43,7 @@ import javax.media.opengl.*; import javax.media.nativewindow.*; import com.jogamp.opengl.impl.*; import com.jogamp.opengl.impl.x11.glx.*; -import com.sun.nativewindow.impl.x11.*; +import com.jogamp.nativewindow.impl.x11.*; public class X11PbufferGLXDrawable extends X11GLXDrawable { protected X11PbufferGLXDrawable(GLDrawableFactory factory, NativeWindow target) { diff --git a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java index 3b2c8f541..63b350bd3 100644 --- a/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java +++ b/src/jogl/classes/com/jogamp/opengl/impl/x11/glx/awt/X11AWTGLXGraphicsConfigurationFactory.java @@ -42,9 +42,9 @@ import javax.media.opengl.*; import javax.media.opengl.awt.*; import com.jogamp.opengl.impl.*; -import com.sun.nativewindow.impl.jawt.*; -import com.sun.nativewindow.impl.jawt.x11.*; -import com.sun.nativewindow.impl.x11.*; +import com.jogamp.nativewindow.impl.jawt.*; +import com.jogamp.nativewindow.impl.jawt.x11.*; +import com.jogamp.nativewindow.impl.x11.*; import com.jogamp.opengl.impl.x11.*; import com.jogamp.opengl.impl.x11.glx.*; diff --git a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java index 98249184d..7c71c4309 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java +++ b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java @@ -3,7 +3,7 @@ package com.jogamp.opengl.util; import javax.media.opengl.*; import javax.media.opengl.fixedfunc.*; -import com.sun.nativewindow.impl.NWReflection; +import com.jogamp.nativewindow.impl.NWReflection; import java.nio.*; import java.util.Iterator; import java.util.ArrayList; diff --git a/src/jogl/classes/com/jogamp/openmax/OMXEventListener.java b/src/jogl/classes/com/jogamp/openmax/OMXEventListener.java new file mode 100644 index 000000000..08cfeccde --- /dev/null +++ b/src/jogl/classes/com/jogamp/openmax/OMXEventListener.java @@ -0,0 +1,14 @@ + +package com.jogamp.openmax; + +public interface OMXEventListener { + + static final int EVENT_CHANGE_SIZE = 1<<0; + static final int EVENT_CHANGE_FPS = 1<<1; + static final int EVENT_CHANGE_BPS = 1<<2; + static final int EVENT_CHANGE_LENGTH = 1<<3; + + public void changedAttributes(OMXInstance omx, int event_mask); + +} + diff --git a/src/jogl/classes/com/jogamp/openmax/OMXInstance.java b/src/jogl/classes/com/jogamp/openmax/OMXInstance.java new file mode 100644 index 000000000..9f5b850ba --- /dev/null +++ b/src/jogl/classes/com/jogamp/openmax/OMXInstance.java @@ -0,0 +1,509 @@ + +package com.jogamp.openmax; + +import javax.media.opengl.*; +import javax.media.opengl.glu.GLU; +import com.jogamp.opengl.util.texture.*; + +import com.jogamp.opengl.impl.egl.EGL; +import com.jogamp.opengl.impl.egl.EGLContext; +import com.jogamp.opengl.impl.egl.EGLDrawable; +import com.jogamp.opengl.impl.egl.EGLExt; + +import java.net.URL; +import java.nio.ByteBuffer; +import java.io.File; +import java.io.FileNotFoundException; +import java.util.*; + +public class OMXInstance { + private long moviePtr = 0; + + protected String path = null; + protected URL url = null; + + // *** Texture impl + protected Texture texture = null; // holds the last fetched texture + + protected float playSpeed = 1.0f; + + /** + * The following data is set by the setStream function, + * and may be set by the native OMX implementation, + * in case the stream attributes changes (see attributesUpdated) + */ + protected int width = 0; + protected int height = 0; + protected int fps = 0; // frames per seconds + protected long bps = 0; // bits per seconds + protected long totalFrames = 0; // duration in frames + protected String acodec = null; + protected String vcodec = null; + + /** + * Old stream values, before the last attributesUpdated) + */ + protected int o_width = 0; + protected int o_height = 0; + protected int o_fps = 0; // frames per seconds + protected long o_bps = 0; // bits per seconds + protected long o_totalFrames = 0; // duration in frames + + static class EGLImageTexture { + public EGLImageTexture(com.jogamp.opengl.util.texture.Texture t, long i, long s) { + texture = t; image = i; sync = s; + } + public String toString() { + return "EGLImageTexture[" + texture + ", image " + image + ", sync "+sync+"]"; + } + protected com.jogamp.opengl.util.texture.Texture texture; + protected long image; + protected long sync; + } + private EGLImageTexture[] eglImgTexs=null; + private HashMap eglImgTexsMap = new HashMap(); + protected int textureNum; + + private EGLExt eglExt = null; + private long eglSurface = 0; + private long eglDisplay = 0; + private long eglContext = 0; + private int sWidth=0, sHeight=0; + + private GL initGLData(GL gl) { + if(null==gl) { + throw new RuntimeException("No current GL"); + } + EGLContext eglCtx = (EGLContext) gl.getContext(); + if(null==eglCtx) { + throw new RuntimeException("No current EGL context"); + } + EGLDrawable eglDrawable = (EGLDrawable) eglCtx.getGLDrawable(); + if(null==eglDrawable) { + throw new RuntimeException("No valid drawable"); + } + eglContext = eglCtx.getContext(); + eglDisplay = eglDrawable.getDisplay(); + eglSurface = eglDrawable.getSurface(); + eglExt = eglCtx.getEGLExt(); + if(null==eglExt) { + throw new RuntimeException("No valid EGLExt"); + } + + int iTmp[] = new int[1]; + EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_WIDTH, iTmp, 0); + sWidth=iTmp[0]; + EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_HEIGHT, iTmp, 0); + sHeight=iTmp[0]; + System.out.println("surface size: "+width+"x"+height); + System.out.println(eglDrawable); + System.out.println(eglCtx); + System.out.println("EGL Extensions : "+EGL.eglQueryString(eglDisplay, EGL.EGL_EXTENSIONS)); + System.out.println("EGL CLIENT APIs: "+EGL.eglQueryString(eglDisplay, EGL.EGL_CLIENT_APIS)); + return gl; + } + + public OMXInstance() { + moviePtr = _createInstance(); + if(0==moviePtr) { + throw new GLException("Couldn't create OMXInstance"); + } + } + native long _createInstance(); + + public synchronized void setStream(int textureNum, URL u) { + if(0==moviePtr) { + throw new GLException("OMX native instance null"); + } + this.textureNum=textureNum; + url = u; + if (url == null) { + System.out.println("setURL (null)"); + stop(); + return; + } + path=null; + if (url.getProtocol() == null || "file".equals(url.getProtocol())) { + // CV only accepts absolute paths + try { + File file = new File(url.getPath()); + if (!file.exists()) { + throw new RuntimeException(new FileNotFoundException(file.toString())); + } + path = file.getCanonicalPath(); + System.out.println("setURL: path "+path); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + path = replaceAll(path, "\\", "/").trim(); + if(null==path) { + throw new RuntimeException("Couldn't parse stream URL: "+url); + } + System.out.println("setURL: clean path "+path); + + System.out.println("setURL: p1 "+this); + _setStream(moviePtr, textureNum, path); + System.out.println("setURL: p2 "+this); + } + native void _setStream(long moviePtr, int textureNum, String path); + + public synchronized void setStreamAllEGLImageTexture2D(GL gl) { + if(0==moviePtr) { + throw new GLException("OMX native instance null"); + } + if(null==vcodec) { + return; + } + gl = initGLData(gl); + + if(null!=eglImgTexs) { + removeAllEGLImageTexture2D(gl); + } else { + eglImgTexs = new EGLImageTexture[textureNum]; + } + + int[] tmp = new int[1]; + int tex, e; + + errorCheckGL(gl, "i.1"); + gl.glEnable(gl.GL_TEXTURE_2D); + errorCheckGL(gl, "i.2"); + + for(int i=0; i<textureNum; i++) { + String s0 = String.valueOf(i); + gl.glGenTextures(1, tmp, 0); + tex=tmp[0]; + if( (e=gl.glGetError()) != GL.GL_NO_ERROR || 0>tex ) { + throw new RuntimeException("TextureName creation failed: "+e); + } + gl.glBindTexture(gl.GL_TEXTURE_2D, tex); + + // create space for buffer with a texture + gl.glTexImage2D( + gl.GL_TEXTURE_2D, // target + 0, // level + gl.GL_RGBA, // internal format + width, // width + height, // height + 0, // border + gl.GL_RGBA, // format + gl.GL_UNSIGNED_BYTE, // type + null); // pixels -- will be provided later + gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST); + gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_NEAREST); + + long image=0, sync=0; + + // create EGLImage from texture + tmp[0] = EGL.EGL_NONE; + image = eglExt.eglCreateImageKHR( + eglDisplay, + eglContext, + eglExt.EGL_GL_TEXTURE_2D_KHR, + tex, + tmp, 0); + if (0==image) { + throw new RuntimeException("EGLImage creation failed: "+EGL.eglGetError()+", dpy "+eglDisplay+", ctx "+eglContext+", tex "+tex); + } + + // Create sync object so that we can be sure that gl has finished + // rendering the EGLImage texture before we tell OpenMAX to fill + // it with a new frame. + tmp[0] = EGL.EGL_NONE; + sync = eglExt.eglCreateFenceSyncKHR( + eglDisplay, + eglExt.EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR, tmp, 0); + + _setStreamEGLImageTexture2D(moviePtr, i, tex, image, sync); + + eglImgTexs[i] = new EGLImageTexture( + com.jogamp.opengl.util.texture.TextureIO.newTexture(tex, + javax.media.opengl.GL2.GL_TEXTURE_2D, + width, + height, + width, + height, + true), + image, sync); + eglImgTexsMap.put(new Integer(tex), eglImgTexs[i]); + } + gl.glDisable(gl.GL_TEXTURE_2D); + } + native void _setStreamEGLImageTexture2D(long moviePtr, int i, int tex, long image, long sync); + + public synchronized void activateStream() { + if(0==moviePtr) { + throw new GLException("OMX native instance null"); + } + _activateStream(moviePtr); + } + native void _activateStream(long moviePtr); + + public synchronized void detachVideoRenderer() { + if(0==moviePtr) { + throw new GLException("OMX native instance null"); + } + _detachVideoRenderer(moviePtr); + } + native void _detachVideoRenderer(long moviePtr); // stop before + + public synchronized void attachVideoRenderer() { + if(0==moviePtr) { + throw new GLException("OMX native instance null"); + } + _attachVideoRenderer(moviePtr); + } + native void _attachVideoRenderer(long moviePtr); // detach before + + public synchronized void setPlaySpeed(float rate) { + if(0==moviePtr) { + throw new GLException("OMX native instance null"); + } + _setPlaySpeed(moviePtr, rate); + playSpeed = rate; + } + public synchronized float getPlaySpeed() { + return playSpeed; + } + native void _setPlaySpeed(long moviePtr, float rate); + + /** @return time position after issuing the command */ + public synchronized float play() { + if(0==moviePtr) { + throw new GLException("OMX native instance null"); + } + return _play(moviePtr); + } + native float _play(long moviePtr); + + /** @return time position after issuing the command */ + public synchronized float pause() { + if(0==moviePtr) { + throw new GLException("OMX native instance null"); + } + return _pause(moviePtr); + } + native float _pause(long moviePtr); + + /** @return time position after issuing the command */ + public synchronized float stop() { + if(0==moviePtr) { + throw new GLException("OMX native instance null"); + } + return _stop(moviePtr); + } + native float _stop(long moviePtr); + + /** @return time position after issuing the command */ + public synchronized float seek(float pos) { + if(0==moviePtr) { + throw new GLException("OMX native instance null"); + } + return _seek(moviePtr, pos); + } + native float _seek(long moviePtr, float position); + + public synchronized Texture getLastTextureID() { + return texture; + } + public synchronized Texture getNextTextureID() { + if(0==moviePtr) { + throw new GLException("OMX native instance null"); + } + texture=null; + EGLImageTexture eglImgTex = (EGLImageTexture) eglImgTexsMap.get(new Integer(_getNextTextureID(moviePtr))); + if(null!=eglImgTex) { + texture = eglImgTex.texture; + } + return texture; + } + native int _getNextTextureID(long moviePtr); + + public synchronized float getCurrentPosition() { + if(0==moviePtr) { + throw new GLException("OMX native instance null"); + } + return _getCurrentPosition(moviePtr); + } + native float _getCurrentPosition(long moviePtr); + + public synchronized void destroy(GL gl) { + removeAllEGLImageTexture2D(gl); + if (moviePtr != 0) { + long ptr = moviePtr; + moviePtr = 0; + _destroyInstance(ptr); + + eglExt=null; + eglSurface=0; + eglDisplay=0; + eglContext=0; + } + } + protected synchronized void finalize() { + if (moviePtr != 0) { + destroy(null); + } + } + native void _destroyInstance(long moviePtr); + + public synchronized boolean isValid() { + return (moviePtr != 0); + } + public synchronized String getPath() { + return path; + } + public synchronized URL getURL() { + return url; + } + public synchronized String getVideoCodec() { + return vcodec; + } + public synchronized String getAudioCodec() { + return acodec; + } + public synchronized long getTotalFrames() { + return totalFrames; + } + public synchronized long getBitrate() { + return bps; + } + public synchronized int getFramerate() { + return fps; + } + public synchronized int getWidth() { + return width; + } + public synchronized int getHeight() { + return height; + } + public synchronized String toString() { + return "OMXInstance [ stream [ video [ "+vcodec+", "+width+"x"+height+", "+fps+"fps, "+bps+"bsp, "+totalFrames+"f ] ] ]"; + } + + /** + * Java callback method issued by the native OMX backend + */ + private void saveAttributes() { + o_width = width; + o_height = height; + o_fps = fps; + o_bps = bps; + o_totalFrames = totalFrames; + } + + private void attributesUpdated() { + int event_mask = 0; + if( o_width != width || o_height != height ) { + event_mask |= OMXEventListener.EVENT_CHANGE_SIZE; + } + if( o_fps != fps ) { + event_mask |= OMXEventListener.EVENT_CHANGE_FPS; + } + if( o_bps != bps ) { + event_mask |= OMXEventListener.EVENT_CHANGE_BPS; + } + if( o_totalFrames != totalFrames ) { + event_mask |= OMXEventListener.EVENT_CHANGE_LENGTH; + } + if(0==event_mask) { + return; + } + + ArrayList listeners = null; + synchronized(this) { + listeners = eventListeners; + } + for(Iterator i = listeners.iterator(); i.hasNext(); ) { + OMXEventListener l = (OMXEventListener) i.next(); + l.changedAttributes(this, event_mask); + } + } + + private String replaceAll(String orig, String search, String repl) { + String dest=null; + // In case replaceAll / java.util.regex.* is not supported (-> CVM) + int i=0,j; + dest = new String(); + while((j=orig.indexOf(search, i))>=0) { + dest=dest.concat(orig.substring(i, j)); + dest=dest.concat(repl); + i=j+1; + } + return dest.concat(orig.substring(i, orig.length())); + } + + private void removeAllEGLImageTexture2D(GL gl) { + if (moviePtr != 0) { + if(null==eglExt) { + throw new RuntimeException("No valid EGLExt"); + } + + texture = null; + for(int i=0; i<textureNum; i++) { + if(null!=eglImgTexs[i]) { + if(0!=eglImgTexs[i].image) { + eglExt.eglDestroyImageKHR( + eglDisplay, + eglImgTexs[i].image); + } + if(0!=eglImgTexs[i].sync) { + eglExt.eglDestroySyncKHR(eglImgTexs[i].sync); + } + if(null!=gl) { + eglImgTexs[i].texture.destroy(gl); + } + eglImgTexs[i]=null; + } + } + eglImgTexsMap.clear(); + } + } + + private void errorCheckGL(GL gl, String s) { + int e; + if( (e=gl.glGetError()) != GL.GL_NO_ERROR ) { + System.out.println("GL Error: ("+s+"): "+e); + } + } + + private void errorCheckEGL(String s) { + int e; + if( (e=EGL.eglGetError()) != EGL.EGL_SUCCESS ) { + System.out.println("EGL Error: ("+s+"): "+e); + } + } + + + // + // OMXEventListener Support + // + + public synchronized void addEventListener(OMXEventListener l) { + if(l == null) { + return; + } + ArrayList newEventListeners = (ArrayList) eventListeners.clone(); + newEventListeners.add(l); + eventListeners = newEventListeners; + } + + public synchronized void removeEventListener(OMXEventListener l) { + if (l == null) { + return; + } + ArrayList newEventListeners = (ArrayList) eventListeners.clone(); + newEventListeners.remove(l); + eventListeners = newEventListeners; + } + + public synchronized OMXEventListener[] getEventListeners() { + return (OMXEventListener[]) eventListeners.toArray(); + } + + private ArrayList eventListeners = new ArrayList(); + +} + |